From e7d6ed09200869eb00e0c44c43f19808aa31f471 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Fri, 4 Aug 2023 17:08:19 +0900 Subject: [PATCH 001/619] =?UTF-8?q?chore:=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EC=B4=88=EA=B8=B0=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 42 +++ build.gradle | 39 +++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63375 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 248 ++++++++++++++++++ gradlew.bat | 92 +++++++ settings.gradle | 1 + .../com/moing/backend/BackendApplication.java | 13 + .../backend/BackendApplicationTests.java | 13 + 9 files changed, 455 insertions(+) create mode 100644 .gitignore create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle create mode 100644 src/main/java/com/moing/backend/BackendApplication.java create mode 100644 src/test/java/com/moing/backend/BackendApplicationTests.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..87cefe4e --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### yml ### +application.yml +.DS_Store +firebase-key.json diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..443f43c2 --- /dev/null +++ b/build.gradle @@ -0,0 +1,39 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '2.7.14' + id 'io.spring.dependency-management' version '1.0.15.RELEASE' +} + +group = 'com.moing' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '11' +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'com.mysql:mysql-connector-j' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.security:spring-security-test' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..033e24c4cdf41af1ab109bc7f253b2b887023340 GIT binary patch literal 63375 zcmb5VV{~QRw)Y#`wrv{~+qP{x72B%VwzFc}c2cp;N~)5ZbDrJayPv(!dGEd-##*zr z)#n-$y^sH|_dchh3@8{H5D*j;5D<{i*8l5IFJ|DjL!e)upfGNX(kojugZ3I`oH1PvW`wFW_ske0j@lB9bX zO;2)`y+|!@X(fZ1<2n!Qx*)_^Ai@Cv-dF&(vnudG?0CsddG_&Wtae(n|K59ew)6St z#dj7_(Cfwzh$H$5M!$UDd8=4>IQsD3xV=lXUq($;(h*$0^yd+b{qq63f0r_de#!o_ zXDngc>zy`uor)4A^2M#U*DC~i+dc<)Tb1Tv&~Ev@oM)5iJ4Sn#8iRw16XXuV50BS7 zdBL5Mefch(&^{luE{*5qtCZk$oFr3RH=H!c3wGR=HJ(yKc_re_X9pD` zJ;uxPzUfVpgU>DSq?J;I@a+10l0ONXPcDkiYcihREt5~T5Gb}sT0+6Q;AWHl`S5dV>lv%-p9l#xNNy7ZCr%cyqHY%TZ8Q4 zbp&#ov1*$#grNG#1vgfFOLJCaNG@K|2!W&HSh@3@Y%T?3YI75bJp!VP*$*!< z;(ffNS_;@RJ`=c7yX04!u3JP*<8jeqLHVJu#WV&v6wA!OYJS4h<_}^QI&97-;=ojW zQ-1t)7wnxG*5I%U4)9$wlv5Fr;cIizft@&N+32O%B{R1POm$oap@&f| zh+5J{>U6ftv|vAeKGc|zC=kO(+l7_cLpV}-D#oUltScw})N>~JOZLU_0{Ka2e1evz z{^a*ZrLr+JUj;)K&u2CoCAXLC2=fVScI(m_p~0FmF>>&3DHziouln?;sxW`NB}cSX z8?IsJB)Z=aYRz!X=yJn$kyOWK%rCYf-YarNqKzmWu$ZvkP12b4qH zhS9Q>j<}(*frr?z<%9hl*i^#@*O2q(Z^CN)c2c z>1B~D;@YpG?G!Yk+*yn4vM4sO-_!&m6+`k|3zd;8DJnxsBYtI;W3We+FN@|tQ5EW= z!VU>jtim0Mw#iaT8t_<+qKIEB-WwE04lBd%Letbml9N!?SLrEG$nmn7&W(W`VB@5S zaY=sEw2}i@F_1P4OtEw?xj4@D6>_e=m=797#hg}f*l^`AB|Y0# z9=)o|%TZFCY$SzgSjS|8AI-%J4x}J)!IMxY3_KYze`_I=c1nmrk@E8c9?MVRu)7+Ue79|)rBX7tVB7U|w4*h(;Gi3D9le49B38`wuv zp7{4X^p+K4*$@gU(Tq3K1a#3SmYhvI42)GzG4f|u zwQFT1n_=n|jpi=70-yE9LA+d*T8u z`=VmmXJ_f6WmZveZPct$Cgu^~gFiyL>Lnpj*6ee>*0pz=t$IJ}+rE zsf@>jlcG%Wx;Cp5x)YSVvB1$yyY1l&o zvwX=D7k)Dn;ciX?Z)Pn8$flC8#m`nB&(8?RSdBvr?>T9?E$U3uIX7T?$v4dWCa46 z+&`ot8ZTEgp7G+c52oHJ8nw5}a^dwb_l%MOh(ebVj9>_koQP^$2B~eUfSbw9RY$_< z&DDWf2LW;b0ZDOaZ&2^i^g+5uTd;GwO(-bbo|P^;CNL-%?9mRmxEw~5&z=X^Rvbo^WJW=n_%*7974RY}JhFv46> zd}`2|qkd;89l}R;i~9T)V-Q%K)O=yfVKNM4Gbacc7AOd>#^&W&)Xx!Uy5!BHnp9kh z`a(7MO6+Ren#>R^D0K)1sE{Bv>}s6Rb9MT14u!(NpZOe-?4V=>qZ>}uS)!y~;jEUK z&!U7Fj&{WdgU#L0%bM}SYXRtM5z!6M+kgaMKt%3FkjWYh=#QUpt$XX1!*XkpSq-pl zhMe{muh#knk{9_V3%qdDcWDv}v)m4t9 zQhv{;} zc{}#V^N3H>9mFM8`i`0p+fN@GqX+kl|M94$BK3J-X`Hyj8r!#x6Vt(PXjn?N)qedP z=o1T^#?1^a{;bZ&x`U{f?}TMo8ToN zkHj5v|}r}wDEi7I@)Gj+S1aE-GdnLN+$hw!=DzglMaj#{qjXi_dwpr|HL(gcCXwGLEmi|{4&4#OZ4ChceA zKVd4K!D>_N=_X;{poT~4Q+!Le+ZV>=H7v1*l%w`|`Dx8{)McN@NDlQyln&N3@bFpV z_1w~O4EH3fF@IzJ9kDk@7@QctFq8FbkbaH7K$iX=bV~o#gfh?2JD6lZf(XP>~DACF)fGFt)X%-h1yY~MJU{nA5 ze2zxWMs{YdX3q5XU*9hOH0!_S24DOBA5usB+Ws$6{|AMe*joJ?RxfV}*7AKN9V*~J zK+OMcE@bTD>TG1*yc?*qGqjBN8mgg@h1cJLDv)0!WRPIkC` zZrWXrceVw;fB%3`6kq=a!pq|hFIsQ%ZSlo~)D z|64!aCnw-?>}AG|*iOl44KVf8@|joXi&|)1rB;EQWgm+iHfVbgllP$f!$Wf42%NO5b(j9Bw6L z;0dpUUK$5GX4QbMlTmLM_jJt!ur`_0~$b#BB7FL*%XFf<b__1o)Ao3rlobbN8-(T!1d-bR8D3S0@d zLI!*GMb5s~Q<&sjd}lBb8Nr0>PqE6_!3!2d(KAWFxa{hm`@u|a(%#i(#f8{BP2wbs zt+N_slWF4IF_O|{w`c~)Xvh&R{Au~CFmW#0+}MBd2~X}t9lz6*E7uAD`@EBDe$>7W zzPUkJx<`f$0VA$=>R57^(K^h86>09?>_@M(R4q($!Ck6GG@pnu-x*exAx1jOv|>KH zjNfG5pwm`E-=ydcb+3BJwuU;V&OS=6yM^4Jq{%AVqnTTLwV`AorIDD}T&jWr8pB&j28fVtk_y*JRP^t@l*($UZ z6(B^-PBNZ+z!p?+e8@$&jCv^EWLb$WO=}Scr$6SM*&~B95El~;W_0(Bvoha|uQ1T< zO$%_oLAwf1bW*rKWmlD+@CP&$ObiDy=nh1b2ejz%LO9937N{LDe7gle4i!{}I$;&Y zkexJ9Ybr+lrCmKWg&}p=`2&Gf10orS?4$VrzWidT=*6{KzOGMo?KI0>GL0{iFWc;C z+LPq%VH5g}6V@-tg2m{C!-$fapJ9y}c$U}aUmS{9#0CM*8pC|sfer!)nG7Ji>mfRh z+~6CxNb>6eWKMHBz-w2{mLLwdA7dA-qfTu^A2yG1+9s5k zcF=le_UPYG&q!t5Zd_*E_P3Cf5T6821bO`daa`;DODm8Ih8k89=RN;-asHIigj`n=ux>*f!OC5#;X5i;Q z+V!GUy0|&Y_*8k_QRUA8$lHP;GJ3UUD08P|ALknng|YY13)}!!HW@0z$q+kCH%xet zlWf@BXQ=b=4}QO5eNnN~CzWBbHGUivG=`&eWK}beuV*;?zt=P#pM*eTuy3 zP}c#}AXJ0OIaqXji78l;YrP4sQe#^pOqwZUiiN6^0RCd#D271XCbEKpk`HI0IsN^s zES7YtU#7=8gTn#lkrc~6)R9u&SX6*Jk4GFX7){E)WE?pT8a-%6P+zS6o&A#ml{$WX zABFz#i7`DDlo{34)oo?bOa4Z_lNH>n;f0nbt$JfAl~;4QY@}NH!X|A$KgMmEsd^&Y zt;pi=>AID7ROQfr;MsMtClr5b0)xo|fwhc=qk33wQ|}$@?{}qXcmECh>#kUQ-If0$ zseb{Wf4VFGLNc*Rax#P8ko*=`MwaR-DQ8L8V8r=2N{Gaips2_^cS|oC$+yScRo*uF zUO|5=?Q?{p$inDpx*t#Xyo6=s?bbN}y>NNVxj9NZCdtwRI70jxvm3!5R7yiWjREEd zDUjrsZhS|P&|Ng5r+f^kA6BNN#|Se}_GF>P6sy^e8kBrgMv3#vk%m}9PCwUWJg-AD zFnZ=}lbi*mN-AOm zCs)r=*YQAA!`e#1N>aHF=bb*z*hXH#Wl$z^o}x##ZrUc=kh%OHWhp=7;?8%Xj||@V?1c ziWoaC$^&04;A|T)!Zd9sUzE&$ODyJaBpvqsw19Uiuq{i#VK1!htkdRWBnb z`{rat=nHArT%^R>u#CjjCkw-7%g53|&7z-;X+ewb?OLWiV|#nuc8mp*LuGSi3IP<<*Wyo9GKV7l0Noa4Jr0g3p_$ z*R9{qn=?IXC#WU>48-k5V2Oc_>P;4_)J@bo1|pf=%Rcbgk=5m)CJZ`caHBTm3%!Z9 z_?7LHr_BXbKKr=JD!%?KhwdYSdu8XxPoA{n8^%_lh5cjRHuCY9Zlpz8g+$f@bw@0V z+6DRMT9c|>1^3D|$Vzc(C?M~iZurGH2pXPT%F!JSaAMdO%!5o0uc&iqHx?ImcX6fI zCApkzc~OOnfzAd_+-DcMp&AOQxE_EsMqKM{%dRMI5`5CT&%mQO?-@F6tE*xL?aEGZ z8^wH@wRl`Izx4sDmU>}Ym{ybUm@F83qqZPD6nFm?t?(7>h*?`fw)L3t*l%*iw0Qu#?$5eq!Qc zpQvqgSxrd83NsdO@lL6#{%lsYXWen~d3p4fGBb7&5xqNYJ)yn84!e1PmPo7ChVd%4 zHUsV0Mh?VpzZD=A6%)Qrd~i7 z96*RPbid;BN{Wh?adeD_p8YU``kOrGkNox3D9~!K?w>#kFz!4lzOWR}puS(DmfjJD z`x0z|qB33*^0mZdM&6$|+T>fq>M%yoy(BEjuh9L0>{P&XJ3enGpoQRx`v6$txXt#c z0#N?b5%srj(4xmPvJxrlF3H%OMB!jvfy z;wx8RzU~lb?h_}@V=bh6p8PSb-dG|-T#A?`c&H2`_!u+uenIZe`6f~A7r)`9m8atC zt(b|6Eg#!Q*DfRU=Ix`#B_dK)nnJ_+>Q<1d7W)eynaVn`FNuN~%B;uO2}vXr5^zi2 z!ifIF5@Zlo0^h~8+ixFBGqtweFc`C~JkSq}&*a3C}L?b5Mh-bW=e)({F_g4O3 zb@SFTK3VD9QuFgFnK4Ve_pXc3{S$=+Z;;4+;*{H}Rc;845rP?DLK6G5Y-xdUKkA6E3Dz&5f{F^FjJQ(NSpZ8q-_!L3LL@H* zxbDF{gd^U3uD;)a)sJwAVi}7@%pRM&?5IaUH%+m{E)DlA_$IA1=&jr{KrhD5q&lTC zAa3c)A(K!{#nOvenH6XrR-y>*4M#DpTTOGQEO5Jr6kni9pDW`rvY*fs|ItV;CVITh z=`rxcH2nEJpkQ^(;1c^hfb8vGN;{{oR=qNyKtR1;J>CByul*+=`NydWnSWJR#I2lN zTvgnR|MBx*XFsfdA&;tr^dYaqRZp*2NwkAZE6kV@1f{76e56eUmGrZ>MDId)oqSWw z7d&r3qfazg+W2?bT}F)4jD6sWaw`_fXZGY&wnGm$FRPFL$HzVTH^MYBHWGCOk-89y zA+n+Q6EVSSCpgC~%uHfvyg@ufE^#u?JH?<73A}jj5iILz4Qqk5$+^U(SX(-qv5agK znUkfpke(KDn~dU0>gdKqjTkVk`0`9^0n_wzXO7R!0Thd@S;U`y)VVP&mOd-2 z(hT(|$=>4FY;CBY9#_lB$;|Wd$aOMT5O_3}DYXEHn&Jrc3`2JiB`b6X@EUOD zVl0S{ijm65@n^19T3l%>*;F(?3r3s?zY{thc4%AD30CeL_4{8x6&cN}zN3fE+x<9; zt2j1RRVy5j22-8U8a6$pyT+<`f+x2l$fd_{qEp_bfxfzu>ORJsXaJn4>U6oNJ#|~p z`*ZC&NPXl&=vq2{Ne79AkQncuxvbOG+28*2wU$R=GOmns3W@HE%^r)Fu%Utj=r9t` zd;SVOnA(=MXgnOzI2@3SGKHz8HN~Vpx&!Ea+Df~`*n@8O=0!b4m?7cE^K*~@fqv9q zF*uk#1@6Re_<^9eElgJD!nTA@K9C732tV~;B`hzZ321Ph=^BH?zXddiu{Du5*IPg} zqDM=QxjT!Rp|#Bkp$(mL)aar)f(dOAXUiw81pX0DC|Y4;>Vz>>DMshoips^8Frdv} zlTD=cKa48M>dR<>(YlLPOW%rokJZNF2gp8fwc8b2sN+i6&-pHr?$rj|uFgktK@jg~ zIFS(%=r|QJ=$kvm_~@n=ai1lA{7Z}i+zj&yzY+!t$iGUy|9jH#&oTNJ;JW-3n>DF+ z3aCOzqn|$X-Olu_p7brzn`uk1F*N4@=b=m;S_C?#hy{&NE#3HkATrg?enaVGT^$qIjvgc61y!T$9<1B@?_ibtDZ{G zeXInVr5?OD_nS_O|CK3|RzzMmu+8!#Zb8Ik;rkIAR%6?$pN@d<0dKD2c@k2quB%s( zQL^<_EM6ow8F6^wJN1QcPOm|ehA+dP(!>IX=Euz5qqIq}Y3;ibQtJnkDmZ8c8=Cf3 zu`mJ!Q6wI7EblC5RvP*@)j?}W=WxwCvF3*5Up_`3*a~z$`wHwCy)2risye=1mSp%p zu+tD6NAK3o@)4VBsM!@);qgsjgB$kkCZhaimHg&+k69~drbvRTacWKH;YCK(!rC?8 zP#cK5JPHSw;V;{Yji=55X~S+)%(8fuz}O>*F3)hR;STU`z6T1aM#Wd+FP(M5*@T1P z^06O;I20Sk!bxW<-O;E081KRdHZrtsGJflFRRFS zdi5w9OVDGSL3 zNrC7GVsGN=b;YH9jp8Z2$^!K@h=r-xV(aEH@#JicPy;A0k1>g1g^XeR`YV2HfmqXY zYbRwaxHvf}OlCAwHoVI&QBLr5R|THf?nAevV-=~V8;gCsX>jndvNOcFA+DI+zbh~# zZ7`qNk&w+_+Yp!}j;OYxIfx_{f0-ONc?mHCiCUak=>j>~>YR4#w# zuKz~UhT!L~GfW^CPqG8Lg)&Rc6y^{%3H7iLa%^l}cw_8UuG;8nn9)kbPGXS}p3!L_ zd#9~5CrH8xtUd?{d2y^PJg+z(xIfRU;`}^=OlehGN2=?}9yH$4Rag}*+AWotyxfCJ zHx=r7ZH>j2kV?%7WTtp+-HMa0)_*DBBmC{sd$)np&GEJ__kEd`xB5a2A z*J+yx>4o#ZxwA{;NjhU*1KT~=ZK~GAA;KZHDyBNTaWQ1+;tOFFthnD)DrCn`DjBZ% zk$N5B4^$`n^jNSOr=t(zi8TN4fpaccsb`zOPD~iY=UEK$0Y70bG{idLx@IL)7^(pL z{??Bnu=lDeguDrd%qW1)H)H`9otsOL-f4bSu};o9OXybo6J!Lek`a4ff>*O)BDT_g z<6@SrI|C9klY(>_PfA^qai7A_)VNE4c^ZjFcE$Isp>`e5fLc)rg@8Q_d^Uk24$2bn z9#}6kZ2ZxS9sI(RqT7?El2@B+($>eBQrNi_k#CDJ8D9}8$mmm z4oSKO^F$i+NG)-HE$O6s1--6EzJa?C{x=QgK&c=)b(Q9OVoAXYEEH20G|q$}Hue%~ zO3B^bF=t7t48sN zWh_zA`w~|){-!^g?6Mqf6ieV zFx~aPUOJGR=4{KsW7I?<=J2|lY`NTU=lt=%JE9H1vBpkcn=uq(q~=?iBt_-r(PLBM zP-0dxljJO>4Wq-;stY)CLB4q`-r*T$!K2o}?E-w_i>3_aEbA^MB7P5piwt1dI-6o!qWCy0 ztYy!x9arGTS?kabkkyv*yxvsPQ7Vx)twkS6z2T@kZ|kb8yjm+^$|sEBmvACeqbz)RmxkkDQX-A*K!YFziuhwb|ym>C$}U|J)4y z$(z#)GH%uV6{ec%Zy~AhK|+GtG8u@c884Nq%w`O^wv2#A(&xH@c5M`Vjk*SR_tJnq z0trB#aY)!EKW_}{#L3lph5ow=@|D5LzJYUFD6 z7XnUeo_V0DVSIKMFD_T0AqAO|#VFDc7c?c-Q%#u00F%!_TW1@JVnsfvm@_9HKWflBOUD~)RL``-!P;(bCON_4eVdduMO>?IrQ__*zE@7(OX zUtfH@AX*53&xJW*Pu9zcqxGiM>xol0I~QL5B%Toog3Jlenc^WbVgeBvV8C8AX^Vj& z^I}H})B=VboO%q1;aU5ACMh{yK4J;xlMc`jCnZR^!~LDs_MP&8;dd@4LDWw~*>#OT zeZHwdQWS!tt5MJQI~cw|Ka^b4c|qyd_ly(+Ql2m&AAw^ zQeSXDOOH!!mAgzAp0z)DD>6Xo``b6QwzUV@w%h}Yo>)a|xRi$jGuHQhJVA%>)PUvK zBQ!l0hq<3VZ*RnrDODP)>&iS^wf64C;MGqDvx>|p;35%6(u+IHoNbK z;Gb;TneFo*`zUKS6kwF*&b!U8e5m4YAo03a_e^!5BP42+r)LFhEy?_7U1IR<; z^0v|DhCYMSj<-;MtY%R@Fg;9Kky^pz_t2nJfKWfh5Eu@_l{^ph%1z{jkg5jQrkvD< z#vdK!nku*RrH~TdN~`wDs;d>XY1PH?O<4^U4lmA|wUW{Crrv#r%N>7k#{Gc44Fr|t z@UZP}Y-TrAmnEZ39A*@6;ccsR>)$A)S>$-Cj!=x$rz7IvjHIPM(TB+JFf{ehuIvY$ zsDAwREg*%|=>Hw$`us~RP&3{QJg%}RjJKS^mC_!U;E5u>`X`jW$}P`Mf}?7G7FX#{ zE(9u1SO;3q@ZhDL9O({-RD+SqqPX)`0l5IQu4q)49TUTkxR(czeT}4`WV~pV*KY&i zAl3~X%D2cPVD^B43*~&f%+Op)wl<&|D{;=SZwImydWL6@_RJjxP2g)s=dH)u9Npki zs~z9A+3fj0l?yu4N0^4aC5x)Osnm0qrhz@?nwG_`h(71P znbIewljU%T*cC=~NJy|)#hT+lx#^5MuDDnkaMb*Efw9eThXo|*WOQzJ*#3dmRWm@! zfuSc@#kY{Um^gBc^_Xdxnl!n&y&}R4yAbK&RMc+P^Ti;YIUh|C+K1|=Z^{nZ}}rxH*v{xR!i%qO~o zTr`WDE@k$M9o0r4YUFFeQO7xCu_Zgy)==;fCJ94M_rLAv&~NhfvcLWCoaGg2ao~3e zBG?Ms9B+efMkp}7BhmISGWmJsKI@a8b}4lLI48oWKY|8?zuuNc$lt5Npr+p7a#sWu zh!@2nnLBVJK!$S~>r2-pN||^w|fY`CT{TFnJy`B|e5;=+_v4l8O-fkN&UQbA4NKTyntd zqK{xEKh}U{NHoQUf!M=2(&w+eef77VtYr;xs%^cPfKLObyOV_9q<(%76-J%vR>w9!us-0c-~Y?_EVS%v!* z15s2s3eTs$Osz$JayyH|5nPAIPEX=U;r&p;K14G<1)bvn@?bM5kC{am|C5%hyxv}a z(DeSKI5ZfZ1*%dl8frIX2?);R^^~LuDOpNpk-2R8U1w92HmG1m&|j&J{EK=|p$;f9 z7Rs5|jr4r8k5El&qcuM+YRlKny%t+1CgqEWO>3;BSRZi(LA3U%Jm{@{y+A+w(gzA< z7dBq6a1sEWa4cD0W7=Ld9z0H7RI^Z7vl(bfA;72j?SWCo`#5mVC$l1Q2--%V)-uN* z9ha*s-AdfbDZ8R8*fpwjzx=WvOtmSzGFjC#X)hD%Caeo^OWjS(3h|d9_*U)l%{Ab8 zfv$yoP{OuUl@$(-sEVNt{*=qi5P=lpxWVuz2?I7Dc%BRc+NGNw+323^ z5BXGfS71oP^%apUo(Y#xkxE)y?>BFzEBZ}UBbr~R4$%b7h3iZu3S(|A;&HqBR{nK& z$;GApNnz=kNO^FL&nYcfpB7Qg;hGJPsCW44CbkG1@l9pn0`~oKy5S777uH)l{irK!ru|X+;4&0D;VE*Ii|<3P zUx#xUqvZT5kVQxsF#~MwKnv7;1pR^0;PW@$@T7I?s`_rD1EGUdSA5Q(C<>5SzE!vw z;{L&kKFM-MO>hy#-8z`sdVx})^(Dc-dw;k-h*9O2_YZw}|9^y-|8RQ`BWJUJL(Cer zP5Z@fNc>pTXABbTRY-B5*MphpZv6#i802giwV&SkFCR zGMETyUm(KJbh+&$8X*RB#+{surjr;8^REEt`2&Dubw3$mx>|~B5IKZJ`s_6fw zKAZx9&PwBqW1Oz0r0A4GtnZd7XTKViX2%kPfv+^X3|_}RrQ2e3l=KG_VyY`H?I5&CS+lAX5HbA%TD9u6&s#v!G> zzW9n4J%d5ye7x0y`*{KZvqyXUfMEE^ZIffzI=Hh|3J}^yx7eL=s+TPH(Q2GT-sJ~3 zI463C{(ag7-hS1ETtU;_&+49ABt5!A7CwLwe z=SoA8mYZIQeU;9txI=zcQVbuO%q@E)JI+6Q!3lMc=Gbj(ASg-{V27u>z2e8n;Nc*pf}AqKz1D>p9G#QA+7mqqrEjGfw+85Uyh!=tTFTv3|O z+)-kFe_8FF_EkTw!YzwK^Hi^_dV5x-Ob*UWmD-})qKj9@aE8g240nUh=g|j28^?v7 zHRTBo{0KGaWBbyX2+lx$wgXW{3aUab6Bhm1G1{jTC7ota*JM6t+qy)c5<@ zpc&(jVdTJf(q3xB=JotgF$X>cxh7k*(T`-V~AR+`%e?YOeALQ2Qud( zz35YizXt(aW3qndR}fTw1p()Ol4t!D1pitGNL95{SX4ywzh0SF;=!wf=?Q?_h6!f* zh7<+GFi)q|XBsvXZ^qVCY$LUa{5?!CgwY?EG;*)0ceFe&=A;!~o`ae}Z+6me#^sv- z1F6=WNd6>M(~ z+092z>?Clrcp)lYNQl9jN-JF6n&Y0mp7|I0dpPx+4*RRK+VQI~>en0Dc;Zfl+x z_e_b7s`t1_A`RP3$H}y7F9_na%D7EM+**G_Z0l_nwE+&d_kc35n$Fxkd4r=ltRZhh zr9zER8>j(EdV&Jgh(+i}ltESBK62m0nGH6tCBr90!4)-`HeBmz54p~QP#dsu%nb~W z7sS|(Iydi>C@6ZM(Us!jyIiszMkd)^u<1D+R@~O>HqZIW&kearPWmT>63%_t2B{_G zX{&a(gOYJx!Hq=!T$RZ&<8LDnxsmx9+TBL0gTk$|vz9O5GkK_Yx+55^R=2g!K}NJ3 zW?C;XQCHZl7H`K5^BF!Q5X2^Mj93&0l_O3Ea3!Ave|ixx+~bS@Iv18v2ctpSt4zO{ zp#7pj!AtDmti$T`e9{s^jf(ku&E|83JIJO5Qo9weT6g?@vX!{7)cNwymo1+u(YQ94 zopuz-L@|5=h8A!(g-MXgLJC0MA|CgQF8qlonnu#j z;uCeq9ny9QSD|p)9sp3ebgY3rk#y0DA(SHdh$DUm^?GI<>%e1?&}w(b zdip1;P2Z=1wM+$q=TgLP$}svd!vk+BZ@h<^4R=GS2+sri7Z*2f`9 z5_?i)xj?m#pSVchk-SR!2&uNhzEi+#5t1Z$o0PoLGz*pT64%+|Wa+rd5Z}60(j?X= z{NLjtgRb|W?CUADqOS@(*MA-l|E342NxRaxLTDqsOyfWWe%N(jjBh}G zm7WPel6jXijaTiNita+z(5GCO0NM=Melxud57PP^d_U## zbA;9iVi<@wr0DGB8=T9Ab#2K_#zi=$igyK48@;V|W`fg~7;+!q8)aCOo{HA@vpSy-4`^!ze6-~8|QE||hC{ICKllG9fbg_Y7v z$jn{00!ob3!@~-Z%!rSZ0JO#@>|3k10mLK0JRKP-Cc8UYFu>z93=Ab-r^oL2 zl`-&VBh#=-?{l1TatC;VweM^=M7-DUE>m+xO7Xi6vTEsReyLs8KJ+2GZ&rxw$d4IT zPXy6pu^4#e;;ZTsgmG+ZPx>piodegkx2n0}SM77+Y*j^~ICvp#2wj^BuqRY*&cjmL zcKp78aZt>e{3YBb4!J_2|K~A`lN=u&5j!byw`1itV(+Q_?RvV7&Z5XS1HF)L2v6ji z&kOEPmv+k_lSXb{$)of~(BkO^py&7oOzpjdG>vI1kcm_oPFHy38%D4&A4h_CSo#lX z2#oqMCTEP7UvUR3mwkPxbl8AMW(e{ARi@HCYLPSHE^L<1I}OgZD{I#YH#GKnpRmW3 z2jkz~Sa(D)f?V?$gNi?6)Y;Sm{&?~2p=0&BUl_(@hYeX8YjaRO=IqO7neK0RsSNdYjD zaw$g2sG(>JR=8Iz1SK4`*kqd_3-?;_BIcaaMd^}<@MYbYisWZm2C2|Np_l|8r9yM|JkUngSo@?wci(7&O9a z%|V(4C1c9pps0xxzPbXH=}QTxc2rr7fXk$9`a6TbWKPCz&p=VsB8^W96W=BsB|7bc zf(QR8&Ktj*iz)wK&mW`#V%4XTM&jWNnDF56O+2bo<3|NyUhQ%#OZE8$Uv2a@J>D%t zMVMiHh?es!Ex19q&6eC&L=XDU_BA&uR^^w>fpz2_`U87q_?N2y;!Z!bjoeKrzfC)} z?m^PM=(z{%n9K`p|7Bz$LuC7!>tFOuN74MFELm}OD9?%jpT>38J;=1Y-VWtZAscaI z_8jUZ#GwWz{JqvGEUmL?G#l5E=*m>`cY?m*XOc*yOCNtpuIGD+Z|kn4Xww=BLrNYS zGO=wQh}Gtr|7DGXLF%|`G>J~l{k^*{;S-Zhq|&HO7rC_r;o`gTB7)uMZ|WWIn@e0( zX$MccUMv3ABg^$%_lNrgU{EVi8O^UyGHPNRt%R!1#MQJn41aD|_93NsBQhP80yP<9 zG4(&0u7AtJJXLPcqzjv`S~5;Q|5TVGccN=Uzm}K{v)?f7W!230C<``9(64}D2raRU zAW5bp%}VEo{4Rko`bD%Ehf=0voW?-4Mk#d3_pXTF!-TyIt6U+({6OXWVAa;s-`Ta5 zTqx&8msH3+DLrVmQOTBOAj=uoxKYT3DS1^zBXM?1W+7gI!aQNPYfUl{3;PzS9*F7g zWJN8x?KjBDx^V&6iCY8o_gslO16=kh(|Gp)kz8qlQ`dzxQv;)V&t+B}wwdi~uBs4? zu~G|}y!`3;8#vIMUdyC7YEx6bb^1o}G!Jky4cN?BV9ejBfN<&!4M)L&lRKiuMS#3} z_B}Nkv+zzxhy{dYCW$oGC&J(Ty&7%=5B$sD0bkuPmj7g>|962`(Q{ZZMDv%YMuT^KweiRDvYTEop3IgFv#)(w>1 zSzH>J`q!LK)c(AK>&Ib)A{g`Fdykxqd`Yq@yB}E{gnQV$K!}RsgMGWqC3DKE(=!{}ekB3+(1?g}xF>^icEJbc z5bdxAPkW90atZT+&*7qoLqL#p=>t-(-lsnl2XMpZcYeW|o|a322&)yO_8p(&Sw{|b zn(tY$xn5yS$DD)UYS%sP?c|z>1dp!QUD)l;aW#`%qMtQJjE!s2z`+bTSZmLK7SvCR z=@I4|U^sCwZLQSfd*ACw9B@`1c1|&i^W_OD(570SDLK`MD0wTiR8|$7+%{cF&){$G zU~|$^Ed?TIxyw{1$e|D$050n8AjJvvOWhLtLHbSB|HIfhMpqVf>AF&}ZQHhOJ14Bz zww+XL+qP}nww+W`F>b!by|=&a(cM4JIDhsTXY8@|ntQG}-}jm0&Bcj|LV(#sc=BNS zRjh;k9l>EdAFdd)=H!U`~$WP*}~^3HZ_?H>gKw>NBa;tA8M1{>St|)yDF_=~{KEPAGkg3VB`QCHol!AQ0|?e^W?81f{@()Wy!vQ$bY; z0ctx)l7VK83d6;dp!s{Nu=SwXZ8lHQHC*J2g@P0a={B8qHdv(+O3wV=4-t4HK1+smO#=S; z3cSI#Nh+N@AqM#6wPqjDmQM|x95JG|l1#sAU|>I6NdF*G@bD?1t|ytHlkKD+z9}#j zbU+x_cR-j9yX4s{_y>@zk*ElG1yS({BInGJcIT>l4N-DUs6fufF#GlF2lVUNOAhJT zGZThq54GhwCG(h4?yWR&Ax8hU<*U)?g+HY5-@{#ls5CVV(Wc>Bavs|l<}U|hZn z_%m+5i_gaakS*Pk7!v&w3&?R5Xb|AkCdytTY;r+Z7f#Id=q+W8cn)*9tEet=OG+Y} z58U&!%t9gYMx2N=8F?gZhIjtkH!`E*XrVJ?$2rRxLhV1z82QX~PZi8^N5z6~f-MUE zLKxnNoPc-SGl7{|Oh?ZM$jq67sSa)Wr&3)0YxlJt(vKf!-^L)a|HaPv*IYXb;QmWx zsqM>qY;tpK3RH-omtta+Xf2Qeu^$VKRq7`e$N-UCe1_2|1F{L3&}M0XbJ@^xRe&>P zRdKTgD6601x#fkDWkoYzRkxbn#*>${dX+UQ;FbGnTE-+kBJ9KPn)501#_L4O_k`P3 zm+$jI{|EC?8BXJY{P~^f-{**E53k%kVO$%p+=H5DiIdwMmUo>2euq0UzU90FWL!>; z{5@sd0ecqo5j!6AH@g6Mf3keTP$PFztq}@)^ZjK;H6Go$#SV2|2bAFI0%?aXgVH$t zb4Kl`$Xh8qLrMbZUS<2*7^F0^?lrOE=$DHW+O zvLdczsu0^TlA6RhDy3=@s!k^1D~Awulk!Iyo#}W$xq8{yTAK!CLl={H0@YGhg-g~+ z(u>pss4k#%8{J%~%8=H5!T`rqK6w^es-cNVE}=*lP^`i&K4R=peg1tdmT~UAbDKc& zg%Y*1E{hBf<)xO>HDWV7BaMWX6FW4ou1T2m^6{Jb!Su1UaCCYY8RR8hAV$7ho|FyEyP~ zEgK`@%a$-C2`p zV*~G>GOAs*3KN;~IY_UR$ISJxB(N~K>=2C2V6>xTmuX4klRXdrJd&UPAw7&|KEwF8Zcy2j-*({gSNR1^p02Oj88GN9a_Hq;Skdp}kO0;FLbje%2ZvPiltDZgv^ z#pb4&m^!79;O8F+Wr9X71laPY!CdNXG?J6C9KvdAE2xWW1>U~3;0v≫L+crb^Bz zc+Nw%zgpZ6>!A3%lau!Pw6`Y#WPVBtAfKSsqwYDWQK-~ zz(mx=nJ6-8t`YXB{6gaZ%G}Dmn&o500Y}2Rd?e&@=hBEmB1C=$OMBfxX__2c2O4K2#(0ksclP$SHp*8jq-1&(<6(#=6&H`Nlc2RVC4->r6U}sTY<1? zn@tv7XwUs-c>Lcmrm5AE0jHI5={WgHIow6cX=UK)>602(=arbuAPZ37;{HTJSIO%9EL`Et5%J7$u_NaC(55x zH^qX^H}*RPDx)^c46x>js=%&?y?=iFs^#_rUl@*MgLD92E5y4B7#EDe9yyn*f-|pQ zi>(!bIg6zY5fLSn@;$*sN|D2A{}we*7+2(4&EhUV%Qqo5=uuN^xt_hll7=`*mJq6s zCWUB|s$)AuS&=)T&_$w>QXHqCWB&ndQ$y4-9fezybZb0bYD^zeuZ>WZF{rc>c4s`` zgKdppTB|o>L1I1hAbnW%H%EkFt%yWC|0~+o7mIyFCTyb?@*Ho)eu(x`PuO8pLikN> z6YeI`V?AUWD(~3=8>}a6nZTu~#QCK(H0+4!ql3yS`>JX;j4+YkeG$ZTm33~PLa3L} zksw7@%e-mBM*cGfz$tS4LC^SYVdBLsR}nAprwg8h2~+Cv*W0%izK+WPVK}^SsL5R_ zpA}~G?VNhJhqx2he2;2$>7>DUB$wN9_-adL@TqVLe=*F8Vsw-yho@#mTD6*2WAr6B zjtLUh`E(;#p0-&$FVw(r$hn+5^Z~9J0}k;j$jL1;?2GN9s?}LASm?*Rvo@?E+(}F& z+=&M-n`5EIz%%F^e)nnWjkQUdG|W^~O|YeY4Fz}>qH2juEere}vN$oJN~9_Th^&b{ z%IBbET*E8%C@jLTxV~h#mxoRrJCF{!CJOghjuKOyl_!Jr?@4Upo7u>fTGtfm|CH2v z&9F+>;6aFbYXLj3{yZ~Yn1J2%!)A3~j2$`jOy{XavW@t)g}}KUVjCWG0OUc7aBc=2 zR3^u=dT47=5SmT{K1aGaVZkOx|24T-J0O$b9dfB25J|7yb6frwS6wZ1^y%EWOm}S< zc1SdYhfsdLG*FB-;!QLV3D!d~hnXTGVQVck9x%=B(Kk8c3y%f0nR95_TbY;l=obSl zEE@fp0|8Q$b3(+DXh?d0FEloGhO0#11CLQT5qtEckBLe-VN-I>9ys}PVK0r;0!jIG zH_q$;a`3Xv9P_V2ekV1SMzd#SKo<1~Dq2?M{(V;AwhH_2x@mN$=|=cG0<3o^j_0OF z7|WJ-f2G=7sA4NVGU2X5`o*D2T7(MbmZ2(oipooE{R?9!{WxX!%ofhsrPAxoIk!Kr z>I$a{Zq=%KaLrDCIL^gmA3z{2z%Wkr)b$QHcNUA^QwydWMJmxymO0QS22?mo%4(Md zgME(zE}ub--3*wGjV`3eBMCQG-@Gel1NKZDGuqobN|mAt0{@ZC9goI|BSmGBTUZ(`Xt z^e2LiMg?6E?G*yw(~K8lO(c4)RY7UWxrXzW^iCg-P41dUiE(i+gDmmAoB?XOB}+Ln z_}rApiR$sqNaT4frw69Wh4W?v(27IlK$Toy<1o)GeF+sGzYVeJ`F)3`&2WDi^_v67 zg;@ehwl3=t+}(DJtOYO!s`jHyo-}t@X|U*9^sIfaZfh;YLqEFmZ^E;$_XK}%eq;>0 zl?+}*kh)5jGA}3daJ*v1knbW0GusR1+_xD`MFPZc3qqYMXd>6*5?%O5pC7UVs!E-` zuMHc6igdeFQ`plm+3HhP)+3I&?5bt|V8;#1epCsKnz0%7m9AyBmz06r90n~9o;K30 z=fo|*`Qq%dG#23bVV9Jar*zRcV~6fat9_w;x-quAwv@BkX0{9e@y0NB(>l3#>82H6 z^US2<`=M@6zX=Pz>kb8Yt4wmeEo%TZ=?h+KP2e3U9?^Nm+OTx5+mVGDvgFee%}~~M zK+uHmj44TVs}!A}0W-A92LWE%2=wIma(>jYx;eVB*%a>^WqC7IVN9{o?iw{e4c=CG zC#i=cRJZ#v3 zF^9V+7u?W=xCY%2dvV_0dCP%5)SH*Xm|c#rXhwEl*^{Ar{NVoK*H6f5qCSy`+|85e zjGaKqB)p7zKNKI)iWe6A9qkl=rTjs@W1Crh(3G57qdT0w2ig^{*xerzm&U>YY{+fZbkQ#;^<$JniUifmAuEd^_M(&?sTrd(a*cD! zF*;`m80MrZ^> zaF{}rDhEFLeH#`~rM`o903FLO?qw#_Wyb5}13|0agjSTVkSI6Uls)xAFZifu@N~PM zQ%o?$k)jbY0u|45WTLAirUg3Zi1E&=G#LnSa89F3t3>R?RPcmkF}EL-R!OF_r1ZN` z?x-uHH+4FEy>KrOD-$KHg3$-Xl{Cf0;UD4*@eb~G{CK-DXe3xpEEls?SCj^p z$Uix(-j|9f^{z0iUKXcZQen}*`Vhqq$T?^)Ab2i|joV;V-qw5reCqbh(8N)c%!aB< zVs+l#_)*qH_iSZ_32E~}>=wUO$G_~k0h@ch`a6Wa zsk;<)^y=)cPpHt@%~bwLBy;>TNrTf50BAHUOtt#9JRq1ro{w80^sm-~fT>a$QC;<| zZIN%&Uq>8`Js_E((_1sewXz3VlX|-n8XCfScO`eL|H&2|BPZhDn}UAf_6s}|!XpmUr90v|nCutzMjb9|&}#Y7fj_)$alC zM~~D6!dYxhQof{R;-Vp>XCh1AL@d-+)KOI&5uKupy8PryjMhTpCZnSIQ9^Aq+7=Mb zCYCRvm4;H=Q8nZWkiWdGspC_Wvggg|7N`iED~Eap)Th$~wsxc(>(KI>{i#-~Dd8iQ zzonqc9DW1w4a*}k`;rxykUk+~N)|*I?@0901R`xy zN{20p@Ls<%`1G1Bx87Vm6Z#CA`QR(x@t8Wc?tpaunyV^A*-9K9@P>hAWW9Ev)E$gb z<(t?Te6GcJX2&0% z403pe>e)>m-^qlJU^kYIH)AutgOnq!J>FoMXhA-aEx-((7|(*snUyxa+5$wx8FNxS zKuVAVWArlK#kDzEM zqR?&aXIdyvxq~wF?iYPho*(h?k zD(SBpRDZ}z$A})*Qh!9&pZZRyNixD!8)B5{SK$PkVET(yd<8kImQ3ILe%jhx8Ga-1 zE}^k+Eo^?c4Y-t2_qXiVwW6i9o2qosBDj%DRPNT*UXI0=D9q{jB*22t4HHcd$T&Xi zT=Vte*Gz2E^qg%b7ev04Z&(;=I4IUtVJkg<`N6i7tjUn-lPE(Y4HPyJKcSjFnEzCH zPO(w%LmJ_=D~}PyfA91H4gCaf-qur3_KK}}>#9A}c5w@N;-#cHph=x}^mQ3`oo`Y$ope#)H9(kQK zGyt<7eNPuSAs$S%O>2ElZ{qtDIHJ!_THqTwcc-xfv<@1>IJ;YTv@!g-zDKBKAH<

Zet1e^8c}8fE97XH}+lF{qbF<`Y%dU|I!~Y`ZrVfKX82i z)(%!Tcf~eE^%2_`{WBPGPU@1NB5SCXe1sAI<4&n1IwO{&S$ThWn37heGOSW%nW7*L zxh0WK!E7zh%6yF-7%~l@I~b`2=*$;RYbi(I#zp$gL_d39U4A)KuB( zcS0bt48&%G_I~( zL(}w&2NA6#$=|g)J+-?ehHflD^lr77ngdz=dszFI;?~ZxeJv=gsm?4$$6#V==H{fa zqO!EkT>1-OQSJoX)cN}XsB;shvrHRwTH(I2^Ah4|rizn!V7T7fLh~Z<`Q+?zEMVxh z$=-x^RR*PlhkV_8mshTvs+zmZWY&Jk{9LX0Nx|+NAEq-^+Rh|ZlinVZ=e8=`WQt;e@= zPU}^1cG*O;G7l{Y#nl znp`y%CO_SC7gk0i0gY&phM04Y)~vU0!3$V$2T+h(1ZS+cCgc zaC?3M;B48^faGo>h~--#FNFauH?0BJJ6_nG5qOlr>k~%DCSJaOfl%KWHusw>tGrTxAhlEVDxc8R2C-)LCt&$Rt9IKor=ml7jirX@?WW+M z^I{b}MD5r$s>^^sN@&g`cXD~S_u09xo;{;noKZatIuzqd zW1e7oTl9>g8opPBT(p+&fo0F#!c{NFYYpIZ6u8hOB{F#{nP)@})X20$3iJtG$cO zJ$Oxl_qH{sL5d?=D$2M4C3Ajc;GN0(B-HVT;@pJ-LvIrN%|SY?t}g!J>ufQrR%hoY z!nr$tq~N%)9}^tEip93XW=MQ1@XovSvn`PTqXeT9@_7hGv4%LK1M**Q%UKi|(v@1_ zKGe*@+1%Y4v&`;5vUL`C&{tc+_7HFs7*OtjY8@Gg`C4O&#An{0xOvgNSehTHS~_1V z=daxCMzI5b_ydM5$z zZl`a{mM}i@x;=QyaqJY&{Q^R*^1Yzq!dHH~UwCCga+Us~2wk59ArIYtSw9}tEmjbo z5!JA=`=HP*Ae~Z4Pf7sC^A3@Wfa0Ax!8@H_&?WVe*)9B2y!8#nBrP!t1fqhI9jNMd zM_5I)M5z6Ss5t*f$Eh{aH&HBeh310Q~tRl3wCEcZ>WCEq%3tnoHE)eD=)XFQ7NVG5kM zaUtbnq2LQomJSWK)>Zz1GBCIHL#2E>T8INWuN4O$fFOKe$L|msB3yTUlXES68nXRX zP6n*zB+kXqqkpQ3OaMc9GqepmV?Ny!T)R@DLd`|p5ToEvBn(~aZ%+0q&vK1)w4v0* zgW44F2ixZj0!oB~^3k|vni)wBh$F|xQN>~jNf-wFstgiAgB!=lWzM&7&&OYS=C{ce zRJw|)PDQ@3koZfm`RQ$^_hEN$GuTIwoTQIDb?W&wEo@c75$dW(ER6q)qhF`{#7UTuPH&)w`F!w z0EKs}=33m}_(cIkA2rBWvApydi0HSOgc>6tu&+hmRSB%)s`v_NujJNhKLS3r6hv~- z)Hm@?PU{zd0Tga)cJWb2_!!9p3sP%Z zAFT|jy;k>4X)E>4fh^6=SxV5w6oo`mus&nWo*gJL zZH{SR!x)V)y=Qc7WEv-xLR zhD4OcBwjW5r+}pays`o)i$rcJb2MHLGPmeOmt5XJDg@(O3PCbxdDn{6qqb09X44T zh6I|s=lM6Nr#cGaA5-eq*T=LQ6SlRq*`~`b+dVi5^>el1p;#si6}kK}>w;1 z6B1dz{q_;PY{>DBQ+v@1pfXTd5a*^H9U*;qdj@XBF}MoSSQxVXeUpEM5Z0909&8$pRfR|B(t0ox&xl8{8mUNd#(zWONW{oycv$VjP1>q;jU@ z@+8E~fjz*I54OFFaQ{A5jn1w>r;l!NRlI(8q3*%&+tM?lov_G3wB`<}bQ>1=&xUht zmti5VZzV1Cx006Yzt|%Vwid>QPX8Nfa8|sue7^un@C+!3h!?-YK>lSfNIHh|0kL8v zbv_BklQ4HOqje|@Fyxn%IvL$N&?m(KN;%`I$N|muStjSsgG;gP4Smgz$2u(mG;DXP zf~uQ z212x^l6!MW>V@ORUGSFLAAjz3i5zO$=UmD_zhIk2OXUz^LkDLWjla*PW?l;`LLos> z7FBvCr)#)XBByDm(=n%{D>BcUq>0GOV9`i-(ZSI;RH1rdrAJ--f0uuAQ4odl z_^$^U_)0BBJwl@6R#&ZtJN+@a(4~@oYF)yG+G#3=)ll8O#Zv3SjV#zSXTW3h9kqn* z@AHL=vf~KMas}6{+u=}QFumr-!c=(BFP_dwvrdehzTyqco)m@xRc=6b#Dy+KD*-Bq zK=y*1VAPJ;d(b?$2cz{CUeG(0`k9_BIuUki@iRS5lp3=1#g)A5??1@|p=LOE|FNd; z-?5MLKd-5>yQ7n__5W^3C!_`hP(o%_E3BKEmo1h=H(7;{6$XRRW6{u+=oQX<((xAJ zNRY`Egtn#B1EBGHLy^eM5y}Jy0h!GAGhb7gZJoZI-9WuSRw)GVQAAcKd4Qm)pH`^3 zq6EIM}Q zxZGx%aLnNP1an=;o8p9+U^>_Bi`e23E^X|}MB&IkS+R``plrRzTE%ncmfvEW#AHJ~ znmJ`x&ez6eT21aLnoI`%pYYj zzQ?f^ob&Il;>6Fe>HPhAtTZa*B*!;;foxS%NGYmg!#X%)RBFe-acahHs3nkV61(E= zhekiPp1d@ACtA=cntbjuv+r-Zd`+lwKFdqZuYba_ey`&H<Psu;Tzwt;-LQxvv<_D5;ik7 zwETZe`+voUhk%$s2-7Rqfl`Ti_{(fydI(DAHKr<66;rYa6p8AD+NEc@Fd@%m`tiK% z=Mebzrtp=*Q%a}2UdK4J&5#tCN5PX>W=(9rUEXZ8yjRu+7)mFpKh{6;n%!bI(qA9kfyOtstGtOl zX!@*O0fly*L4k##fsm&V0j9Lj<_vu1)i?!#xTB7@2H&)$Kzt@r(GH=xRZlIimTDd_o(%9xO388LwC#;vQ?7OvRU_s< zDS@6@g}VnvQ+tn(C#sx0`J^T4WvFxYI17;uPs-Ub{R`J-NTdtBGl+Q>e81Z3#tDUr ztnVc*p{o|RNnMYts4pdw=P!uJkF@8~h)oV4dXu5F7-j0AW|=mt!QhP&ZV!!82*c7t zuOm>B*2gFtq;A8ynZ~Ms?!gEi5<{R_8tRN%aGM!saR4LJQ|?9w>Ff_61(+|ol_vL4 z-+N>fushRbkB4(e{{SQ}>6@m}s1L!-#20N&h%srA=L50?W9skMF9NGfQ5wU*+0<@> zLww8%f+E0Rc81H3e_5^DB@Dn~TWYk}3tqhO{7GDY;K7b*WIJ-tXnYM@z4rn(LGi?z z8%$wivs)fC#FiJh?(SbH-1bgdmHw&--rn7zBWe1xAhDdv#IRB@DGy}}zS%M0(F_3_ zLb-pWsdJ@xXE;=tpRAw?yj(Gz=i$;bsh&o2XN%24b6+?_gJDBeY zws3PE2u!#Cec>aFMk#ECxDlAs;|M7@LT8)Y4(`M}N6IQ{0YtcA*8e42!n^>`0$LFU zUCq2IR2(L`f++=85M;}~*E($nE&j;p{l%xchiTau*tB9bI= zn~Ygd@<+9DrXxoGPq}@vI1Q3iEfKRleuy*)_$+hg?+GOgf1r?d@Or42|s|D>XMa;ebr1uiTNUq@heusd6%WwJqyCCv!L*qou9l!B22H$bQ z)<)IA>Yo77S;|`fqBk!_PhLJEQb0wd1Z|`pCF;hol!34iQYtqu3K=$QxLW7(HFx~v>`vVRr zyqk^B4~!3F8t8Q_D|GLRrAbbQDf??D&Jd|mgw*t1YCd)CM2$76#Cqj1bD*vADwavp zS<`n@gLU4pwCqNPsIfHKl{5}gu9t-o+O< z??!fMqMrt$s}02pdBbOScUrc1T*{*-ideR6(1q4@oC6mxg8v8Y^h^^hfx6| z|Mld6Ax1CuSlmSJmHwdOix?$8emihK#&8&}u8m!#T1+c5u!H)>QW<7&R$eih)xkov zHvvEIJHbkt+2KQ<-bMR;2SYX?8SI=_<-J!GD5@P2FJ}K z5u82YFotCJF(dUeJFRX_3u8%iIYbRS??A?;iVO?84c}4Du9&jG<#urlZ_Unrcg8dR z!5I3%9F*`qwk#joKG_Q%5_xpU7|jm4h0+l$p;g%Tr>i74#3QnMXdz|1l2MQN$yw|5 zThMw15BxjWf2{KM)XtZ+e#N)ihlkxPe=5ymT9>@Ym%_LF}o z1XhCP`3E1A{iVoHA#|O|&5=w;=j*Qf`;{mBAK3={y-YS$`!0UmtrvzHBfR*s{z<0m zW>4C=%N98hZlUhwAl1X`rR)oL0&A`gv5X79??p_==g*n4$$8o5g9V<)F^u7v0Vv^n z1sp8{W@g6eWv2;A31Rhf5j?KJhITYfXWZsl^`7z`CFtnFrHUWiD?$pwU6|PQjs|7RA0o9ARk^9$f`u3&C|#Z3iYdh<0R`l2`)6+ z6tiDj@xO;Q5PDTYSxsx6n>bj+$JK8IPJ=U5#dIOS-zwyK?+t^V`zChdW|jpZuReE_ z)e~ywgFe!0q|jzsBn&(H*N`%AKpR@qM^|@qFai0};6mG_TvXjJ`;qZ{lGDZHScZk( z>pO+%icp)SaPJUwtIPo1BvGyP8E@~w2y}=^PnFJ$iHod^JH%j1>nXl<3f!nY9K$e` zq-?XYl)K`u*cVXM=`ym{N?z=dHQNR23M8uA-(vsA$6(xn+#B-yY!CB2@`Uz({}}w+ z0sni*39>rMC!Ay|1B@;al%T&xE(wCf+`3w>N)*LxZZZYi{5sqiVWgbNd>W*X?V}C- zjQ4F7e_uCUOHbtewQkq?m$*#@ZvWbu{4i$`aeKM8tc^ zL5!GL8gX}c+qNUtUIcps1S)%Gsx*MQLlQeoZz2y2OQb(A73Jc3`LmlQf0N{RTt;wa`6h|ljX1V7UugML=W5-STDbeWTiEMjPQ$({hn_s&NDXzs6?PLySp$?L`0ilH3vCUO{JS0Dp`z;Ry$6}R@1NdY7rxccbm$+;ApSe=2q!0 z()3$vYN0S$Cs)#-OBs{_2uFf}L4h$;7^2w20=l%5r9ui&pTEgg4U!FoCqyA6r2 zC5s72l}i*9y|KTjDE5gVlYe4I2gGZD)e`Py2gq7cK4at{bT~DSbQQ4Z4sl)kqXbbr zqvXtSqMrDdT2qt-%-HMoqeFEMsv~u)-NJ%Z*ipSJUm$)EJ+we|4*-Mi900K{K|e0; z1_j{X5)a%$+vM7;3j>skgrji92K1*Ip{SfM)=ob^E374JaF!C(cZ$R_E>Wv+?Iy9M z?@`#XDy#=z%3d9&)M=F8Xq5Zif%ldIT#wrlw(D_qOKo4wD(fyDHM5(wm1%7hy6euJ z%Edg!>Egs;ZC6%ktLFtyN0VvxN?*4C=*tOEw`{KQvS7;c514!FP98Nf#d#)+Y-wsl zP3N^-Pnk*{o(3~m=3DX$b76Clu=jMf9E?c^cbUk_h;zMF&EiVz*4I(rFoaHK7#5h0 zW7CQx+xhp}Ev+jw;SQ6P$QHINCxeF8_VX=F3&BWUd(|PVViKJl@-sYiUp@xLS2NuF z8W3JgUSQ&lUp@2E(7MG`sh4X!LQFa6;lInWqx}f#Q z4xhgK1%}b(Z*rZn=W{wBOe7YQ@1l|jQ|9ELiXx+}aZ(>{c7Ltv4d>PJf7f+qjRU8i%XZZFJkj&6D^s;!>`u%OwLa*V5Js9Y$b-mc!t@{C415$K38iVu zP7!{3Ff%i_e!^LzJWhBgQo=j5k<<($$b&%%Xm_f8RFC_(97&nk83KOy@I4k?(k<(6 zthO$3yl&0x!Pz#!79bv^?^85K5e7uS$ zJ33yka2VzOGUhQXeD{;?%?NTYmN3{b0|AMtr(@bCx+c=F)&_>PXgAG}4gwi>g82n> zL3DlhdL|*^WTmn;XPo62HhH-e*XIPSTF_h{#u=NY8$BUW=5@PD{P5n~g5XDg?Fzvb_u ziK&CJqod4srfY2T?+4x@)g9%3%*(Q2%YdCA3yM{s=+QD0&IM`8k8N&-6%iIL3kon> z0>p3BUe!lrz&_ZX2FiP%MeuQY-xVV%K?=bGPOM&XM0XRd7or< zy}jn_eEzuQ>t2fM9ict#ZNxD7HUycsq76IavfoNl$G1|t*qpUSX;YgpmJrr_8yOJ2 z(AwL;Ugi{gJ29@!G-mD82Z)46T`E+s86Qw|YSPO*OoooraA!8x_jQXYq5vUw!5f_x zubF$}lHjIWxFar8)tTg8z-FEz)a=xa`xL~^)jIdezZsg4%ePL$^`VN#c!c6`NHQ9QU zkC^<0f|Ksp45+YoX!Sv>+57q}Rwk*2)f{j8`d8Ctz^S~me>RSakEvxUa^Pd~qe#fb zN7rnAQc4u$*Y9p~li!Itp#iU=*D4>dvJ{Z~}kqAOBcL8ln3YjR{Sp!O`s=5yM zWRNP#;2K#+?I&?ZSLu)^z-|*$C}=0yi7&~vZE$s``IE^PY|dj^HcWI$9ZRm>3w(u` z-1%;;MJbzHFNd^!Ob!^PLO-xhhj@XrI81Y)x4@FdsI( za`o4Gy(`T$P?PB?s>o+eIOtuirMykbuAi65Y_UN1(?jTCy@J8Px`%;bcNmPm#Fr!= z5V!YViFJ!FBfEq>nJFk0^RAV1(7w+X`HRgP;nJHJdMa!}&vvduCMoslwHTes_I76|h>;(-9lbfGnt zoZomakOt759AuTX4b$)G8TzJ&m*BV8!vMs9#=e0tWa z%)84R=3?tfh72~=Rc;fXwj+x z+25xapYK@2@;}6)@8IL+F6iuJ_B{&A-0=U=U6WMbY>~ykVFp$XkH)f**b>TE5)shN z39E2L@JPCSl!?pkvFeh@6dCv9oE}|{GbbVM!XIgByN#md&tXy@>QscU0#z!I&X4;d z&B&ZA4lbrHJ!x4lCN4KC-)u#gT^cE{Xnhu`0RXVKn|j$vz8m}v^%*cQ{(h%FW8_8a zFM{$PirSI8@#*xg2T){A+EKX(eTC66Fb})w{vg%Vw)hvV-$tttI^V5wvU?a{(G}{G z@ob7Urk1@hDN&C$N!Nio9YrkiUC{5qA`KH*7CriaB;2~2Od>2l=WytBRl#~j`EYsj}jqK2xD*3 ztEUiPZzEJC??#Tj^?f)=sRXOJ_>5aO(|V#Yqro05p6)F$j5*wYr1zz|T4qz$0K(5! zr`6Pqd+)%a9Xq3aNKrY9843)O56F%=j_Yy_;|w8l&RU1+B4;pP*O_}X8!qD?IMiyT zLXBOOPg<*BZtT4LJ7DfyghK|_*mMP7a1>zS{8>?}#_XXaLoUBAz(Wi>$Q!L;oQ&cL z6O|T6%Dxq3E35$0g5areq9$2+R(911!Z9=wRPq-pju7DnN9LAfOu3%&onnfx^Px5( zT2^sU>Y)88F5#ATiVoS$jzC-M`vY8!{8#9O#3c&{7J1lo-rcNK7rlF0Zt*AKE(WN* z*o?Tv?Sdz<1v6gfCok8MG6Pzecx9?C zrQG5j^2{V556Hj=xTiU-seOCr2ni@b<&!j>GyHbv!&uBbHjH-U5Ai-UuXx0lcz$D7%=! z&zXD#Jqzro@R=hy8bv>D_CaOdqo6)vFjZldma5D+R;-)y1NGOFYqEr?h zd_mTwQ@K2veZTxh1aaV4F;YnaWA~|<8$p}-eFHashbWW6Dzj=3L=j-C5Ta`w-=QTw zA*k9!Ua~-?eC{Jc)xa;PzkUJ#$NfGJOfbiV^1au;`_Y8|{eJ(~W9pP9q?gLl5E6|e{xkT@s|Ac;yk01+twk_3nuk|lRu{7-zOjLAGe!)j?g+@-;wC_=NPIhk(W zfEpQrdRy z^Q$YBs%>$=So>PAMkrm%yc28YPi%&%=c!<}a=)sVCM51j+x#<2wz?2l&UGHhOv-iu z64x*^E1$55$wZou`E=qjP1MYz0xErcpMiNYM4+Qnb+V4MbM;*7vM_Yp^uXUuf`}-* z_2CnbQ);j5;Rz?7q)@cGmwE^P>4_u9;K|BFlOz_|c^1n~%>!uO#nA?5o4A>XLO{X2 z=8M%*n=IdnXQ}^+`DXRKM;3juVrXdgv79;E=ovQa^?d7wuw~nbu%%lsjUugE8HJ9zvZIM^nWvjLc-HKc2 zbj{paA}ub~4N4Vw5oY{wyop9SqPbWRq=i@Tbce`r?6e`?`iOoOF;~pRyJlKcIJf~G z)=BF$B>YF9>qV#dK^Ie#{0X(QPnOuu((_-u?(mxB7c9;LSS-DYJ8Wm4gz1&DPQ8;0 z=Wao(zb1RHXjwbu_Zv<=9njK28sS}WssjOL!3-E5>d17Lfnq0V$+IU84N z-4i$~!$V-%Ik;`Z3MOqYZdiZ^3nqqzIjLE+zpfQC+LlomQu-uNCStj%MsH(hsimN# z%l4vpJBs_2t7C)x@6*-k_2v0FOk<1nIRO3F{E?2DnS}w> z#%9Oa{`RB5FL5pKLkg59#x~)&I7GzfhiVC@LVFSmxZuiRUPVW*&2ToCGST0K`kRK) z02#c8W{o)w1|*YmjGSUO?`}ukX*rHIqGtFH#!5d1Jd}&%4Kc~Vz`S7_M;wtM|6PgI zNb-Dy-GI%dr3G3J?_yBX#NevuYzZgzZ!vN>$-aWOGXqX!3qzCIOzvA5PLC6GLIo|8 zQP^c)?NS29hPmk5WEP>cHV!6>u-2rR!tit#F6`_;%4{q^6){_CHGhvAs=1X8Fok+l zt&mk>{4ARXVvE-{^tCO?inl{)o}8(48az1o=+Y^r*AIe%0|{D_5_e>nUu`S%zR6|1 zu0$ov7c`pQEKr0sIIdm7hm{4K_s0V%M-_Mh;^A0*=$V9G1&lzvN9(98PEo=Zh$`Vj zXh?fZ;9$d!6sJRSjTkOhb7@jgSV^2MOgU^s2Z|w*e*@;4h?A8?;v8JaLPCoKP_1l- z=Jp0PYDf(d2Z`;O7mb6(_X_~z0O2yq?H`^c=h|8%gfywg#}wIyv&_uW{-e8e)YmGR zI0NNSDoJWa%0ztGzkwl>IYW*DesPRY?oH+ow^(>(47XUm^F`fAa0B~ja-ae$e>4-A z64lb_;|W0ppKI+ zxu2VLZzv4?Mr~mi?WlS-1L4a^5k+qb5#C)ktAYGUE1H?Vbg9qsRDHAvwJUN=w~AuT zUXYioFg2Dx-W)}w9VdFK#vpjoSc!WcvRZ_;TgHu;LSY*i7K_>Px{%C4-IL?6q?Qa_ zL7l=EEo|@X&$gX;fYP02qJF~LN9?E-OL2G(Fo4hW)G{`qnW zTIuc+-1VJvKgph0jAc(LzM);Pg$MPln?U|ek{_5nNJHfm-Y#ec+n#Yf_e>XfbLbN)eqHEDr0#?<;TskL5-0JGv|Ut{=$Xk8hlwbaMXdcI3GL zY-hykR{zX9liy$Z2F3!z346uu%9@-y6Gda`X2*ixlD_P@<}K?AoV?(%lM%* z(xNk=|A()443aGj)-~IDf3J+UA2p2lh6ei^pG*HL#SiThnIr5WZDXebI)F7X zGmP-3bH$i$+(IwqgbM7h%G5oJ@4{Z~qZ#Zs*k7eXJIqg;@0kAGV|b=F#hZs)2BYu1 zr8sj#Zd+Iu^G}|@-dR5S*U-;DqzkX3V0@q-k8&VHW?h0b0?tJ-Atqmg^J8iF7DP6k z)W{g?5~F*$5x?6W)3YKcrNu8%%(DglnzMx5rsU{#AD+WPpRBf``*<8F-x75D$$13U zcaNXYC0|;r&(F@!+E=%+;bFKwKAB$?6R%E_QG5Yn5xX#h+zeI-=mdXD5+D+lEuM`M ze+*G!zX^xbnA?~LnPI=D2`825Ax8rM()i*{G0gcV5MATV?<7mh+HDA7-f6nc@95st zzC_si${|&=$MUj@nLxl_HwEXb2PDH+V?vg zA^DJ%dn069O9TNK-jV}cQKh|$L4&Uh`?(z$}#d+{X zm&=KTJ$+KvLZv-1GaHJm{>v=zXW%NSDr8$0kSQx(DQ)6S?%sWSHUazXSEg_g3agt2@0nyD?A?B%9NYr(~CYX^&U#B4XwCg{%YMYo%e68HVJ7`9KR`mE*Wl7&5t71*R3F>*&hVIaZXaI;2a$?;{Ew{e3Hr1* zbf$&Fyhnrq7^hNC+0#%}n^U2{ma&eS)7cWH$bA@)m59rXlh96piJu@lcKl<>+!1#s zW#6L5Ov%lS(?d66-(n`A%UuiIqs|J|Ulq0RYq-m&RR0>wfA1?<34tI?MBI#a8lY{m z{F2m|A@=`DpZpwdIH#4)9$#H3zr4kn2OX!UE=r8FEUFAwq6VB?DJ8h59z$GXud$#+ zjneIq8uSi&rnG0IR8}UEn5OcZC?@-;$&Ry9hG{-1ta`8aAcOe1|82R7EH`$Qd3sf* zbrOk@G%H7R`j;hOosRVIP_2_-TuyB@rdj?(+k-qQwnhV3niH+CMl>ELX(;X3VzZVJ ztRais0C^L*lmaE(nmhvep+peCqr!#|F?iVagZcL>NKvMS_=*Yl%*OASDl3(mMOY9! z=_J$@nWpA-@><43m4olSQV8(PwhsO@+7#qs@0*1fDj70^UfQ(ORV0N?H{ceLX4<43 zEn)3CGoF&b{t2hbIz;Og+$+WiGf+x5mdWASEWIA*HQ9K9a?-Pf9f1gO6LanVTls)t z^f6_SD|>2Kx8mdQuiJwc_SmZOZP|wD7(_ti#0u=io|w~gq*Odv>@8JBblRCzMKK_4 zM-uO0Ud9>VD>J;zZzueo#+jbS7k#?W%`AF1@ZPI&q%}beZ|ThISf-ly)}HsCS~b^g zktgqOZ@~}1h&x50UQD~!xsW-$K~whDQNntLW=$oZDClUJeSr2$r3}94Wk1>co3beS zoY-7t{rGv|6T?5PNkY zj*XjF()ybvnVz5=BFnLO=+1*jG>E7F%&vm6up*QgyNcJJPD|pHoZ!H6?o3Eig0>-! zt^i-H@bJ;^!$6ZSH}@quF#RO)j>7A5kq4e+7gK=@g;POXcGV28Zv$jybL1J`g@wC# z_DW1ck}3+n@h2LFQhwVfaV@D+-kff4celZC0;0ef?pA#*PPd8Kk8sO1wza&BHQFblVU8P1=-qScHff^^fR zycH!hlHQs7iejITpc4UaBxzqTJ}Z#^lk{W(cr`qtW~Ap;HvuUf#MxgEG?tEU+B?G% znub0I(s@XvI(lva}$Z7<}Qg=rWd5n)}rX{nb+Aw;}?l9LZI-`N-*hts=c6XgjfJs ztp>-686v6ug{glEZ}K=jVG|N1WSWrU*&ue|4Q|O@;s0#L5P*U%Vx;)w7S0ZmLuvwA z@zs2Kut)n1K7qaywO#TbBR`Q~%mdr`V)D`|gN0!07C1!r3{+!PYf9*;h?;dE@#z(k z;o`g~<>P|Sy$ldHTUR3v=_X0Iw6F>3GllrFXVW?gU0q6|ocjd!glA)#f0G7i20ly>qxRljgfO2)RVpvmg#BSrN)GbGsrIb}9 z1t+r;Q>?MGLk#LI5*vR*C8?McB|=AoAjuDk&Pn`KQo z`!|mi{Cz@BGJ!TwMUUTkKXKNtS#OVNxfFI_Gfq3Kpw0`2AsJv9PZPq9x?~kNNR9BR zw#2jp%;FJNoOzW>tE#zskPICp>XSs?|B0E%DaJH)rtLA}$Y>?P+vEOvr#8=pylh zch;H3J`RE1{97O+1(1msdshZx$it^VfM$`-Gw>%NN`K|Tr$0}U`J?EBgR%bg=;et0 z_en)!x`~3so^V9-jffh3G*8Iy6sUq=uFq%=OkYvHaL~#3jHtr4sGM?&uY&U8N1G}QTMdqBM)#oLTLdKYOdOY%{5#Tgy$7QA! zWQmP!Wny$3YEm#Lt8TA^CUlTa{Cpp=x<{9W$A9fyKD0ApHfl__Dz4!HVVt(kseNzV z5Fb`|7Mo>YDTJ>g;7_MOpRi?kl>n(ydAf7~`Y6wBVEaxqK;l;}6x8(SD7}Tdhe2SR zncsdn&`eI}u}@^~_9(0^r!^wuKTKbs-MYjXy#-_#?F=@T*vUG@p4X+l^SgwF>TM}d zr2Ree{TP5x@ZtVcWd3++o|1`BCFK(ja-QP?zj6=ZOq)xf$CfSv{v;jCcNt4{r8f+m zz#dP|-~weHla%rsyYhB_&LHkwuj83RuCO0p;wyXsxW5o6{)zFAC~2%&NL? z=mA}szjHKsVSSnH#hM|C%;r0D$7)T`HQ1K5vZGOyUbgXjxD%4xbs$DAEz)-;iO?3& zXcyU*Z8zm?pP}w&9ot_5I;x#jIn^Joi5jBDOBP1)+p@G1U)pL6;SIO>Nhw?9St2UN zMedM(m(T6bNcPPD`%|9dvXAB&IS=W4?*7-tqldqALH=*UapL!4`2TM_{`W&pm*{?| z0DcsaTdGA%RN={Ikvaa&6p=Ux5ycM){F1OgOh(^Yk-T}a5zHH|=%Jk)S^vv9dY~`x zG+!=lsDjp!D}7o94RSQ-o_g#^CnBJlJ@?saH&+j0P+o=eKqrIApyR7ttQu*0 z1f;xPyH2--)F9uP2#Mw}OQhOFqXF#)W#BAxGP8?an<=JBiokg;21gKG_G8X!&Hv;7 zP9Vpzm#@;^-lf=6POs>UrGm-F>-! zm;3qp!Uw?VuXW~*Fw@LC)M%cvbe9!F(Oa^Y6~mb=8%$lg=?a0KcGtC$5y?`L5}*-j z7KcU8WT>2PpKx<58`m((l9^aYa3uP{PMb)nvu zgt;ia9=ZofxkrW7TfSrQf4(2juZRBgcE1m;WF{v1Fbm}zqsK^>sj=yN(x}v9#_{+C zR4r7abT2cS%Wz$RVt!wp;9U7FEW&>T>YAjpIm6ZSM4Q<{Gy+aN`Vb2_#Q5g@62uR_>II@eiHaay+JU$J=#>DY9jX*2A=&y8G%b zIY6gcJ@q)uWU^mSK$Q}?#Arq;HfChnkAOZ6^002J>fjPyPGz^D5p}o;h2VLNTI{HGg!obo3K!*I~a7)p-2Z3hCV_hnY?|6i`29b zoszLpkmch$mJeupLbt4_u-<3k;VivU+ww)a^ekoIRj4IW4S z{z%4_dfc&HAtm(o`d{CZ^AAIE5XCMvwQSlkzx3cLi?`4q8;iFTzuBAddTSWjfcZp* zn{@Am!pl&fv#k|kj86e$2%NK1G4kU=E~z9L^`@%2<%Dx%1TKk_hb-K>tq8A9bCDfW z@;Dc3KqLafkhN6414^46Hl8Tcv1+$q_sYjj%oHz)bsoGLEY1)ia5p=#eii(5AM|TW zA8=;pt?+U~>`|J(B85BKE0cB4n> zWrgZ)Rbu}^A=_oz65LfebZ(1xMjcj_g~eeoj74-Ex@v-q9`Q{J;M!mITVEfk6cn!u zn;Mj8C&3^8Kn%<`Di^~Y%Z$0pb`Q3TA}$TiOnRd`P1XM=>5)JN9tyf4O_z}-cN|i> zwpp9g`n%~CEa!;)nW@WUkF&<|wcWqfL35A}<`YRxV~$IpHnPQs2?+Fg3)wOHqqAA* zPv<6F6s)c^o%@YqS%P{tB%(Lxm`hsKv-Hb}MM3=U|HFgh8R-|-K(3m(eU$L@sg=uW zB$vAK`@>E`iM_rSo;Cr*?&wss@UXi19B9*0m3t3q^<)>L%4j(F85Ql$i^;{3UIP0c z*BFId*_mb>SC)d#(WM1%I}YiKoleKqQswkdhRt9%_dAnDaKM4IEJ|QK&BnQ@D;i-ame%MR5XbAfE0K1pcxt z{B5_&OhL2cx9@Sso@u2T56tE0KC`f4IXd_R3ymMZ%-!e^d}v`J?XC{nv1mAbaNJX| zXau+s`-`vAuf+&yi2bsd5%xdqyi&9o;h&fcO+W|XsKRFOD+pQw-p^pnwwYGu=hF7& z{cZj$O5I)4B1-dEuG*tU7wgYxNEhqAxH?p4Y1Naiu8Lt>FD%AxJ811`W5bveUp%*e z9H+S}!nLI;j$<*Dn~I*_H`zM^j;!rYf!Xf#X;UJW<0gic?y>NoFw}lBB6f#rl%t?k zm~}eCw{NR_%aosL*t$bmlf$u|U2hJ*_rTcTwgoi_N=wDhpimYnf5j!bj0lQ*Go`F& z6Wg+xRv55a(|?sCjOIshTEgM}2`dN-yV>)Wf$J58>lNVhjRagGZw?U9#2p!B5C3~Nc%S>p`H4PK z7vX@|Uo^*F4GXiFnMf4gwHB;Uk8X4TaLX4A>B&L?mw4&`XBnLCBrK2FYJLrA{*))0 z$*~X?2^Q0KS?Yp##T#ohH1B)y4P+rR7Ut^7(kCwS8QqgjP!aJ89dbv^XBbLhTO|=A z|3FNkH1{2Nh*j{p-58N=KA#6ZS}Ir&QWV0CU)a~{P%yhd-!ehF&~gkMh&Slo9gAT+ zM_&3ms;1Um8Uy0S|0r{{8xCB&Tg{@xotF!nU=YOpug~QlZRKR{DHGDuk(l{)d$1VD zj)3zgPeP%wb@6%$zYbD;Uhvy4(D|u{Q_R=fC+9z#sJ|I<$&j$|kkJiY?AY$ik9_|% z?Z;gOQG5I%{2{-*)Bk|Tia8n>TbrmjnK+8u*_cS%*;%>R|K|?urtIdgTM{&}Yn1;| zk`xq*Bn5HP5a`ANv`B$IKaqA4e-XC`sRn3Z{h!hN0=?x(kTP+fE1}-<3eL+QDFXN- z1JmcDt0|7lZN8sh^=$e;P*8;^33pN>?S7C0BqS)ow4{6ODm~%3018M6P^b~(Gos!k z2AYScAdQf36C)D`w&p}V89Lh1s88Dw@zd27Rv0iE7k#|U4jWDqoUP;-He5cd4V7Ql)4S+t>u9W;R-8#aee-Ct1{fPD+jv&zV(L&k z)!65@R->DB?K6Aml57?psj5r;%w9Vc3?zzGs&kTA>J9CmtMp^Wm#1a@cCG!L46h-j z8ZUL4#HSfW;2DHyGD|cXHNARk*{ql-J2W`9DMxzI0V*($9{tr|O3c;^)V4jwp^RvW z2wzIi`B8cYISb;V5lK}@xtm3NB;88)Kn}2fCH(WRH1l@3XaO7{R*Lc7{ZN1m+#&diI7_qzE z?BS+v<)xVMwt{IJ4yS2Q4(77II<>kqm$Jc3yWL42^gG6^Idg+y3)q$-(m2>E49-fV zyvsCzJ5EM4hyz1r#cOh5vgrzNGCBS}(Bupe`v6z{e z)cP*a8VCbRuhPp%BUwIRvj-$`3vrbp;V3wmAUt{?F z0OO?Mw`AS?y@>w%(pBO=0lohnxFWx`>Hs}V$j{XI2?}BtlvIl7!ZMZukDF7 z^6Rq2H*36KHxJ1xWm5uTy@%7;N0+|<>Up>MmxKhb;WbH1+=S94nOS-qN(IKDIw-yr zi`Ll^h%+%k`Yw?o3Z|ObJWtfO|AvPOc96m5AIw;4;USG|6jQKr#QP}+BLy*5%pnG2 zyN@VMHkD`(66oJ!GvsiA`UP;0kTmUST4|P>jTRfbf&Wii8~a`wMwVZoJ@waA{(t(V zwoc9l*4F>YUM8!aE1{?%{P4IM=;NUF|8YkmG0^Y_jTJtKClDV3D3~P7NSm7BO^r7& zWn!YrNc-ryEvhN$$!P%l$Y_P$s8E>cdAe3=@!Igo^0diL6`y}enr`+mQD;RC?w zb8}gXT!aC`%rdxx2_!`Qps&&w4i0F95>;6;NQ-ys;?j#Gt~HXzG^6j=Pv{3l1x{0( z4~&GNUEbH=9_^f@%o&BADqxb54EAq=8rKA~4~A!iDp9%eFHeA1L!Bb8Lz#kF(p#)X zn`CglEJ(+tr=h4bIIHlLkxP>exGw~{Oe3@L^zA)|Vx~2yNuPKtF^cV6X^5lw8hU*b zK-w6x4l&YWVB%0SmN{O|!`Sh6H45!7}oYPOc+a#a|n3f%G@eO)N>W!C|!FNXV3taFdpEK*A1TFGcRK zV$>xN%??ii7jx5D69O>W6O`$M)iQU7o!TPG*+>v6{TWI@p)Yg$;8+WyE9DVBMB=vnONSQ6k1v z;u&C4wZ_C`J-M0MV&MpOHuVWbq)2LZGR0&@A!4fZwTM^i;GaN?xA%0)q*g(F0PIB( zwGrCC#}vtILC_irDXI5{vuVO-(`&lf2Q4MvmXuU8G0+oVvzZp0Y)zf}Co0D+mUEZz zgwR+5y!d(V>s1} zji+mrd_6KG;$@Le2Ic&am6O+Rk1+QS?urB4$FQNyg2%9t%!*S5Ts{8j*&(H1+W;0~ z$frd%jJjlV;>bXD7!a-&!n52H^6Yp}2h3&v=}xyi>EXXZDtOIq@@&ljEJG{D`7Bjr zaibxip6B6Mf3t#-*Tn7p z96yx1Qv-&r3)4vg`)V~f8>>1_?E4&$bR~uR;$Nz=@U(-vyap|Jx zZ;6Ed+b#GXN+gN@ICTHx{=c@J|97TIPWs(_kjEIwZFHfc!rl8Ep-ZALBEZEr3^R-( z7ER1YXOgZ)&_=`WeHfWsWyzzF&a;AwTqzg~m1lOEJ0Su=C2<{pjK;{d#;E zr2~LgXN?ol2ua5Y*1)`(be0tpiFpKbRG+IK(`N?mIgdd9&e6vxzqxzaa`e7zKa3D_ zHi+c1`|720|dn(z4Qos^e7sn(PU%NYLv$&!|4kEse%DK;YAD06@XO3!EpKpz!^*?(?-Ip zC_Zlb(-_as+-D?0Ag9`|4?)bN)5o(J=&udAY|YgV(YuK9k=E>0z`$dSaL(wmxd!1f zME&3wwv@#{dgeMlZ4}GL!I`VZxtdQY$lmauCN_|mGXqEEj@i~du$|>5UvLjsbq!{; z@jEf;21iC1jFEmIPE^4gykHQzCMLj=2Ek4&FvlpqTlS(0YT%*W<>XgH$4ww`D`aihBGkPM(&EG};Cl&wzg8!jL z`rkqPzvH(0Kd{2n=?Bt8aAU&0IyiA+V-qnXVId^qG!SWZ7%_f&i!D{R#7Jo$%tICxY%j)ebORE>3H_c|to}c#HX;HAC?~B;2mmQrMp2;8T zmzde!k7BYg^Z1r|DUvSD3@{6S<1kndb%Qt%GA# z+sB2&F5L`R&fLRdAlpU_pVsJsYDEz{^ zKGaAz#%W+MPGT+D$+xowMY0=ipM)0p?zym&Aoi)qL(pO_weO(k?s|ELHl^W zviJiFUXRL&?`;3_;mvc02A@sbsW9}#{anvGafZ#ST;}za?XS3}ZG3B4m(SW{>w}Fh z)T5Yi*``Tstmi9SHXmuWSND@cj}qtY!`tuD29Dpu+-D3$h<5FY>jE>YJvqBmhw?oll`x7Ono(}R~P zle_eBwYy0Rr7kmf_SEt_gn4)AO-r`}^Z5Y%Rm8)K-?X>rvDL+QT?#)QwDsQ2c$tc* z&#hbgkL6}GnBDH;+lREM6MGIskRa@r>5Iq(ll2IepuhW86w@14=E{6$cz*cBDQ)CT>}v-DLM-v8)xaPBnmGBKM63RgDGqh!<*j90tSE4|G^+r@#-7g2 zs8KE8eZPZhQuN>wBU%8CmkE9LH1%O;-*ty0&K~01>F3XB>6sAm*m3535)9T&Fz}A4 zwGjZYVea@Fesd=Rv?ROE#q=}yfvQEP8*4zoEw4@^Qvw54utUfaR1T6gLmq?c9sON> z>Np6|0hdP_VURy81;`8{ZYS)EpU9-3;huFq)N3r{yP1ZBCHH7=b?Ig6OFK~%!GwtQ z3`RLKe8O&%^V`x=J4%^Oqg4ZN9rW`UQN^rslcr_Utzd-@u-Sm{rphS-y}{k41)Y4E zfzu}IC=J0JmRCV6a3E38nWl1G495grsDDc^H0Fn%^E0FZ=CSHB4iG<6jW1dY`2gUr zF>nB!y@2%rouAUe9m0VQIg$KtA~k^(f{C*Af_tOl=>vz>$>7qh+fPrSD0YVUnTt)? z;@1E0a*#AT{?oUs#bol@SPm0U5g<`AEF^=b-~&4Er)MsNnPsLb^;fL2kwp|$dwiE3 zNc5VDOQ%Q8j*d5vY##)PGXx51s8`0}2_X9u&r(k?s7|AgtW0LYbtlh!KJ;C9QZuz< zq>??uxAI1YP|JpN$+{X=97Cdu^mkwlB={`aUp+Uyu1P139=t%pSVKo7ZGi_v(0z>l zHLGxV%0w&#xvev)KCQ{7GC$nc3H?1VOsYGgjTK;Px(;o0`lerxB<+EJX9G9f8b+)VJdm(Ia)xjD&5ZL45Np?9 zB%oU;z05XN7zt{Q!#R~gcV^5~Y^gn+Lbad7C{UDX2Nznj8e{)TLH|zEc|{a#idm@z z6(zon+{a>FopmQsCXIs*4-dLGgTc)iOhO3r=l?imNUR-pWl!ktO0r_a0Nqo@bu8MzyjSq9zkqPe*`Sxz75rZ zr9X%(=PVqCRB=zfX+_u&*k4#s1k4OV11YgkCrlr6V;vz<{99HKC@qQ+H8xv5)sc63 z69;U4O&{fb5(fN``jJH#3=GHsV56@{d@7`VhA$K^;GU+R-V%%cnmjYs?>c5^6Ugv} zn<}L&i;2`zzW@(kxf$$gVH@7nh}2%G%ciQ_B?r{13?Q@=Q+6msQGtnyY%Gkjeor?g z7F*tMqLdhcq+LCCo^D;CtOACCBhXgK-M&w{*dcUdmtv@XFTofmmpcWKtCn^`#?oZC zUOm52 z7sK$hR|Vh6y&pfIUK&!`8HH*>12$nWA)Ynp+XwOj=jNLD z{QA4gezbe>wiP?`jJO;c&EId;=2u80s_r97;TX!6@*(<%WL+^bmxheMB3pKx0OpH^ zPs}knV+jpJ4TaD@r^V`mTsjf`7!z^H}eHQ#Rp z72(>Dm#QO!ZYR*O@yHic`3*T^t7jc=d`Jz6Lk@Y-bL%cOp_~=#xzIJl?`{Qu;$uC~NkePE+7wSW_FM`&V{gFN zl;lq@;FtAsl!h;tnOvj z#gYx!q$5MdZ0Jxjy=t*q)HFeeyI-vgaGdh1QNhqGRy8qS)|6S0QK7Gj9R?Co{Knh> za>xkQZ0}bBx!9@EUxRBYGm25^G}&j-`0VWX04E|J!kJ8^WoZ(jbhU_twFwWIH32fv zi=pg~(b#ajW=`)Vikwwe39lpML?|sY$?*6*kYBxku_<=#$gfTqQ_F!9F0=OkHnzBo zEwR!H_h|MNjuG$Tj6zaaouO}HYWCF8vN4C%EX-%Iu%ho;q$G#ErnafhXR*4J2Rp5* zhsi0;wlSwE*inVFO>{(8?N~82zijpt+9Y_-^>xnE%T*zk9gi|j7b@s<5{|qEquUD( zS;-%RySZOCOEh*>!kvbsQ265* z>X8*_Wy&~FB@aDHz%glyiAujXq-|2kDUjFTn9Rafsl+XNyFP%PG|l&ZGWBcEXxy=9 zeDn2PIoVuL$gX0RgVK1O$x3%pOzS7x^U5Pi;mtT)%cY;&e&M7GLM}zP+IPbqLt=^5 z7qLfri8myf;~2psc@^cA6mG&{C%e_(M$$!wC^5p^T1QzrS%I?(U{qcd+oJJkQxe10 zON{Q*?iz%F4MbEsoEc+x3E?&2wVR^v3|Q0lDaMvgS7mNjI{2w! z9|~=!83T%GW*iaChSS!`Xd^beFp9N4%K+k*j#jFumk}U?=WKL_kJAltxnxp~+lZzT zp@&&kSPTg3oSGos`rVBhK0|4NdHM_hnKuw1#0JV{gi_dKDJLB+ix~~HpU9%jD)@YY zOK)L7kgbLyN2%Dx#fuY}8swh4ACk7%BpP-n5(RhDq{gEHP*Fo4IviX{C49|B5h~SC zFr`=0)=h2^F5UpCAgt?R5u{6VvpUf#*nC zCQ`$!|C;L2lpjlG?(>T$(_$O3_YNNbPT~(?!j3aD8k=yu^ogw4bkjvgF|3BOq(hB& zG;^cPXmcUP$ox8zElCJ-zMbK9q^8{rri#8Cek5Ydr0YT-KTh@J z6^AcB9ejew8BY5kzZUZX(7Po==eW<(;uV~E7(BY5c0^xr`cuRwn)47bN?zOb!0?cw z#v}R$z66&m#+AHfo@(^V2#S~bhoUkkTArg+6w>JzZ52r96^({1W!?>4$h0l|-jDfj z>7(<+%67#(A|4hZ3>Y;hd&S?}F;`Vtqz|pK&B>NJ=Faci;gkf-+GmfQR8^zo_vul2 zB!)kfu4Dq_g)8TBBo52*sB6F`qa&JCR=_A$QWgX_K}fZm{Cb2#1q`^S3+WaS>sS#@ z-4k*G=#?z6d_e7JJ+Z8^(t0tNdL{K5F;2nfQbXgld}a(X)Gr;WojOy`^?es~AClT$ z5^lD{WJek0!p-QEH5E7n6DKQ0%_ZBZ=|jfV_MM{VmL8y-Wd|>OmeemP=C@xI@@M~1 zW2S*im@Rc=O>V886_UJ@oh1!2H$Ku&U*Hh_oxd{32)vf1$cRiepv28ricM;}#p!+k zaK{z1I=9Y%3m4|Pj*BD*Fn5Vh?O@oD^1UcjyeNh0fbhh~V6xb#4njlGW8OehUe!MnoR(wn#nsoyL1m!Rov)Nv4~&JEVl7L z#^qYdTpNI#u`N0UbVMiDmD>g2VQcG3>4D6gErgddZnSQTs){BExxRJRB?bIxTdZa z;!S8FHJPPiIDQ*FAUiWSYnjILFjDvxvSC zk z=j4Kx@Pg~&2Z?cmMDa;)#xVeorJrxDBqy{+`kG+ZPQqC@#ku-c3ucU+69$#q_*se` z-H#PFW^>-C0>++|6r=<$Z8)ZFaK=ZjwsNYXqRpl9G|yme@Eld5B-*I69Nx_TResHi z!5nm+>6zaJYQO#%D{~o-oOJ;q`fa5}l!8G*U-E$OM&7@dqciBCWtd}|SrDXz$TB($&m*=Epuolu2k`KUwO7maP3P0ok zmF57lSh0Ba@&sO1iZ5^+3s8{B8t|M;Pg&O+{tZJCiLWd6H@{b~9{CLF9s3Kn zt5)Rs9ejne?o{%f>B$Dl%X7fd~KY)I|(pxUeHj;gNsK6;ZR>`ciu;GxvhDUt!+31Knss2U(%ts8K z18)8;<2ax9RG?!|Lwdt^i5L^&O788roKmVAB)=EdK~HqR2Q=)H_VW}xY=95MP_Ov< zPEz3%DRK}+(aUBwsr83H8>`H^v~|A_t}0vPmRwKPt1{|qOY|PZu}j9+{ZhF&-H_TB zU9xWLpNTc`enI|)h9jQeqf5RfGLFk_vfX`40iMpd%KZF!lKbZTdBw$<^G6nuS+$fT zrbK)xo&;buPJcpOZ=x>n+bRXVFDs(23Xr=rDE&!)pVXZ;;A07NXGl_0m`{Z)DQIu$ zFDvY4xu-ifTe_$|n2B83eI;KUg6pVbw+N!nyLj~wnRi{4mNy{WDV)G1!6$y=+x6U{ z%4_9=Q^L!x_gAYp?J3+u5hA5cO8aHeI=6AC8^S{mzhqCBvBLYEutUC(X0>hKg|AvN zvkmJCQNA45_KjW{aEcyrBppcO6G0zTy%v1&@~+2!n?kA9?>0>AjFN|JdCnHQ8$hEU zw#mwGifHppLP?89LMb(Y3Li9iCPx7W%ek}2FgD2YSzjsR4Xj<=zN{Yo@7s7(k%mP4 znT2p&4EQ@q_chd-E z78uvD*C@oba`U3W2Iw`M#`5C8jOHv8^Li<|j^SI>>>`77Dp71Vtz=J?4Zck4SdRbd zfF}C_>Y(#)r@y!Q0`tMlG#b9>5`fAI$B&tWJfbGlYW$J4V+-s=HH!`+;1XeL@USdx zR0$G&&XBf9lQtkH5)p=U!8J!1{oc4E!N-~Abxl6E;;=3-hMYZ+44?u}zabmCE)yB?*_w91m$n1Yskp&@ z;kxeJX-#ioX^{elyLu~gzx|_KxLpX62MF%Axq3$!Z_P`pBWR?zP8OI`PV~6Aa0Oi0 zv_Ot1m&plf-ZF{e(z(Ms3*S5q$e|j;gOwGrmWsCHfLi(h8y?gc$(2H{884C1FvHQQ12tX=qFUsK~zM!W=K>;zaRsu4Xmcc@8nSs!vK+{ z?}bq}-m&p5jRSam67n>yG9ez=I^|J1O;Np8s=P~9MXYLxD+cFQK7PhG=bkjo{Naae zjp3NWWrlFWDb3Z5D07Q|WjZ=wOQ=aKA%en=O@hL$QCKpIXNZE=InFk|Fhq-&H!6&X z*MVy8=hL7Aw&pQjHrFf27C%3B<>FX{@fOLNhUoxL4*@nY}&M3G*T-p67a zo}~_&yGOB)#vbU|Q3FA8S^X)c-yBlmN(_%}`7Ha3uWFe?>9f=3hlO{^gv~$p`v?vk z_P*r43|(S{%ihs;)YH|jAMpP=-Ms7Ne75_YZZiL3CHVjSU`X1|?Ehh&gA=Xn7W7d@ zf8bM9Y>lG!`PWFDDA9G;x*{1Eh^55u66*9D+-4^dYZ{xXP@?sQLVrY%(azM;C^4FuN7CQ%$!3sr1JL=!Be& zuOZL^bLp$Qo2rL=WDzQIls%s!Go z{s}Q0b#+#8bKga|01t%^9Z=wEsevvXM_{$dCR97ed3@1kX)mtSS!JN^rtqKOj}p~> zfpCI@DX*DqcB6ZnBcl~}sGO~1s$AtfkX6fy3N8*ebvZc*KBW;dA=)?#BE&}-or74i zZUt5;{FBPnkZD8YUXDsx&2LvSziAlec3oc>&Lf1Doc3g?H9{OO_$M4B0qTat0UsWP zTlxUeQ3B;oJ%en4n?zQB6*Fb#wH7`$SQN5GI|=DnJKiYm{?-?#-H;#sIjz7kQ4&VW zN9d1(1$_W~S=<%qDD!mwRytas=eqX^iW}YSx3;wJ#)Xp_`Qk1DFiXac$-3;jQbCif zLA-T_s~5yP@Q@W>pXKl^gipQ>gp@HlBB>WDVpW199;V%?N1`U$ovLE;NI2?|_q2~5 zlg>xT9NADWkv5-*FjS~nP^7$k!N2z?dr!)&l0+4xDK7=-6Rkd$+_^`{bVx!5LgC#N z-dv-k@OlYCEvBfcr1*RsNwcV?QT0bm(q-IyJJ$hm2~mq{6zIn!D20k5)fe(+iM6DJ ze-w_*F|c%@)HREgpRrl@W5;_J5vB4c?UW8~%o0)(A4`%-yNk1(H z5CGuzH(uHQ`&j+IRmTOKoJ?#Ct$+1grR|IitpDGt!~ZdqSJ?cOtw-R=EQ+q4UvclH zdX=xlK-fhQKoKCPBoFAZ*(~11O6-tXo>i0w!T$u{lg!#itEUX3V{$S*naW!C@%rll zS{L(1t%xz(*B`{1NL!*aMc<~fE=g;gXi&Gb$HpD!P)8?JzfN;4F&wv(5HH<=c>>)n z({271)xREH89=C(5YKL{mmJJ_d>qHz;;gTvTlgM*vz9@YTTYZ#%_2A zS0G-t9oMQEpvfv(UjfQ8T$vAHi)zOj3>D*{xSRiu3acc=7cvLyD?_ZObdu$5@b*!y zaZ#u?7uF}SrHVQa=sTOhGW{6WUlq#RhPPm^GsRH#qlX8{Kq-i~98l;eq>KdCnWyKl zUu&UWBqu#Tt9jQ97U4}3)&(p2-eCLznXMEm!>i^EMpeVzPg%p;?@O;dJBQQY(vV;d z3v+-3oTPC!2LTUAx^S2t{v;S_h(EZ^0_dS5g^F*m{TEIy^Qal~%mu3h7*o`jWOH}i ztv8M)3X3a*+ry_KkYXYE4dB0?M|t}#Tp+(}6CQ zBbq;xhoHj}b@j-@koDB#XcCY~>_x&Y;i%MH|3tF^X2h{36UCVfQ-;oEA+4ZkJ`^Qi zQf^8}6eFO$Z+Dj-F1wkG##tTx>FjR2oOXFmbKFj6K3+=kePQ<4d7%z5R5cOB;zO6| zm9^m#U4lcA;7t&*=q|a-!`!)}SgYXT#i8hnxtx@kaoBF$QAS-hT7N5kH^l zB^i+})V>L;9_0Qqf-dyF%ky8Mp-dp#%!Nls3vCt}q3QLM3M-(Zs1k}1bqQ9PVU)U` ztE=?;^6=x}_VD%N@${>qhpkU*)AuUBu_cqYiY&@;O$HV*z@~#Tzh?#=CK`=KwBv+o zh%zu%0xPKYtyC)DaQ zpDW}*86g%>BH3IcWMq`g$j()0kWE(qkIL8A&A0mf&+BzxpKF}=`#jG% z&*wa!&pGFLs5_b#QTZE4Bp+})qzyPQ7B4Z7Y*&?0PSX&|FIR;WBP1|coF9ZeP*$9w z!6aJ_3%Sh=HY3FAt8V144|yfu}IAyYHr1OYKIZ51F>_uY^%N#!k~eU53at-_E-Gh?ahmM5y* z+BTIbeH;%v1}Cjo{8d%UeSMWg(nphxEU`sL< zQR~LrTq>Da(FqSP2%&^1ZL#DTo5Sbl9;&57tQ-@U&I#lj)aNSkcfEJwQD!33?anVU z?pw2q7WtMvfji493`rSFnyp7{w87cW`ak=UEYlk5PCB1K6UDVKXyozOChH4yHh~Q< zv>yvKw6WLfi!PZUx60JZcTNM7jo{ww9b8Q+S7C3WA5&llSwdwh$=Q(*(f3ofqcz=nwOmOy z(J!K=*wNoRU*${{Mbwapi9pTB(&VVKefqd-qrUb9*Eyr2E@oZ9Cgf}Mc;QP<0D)R4 zz=!*^VIG4T*7Xl=sJxrWv9hW^eJ%qYp5(d0?E6LZzJ}=7E+1{?GQA;z+!^VBD81}O z0kJ^dKy&WMw+1+aGVYY-v@i28@Gm+sX5=@U%F=Z?W)oar}2~Rc&F|+3A)n-U2GF10+QdxDb^iA@7eL$c7yhBtL z>lABrh^qy9XZ${E1}Ss5!N4;ig0-pUh6@|RPCHOWvgG{|l}2enRgJftsN%D|ck0YO zuAQd2aMPSyGuJ~jm)aY=+p~mGudw4erwE%P^)5f<*$$2C-4^I=e8-}7##ZQ!8!Tep z+Z_!}CAI~sry$|XK$ktXaxP*x<_ijCPp`2=6sNLZU<@9Sz-rz7^BCE9yh0jV4(I!Z zxmA4d;>B-!vD}Xp*&*N%`b^e&R;D97WS}{~{O-EtXeZNfdf51tw!WR6Noo4hjHPv5 z?heYYRSBPjMc}tFEU^|U8a1CxxK%)WTcn9P%`wR^I$QSeMn6=w>Z9OoVvcrl`zYlZ z2y`mAu0bV(Scc>G_EmIo_4 zm*~h`mxYZC&+U>C5G1FZH5L^U>Cq-9UDRQa35jz&NBj*0{uJKfZs5=Fn@&)Xh6aX(H3w9m9BGLePqVotxTeSPh5-mc7$# z-80t6yB0$Nx<54ohdO*QL7m_(&+#*=eoNiYDB4rE4Cag@qfyZS};Fx;Vf1;oync2k z9v#-w?d6R& zOI`CCS_d=tf3|?g3Z}b6-_Rdg3y~enQhmgkni0Cvf9m6%Ft8r;NC5|b%t&?lkl*4{ z8Ui^;Ds^gq6ti(1xB7y_$zA!i-M~#!!tl$ErTR>P~>T=Yky)8(uvPbvLmB=UfoD zrfl}8<1OQrm?8#j1!?s*T>AoectQl&m!o&*^JcIW`_&bk3tN}k^0rjl=HL$z*uIYt z?7l?^Dqr?q1210Sp$xoAy!&{2^{^Anl460 zI&7urrc&|Y{rjv04VOl{y7c82N6xzg5ueYmQ(q(zC3w_C#x*~%yf5j7MI{W`tsoxzA*PrmK)cTskU| zf2C}Bq$>S$-1JgIh0aW@LxI|-8(OGuD#^M01ghh}&#ObO>tZgSw_LW`zdf&IN$YO# z)|X_9m#JwLW5pErZB3ScggKcNzxA9(hyKkK9I#pR&79&*+SV_eu={00{HF=Bb+AEe znaSof+r1jZ!EL5XgqXWkckaFSSyEk}o!%p8XsD}O>borZ6x%X2b&q!s&1-O(>`kZ$ zB2l^5Cx9xQx9)PXN1xPM)@+LxACH_iZ8zGc(>wnFS_O|@hKsxpMjXOzLEa7OvSlM&&G9ioQw9~RsD4F zK7Q+_&|Q6{eZ^8Rx@pKL`le6kH+(fLc{=V&{b%I5=n}VHV4)X_2Y!pYxgC8wU)yP! zPF3t$?(jsC>Ge=&{kmPGUEETpaw(QTAl)m#{qR3_aq9!wK%6XHfV4C>Y^>Z|%ns7j z{Ja?^IA{+@;kR#IjHxkar%3$eJT4?xNBKUVmoO z`A8Zo-{~_;vcikZ(p}EZzU4kO6WPqkMyE{VvS?;44Z@lj zz^fKX9UL!8Wc(9VgI?P4*zpis8dzl};I>yr1>dtXU=FTAlx}Eht4-*7RACL^AflGh zyZb1hTf(~CkMo%#Q%NMgM9tE2D+)joqbtHYA89Ql1nqVTt+MxZ^*FRd&n5YlIi!8m z>$Ysd!l{+C)y;Wa(ZV-=<+NZKV;v4mt}v2m>`v$-$3b;GsLxf= zd~f(rmfpl``{0aVwN7y!>eGyJFP`L+TxHjHTOS{K^$L2`@6(Rli`{EFwpH@R%eZ6g zwf7rc43Yk!=k;{ z-Rn%~B3amGr}}SxfE$vS8FIPL=Qt57$|R#sSoFgdNUT?fYOYjPl%ZBFpi=jq=DWby7Zxm@y;B<89!9= zbgEH*Uy)~iq5kJLX$+ps$kV`#6jW#|9BGz^`ivNeid(wVbk4jl)VBpW&~;eXNi{#` zwx?{DXR~*sqQcFhY0XCfQ4-*2aN1BGX>$_swtKEqnd>j6vcZ!#0)pXRi?<{!P?tGw z2x_`RD$W)qD{?z}VDPt?+)8*rqLWFIPQ(9-VbBdf{7ff?w9CZ{sIi_gnuC$I0(+P8 zms9XB%}VQ>>pve##}jog6+cD?v~n4Pa9Vmc zg#K$|+`adO=B7`uj35Y}6EZ z{dY`x@w8;R-7zrsr1O_~Jvl*|o-x%jF=Rr1C}GXP^|IYN`1sqmG-oI@R#%X66c#5W z$$tQB)sqwiVm;Y^`Dw3mo|firP{*HsOQJre5%Dm^H@we0FN88VWJ0dja?_U38z73f zrCV!b3qNP0kM#%9T!W5`ynGcg%BL28FW1J-J1_S`BJGCaReQ!am(2%qZ3lLgzq|ns z!!fF@`0=*z)J2BwZ*hO|Yu^cI_nF$9l-Pb3jE7=P8gZ#!xiuZ7-cSa`gb`6mxGTgg z-DLdID?M!Z%+hHB#{?&0$GFRpf+_}q<_wbzX6K?w;%6szz1RbySDSr2r^h_qi$khs zXdZ9A0!_Bf)TR2-^-K~q`FQ!#1x(U4VbV%AA@Ei{%cA(EwC{XfjRi?`&9rav5;Q5% zO1`Rn@OA_ZB@N*mC#)?d3P!}Eh;=NgpIKsy{(yr`hv=aouwt@r&P&}Z3DNWo9ro30 zX52~(aTV$*HHlgB66-4GQru!_AZ|)V*I5X=WG)`N@U&D>e@@C#V@JwEL*L`7#$yes z62C^5%Qniaow2$3HrAc7U{qzpb&FA*xLI1JSWR@`RF=JCcvTI)%dH7;sWInt9JLu# z|Ao|Q?K)cDg_JKsym=joo5gR80wtv01N`um1nQ@Ms0Y*bVzxL34} zo?gizp?`=Y{*W>^Hy2%Jl)y?A+&7s1UVHFixuIy~sawXjcDCL`129cK7|ZQS0u;A} zTJC#WNmqkIrnHpAhHVcM(U^vJA~dl@jf_bs*3?i+=&vuC?Aiy_pcB~=1syDni4 zw+FLuz>F773u#$;NUQ9WDtUPY@+rA3WBhQdKFKOyzkA(URa7;4tW>3jQIfi8v0h3g zJC_HVDXS#>DWb|&se7FHnr=q&l#xg9o02}}u=b-R>@sw={Z zHF*?t2FmhqZ=|qa>x=A!*$S+0T zhO*D*M?NTf-eX`eO)9TIQu{7Dm77Acnj4b1jI9@c*ZL8wL%8kLEhd$KM8=Y!fbN@9 zC7B5#y>JM1n5M)!&im==EgHs2j+xCZG~+~QWCi?s!QyFo2kqx{%jE2n3^N*Ayz6Lp zhg5g^3# z+5FoJ@$u@9WJgPKpUWEd4}4AK9TJKU8W%ms!d0p%OIOX+bY+55zl!vIaz$XFI9Ep+ z;bL_}7PDI2Y`Ng*XY(65 zh0%`@Lve%fc;)N4_g12bNrt6gH=N#OHtxO`$lpWlw=Z6MF+E@;>GkZ#lAZTn`aHwf z&I1|aV#b_VHMIgBN*RzU9i@Z@m}0i>o?({&%fpEfaOpFeaJ7V37;m0?kzd}}Lk@9$ zL}8TEo7WZAcRi%zFZxkr6<0k#X-;lTD`Oc~cDb@olwgWCewvk{GJ}hCXbF!AdiLpd z|Cck$ZTKI?Ack{34Lva7+k=H8K2HTZiurox6F+>dy+@R9T^awxj590D$|kXUg+Ygc z(f)jlRwN(4z$#%PnOVc;#Fv{nAi{#UcXPNcmP#5O{zh_*`=q^JCeia{sN4zHjk2*y zqUVh{Ya{j>SPmP^i#Qfcq_MTqo8g52Fi^F zKBc$$HVI!xFx*4Y9l+nt)$AoZORD}%5I10oI3kx`-N30QueiwIw#0VV2E*Fb-nKW% z=+r^hos`Y-7~{cA1FVbK$_=~*z53+Q8KGjg;>ztg((H12%QTf4OYU8y)C}h5yo#$% z&Q$`vMM*g?ZcatAn2j!hFv8KuN(dw)T*}sF#THDHxo8xC^?vJ zc`U6bVo~hOr6I!8*GTZ<^D~;unKjK=!IR|GB4E>Mcvt*2GK);93jIDd<(nNjHO z4Hi@2^%Uyx=^Z~5eZ!5rO5%4H|eFoNjD#+Kcu%_57zZb4Z@Ak#X6txD^{U3wBl^r+W- zLorkK;uc;NgTj7dGxHQS+@T*T>Q*j4^Ll$ejQqWrwcHyG9y%Mk%m8nBVG5hvSaYm5 zJN^#-Q46kZG)@T8n2^QCjxIwxUVi%s>EY`E?#@_(A~njFrTiDq;8v|W-1jT|ROlNI zU$h|YoD4PVTE^&NC6_m{EAFBVqsM`P*`-AcDGWQygURzM32Xeq2xng~XQsYeTZ5v$ zQLaa2M_Iplw}4eL6fLPu`6`PYcVMysO>`{8CB~glD=TX7?JZcHfHNmykBM?QD)#D) zGp>R*<^D?WhFQKRc^}22l6F=D2RPrxaX2ZF!b1X0XF*d4%=!sbNcS1q2WOUE(7e4$ z^L8f;F)__d3>&KQFE8%$I4h^y5FYBfB&fWzn71_OSrPe-DHV{O#Q;GP z+Tw!J?eVjX19RKH?*hKQWQt8r7B#lYX8xoSHFGCW-*DSQ4EM4M3Mw%gkSYNK18@(e zfzMF}WWaCyS@1y%-~Xg0ry~tkQkUmKuI5lGAua{{vn22V!2T()AU5FpKh@Nv)s^Js zv~@VuUG;=CnLmQR{PeUBQf2;lAV!vG>^Z0N zL88rrjL-*J!43;7C=w9xhcw`yjRKq7o4L9=0SmR9PA-nX12@#h(iIu-0N_xm2OV)( zU_raT0y>$wm^oMi2|U3N;OhF9uy}`<-xVka#DV*l{O0yHzi9vUxa1Qtpi$buR*8cU zd4~lS1pT$L^!0=6qUKOpM+XPsy{f7W#1bjrEwaeN!Ik9(zySIT^pEHvHgJUneFN4) zk=k|$55(g8slmS|@+*4fr2urd3LwjIIZA**g+%l(SZNn4HwQ}y6o`vw>2&mR1X+&q zDa1Af0B;4rAMZMOlHbAqK|R_xuwJ7ANARtFE({-P2o{tJJR<>2KVp)ZK-M;)ejx zd*E~Mka<{OL7%CAhk4n|1qg?97-I!l0rOinjVi#arbgg4bi5;nY5oFL`UWtPk5&L#grSxv zE3!}=1px!ZTLT90aYc^s`~{VojjJml&<`@e41dFP+XU6D0AOkbn2rlI3>^LcqauG& zc$m3Z{!u8LvUrm^fT{qX5yD9{?r(CCiUdck%!T`KIZd2oQJz1joB&M(Teg_>;yS<2-5>BWfSPpG`Rt{!j6>kqMAvl^zk0JUEfy$HVJMkxP-GkwZuxL62me2#pj_5*ZIU zP~#C^OZLfl$HO)v;~~c&JHivn|1I9H5y_CDkt0JLLGKm(4*KLVhJ2jh2#vJuM6`b& zE==-lvME^Oj022xF&IV*? '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..6689b85b --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..0f5036dc --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'backend' diff --git a/src/main/java/com/moing/backend/BackendApplication.java b/src/main/java/com/moing/backend/BackendApplication.java new file mode 100644 index 00000000..68e601f6 --- /dev/null +++ b/src/main/java/com/moing/backend/BackendApplication.java @@ -0,0 +1,13 @@ +package com.moing.backend; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class BackendApplication { + + public static void main(String[] args) { + SpringApplication.run(BackendApplication.class, args); + } + +} diff --git a/src/test/java/com/moing/backend/BackendApplicationTests.java b/src/test/java/com/moing/backend/BackendApplicationTests.java new file mode 100644 index 00000000..9a6d1dd7 --- /dev/null +++ b/src/test/java/com/moing/backend/BackendApplicationTests.java @@ -0,0 +1,13 @@ +package com.moing.backend; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class BackendApplicationTests { + + @Test + void contextLoads() { + } + +} From f18a7af99f05ddb76e8f5a4ceba52a2602e22eb5 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Fri, 4 Aug 2023 17:18:49 +0900 Subject: [PATCH 002/619] =?UTF-8?q?docs:=20ISSUE,=20PR=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/ISSUE_TEMPLATE/feature.md | 17 +++++++++++++++++ .github/ISSUE_TEMPLATE/fix.md | 17 +++++++++++++++++ .github/pull_request_template.md | 13 +++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/feature.md create mode 100644 .github/ISSUE_TEMPLATE/fix.md create mode 100644 .github/pull_request_template.md diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 00000000..cae79156 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,17 @@ +--- +name: feature +about: feat +title: 'feat/ :' +labels: '' +assignees: '' + +--- + +## 📢 description + +## ✅ to do +- [ ] +- [ ] +- [ ] + +## 🔗 etc diff --git a/.github/ISSUE_TEMPLATE/fix.md b/.github/ISSUE_TEMPLATE/fix.md new file mode 100644 index 00000000..418a400f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/fix.md @@ -0,0 +1,17 @@ +--- +name: fix +about: fix +title: 'fix/ :' +labels: '' +assignees: '' + +--- + +## description + +## to do +[ ] +[ ] +[ ] + +## etc diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..0f05cb3e --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ +## PR 타입 +- [ ] 기능 추가 +- [ ] 버그 수정 +- [ ] 의존성, 환경 변수, 빌드 관련 업데이트 +- [ ] 기타 사소한 수 + +## 개요 + +## 변경 사항 + +## 코드 리뷰 시 참고 사항 + +## 테스트 결과 From 00ce8341762f58577a8d4a5a1e25329dd9a46397 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 5 Aug 2023 03:33:48 +0900 Subject: [PATCH 003/619] =?UTF-8?q?feat:=20globalException=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/pull_request_template.md | 2 +- build.gradle | 48 ++++++++++++++ .../global/annotation/DomainService.java | 15 +++++ .../moing/backend/global/annotation/Enum.java | 19 ++++++ .../global/annotation/EnumValidator.java | 31 +++++++++ .../exception/ApplicationException.java | 23 +++++++ .../exception/GlobalExceptionHandler.java | 58 +++++++++++++++++ .../config/querydsl/QuerydslConfig.java | 19 ++++++ .../global/config/response/ErrorCode.java | 19 ++++++ .../global/config/response/ErrorResponse.java | 22 +++++++ .../config/response/SuccessResponse.java | 25 ++++++++ .../moing/backend/global/util/AesUtil.java | 63 +++++++++++++++++++ 12 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/global/annotation/DomainService.java create mode 100644 src/main/java/com/moing/backend/global/annotation/Enum.java create mode 100644 src/main/java/com/moing/backend/global/annotation/EnumValidator.java create mode 100644 src/main/java/com/moing/backend/global/config/exception/ApplicationException.java create mode 100644 src/main/java/com/moing/backend/global/config/exception/GlobalExceptionHandler.java create mode 100644 src/main/java/com/moing/backend/global/config/querydsl/QuerydslConfig.java create mode 100644 src/main/java/com/moing/backend/global/config/response/ErrorCode.java create mode 100644 src/main/java/com/moing/backend/global/config/response/ErrorResponse.java create mode 100644 src/main/java/com/moing/backend/global/config/response/SuccessResponse.java create mode 100644 src/main/java/com/moing/backend/global/util/AesUtil.java diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 0f05cb3e..9c36590f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,7 +2,7 @@ - [ ] 기능 추가 - [ ] 버그 수정 - [ ] 의존성, 환경 변수, 빌드 관련 업데이트 -- [ ] 기타 사소한 수 +- [ ] 기타 사소한 수정 ## 개요 diff --git a/build.gradle b/build.gradle index 443f43c2..e13cb6d2 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,8 @@ plugins { id 'java' id 'org.springframework.boot' version '2.7.14' id 'io.spring.dependency-management' version '1.0.15.RELEASE' + id "org.asciidoctor.jvm.convert" version "3.3.2" + id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'com.moing' @@ -15,10 +17,13 @@ configurations { compileOnly { extendsFrom annotationProcessor } + asciidoctorExt + querydsl.extendsFrom compileClasspath } repositories { mavenCentral() + google() } dependencies { @@ -32,8 +37,51 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' + implementation 'org.springframework:spring-context:5.3.15' + + + implementation 'com.google.firebase:firebase-admin:8.2.0' + implementation 'com.google.firebase:firebase-messaging:23.0.0' + implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.2.2' + implementation 'org.springframework:spring-context:5.3.15' + + implementation 'com.google.code.gson:gson:2.8.7' + + asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' + + implementation 'com.querydsl:querydsl-jpa:5.0.0' + implementation 'com.querydsl:querydsl-apt:5.0.0' } tasks.named('test') { useJUnitPlatform() } + +ext { + snippetsDir = file('build/generated-snippets') +} + +test { + outputs.dir snippetsDir +} + +asciidoctor { + inputs.dir snippetsDir + configurations 'asciidoctorExt' + dependsOn test +} + +def querydslDir = "$buildDir/generated/querydsl" + +querydsl { + jpa = true + querydslSourcesDir = querydslDir +} +sourceSets { + main.java.srcDir querydslDir +} + +compileQuerydsl { + options.annotationProcessorPath = configurations.querydsl +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/annotation/DomainService.java b/src/main/java/com/moing/backend/global/annotation/DomainService.java new file mode 100644 index 00000000..31a2c872 --- /dev/null +++ b/src/main/java/com/moing/backend/global/annotation/DomainService.java @@ -0,0 +1,15 @@ +package com.moing.backend.global.annotation; + +import org.springframework.stereotype.Service; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Service +public @interface DomainService { + +} diff --git a/src/main/java/com/moing/backend/global/annotation/Enum.java b/src/main/java/com/moing/backend/global/annotation/Enum.java new file mode 100644 index 00000000..b804e2ac --- /dev/null +++ b/src/main/java/com/moing/backend/global/annotation/Enum.java @@ -0,0 +1,19 @@ +package com.moing.backend.global.annotation; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Constraint(validatedBy = {EnumValidator.class}) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Enum { + String message() default "enum 형식메 맞지 않습니다."; + Class[] groups() default {}; + Class[] payload() default {}; + Class> enumClass(); + boolean ignoreCase() default false; +} diff --git a/src/main/java/com/moing/backend/global/annotation/EnumValidator.java b/src/main/java/com/moing/backend/global/annotation/EnumValidator.java new file mode 100644 index 00000000..ff82b057 --- /dev/null +++ b/src/main/java/com/moing/backend/global/annotation/EnumValidator.java @@ -0,0 +1,31 @@ +package com.moing.backend.global.annotation; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class EnumValidator implements ConstraintValidator { + + private Enum annotation; + + @Override + public void initialize(Enum constraintAnnotation) { + this.annotation = constraintAnnotation; + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + boolean result = false; + Object[] enumValues = this.annotation.enumClass().getEnumConstants(); + if (enumValues != null) { + for (Object enumValue : enumValues) { + if (value.equals(enumValue.toString()) + || (this.annotation.ignoreCase() && value.equalsIgnoreCase(enumValue.toString()))) { + result = true; + break; + } + } + } + return result; + } + +} diff --git a/src/main/java/com/moing/backend/global/config/exception/ApplicationException.java b/src/main/java/com/moing/backend/global/config/exception/ApplicationException.java new file mode 100644 index 00000000..af382e42 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/exception/ApplicationException.java @@ -0,0 +1,23 @@ +package com.moing.backend.global.config.exception; + +import com.moing.backend.global.config.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class ApplicationException extends RuntimeException { + + private final ErrorCode errorCode; + private final HttpStatus httpStatus; + + protected ApplicationException(ErrorCode errorCode, HttpStatus httpStatus, String message) { + super(message); + this.errorCode = errorCode; + this.httpStatus = httpStatus; + } + + public ErrorCode getErrorCode() { return errorCode;} + + public HttpStatus getHttpStatus() { + return httpStatus; + } + +} diff --git a/src/main/java/com/moing/backend/global/config/exception/GlobalExceptionHandler.java b/src/main/java/com/moing/backend/global/config/exception/GlobalExceptionHandler.java new file mode 100644 index 00000000..cedd87f0 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/exception/GlobalExceptionHandler.java @@ -0,0 +1,58 @@ +package com.moing.backend.global.config.exception; + +import com.moing.backend.global.config.response.ErrorCode; +import com.moing.backend.global.config.response.ErrorResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.context.support.DefaultMessageSourceResolvable; + +import java.util.function.Consumer; +import java.util.regex.PatternSyntaxException; +import java.util.stream.Collectors; + +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + + private static final String LOG_FORMAT = "Class : {}, Code : {}, Message : {}"; + + @ExceptionHandler(ApplicationException.class) + public ResponseEntity handleApplicationException(ApplicationException ex) { + return handleException(ex, ex.getErrorCode(), ex.getMessage(), ex.getHttpStatus(), log::warn); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity inputMethodArgumentInvalidExceptionHandler (MethodArgumentNotValidException ex) { + String message = ex.getBindingResult().getFieldErrors().stream() + .map(DefaultMessageSourceResolvable::getDefaultMessage) + .collect(Collectors.joining(", ")); + return handleException(ex, ErrorCode.BAD_REQUEST, message, HttpStatus.BAD_REQUEST, log::warn); + } + + @ExceptionHandler(PatternSyntaxException.class) + public ResponseEntity inputPatternSyntaxExceptionHandler(PatternSyntaxException ex) { + return handleException(ex, ErrorCode.BAD_REQUEST, ErrorCode.BAD_REQUEST.getMessage(), HttpStatus.BAD_REQUEST, log::warn); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public ResponseEntity httpRequestNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException ex) { + return handleException(ex, ErrorCode.METHOD_NOT_ALLOWED, ErrorCode.METHOD_NOT_ALLOWED.getMessage(), HttpStatus.METHOD_NOT_ALLOWED, log::warn); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity internalServerErrorHandler(Exception ex) { + return handleException(ex, ErrorCode.INTERNAL_SERVER_ERROR, ErrorCode.INTERNAL_SERVER_ERROR.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR, log::error); + } + + private ResponseEntity handleException(Exception ex, ErrorCode errorCode, String message, HttpStatus httpStatus, Consumer logger) { + logger.accept(String.format(LOG_FORMAT, ex.getClass().getSimpleName(), errorCode.getErrorCode(), ex.getMessage())); + ErrorResponse errorResponse = new ErrorResponse(errorCode.getErrorCode(), message); + return ResponseEntity.status(httpStatus.value()).body(errorResponse); + } + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/querydsl/QuerydslConfig.java b/src/main/java/com/moing/backend/global/config/querydsl/QuerydslConfig.java new file mode 100644 index 00000000..4d09a493 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/querydsl/QuerydslConfig.java @@ -0,0 +1,19 @@ +package com.moing.backend.global.config.querydsl; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +@Configuration +public class QuerydslConfig { + @PersistenceContext + private EntityManager entityManager; + + @Bean + public JPAQueryFactory jpaQueryFactory() { + return new JPAQueryFactory(this.entityManager); + } +} diff --git a/src/main/java/com/moing/backend/global/config/response/ErrorCode.java b/src/main/java/com/moing/backend/global/config/response/ErrorCode.java new file mode 100644 index 00000000..cbb3691d --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/response/ErrorCode.java @@ -0,0 +1,19 @@ +package com.moing.backend.global.config.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum ErrorCode { + + BAD_REQUEST(false, "400", "올바른 패턴을 입력하세요."), + METHOD_NOT_ALLOWED(false,"405", "클라이언트가 사용한 HTTP 메서드가 리소스에서 허용되지 않습니다."), + INTERNAL_SERVER_ERROR(false,"500", "서버에서 요청을 처리하는 동안 오류가 발생했습니다."); + + private Boolean isSuccess; + private String errorCode; + private String message; + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/response/ErrorResponse.java b/src/main/java/com/moing/backend/global/config/response/ErrorResponse.java new file mode 100644 index 00000000..ce1f9c87 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/response/ErrorResponse.java @@ -0,0 +1,22 @@ +package com.moing.backend.global.config.response; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@RequiredArgsConstructor +public class ErrorResponse { + private Boolean isSuccess; + private LocalDateTime timeStamp; + private String errorCode; + private String message; + + public ErrorResponse(String errorCode, String message) { + this.isSuccess=false; + this.timeStamp = LocalDateTime.now().withNano(0); + this.errorCode = errorCode; + this.message = message; + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/response/SuccessResponse.java b/src/main/java/com/moing/backend/global/config/response/SuccessResponse.java new file mode 100644 index 00000000..7f8609e0 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/response/SuccessResponse.java @@ -0,0 +1,25 @@ +package com.moing.backend.global.config.response; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor + +public class SuccessResponse { + private Boolean isSuccess; + private String message; + @JsonInclude(JsonInclude.Include.NON_NULL) + private T data; + + public static SuccessResponse create(String message) { + return new SuccessResponse<>(true, message, null); + } + + public static SuccessResponse create(String message, T data) { + return new SuccessResponse<>(true, message, data); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/util/AesUtil.java b/src/main/java/com/moing/backend/global/util/AesUtil.java new file mode 100644 index 00000000..a003a0bd --- /dev/null +++ b/src/main/java/com/moing/backend/global/util/AesUtil.java @@ -0,0 +1,63 @@ +package com.moing.backend.global.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; + +@Component +public class AesUtil { + private final SecretKeySpec secretKeySpec; + private final IvParameterSpec ivParameterSpec; + + public AesUtil(@Value("${aes.secret.key}") String key, @Value("${aes.secret.alg}") String alg) { + this.secretKeySpec = createSecretKeySpec(key, alg); + this.ivParameterSpec = createIvParameterSpec(key); + } + + public String encrypt(String text) { + try { + Cipher cipher = Cipher.getInstance(secretKeySpec.getAlgorithm()); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); + byte[] encrypted = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(encrypted); + } catch (Exception e) { + throw new RuntimeException("Failed to encrypt text: " + e.getMessage(), e); + } + } + + public String decrypt(String cipherText) { + try { + Cipher cipher = Cipher.getInstance(secretKeySpec.getAlgorithm()); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); + byte[] decodedBytes = Base64.getDecoder().decode(cipherText); + byte[] decrypted = cipher.doFinal(decodedBytes); + return new String(decrypted, StandardCharsets.UTF_8); + } catch (Exception e) { + throw new RuntimeException("Failed to decrypt cipherText: " + e.getMessage(), e); + } + } + + private SecretKeySpec createSecretKeySpec(String key, String alg) { + try { + byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); + MessageDigest sha = MessageDigest.getInstance("SHA-256"); + byte[] hash = sha.digest(keyBytes); + return new SecretKeySpec(hash, alg); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("Failed to create SecretKeySpec: " + e.getMessage(), e); + } + } + + private IvParameterSpec createIvParameterSpec(String key) { + byte[] iv = key.substring(0, 16).getBytes(StandardCharsets.UTF_8); + return new IvParameterSpec(iv); + } +} + From 63d8ab5c38d28c28a67252e15f54f8a178d3ca09 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Mon, 7 Aug 2023 22:03:28 +0900 Subject: [PATCH 004/619] =?UTF-8?q?feat:=20=EC=86=8C=EC=85=9C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8,=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85,=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EC=9E=AC=EB=B0=9C=EA=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 57 +- src/docs/asciidoc/Auth-API.adoc | 31 + src/docs/asciidoc/Overview.adoc | 83 + src/docs/asciidoc/api.adoc | 13 + .../com/moing/backend/BackendApplication.java | 4 + .../dto/request/SignInRequest.java | 16 + .../dto/request/SignUpRequest.java | 14 + .../response/KakaoAccessTokenResponse.java | 19 + .../dto/response/KakaoUserResponse.java | 44 + .../dto/response/ReissueTokenResponse.java | 25 + .../dto/response/SignInResponse.java | 26 + .../service/MemberAuthUserCase.java | 34 + .../service/ReissueTokenUserCase.java | 30 + .../application/service/SignInUserCase.java | 45 + .../application/service/SignUpUserCase.java | 41 + .../service/apple/AppleSignInUserCase.java | 25 + .../service/apple/AppleTokenUserCase.java | 97 ++ .../service/apple/feign/AppleFeignClient.java | 17 + .../service/apple/feign/response/Keys.java | 27 + .../service/kakao/KakaoSignInUserCase.java | 39 + .../service/kakao/KakaoTokenUserCase.java | 39 + .../AccountAlreadyExistedException.java | 12 + .../auth/exception/AppIdInvalidException.java | 11 + .../domain/auth/exception/AuthException.java | 11 + .../auth/exception/TokenInvalidException.java | 11 + .../auth/presentation/AuthController.java | 71 + .../constant/AuthResponseMessage.java | 14 + .../application/mapper/MemberMapper.java | 36 + .../domain/constant/RegistrationStatus.java | 12 + .../domain/member/domain/constant/Role.java | 14 + .../domain/constant/SocialProvider.java | 10 + .../domain/member/domain/entity/Member.java | 154 ++ .../repository/MemberCustomRepository.java | 9 + .../MemberCustomRepositoryImpl.java | 26 + .../domain/repository/MemberRepository.java | 8 + .../domain/service/MemberQueryService.java | 20 + .../domain/service/MemberSaveService.java | 23 + .../member/exception/MemberException.java | 11 + .../NotFoundBySocialIdException.java | 11 + .../global/config/redis/RedisConfig.java | 42 + .../global/config/redis/RedisUtil.java | 35 + .../redis/constant/RefreshTokenConstant.java | 23 + .../global/config/response/ErrorCode.java | 19 - .../config/security/SecurityConfig.java | 71 + .../global/config/security/dto/User.java | 19 + .../filter/JwtAccessDeniedHandler.java | 26 + .../config/security/filter/JwtAuthFilter.java | 81 + .../filter/JwtAuthenticationEntryPoint.java | 61 + .../config/security/jwt/JwtExceptionList.java | 21 + .../security/jwt/JwtSecurityConfig.java | 24 + .../security/jwt/NotFoundRefreshToken.java | 13 + .../global/config/security/jwt/TokenUtil.java | 169 +++ .../oauth/CustomOAuth2UserService.java | 44 + .../security/oauth/CustomUserDetails.java | 58 + .../oauth/CustomUserDetailsService.java | 29 + .../security/oauth/OAuth2Attribute.java | 170 +++ .../security/oauth/OAuth2FailureHandler.java | 38 + .../security/oauth/OAuth2SuccessHandler.java | 62 + .../security/util/AuthenticationUtil.java | 56 + .../config/webclient/WebClientConfig.java | 77 + .../exception/ApplicationException.java | 7 +- .../exception/GlobalExceptionHandler.java | 8 +- .../InternalServerErrorException.java | 6 + .../global/interceptor/AuthInterceptor.java | 35 + .../backend/global/response/ErrorCode.java | 24 + .../{config => }/response/ErrorResponse.java | 11 +- .../response/SuccessResponse.java | 2 +- .../global/response/TokenInfoResponse.java | 29 + .../backend/global/util/AesConverter.java | 31 + .../moing/backend/global/util/AesUtil.java | 42 +- .../backend/global/util/SecurityUtils.java | 25 + src/main/resources/static/docs/Auth-API.html | 1166 ++++++++++++++ src/main/resources/static/docs/Overview.html | 591 ++++++++ src/main/resources/static/docs/api.html | 1337 +++++++++++++++++ .../backend/BackendApplicationTests.java | 2 +- .../backend/config/CommonControllerTest.java | 80 + .../moing/backend/config/RestDocsConfig.java | 19 + .../representation/AuthControllerTest.java | 293 ++++ 78 files changed, 5971 insertions(+), 65 deletions(-) create mode 100644 src/docs/asciidoc/Auth-API.adoc create mode 100644 src/docs/asciidoc/Overview.adoc create mode 100644 src/docs/asciidoc/api.adoc create mode 100644 src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/dto/response/ReissueTokenResponse.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/dto/response/SignInResponse.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/AppleFeignClient.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/response/Keys.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/exception/AccountAlreadyExistedException.java create mode 100644 src/main/java/com/moing/backend/domain/auth/exception/AppIdInvalidException.java create mode 100644 src/main/java/com/moing/backend/domain/auth/exception/AuthException.java create mode 100644 src/main/java/com/moing/backend/domain/auth/exception/TokenInvalidException.java create mode 100644 src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java create mode 100644 src/main/java/com/moing/backend/domain/auth/presentation/constant/AuthResponseMessage.java create mode 100644 src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/constant/RegistrationStatus.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/constant/Role.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/constant/SocialProvider.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/entity/Member.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/service/MemberQueryService.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/member/exception/MemberException.java create mode 100644 src/main/java/com/moing/backend/domain/member/exception/NotFoundBySocialIdException.java create mode 100644 src/main/java/com/moing/backend/global/config/redis/RedisConfig.java create mode 100644 src/main/java/com/moing/backend/global/config/redis/RedisUtil.java create mode 100644 src/main/java/com/moing/backend/global/config/redis/constant/RefreshTokenConstant.java delete mode 100644 src/main/java/com/moing/backend/global/config/response/ErrorCode.java create mode 100644 src/main/java/com/moing/backend/global/config/security/SecurityConfig.java create mode 100644 src/main/java/com/moing/backend/global/config/security/dto/User.java create mode 100644 src/main/java/com/moing/backend/global/config/security/filter/JwtAccessDeniedHandler.java create mode 100644 src/main/java/com/moing/backend/global/config/security/filter/JwtAuthFilter.java create mode 100644 src/main/java/com/moing/backend/global/config/security/filter/JwtAuthenticationEntryPoint.java create mode 100644 src/main/java/com/moing/backend/global/config/security/jwt/JwtExceptionList.java create mode 100644 src/main/java/com/moing/backend/global/config/security/jwt/JwtSecurityConfig.java create mode 100644 src/main/java/com/moing/backend/global/config/security/jwt/NotFoundRefreshToken.java create mode 100644 src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java create mode 100644 src/main/java/com/moing/backend/global/config/security/oauth/CustomOAuth2UserService.java create mode 100644 src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetails.java create mode 100644 src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetailsService.java create mode 100644 src/main/java/com/moing/backend/global/config/security/oauth/OAuth2Attribute.java create mode 100644 src/main/java/com/moing/backend/global/config/security/oauth/OAuth2FailureHandler.java create mode 100644 src/main/java/com/moing/backend/global/config/security/oauth/OAuth2SuccessHandler.java create mode 100644 src/main/java/com/moing/backend/global/config/security/util/AuthenticationUtil.java create mode 100644 src/main/java/com/moing/backend/global/config/webclient/WebClientConfig.java rename src/main/java/com/moing/backend/global/{config => }/exception/ApplicationException.java (74%) rename src/main/java/com/moing/backend/global/{config => }/exception/GlobalExceptionHandler.java (93%) create mode 100644 src/main/java/com/moing/backend/global/exception/InternalServerErrorException.java create mode 100644 src/main/java/com/moing/backend/global/interceptor/AuthInterceptor.java create mode 100644 src/main/java/com/moing/backend/global/response/ErrorCode.java rename src/main/java/com/moing/backend/global/{config => }/response/ErrorResponse.java (60%) rename src/main/java/com/moing/backend/global/{config => }/response/SuccessResponse.java (92%) create mode 100644 src/main/java/com/moing/backend/global/response/TokenInfoResponse.java create mode 100644 src/main/java/com/moing/backend/global/util/AesConverter.java create mode 100644 src/main/java/com/moing/backend/global/util/SecurityUtils.java create mode 100644 src/main/resources/static/docs/Auth-API.html create mode 100644 src/main/resources/static/docs/Overview.html create mode 100644 src/main/resources/static/docs/api.html create mode 100644 src/test/java/com/moing/backend/config/CommonControllerTest.java create mode 100644 src/test/java/com/moing/backend/config/RestDocsConfig.java create mode 100644 src/test/java/com/moing/backend/domain/auth/representation/AuthControllerTest.java diff --git a/build.gradle b/build.gradle index e13cb6d2..587b2a34 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ configurations { compileOnly { extendsFrom annotationProcessor } - asciidoctorExt + asciidoctorExtensions querydsl.extendsFrom compileClasspath } @@ -39,19 +39,44 @@ dependencies { testImplementation 'org.springframework.security:spring-security-test' implementation 'org.springframework:spring-context:5.3.15' - - implementation 'com.google.firebase:firebase-admin:8.2.0' - implementation 'com.google.firebase:firebase-messaging:23.0.0' implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.2.2' implementation 'org.springframework:spring-context:5.3.15' implementation 'com.google.code.gson:gson:2.8.7' - asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' + // Push Alarm + implementation 'com.google.firebase:firebase-admin:8.2.0' + implementation 'com.google.firebase:firebase-messaging:23.0.0' + + // RestDocs + asciidoctorExtensions 'org.springframework.restdocs:spring-restdocs-asciidoctor' testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' + // Qeurydsl implementation 'com.querydsl:querydsl-jpa:5.0.0' implementation 'com.querydsl:querydsl-apt:5.0.0' + + // Jwt + implementation 'io.jsonwebtoken:jjwt-api:0.11.2' + implementation 'io.jsonwebtoken:jjwt-jackson:0.11.2' + implementation 'io.jsonwebtoken:jjwt-impl:0.11.2' + + // Redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + + // WebClient + implementation 'org.springframework.boot:spring-boot-starter-webflux' + + // Feign + implementation 'io.github.openfeign:feign-httpclient:12.1' + implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:3.1.4' + + // Throttling + implementation 'com.bucket4j:bucket4j-core:8.1.1' + implementation 'com.bucket4j:bucket4j-jcache:8.1.1' + implementation 'javax.cache:cache-api:1.1.1' + implementation 'org.redisson:redisson:3.19.0' + } tasks.named('test') { @@ -67,10 +92,28 @@ test { } asciidoctor { - inputs.dir snippetsDir - configurations 'asciidoctorExt' dependsOn test + configurations 'asciidoctorExtensions' + inputs.dir snippetsDir + + // 특정 .adoc에 다른 adoc 파일을 가져와서(include) 사용하고 싶을 경우 경로를 baseDir로 맞춰주는 설정입니다. + // 개별 adoc으로 운영한다면 필요 없는 옵션입니다. + baseDirFollowsSourceFile() +} + +asciidoctor.doFirst { + delete file('src/main/resources/static/docs') +} + +task copyDocument(type: Copy) { + dependsOn asciidoctor + from file("build/docs/asciidoc") + into file("src/main/resources/static/docs") } +build { + dependsOn copyDocument +} + def querydslDir = "$buildDir/generated/querydsl" diff --git a/src/docs/asciidoc/Auth-API.adoc b/src/docs/asciidoc/Auth-API.adoc new file mode 100644 index 00000000..37e3779f --- /dev/null +++ b/src/docs/asciidoc/Auth-API.adoc @@ -0,0 +1,31 @@ +[[Auth-API]] +== Auth API + +[[Auth-Kako-소셜-로그인]] +=== Auth Kakao 소셜 로그인 회원가입 전 +operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-request,request-fields,http-response,response-fields'] + +=== Auth Kakao 소셜 로그인 회원가입 후 +operation::auth-controller-test/kakao_소셜_로그인_회원가입_후[snippets='http-request,request-fields,http-response,response-fields'] + +--- + +[[Auth-Apple-소셜-로그인]] +=== Auth Apple 소셜 로그인 회원가입 전 +operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-request,request-fields,http-response,response-fields'] + +=== Auth Apple 소셜 로그인 회원가입 후 +operation::auth-controller-test/apple_소셜_로그인_회원가입_후[snippets='http-request,request-fields,http-response,response-fields'] + + +[[Auth-회원가입]] +=== Auth 회원가입 +operation::auth-controller-test/sign_up[snippets='http-request,request-fields,http-response,response-fields'] + +[[Auth-회원가입]] +=== Auth 회원가입 +operation::auth-controller-test/sign_up[snippets='http-request,request-fields,http-response,response-fields'] + +[[Auth-토큰-재발급]] +=== Auth 토큰 재발급 +operation::auth-controller-test/reissue_token[snippets='http-request,http-response,response-fields'] diff --git a/src/docs/asciidoc/Overview.adoc b/src/docs/asciidoc/Overview.adoc new file mode 100644 index 00000000..1ba5a3e8 --- /dev/null +++ b/src/docs/asciidoc/Overview.adoc @@ -0,0 +1,83 @@ +[[Overview-Response]] +== ErrorCode + + +=== Error Response DTO +|=== +| isSuccess(Boolean) | timeStamp(LocalDateTime) | errorCode(String) | message(String) +|=== + +=== Common ErrorCode +|=== +| ErrorCode | Scope | Description + +| `400` +| 전체 +| 요청 형식 자체가 틀리거나 권한이 없음 + +| `403` +| 전체 +| 접근 권한이 존재하지 않음 (로그인 안한 경우) + +| `405` +| 전체 +| HTTP 메서드가 리소스에서 허용되지 않음 + +| `500` +| 전체 +| 서버오류 + +| `J0001` +| 전체 +| 예상치 못한 오류 + +| `J0002` +| 전체 +| 잘못된 JWT 서명 + +|`J0003` +| 전체 +| 만료된 토큰 + +| `J0004` +| 전체 +| 지원되지 않는 토큰 + +| `J0005` +| 전체 +| 접근이 거부됨 + +| `J0006` +| 전체 +| 토큰이 잘못됨 + +| `J0007` +| 전체 +| 추가 정보 입력 (닉네임) 안함 + +| `J0008` +| 재발급 시 +| 유효하지 않은 refresh Token +|=== + +=== User / Auth ErrorCode +|=== +| ErrorCode | Scope | Description +| `U0001` +| 전체 +| 해당 유저 존재하지 않음 + +|`AU0001` +| 로그인할 때 +| 이미 다른 소셜 플랫폼으로 가입함 + +| `AU0002` +| 로그인할 때 +| 입력 토큰이 유효하지 않음 + +| `AU0003` +| 로그인할 때 +| appId가 일치하지 않음 (유효하지 않음) +|=== + + diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc new file mode 100644 index 00000000..586b66ff --- /dev/null +++ b/src/docs/asciidoc/api.adoc @@ -0,0 +1,13 @@ += Moing API Doc +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: left +:toclevels: 2 +:sectlinks: + +include::Overview.adoc[] + +include::Auth-API.adoc[] + + diff --git a/src/main/java/com/moing/backend/BackendApplication.java b/src/main/java/com/moing/backend/BackendApplication.java index 68e601f6..8e3ecf24 100644 --- a/src/main/java/com/moing/backend/BackendApplication.java +++ b/src/main/java/com/moing/backend/BackendApplication.java @@ -2,8 +2,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableFeignClients @SpringBootApplication +@EnableJpaAuditing public class BackendApplication { public static void main(String[] args) { diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java new file mode 100644 index 00000000..0a11219f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.auth.application.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Data +public class SignInRequest { + + private String token; +} + diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java new file mode 100644 index 00000000..33877ec9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.auth.application.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Data +public class SignUpRequest { + private String nickName; +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java new file mode 100644 index 00000000..87fb3ca0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.auth.application.dto.response; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Data +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class KakaoAccessTokenResponse { + + private String appId; +} + diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java new file mode 100644 index 00000000..a8e484a8 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java @@ -0,0 +1,44 @@ +package com.moing.backend.domain.auth.application.dto.response; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Data +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class KakaoUserResponse { + private Long id; + private Properties properties; + private KakaoAccount kakaoAccount; + + @Data + @NoArgsConstructor + @AllArgsConstructor + @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) + public static class Properties { + + private String nickname; + } + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class KakaoAccount { + + private String email; + private String gender; + private String ageRange; + } + public void adaptResponse() { + if(kakaoAccount.gender == null || kakaoAccount.gender.isBlank()) kakaoAccount.gender = "undef"; + if(kakaoAccount.ageRange == null || kakaoAccount.ageRange.isBlank()) kakaoAccount.ageRange = "undef"; + if(properties.nickname==null||properties.nickname.isBlank()) properties.nickname="undef"; + if(kakaoAccount.email.length() > 50) kakaoAccount.email = kakaoAccount.email.substring(0, 50); + if(properties.nickname.length() > 7) properties.nickname = properties.nickname.substring(0, 7); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/ReissueTokenResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/ReissueTokenResponse.java new file mode 100644 index 00000000..3f3cff58 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/ReissueTokenResponse.java @@ -0,0 +1,25 @@ +package com.moing.backend.domain.auth.application.dto.response; + +import com.moing.backend.global.response.TokenInfoResponse; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ReissueTokenResponse { + + private String accessToken; + private String refreshToken; + + public static ReissueTokenResponse from(TokenInfoResponse tokenInfoResponse) { + return ReissueTokenResponse.builder() + .accessToken(tokenInfoResponse.getAccessToken()) + .refreshToken(tokenInfoResponse.getRefreshToken()) + .build(); + } + +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/SignInResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/SignInResponse.java new file mode 100644 index 00000000..ffb5b7ae --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/SignInResponse.java @@ -0,0 +1,26 @@ +package com.moing.backend.domain.auth.application.dto.response; + +import com.moing.backend.domain.member.domain.constant.RegistrationStatus; +import com.moing.backend.global.response.TokenInfoResponse; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class SignInResponse { + private String accessToken; + private String refreshToken; + private Boolean registrationStatus; + + public static SignInResponse from(TokenInfoResponse tokenInfoResponse, RegistrationStatus registrationStatus) { + return SignInResponse.builder() + .accessToken(tokenInfoResponse.getAccessToken()) + .refreshToken(tokenInfoResponse.getRefreshToken()) + .registrationStatus(registrationStatus.equals(RegistrationStatus.COMPLETED)) + .build(); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java new file mode 100644 index 00000000..5de09d77 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java @@ -0,0 +1,34 @@ +package com.moing.backend.domain.auth.application.service; + +import com.moing.backend.domain.auth.exception.AccountAlreadyExistedException; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberSaveService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.Optional; + +@Service +@Transactional +@RequiredArgsConstructor +public class MemberAuthUserCase { + + private final MemberSaveService memberSaveService; + + @Transactional + public Member auth(Member member, String providerInfo) { + Member signInMember = memberSaveService.saveMember(member); + checkRegistration(signInMember, providerInfo); + return signInMember; + } + + + // 다른 플랫폼으로 가입했으면 에러 출력 + private void checkRegistration(Member signInMember, String providerInfo) { + Optional.of(signInMember) + .filter(m -> providerInfo.contains(m.getProvider().name().toLowerCase())) + .orElseThrow(()->new AccountAlreadyExistedException()); + } + +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUserCase.java new file mode 100644 index 00000000..5167d875 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUserCase.java @@ -0,0 +1,30 @@ +package com.moing.backend.domain.auth.application.service; + +import com.moing.backend.domain.auth.application.dto.response.ReissueTokenResponse; +import com.moing.backend.global.config.security.jwt.NotFoundRefreshToken; +import com.moing.backend.global.config.security.jwt.TokenUtil; +import com.moing.backend.global.response.TokenInfoResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class ReissueTokenUserCase { + + private final TokenUtil tokenUtil; + + public ReissueTokenResponse reissueToken(String token) { + // refresh 토큰이 유효한지 확인 + if (token != null && tokenUtil.verifyToken(token)) { + + // 토큰 새로 받아오기 + TokenInfoResponse newToken = tokenUtil.tokenReissue(token); + + return ReissueTokenResponse.from(newToken); + } + throw new NotFoundRefreshToken(); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java new file mode 100644 index 00000000..8c4491bd --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java @@ -0,0 +1,45 @@ +package com.moing.backend.domain.auth.application.service; + +import com.moing.backend.domain.auth.application.dto.response.SignInResponse; +import com.moing.backend.domain.auth.application.service.apple.AppleSignInUserCase; +import com.moing.backend.domain.auth.application.service.kakao.KakaoSignInUserCase; +import com.moing.backend.domain.member.domain.constant.RegistrationStatus; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.global.config.security.jwt.TokenUtil; +import com.moing.backend.global.config.security.util.AuthenticationUtil; +import com.moing.backend.global.response.TokenInfoResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class SignInUserCase { + + private final MemberAuthUserCase internalAuthService; + private final TokenUtil tokenUtil; + private final KakaoSignInUserCase kakaoSignInUserCase; + private final AppleSignInUserCase appleSignInUserCase; + + public SignInResponse signIn(String token, String providerInfo) { + //1. 사용자 정보 가져오기 + Member member = getUserDataFromPlatform(token, providerInfo); + //2. 로그인 및 회원가입 + Member authenticatedMember = internalAuthService.auth(member, providerInfo); + //3. security 처리 + AuthenticationUtil.makeAuthentication(authenticatedMember); + //4. token 만들기 + TokenInfoResponse tokenResponse = tokenUtil.createToken(authenticatedMember, authenticatedMember.getRegistrationStatus().equals(RegistrationStatus.COMPLETED)); + //5. refresh token 저장 + tokenUtil.storeRefreshToken(authenticatedMember.getSocialId(), tokenResponse); + + return SignInResponse.from(tokenResponse, authenticatedMember.getRegistrationStatus()); + } + + private Member getUserDataFromPlatform(String accessToken, String providerInfo) { + if (providerInfo.contains("kakao")) return kakaoSignInUserCase.getUserData(accessToken); + else return appleSignInUserCase.getUserData(accessToken); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java new file mode 100644 index 00000000..6509a057 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java @@ -0,0 +1,41 @@ +package com.moing.backend.domain.auth.application.service; + +import com.moing.backend.domain.auth.application.dto.request.SignUpRequest; +import com.moing.backend.domain.auth.application.dto.response.SignInResponse; +import com.moing.backend.domain.member.domain.constant.RegistrationStatus; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.global.config.security.jwt.TokenUtil; +import com.moing.backend.global.config.security.util.AuthenticationUtil; +import com.moing.backend.global.response.TokenInfoResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class SignUpUserCase { + + private final TokenUtil tokenUtil; + private final MemberQueryService memberQueryService; + + public SignInResponse signUp(String token, SignUpRequest signUpRequest) { + + //1. 유저 찾기 + String socialId = tokenUtil.getSocialId(token); + Member member = memberQueryService.getMemberBySocialId(socialId); + //2. signUp 처리 + member.signUp(signUpRequest.getNickName()); + //3. security 처리 + AuthenticationUtil.makeAuthentication(member); + //4. token 만들기 + TokenInfoResponse tokenResponse = tokenUtil.createToken(member, member.getRegistrationStatus().equals(RegistrationStatus.COMPLETED)); + //5. refresh token 저장 + tokenUtil.storeRefreshToken(member.getSocialId(), tokenResponse); + + return SignInResponse.from(tokenResponse, member.getRegistrationStatus()); + } + +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java new file mode 100644 index 00000000..b22ca1aa --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java @@ -0,0 +1,25 @@ +package com.moing.backend.domain.auth.application.service.apple; + +import com.moing.backend.domain.member.application.mapper.MemberMapper; +import com.moing.backend.domain.member.domain.entity.Member; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@AllArgsConstructor +public class AppleSignInUserCase { + + private final AppleTokenUserCase appleTokenUserCase; + private final MemberMapper memberMapper; + + public Member getUserData(String identityToken) { + Jws oidcTokenJws = appleTokenUserCase.sigVerificationAndGetJws(identityToken); + + String socialId = oidcTokenJws.getBody().getSubject(); + String email = (String) oidcTokenJws.getBody().get("email"); + + return memberMapper.createAppleMember(socialId, email); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java new file mode 100644 index 00000000..945f5250 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java @@ -0,0 +1,97 @@ +package com.moing.backend.domain.auth.application.service.apple; + +import com.moing.backend.domain.auth.application.service.apple.feign.AppleFeignClient; +import com.moing.backend.domain.auth.application.service.apple.feign.response.Keys; +import com.moing.backend.domain.auth.exception.TokenInvalidException; +import com.moing.backend.global.exception.InternalServerErrorException; +import io.jsonwebtoken.*; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.math.BigInteger; +import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.RSAPublicKeySpec; +import java.util.Base64; + +@Component +@RequiredArgsConstructor +public class AppleTokenUserCase { + + @Value("${app-id.apple}") + private String appId; + + private final AppleFeignClient appleFeignClient; + + public Jws sigVerificationAndGetJws(String unverifiedToken) { + + try { + String kid = getKidFromUnsignedTokenHeader( + unverifiedToken, + "https://appleid.apple.com", + appId); + + Keys keys = appleFeignClient.getKeys(); + Keys.PubKey pubKey = keys.getKeys().stream() + .filter((key) -> key.getKid().equals(kid)) + .findAny() + .orElseThrow(() -> new TokenInvalidException()); + + return getOIDCTokenJws(unverifiedToken, pubKey.getN(), pubKey.getE()); + } catch (Exception e) { + throw new InternalServerErrorException("Token verification failed"); + } + } + + + private Jws getOIDCTokenJws(String token, String modulus, String exponent) { + try { + return Jwts.parserBuilder() + .setSigningKey(getRSAPublicKey(modulus, exponent)) + .build() + .parseClaimsJws(token); + } catch (Exception e) { + throw new TokenInvalidException(); + } + } + + private Key getRSAPublicKey(String modulus, String exponent) { + try { + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + byte[] decodeN = Base64.getUrlDecoder().decode(modulus); + byte[] decodeE = Base64.getUrlDecoder().decode(exponent); + BigInteger n = new BigInteger(1, decodeN); + BigInteger e = new BigInteger(1, decodeE); + + RSAPublicKeySpec keySpec = new RSAPublicKeySpec(n, e); + return keyFactory.generatePublic(keySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new InternalServerErrorException("Key creation failed"); + } + } + + private String getKidFromUnsignedTokenHeader(String token, String iss, String aud) { + return (String) getUnsignedTokenClaims(token, iss, aud).getHeader().get("kid"); + } + + private Jwt getUnsignedTokenClaims(String token, String iss, String aud) { + try { + return Jwts.parserBuilder() + .requireAudience(aud) + .requireIssuer(iss) + .build() + .parseClaimsJwt(getUnsignedToken(token)); + } catch (Exception e) { + throw new TokenInvalidException(); + } + } + + private String getUnsignedToken(String token) { + String[] splitToken = token.split("\\."); + if (splitToken.length != 3) throw new TokenInvalidException(); + return splitToken[0] + "." + splitToken[1] + "."; + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/AppleFeignClient.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/AppleFeignClient.java new file mode 100644 index 00000000..2c230bdc --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/AppleFeignClient.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.auth.application.service.apple.feign; + +import com.moing.backend.domain.auth.application.service.apple.feign.response.Keys; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +@FeignClient(name = "appleClient", url = "https://appleid.apple.com/auth") +public interface AppleFeignClient { + + @Cacheable(cacheNames = "appleOICD", cacheManager = "oidcCacheManager") + @GetMapping(value = "/keys") + Keys getKeys(); + + @GetMapping(value = "/token") + String getAccessToken(); +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/response/Keys.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/response/Keys.java new file mode 100644 index 00000000..2741263b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/response/Keys.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.auth.application.service.apple.feign.response; + +import lombok.Data; + +import java.util.List; + +@Data +public class Keys { + + private List keys; + + @Data + public static class PubKey{ + private String alg; + + private String e; + + private String kid; + + private String kty; + + private String n; + + private String use; + } +} + diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java new file mode 100644 index 00000000..fde2e577 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java @@ -0,0 +1,39 @@ +package com.moing.backend.domain.auth.application.service.kakao; + +import com.moing.backend.domain.auth.application.dto.response.KakaoUserResponse; +import com.moing.backend.domain.member.application.mapper.MemberMapper; +import com.moing.backend.domain.auth.exception.TokenInvalidException; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.global.exception.InternalServerErrorException; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +@Service +@RequiredArgsConstructor +public class KakaoSignInUserCase { + + private final WebClient webClient; + private final MemberMapper memberMapper; + private final KakaoTokenUserCase kakaoTokenUserCase; + + public Member getUserData(String accessToken) { + + kakaoTokenUserCase.verifyAccessToken(accessToken); + + + KakaoUserResponse kakaoUserResponse = webClient.get() + .uri("https://kapi.kakao.com/v2/user/me") + .headers(h -> h.setBearerAuth(accessToken)) + .retrieve() + .onStatus(HttpStatus::is4xxClientError, response -> Mono.error(new TokenInvalidException())) + .onStatus(HttpStatus::is5xxServerError, response -> Mono.error(new InternalServerErrorException("Kakao Internal Server Error"))) + .bodyToMono(KakaoUserResponse.class) + .block(); + kakaoUserResponse.adaptResponse(); + + return memberMapper.createKakaoMember(kakaoUserResponse); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java new file mode 100644 index 00000000..3b4ccc95 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java @@ -0,0 +1,39 @@ +package com.moing.backend.domain.auth.application.service.kakao; + +import com.moing.backend.domain.auth.application.dto.response.KakaoAccessTokenResponse; +import com.moing.backend.domain.auth.exception.AppIdInvalidException; +import com.moing.backend.domain.auth.exception.TokenInvalidException; +import com.moing.backend.global.exception.InternalServerErrorException; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +@Component +@RequiredArgsConstructor +public class KakaoTokenUserCase { + + @Value("${app-id.kakao}") + private String appId; + + private final WebClient webClient; + + public void verifyAccessToken(String accessToken) { + + + + KakaoAccessTokenResponse kakaoAccessTokenResponse = webClient.get() + .uri("https://kapi.kakao.com/v1/user/access_token_info") + .headers(h -> h.setBearerAuth(accessToken)) + .retrieve() + .onStatus(HttpStatus::is4xxClientError, response -> Mono.error(new TokenInvalidException())) + .onStatus(HttpStatus::is5xxServerError, response -> Mono.error(new InternalServerErrorException("Kakao Internal Server Error "))) + .bodyToMono(KakaoAccessTokenResponse.class) + .block(); + + if (!kakaoAccessTokenResponse.getAppId().equals(appId)) throw new AppIdInvalidException(); + + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/exception/AccountAlreadyExistedException.java b/src/main/java/com/moing/backend/domain/auth/exception/AccountAlreadyExistedException.java new file mode 100644 index 00000000..d6c44e68 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/exception/AccountAlreadyExistedException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.auth.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class AccountAlreadyExistedException extends AuthException { + public AccountAlreadyExistedException() { + super(ErrorCode.ACCOUNT_ALREADY_EXIST, + HttpStatus.UNAUTHORIZED); + } +} + diff --git a/src/main/java/com/moing/backend/domain/auth/exception/AppIdInvalidException.java b/src/main/java/com/moing/backend/domain/auth/exception/AppIdInvalidException.java new file mode 100644 index 00000000..6a48c7bb --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/exception/AppIdInvalidException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.auth.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class AppIdInvalidException extends AuthException{ + public AppIdInvalidException() { + super(ErrorCode.APPID_INVALID_ERROR, + HttpStatus.CONFLICT); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/exception/AuthException.java b/src/main/java/com/moing/backend/domain/auth/exception/AuthException.java new file mode 100644 index 00000000..8dde5a90 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/exception/AuthException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.auth.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class AuthException extends ApplicationException { + protected AuthException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/exception/TokenInvalidException.java b/src/main/java/com/moing/backend/domain/auth/exception/TokenInvalidException.java new file mode 100644 index 00000000..65dc4e0b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/exception/TokenInvalidException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.auth.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class TokenInvalidException extends AuthException { + public TokenInvalidException() { + super(ErrorCode.TOKEN_INVALID_ERROR, + HttpStatus.CONFLICT); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java new file mode 100644 index 00000000..484e7af7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java @@ -0,0 +1,71 @@ +package com.moing.backend.domain.auth.presentation; + +import com.moing.backend.domain.auth.application.dto.request.SignInRequest; +import com.moing.backend.domain.auth.application.dto.request.SignUpRequest; +import com.moing.backend.domain.auth.application.dto.response.ReissueTokenResponse; +import com.moing.backend.domain.auth.application.dto.response.SignInResponse; +import com.moing.backend.domain.auth.application.service.ReissueTokenUserCase; +import com.moing.backend.domain.auth.application.service.SignInUserCase; +import com.moing.backend.domain.auth.application.service.SignUpUserCase; +import com.moing.backend.global.response.SuccessResponse; +import com.moing.backend.global.response.TokenInfoResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; + +import static com.moing.backend.domain.auth.presentation.constant.AuthResponseMessage.*; + +@RestController +@AllArgsConstructor +@RequestMapping("/auth") +public class AuthController { + + private final SignInUserCase authService; + + private final SignUpUserCase signUpService; + + private final ReissueTokenUserCase reissueTokenService; + + /** + * 소셜 로그인 (애플/ 카카오) + * [POST] /auth/signIn/kakao||apple + * 작성자 : 김민수 + */ + @PostMapping("/signIn/{provider}") + public ResponseEntity> signIn(@PathVariable String provider, + @Valid @RequestBody SignInRequest signInRequest) { + return ResponseEntity.ok(SuccessResponse.create(SIGN_IN_SUCCESS.getMessage(), this.authService.signIn(signInRequest.getToken(), provider))); + } + + /** + * 회원가입 (초기 로그인한 사용자 닉네임 입력) + * [PUT] /auth/signUp + * 작성자 : 김민수 + */ + @PutMapping("/signUp") + public ResponseEntity> signUp(HttpServletRequest request, @Valid @RequestBody SignUpRequest signUpRequest) { + String token = request.getHeader("Authorization"); + return ResponseEntity.ok(SuccessResponse.create(SIGN_UP_SUCCESS.getMessage(), this.signUpService.signUp(token, signUpRequest))); + } + + + /** + * 토큰 재발급 + * [GET] /auth/reissue + * 작성자 : 김민수 + */ + @GetMapping("/reissue") + public ResponseEntity> reissue(HttpServletRequest request) { + + // 헤더로부터 RefreshToken 추출. + String token = request.getHeader("RefreshToken"); + // 토큰 재발행 + ReissueTokenResponse reissueToken = reissueTokenService.reissueToken(token); + + return ResponseEntity.ok(SuccessResponse.create(REISSUE_TOKEN_SUCCESS.getMessage(), reissueToken)); + } + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/constant/AuthResponseMessage.java b/src/main/java/com/moing/backend/domain/auth/presentation/constant/AuthResponseMessage.java new file mode 100644 index 00000000..1eb7f046 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/presentation/constant/AuthResponseMessage.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.auth.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum AuthResponseMessage { + SIGN_IN_SUCCESS("로그인을 했습니다"), + SIGN_UP_SUCCESS("회원 가입을 했습니다"), + REISSUE_TOKEN_SUCCESS("토큰을 재발급했습니다"); + private final String message; +} + diff --git a/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java b/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java new file mode 100644 index 00000000..4dc96a31 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java @@ -0,0 +1,36 @@ +package com.moing.backend.domain.member.application.mapper; + +import com.moing.backend.domain.auth.application.dto.response.KakaoUserResponse; +import com.moing.backend.domain.member.domain.constant.Role; +import com.moing.backend.domain.member.domain.constant.SocialProvider; +import com.moing.backend.domain.member.domain.entity.Member; +import org.springframework.stereotype.Component; + +@Component +public class MemberMapper { + + public Member createKakaoMember(KakaoUserResponse kakaoUserResponse) { + Member newMember = Member.builder() + .socialId(SocialProvider.KAKAO + "@" + kakaoUserResponse.getId()) + .provider(SocialProvider.KAKAO) + .email(kakaoUserResponse.getKakaoAccount().getEmail()) + .nickName(kakaoUserResponse.getProperties().getNickname()) + .gender(kakaoUserResponse.getKakaoAccount().getGender()) + .ageRange(kakaoUserResponse.getKakaoAccount().getAgeRange()) + .role(Role.USER) + .build(); + + return newMember; + } + + public Member createAppleMember(String socialId, String email) { + Member newMember = Member.builder() + .socialId(SocialProvider.APPLE + "@" + socialId) + .provider(SocialProvider.APPLE) + .email(email) + .role(Role.USER) + .build(); + + return newMember; + } +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/constant/RegistrationStatus.java b/src/main/java/com/moing/backend/domain/member/domain/constant/RegistrationStatus.java new file mode 100644 index 00000000..22b747fa --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/constant/RegistrationStatus.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.member.domain.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum RegistrationStatus { + UNCOMPLETED("회원가입을 합니다. 추가 정보를 입력하세요."), + COMPLETED("로그인을 합니다."); + private String message; +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/constant/Role.java b/src/main/java/com/moing/backend/domain/member/domain/constant/Role.java new file mode 100644 index 00000000..d4ac6927 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/constant/Role.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.member.domain.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum Role { + USER("ROLE_USER"), + ADMIN("ROLE_ADMIN"); + + private final String key; +} + diff --git a/src/main/java/com/moing/backend/domain/member/domain/constant/SocialProvider.java b/src/main/java/com/moing/backend/domain/member/domain/constant/SocialProvider.java new file mode 100644 index 00000000..400ffc8e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/constant/SocialProvider.java @@ -0,0 +1,10 @@ +package com.moing.backend.domain.member.domain.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum SocialProvider { + GOOGLE, NAVER, APPLE, KAKAO; +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java new file mode 100644 index 00000000..a18f85ea --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -0,0 +1,154 @@ +package com.moing.backend.domain.member.domain.entity; + +import com.moing.backend.domain.member.domain.constant.RegistrationStatus; +import com.moing.backend.domain.member.domain.constant.Role; +import com.moing.backend.domain.member.domain.constant.SocialProvider; +import com.moing.backend.global.util.AesConverter; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; +import org.springframework.security.oauth2.core.user.OAuth2User; + +import javax.persistence.*; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class Member { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "member_id") + private Long memberId; + + @Column(nullable = false, unique = true) + private String socialId; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private SocialProvider provider; + + @Enumerated(EnumType.STRING) + private RegistrationStatus registrationStatus; + + @Convert(converter = AesConverter.class) + @Column(nullable = false, unique = true) + private String email; + + @Convert(converter = AesConverter.class) + private String profileImage; //없으면 undef + + + private String gender; //없으면 undef + + + private String ageRange; //없으면 undef + private boolean isDeleted; + + // 추가정보 + @Convert(converter = AesConverter.class) + private String nickName; //없으면 undef + + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private Role role; + + @Convert(converter = AesConverter.class) + private String introduction; //없으면 undef + + + private String fcmToken; //없으면 undef + + private String reasonToDelete; //없으면 undef + + @ColumnDefault("true") + private boolean isNewUploadPush; + + @ColumnDefault("true") + private boolean isRemindPush; + + @ColumnDefault("true") + private boolean isFirePush; + + + //==생성 메서드==// + public static Member valueOf(OAuth2User oAuth2User) { + var attributes = oAuth2User.getAttributes(); + return Member.builder() + .socialId((String) attributes.get("socialId")) + .provider((SocialProvider) attributes.get("provider")) + .nickName((String) attributes.get("nickname")) + .email((String) attributes.get("email")) + .gender((String) attributes.get("gender")) + .ageRange((String) attributes.get("age")) + .role((Role) attributes.get("role")) + .registrationStatus(RegistrationStatus.UNCOMPLETED) + .build(); + } + + @PrePersist + public void prePersist() { + if (profileImage == null) profileImage = "undef"; + if (gender == null) gender = "undef"; + if (ageRange == null) ageRange = "undef"; + if (nickName == null) nickName = "undef"; + if (introduction == null) introduction = "undef"; + if (fcmToken == null) fcmToken = "undef"; + if (reasonToDelete == null) reasonToDelete = "undef"; + if (registrationStatus == null) registrationStatus = RegistrationStatus.UNCOMPLETED; + } + + public void signUp(String nickName) { + this.nickName = nickName; + this.registrationStatus = RegistrationStatus.COMPLETED; + } + + public void updateFcmToken(String fcmToken) { + this.fcmToken = fcmToken; + } + + @Builder + public Member(String email, String profileImage, String gender, String ageRange, Role role) { + this.email = email; + this.profileImage = profileImage; + this.gender = gender; + this.ageRange = ageRange; + this.role = role; + } + + + public void updateMember(String nickName, String fcmToken) { + this.nickName = nickName; + this.fcmToken = fcmToken; + } + + public void updateMypage(String nickName, String introduction) { + this.nickName = nickName; + this.introduction = introduction; + } + + public void deleteAccount(String reasonToDelete) { + this.isDeleted = true; + this.reasonToDelete = reasonToDelete; + } + + public void updateNewUploadPush(boolean newUploadPush) { + this.isNewUploadPush = newUploadPush; + } + + public void updateRemindPush(boolean remindPush) { + this.isRemindPush = remindPush; + } + + public void updateFirePush(boolean firePush) { + this.isFirePush = firePush; + } + + public void updateProfile(String string) { + this.profileImage = string; + } + +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java new file mode 100644 index 00000000..cb097741 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java @@ -0,0 +1,9 @@ +package com.moing.backend.domain.member.domain.repository; + +import com.moing.backend.domain.member.domain.entity.Member; + +import java.util.Optional; + +public interface MemberCustomRepository { + Optional findBySocialIdNotDeleted(String socialId); +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java new file mode 100644 index 00000000..219349f7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java @@ -0,0 +1,26 @@ +package com.moing.backend.domain.member.domain.repository; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.util.Optional; + +import static com.moing.backend.domain.member.domain.entity.QMember.member; + +public class MemberCustomRepositoryImpl implements MemberCustomRepository { + + private final JPAQueryFactory queryFactory; + + public MemberCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + @Override + public Optional findBySocialIdNotDeleted(String socialId) { + return Optional.ofNullable(queryFactory.selectFrom(member) + .where(member.socialId.eq(socialId)) + .where(member.isDeleted.eq(false)) + .fetchFirst()); + } +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java new file mode 100644 index 00000000..c797cf41 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java @@ -0,0 +1,8 @@ +package com.moing.backend.domain.member.domain.repository; + +import com.moing.backend.domain.member.domain.entity.Member; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberRepository extends JpaRepository, MemberCustomRepository { + +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberQueryService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberQueryService.java new file mode 100644 index 00000000..e82e5238 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberQueryService.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.member.domain.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.repository.MemberRepository; +import com.moing.backend.domain.member.exception.NotFoundBySocialIdException; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MemberQueryService { + private final MemberRepository memberRepository; + + public Member getMemberBySocialId(String socialId){ + return memberRepository.findBySocialIdNotDeleted(socialId).orElseThrow(()->new NotFoundBySocialIdException()); + } +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java new file mode 100644 index 00000000..34dc324a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java @@ -0,0 +1,23 @@ +package com.moing.backend.domain.member.domain.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.repository.MemberRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.AllArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@AllArgsConstructor +public class MemberSaveService { + + private final MemberRepository memberRepository; + + public Member saveMember(Member member) { + if(memberRepository.findBySocialIdNotDeleted(member.getSocialId()).isEmpty()){ + return memberRepository.save(member); + } + return memberRepository.findBySocialIdNotDeleted(member.getSocialId()).get(); + } +} diff --git a/src/main/java/com/moing/backend/domain/member/exception/MemberException.java b/src/main/java/com/moing/backend/domain/member/exception/MemberException.java new file mode 100644 index 00000000..7df8cf88 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/exception/MemberException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.member.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class MemberException extends ApplicationException { + protected MemberException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} diff --git a/src/main/java/com/moing/backend/domain/member/exception/NotFoundBySocialIdException.java b/src/main/java/com/moing/backend/domain/member/exception/NotFoundBySocialIdException.java new file mode 100644 index 00000000..4b3f3fd4 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/exception/NotFoundBySocialIdException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.member.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundBySocialIdException extends MemberException { + public NotFoundBySocialIdException() { + super(ErrorCode.NOT_FOUND_BY_SOCIAL_ID_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/global/config/redis/RedisConfig.java b/src/main/java/com/moing/backend/global/config/redis/RedisConfig.java new file mode 100644 index 00000000..7b804c78 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/redis/RedisConfig.java @@ -0,0 +1,42 @@ +package com.moing.backend.global.config.redis; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + + @Value("${spring.redis.host}") + private String redisHost; + + @Value("${spring.redis.port}") + private String redisPort; + + @Value("${spring.redis.password}") + private String redisPassword; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); + redisStandaloneConfiguration.setHostName(redisHost); + redisStandaloneConfiguration.setPort(Integer.parseInt(redisPort)); + redisStandaloneConfiguration.setPassword(redisPassword); + LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration); + return lettuceConnectionFactory; + } + + @Bean + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + return redisTemplate; + } +} diff --git a/src/main/java/com/moing/backend/global/config/redis/RedisUtil.java b/src/main/java/com/moing/backend/global/config/redis/RedisUtil.java new file mode 100644 index 00000000..978fd649 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/redis/RedisUtil.java @@ -0,0 +1,35 @@ +package com.moing.backend.global.config.redis; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +@Repository +public class RedisUtil { + + private RedisTemplate redisTemplate; + + @Value("${jwt.refresh-token-period}") + private long refreshTokenValidityTime; + + public RedisUtil(final RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + public void save(String refreshToken, String socialId) { + //동일한 key 값으로 저장하면 value값 updat됨 + redisTemplate.opsForValue().set(socialId, refreshToken, refreshTokenValidityTime, TimeUnit.SECONDS); + } + + public void deleteById(String socialId) { + redisTemplate.delete(String.valueOf(socialId)); + } + + public Optional findById(final String socialId) { + String refreshToken = (String) redisTemplate.opsForValue().get(socialId); + return Optional.ofNullable(refreshToken); + } +} diff --git a/src/main/java/com/moing/backend/global/config/redis/constant/RefreshTokenConstant.java b/src/main/java/com/moing/backend/global/config/redis/constant/RefreshTokenConstant.java new file mode 100644 index 00000000..f8213e9c --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/redis/constant/RefreshTokenConstant.java @@ -0,0 +1,23 @@ +package com.moing.backend.global.config.redis.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +public class RefreshTokenConstant { + @Getter + @RequiredArgsConstructor + public enum ERefreshTokenMessage { + TOKEN_REFRESH_SUCCESS("토큰 재발급을 완료하였습니다"); + private final String message; + } + + @Getter + @RequiredArgsConstructor + public enum RefreshTokenExceptionList { + NOT_FOUND_TOKEN_ERROR("R0003", HttpStatus.NOT_FOUND, "Refresh-Token을 찾을 수 없습니다. 아예 새롭게 로그인을 하세요"); + private final String errorCode; + private final HttpStatus httpStatus; + private final String message; + } +} diff --git a/src/main/java/com/moing/backend/global/config/response/ErrorCode.java b/src/main/java/com/moing/backend/global/config/response/ErrorCode.java deleted file mode 100644 index cbb3691d..00000000 --- a/src/main/java/com/moing/backend/global/config/response/ErrorCode.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.moing.backend.global.config.response; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import org.springframework.http.HttpStatus; - -@Getter -@AllArgsConstructor -public enum ErrorCode { - - BAD_REQUEST(false, "400", "올바른 패턴을 입력하세요."), - METHOD_NOT_ALLOWED(false,"405", "클라이언트가 사용한 HTTP 메서드가 리소스에서 허용되지 않습니다."), - INTERNAL_SERVER_ERROR(false,"500", "서버에서 요청을 처리하는 동안 오류가 발생했습니다."); - - private Boolean isSuccess; - private String errorCode; - private String message; - -} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java new file mode 100644 index 00000000..c1e18b11 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java @@ -0,0 +1,71 @@ +package com.moing.backend.global.config.security; + +import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.global.config.security.filter.JwtAccessDeniedHandler; +import com.moing.backend.global.config.security.filter.JwtAuthenticationEntryPoint; +import com.moing.backend.global.config.security.jwt.JwtSecurityConfig; +import com.moing.backend.global.config.security.jwt.TokenUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +@RequiredArgsConstructor +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + private final TokenUtil tokenUtil; + private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; + private final JwtAccessDeniedHandler jwtAccessDeniedHandler; + private final MemberQueryService memberQueryService; + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("antMatchers/resource/**", "/css/**", "/js/**", "/img/**", "/lib/**"); + } + + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf().disable() //CSRF 보호 비활성화 + .formLogin().disable() //폼 로그인 비활성화 + .httpBasic().disable() // HTTP 기본 인증 비활성화 + .exceptionHandling() //예외 처리 설정 + .authenticationEntryPoint(jwtAuthenticationEntryPoint) //인증되지 않은 사용자가 보호된 리소스에 액세스 할 때 호출되는 JwtAuthenticationEntryPoint 설정 + .accessDeniedHandler(jwtAccessDeniedHandler) //권한이 없는 사용자가 보호된 리소스에 액세스 할 때 호출되는 JwtAccessDeniedHandler 설정 + .and() + .headers().frameOptions().sameOrigin() + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //Spring Security에서 세션을 사용하지 않도록 설정 + .and() + .authorizeRequests() + .antMatchers("/auth/**", "/docs/**").permitAll() + .anyRequest().authenticated() + .and() + .apply(new JwtSecurityConfig(tokenUtil, memberQueryService)); + } + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + + configuration.addAllowedOriginPattern("*"); + configuration.addAllowedHeader("*"); + configuration.addAllowedMethod("*"); + configuration.setAllowCredentials(false); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + return source; + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/security/dto/User.java b/src/main/java/com/moing/backend/global/config/security/dto/User.java new file mode 100644 index 00000000..6e3580d2 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/dto/User.java @@ -0,0 +1,19 @@ +package com.moing.backend.global.config.security.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Data +public class User { + private String socialId; + private String email; + private List roles; +} + diff --git a/src/main/java/com/moing/backend/global/config/security/filter/JwtAccessDeniedHandler.java b/src/main/java/com/moing/backend/global/config/security/filter/JwtAccessDeniedHandler.java new file mode 100644 index 00000000..65718db1 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/filter/JwtAccessDeniedHandler.java @@ -0,0 +1,26 @@ +package com.moing.backend.global.config.security.filter; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.moing.backend.global.response.ErrorResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class JwtAccessDeniedHandler implements AccessDeniedHandler { + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException { + ErrorResponse errorResponse = new ErrorResponse("403", "접근이 금지되었습니다. 권한이 없는 사용자가 접근하려고 했습니다."); + response.setStatus(HttpStatus.FORBIDDEN.value()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(response.getWriter(), errorResponse); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthFilter.java b/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthFilter.java new file mode 100644 index 00000000..9f744a3d --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthFilter.java @@ -0,0 +1,81 @@ +package com.moing.backend.global.config.security.filter; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.global.config.security.jwt.JwtExceptionList; +import com.moing.backend.global.config.security.jwt.TokenUtil; +import com.moing.backend.global.config.security.util.AuthenticationUtil; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.UnsupportedJwtException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Slf4j +@RequiredArgsConstructor +public class JwtAuthFilter extends OncePerRequestFilter { + + public static final String AUTHORIZATION_HEADER = "Authorization"; + private final TokenUtil tokenUtil; + private final MemberQueryService memberQueryService; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException, JwtException { + String token = resolveToken(request); + String requestURI = request.getRequestURI(); + try { + if (StringUtils.hasText(token) && tokenUtil.verifyToken(token)) { + boolean isAdditionalInfoProvided = tokenUtil.getAdditionalInfoProvided(token); + if (isAdditionalInfoProvided) { + // 토큰 파싱해서 socialId 정보 가져오기 + String socialId = tokenUtil.getSocialId(token); + Member member = memberQueryService.getMemberBySocialId(socialId); + + // 이메일로 Authentication 정보 생성 + AuthenticationUtil.makeAuthentication(member); + log.debug("Security Context에 '{}' 인증 정보를 저장했습니다, uri: {}", member.getSocialId(), requestURI); + } else { + request.setAttribute("exception", JwtExceptionList.ADDITIONAL_REQUIRED_TOKEN.getErrorCode()); + } + } + } catch (SecurityException | MalformedJwtException e) { + request.setAttribute("exception", JwtExceptionList.MAL_FORMED_TOKEN.getErrorCode()); + } catch (ExpiredJwtException e) { + request.setAttribute("exception", JwtExceptionList.EXPIRED_TOKEN.getErrorCode()); + log.info("JwtAuthFilter: Caught ExpiredJwtException"); + log.info(String.valueOf(request.getAttribute("exception"))); + } catch (UnsupportedJwtException e) { + request.setAttribute("exception", JwtExceptionList.UNSUPPORTED_TOKEN.getErrorCode()); + } catch (IllegalArgumentException e) { + request.setAttribute("exception", JwtExceptionList.ILLEGAL_TOKEN.getErrorCode()); + } catch (Exception e) { + log.error("================================================"); + log.error("JwtFilter - doFilterInternal() 오류발생"); + log.error("token : {}", token); + log.error("Exception Message : {}", e.getMessage()); + log.error("Exception StackTrace : {"); + e.printStackTrace(); + log.error("}"); + log.error("================================================"); + request.setAttribute("exception", JwtExceptionList.UNKNOWN_ERROR.getErrorCode()); + } + filterChain.doFilter(request, response); + } + + private String resolveToken(HttpServletRequest request) { + String bearerToken = request.getHeader(AUTHORIZATION_HEADER); + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { + return bearerToken.substring(7); + } + return null; + } +} diff --git a/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthenticationEntryPoint.java b/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthenticationEntryPoint.java new file mode 100644 index 00000000..89133842 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthenticationEntryPoint.java @@ -0,0 +1,61 @@ +package com.moing.backend.global.config.security.filter; + +import com.moing.backend.global.config.security.jwt.JwtExceptionList; +import com.nimbusds.jose.shaded.json.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.time.LocalDateTime; + +/** + * 인증되지 않은 사용자가 보호된 리소스에 액세스 할 때 호출 + */ +@Component +@Slf4j +public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { + String exception = String.valueOf(request.getAttribute("exception")); + log.info("commonce:" + exception); + + if (exception.equals(JwtExceptionList.ADDITIONAL_REQUIRED_TOKEN.getErrorCode())) + setResponse(response, JwtExceptionList.ADDITIONAL_REQUIRED_TOKEN); + + else if (exception.equals(JwtExceptionList.UNKNOWN_ERROR.getErrorCode())) + setResponse(response, JwtExceptionList.UNKNOWN_ERROR); + + else if (exception.equals(JwtExceptionList.MAL_FORMED_TOKEN.getErrorCode())) + setResponse(response, JwtExceptionList.MAL_FORMED_TOKEN); + + else if (exception.equals(JwtExceptionList.ILLEGAL_TOKEN.getErrorCode())) + setResponse(response, JwtExceptionList.ILLEGAL_TOKEN); + + else if (exception.equals(JwtExceptionList.EXPIRED_TOKEN.getErrorCode())) + setResponse(response, JwtExceptionList.EXPIRED_TOKEN); + + else if (exception.equals(JwtExceptionList.UNSUPPORTED_TOKEN.getErrorCode())) + setResponse(response, JwtExceptionList.UNSUPPORTED_TOKEN); + + else setResponse(response, JwtExceptionList.ACCESS_DENIED); + + } + + private void setResponse(HttpServletResponse response, JwtExceptionList exceptionCode) throws IOException { + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + + JSONObject responseJson = new JSONObject(); + responseJson.put("isSuccess", false); + responseJson.put("timestamp", LocalDateTime.now().withNano(0).toString()); + responseJson.put("errorCode", exceptionCode.getErrorCode()); + responseJson.put("message", exceptionCode.getMessage()); + + response.getWriter().print(responseJson); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/security/jwt/JwtExceptionList.java b/src/main/java/com/moing/backend/global/config/security/jwt/JwtExceptionList.java new file mode 100644 index 00000000..a7052801 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/jwt/JwtExceptionList.java @@ -0,0 +1,21 @@ +package com.moing.backend.global.config.security.jwt; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum JwtExceptionList { + UNKNOWN_ERROR("J0001", HttpStatus.INTERNAL_SERVER_ERROR, "예상치 못한 오류가 발생했습니다."), + MAL_FORMED_TOKEN("J0002", HttpStatus.UNAUTHORIZED, "잘못된 JWT 서명입니다."), + EXPIRED_TOKEN("J0003", HttpStatus.UNAUTHORIZED, "만료된 토큰입니다."), + UNSUPPORTED_TOKEN("J0004", HttpStatus.UNAUTHORIZED, "지원되지 않는 토큰입니다."), + ACCESS_DENIED("J0005", HttpStatus.UNAUTHORIZED, "접근이 거부되었습니다."), + ILLEGAL_TOKEN("J0006", HttpStatus.UNAUTHORIZED, "JWT 토큰이 잘못되었습니다."), + ADDITIONAL_REQUIRED_TOKEN("J0007", HttpStatus.UNAUTHORIZED, "추가 정보를 입력해야 합니다."); + private final String errorCode; + private final HttpStatus httpStatus; + private final String message; + +} diff --git a/src/main/java/com/moing/backend/global/config/security/jwt/JwtSecurityConfig.java b/src/main/java/com/moing/backend/global/config/security/jwt/JwtSecurityConfig.java new file mode 100644 index 00000000..9d1f751b --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/jwt/JwtSecurityConfig.java @@ -0,0 +1,24 @@ +package com.moing.backend.global.config.security.jwt; + +import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.global.config.security.filter.JwtAuthFilter; +import lombok.RequiredArgsConstructor; +import org.springframework.security.config.annotation.SecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.DefaultSecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +@RequiredArgsConstructor +public class JwtSecurityConfig extends SecurityConfigurerAdapter { + + private final TokenUtil tokenUtil; + + private final MemberQueryService memberQueryService; + + @Override + public void configure(HttpSecurity http) { + JwtAuthFilter customFilter = new JwtAuthFilter(tokenUtil, memberQueryService); + //UsernamePasswordAuthenticationFilter 앞에 필터로 JwtFilter 추가 + http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); + } +} diff --git a/src/main/java/com/moing/backend/global/config/security/jwt/NotFoundRefreshToken.java b/src/main/java/com/moing/backend/global/config/security/jwt/NotFoundRefreshToken.java new file mode 100644 index 00000000..96a2402f --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/jwt/NotFoundRefreshToken.java @@ -0,0 +1,13 @@ +package com.moing.backend.global.config.security.jwt; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundRefreshToken extends ApplicationException { + public NotFoundRefreshToken() { + super(ErrorCode.NOT_FOUND_REFRESH_TOKEN_ERROR, + HttpStatus.NOT_FOUND); + } + +} diff --git a/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java b/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java new file mode 100644 index 00000000..b351e1fd --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java @@ -0,0 +1,169 @@ +package com.moing.backend.global.config.security.jwt; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.global.config.redis.RedisUtil; +import com.moing.backend.global.response.TokenInfoResponse; +import io.jsonwebtoken.*; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.security.Keys; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.security.Key; +import java.util.Date; + +@Slf4j +@Component +@RequiredArgsConstructor +public class TokenUtil implements InitializingBean { + + private static final String ADDITIONAL_INFO = "isAdditionalInfoProvided"; + private final RedisUtil redisUtil; + private final MemberQueryService memberQueryService; + + @Value("${jwt.secret}") + private String secretKey; + + @Value("${jwt.access-token-period}") + private long accessTokenValidityTime; + + @Value("${jwt.refresh-token-period}") + private long refreshTokenValidityTime; + + @Value("${jwt.reissue-token-period}") + private Long reissueTokenValidityTime; + + private Key key; + + @Override + public void afterPropertiesSet() { + byte[] keyBytes = Decoders.BASE64.decode(secretKey); + this.key = Keys.hmacShaKeyFor(keyBytes); + } + + + /** + * 토큰 만드는 함수 + * + * @param member + * @return TokenInfoResponse + */ + public TokenInfoResponse createToken(Member member, boolean isAdditionalInfoProvided) { + // claim 생성 + Claims claims = getClaims(member, isAdditionalInfoProvided); + + Date now = new Date(); + Date accessTokenValidity = new Date(now.getTime() + this.accessTokenValidityTime); + Date refreshTokenValidity = new Date(now.getTime() + this.refreshTokenValidityTime); + + String accessToken = Jwts.builder() + .setClaims(claims) + .setIssuedAt(now) + .setExpiration(accessTokenValidity) + .signWith(SignatureAlgorithm.HS256, secretKey) + .compact(); + + String refreshToken = Jwts.builder() + .setClaims(claims) + .setIssuedAt(now) + .setExpiration(refreshTokenValidity) + .signWith(SignatureAlgorithm.HS256, secretKey) + .compact(); + + return TokenInfoResponse.from("Bearer", accessToken, refreshToken, refreshTokenValidityTime); + } + + public boolean verifyToken(String token) { + try { + Jws claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); + return claims.getBody().getExpiration().after(new Date()); + } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { + log.info("잘못된 JWT 서명입니다."); + throw e; + } catch (ExpiredJwtException e) { + log.info("만료된 JWT 토큰입니다."); + throw e; + } catch (UnsupportedJwtException e) { + log.info("지원되지 않는 JWT 토큰입니다."); + throw e; + } catch (IllegalArgumentException e) { + log.info("JWT 토큰이 잘못되었습니다."); + throw e; + } catch (Exception e) { + log.info(e.getMessage()); + throw e; + } + } + + //refresh token 관련 + public void storeRefreshToken(String socialId, TokenInfoResponse token) { + redisUtil.save(token.getRefreshToken(), socialId); + } + + public TokenInfoResponse tokenReissue(String token) { + String socialId = getSocialId(token); + Member member = memberQueryService.getMemberBySocialId(socialId); + + // socialId 에 해당하는 refreshToken redis 에서 가져오기 + String storedRefreshToken = redisUtil.findById(socialId).orElseThrow(() -> new NotFoundRefreshToken()); + + // Token 생성 + TokenInfoResponse newToken = createToken(member, true); + + // refreshToken 기간이 얼마남지 않았을 경우 (3일 미만) + if (isExpired(token)) { + log.info("Refresh token reissue"); + storeRefreshToken(socialId, newToken); + } + + // refreshToken 의 유효기간이 3일 이상 남았을 경우 (refreshToken 그대로 넣어서 응답) + else newToken.updateRefreshToken(token); + + return newToken; + } + + + private boolean isExpired(String token) { + Date expireDate = getExpiration(token); + Date currentDate = new Date(); + + if (expireDate.getTime() - currentDate.getTime() < reissueTokenValidityTime) + return true; + else + return false; + } + + + //토큰 만료시키기 + public void expireRefreshToken(String socialId) { + redisUtil.deleteById(socialId); + } + + // get 함수 + public boolean getAdditionalInfoProvided(String token) { + Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody(); + return claims.get(ADDITIONAL_INFO, Boolean.class); + } + + private static Claims getClaims(Member member, boolean isAdditionalInfoProvided) { + // claim 에 socialId 정보 추가 + Claims claims = Jwts.claims().setSubject(member.getSocialId()); + claims.put(ADDITIONAL_INFO, isAdditionalInfoProvided); + return claims; + } + + private Date getExpiration(String token) { + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getExpiration(); + } + + public String getSocialId(String token) { + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); + } + + +} + diff --git a/src/main/java/com/moing/backend/global/config/security/oauth/CustomOAuth2UserService.java b/src/main/java/com/moing/backend/global/config/security/oauth/CustomOAuth2UserService.java new file mode 100644 index 00000000..94cda61a --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/oauth/CustomOAuth2UserService.java @@ -0,0 +1,44 @@ +package com.moing.backend.global.config.security.oauth; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.user.DefaultOAuth2User; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.Map; + +@Slf4j +@Service +public class CustomOAuth2UserService implements OAuth2UserService { + + @Override + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + OAuth2UserService oAuth2UserService = new DefaultOAuth2UserService(); + OAuth2User oAuth2User = oAuth2UserService.loadUser(userRequest); + + // 유저 정보 얻어오기 + String provider = userRequest.getClientRegistration().getRegistrationId(); + String userNameAttributeName = userRequest.getClientRegistration() + .getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName(); + + // 로그인 종류(Google, Kakao, Naver)에 맞게 OAuth2Attribute 생성 + OAuth2Attribute oAuth2Attribute = + OAuth2Attribute.of(provider, userNameAttributeName, oAuth2User.getAttributes()); + + log.info("{} : {}", provider, oAuth2Attribute); + + Map memberAttribute = oAuth2Attribute.convertToMap(); + + // 인증 정보 생성 후 반환 + return new DefaultOAuth2User( + Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")), + memberAttribute, "email"); + } +} + diff --git a/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetails.java b/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetails.java new file mode 100644 index 00000000..a27370a0 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetails.java @@ -0,0 +1,58 @@ +package com.moing.backend.global.config.security.oauth; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import com.moing.backend.domain.member.domain.entity.Member; + +import java.util.Arrays; +import java.util.Collection; + +public class CustomUserDetails implements UserDetails { + + private Member member; + + public CustomUserDetails(Member member) { + this.member = member; + } + + @Override + public Collection getAuthorities() { + return Arrays.asList(new SimpleGrantedAuthority(member.getRole().name())); + } + + @Override + public String getPassword() { + // 비밀번호는 소셜 로그인에 사용되지 않으므로 null을 반환합니다. + return null; + } + + @Override + public String getUsername() { + return member.getNickName(); + } + + @Override + public boolean isAccountNonExpired() { + return !member.isDeleted(); + } + + @Override + public boolean isAccountNonLocked() { + return !member.isDeleted(); + } + + @Override + public boolean isCredentialsNonExpired() { + return !member.isDeleted(); + } + + @Override + public boolean isEnabled() { + return !member.isDeleted(); + } + + public Member getMember() { + return member; + } +} diff --git a/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetailsService.java b/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetailsService.java new file mode 100644 index 00000000..bf1bb588 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetailsService.java @@ -0,0 +1,29 @@ +package com.moing.backend.global.config.security.oauth; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class CustomUserDetailsService implements UserDetailsService { + private final MemberQueryService memberQueryService; + + @Override + @Transactional(readOnly = true) + public UserDetails loadUserByUsername(String socialId) throws UsernameNotFoundException { + Member member = this.memberQueryService.getMemberBySocialId(socialId); + + if (member == null) { + throw new UsernameNotFoundException("User not found with socialId: " + socialId); + } + + return new CustomUserDetails(member); + } +} + diff --git a/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2Attribute.java b/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2Attribute.java new file mode 100644 index 00000000..275e2e6c --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2Attribute.java @@ -0,0 +1,170 @@ +package com.moing.backend.global.config.security.oauth; + +import com.moing.backend.domain.member.domain.constant.SocialProvider; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +import java.util.HashMap; +import java.util.Map; + +@ToString +@Builder(access = AccessLevel.PRIVATE) +@Getter +class OAuth2Attribute { + private Map attributes; + + private String socialId; + private SocialProvider provider; + private String name; + private String nickname; + private String email; + private String ageRange; + private String gender; + + + static OAuth2Attribute of(String provider, String attributeKey, + Map attributes) { + switch (provider) { + case "google": + return ofGoogle(attributeKey, attributes); + case "kakao": + return ofKakao("id", attributes); + case "naver": + return ofNaver("id", attributes); + case "apple": + return ofApple("id", attributes); + default: + throw new RuntimeException(); + } + } + + private static OAuth2Attribute ofGoogle(String attributeKey, + Map attributes) { + OAuth2Attribute oAuth2Attribute = OAuth2Attribute.builder() + .socialId(SocialProvider.GOOGLE + "@" + attributes.get(attributeKey)) + .provider(SocialProvider.GOOGLE) + .name((String) attributes.get("name")) + .nickname((String) attributes.get("name")) + .email((String) attributes.get("email")) + .ageRange("undef") + .gender("undef") + .build(); + + oAuth2Attribute.adaptGoogleResponse(); + + return oAuth2Attribute; + } + + private static OAuth2Attribute ofKakao(String attributeKey, + Map attributes) { + Map kakaoAccount = (Map) attributes.get("kakao_account"); + Map profile = (Map) kakaoAccount.get("profile"); + + OAuth2Attribute oAuth2Attribute = OAuth2Attribute.builder() + .socialId(SocialProvider.APPLE + "@" + attributes.get(attributeKey)) + .provider(SocialProvider.APPLE) + .name((String) profile.get("nickname")) + .nickname((String) profile.get("nickname")) + .email((String) kakaoAccount.get("email")) + .gender((String) kakaoAccount.get("gender")) + .ageRange((String) kakaoAccount.get("age_range")) + .build(); + + oAuth2Attribute.adaptKakaoResponse(); + + return oAuth2Attribute; + } + + private static OAuth2Attribute ofNaver(String attributeKey, + Map attributes) { + Map response = (Map) attributes.get("response"); + + System.out.println(response); + + OAuth2Attribute oAuth2Attribute = OAuth2Attribute.builder() + .socialId(SocialProvider.NAVER + "@" + response.get(attributeKey)) + .provider(SocialProvider.NAVER) + .name((String) response.get("nickname")) + .nickname((String) response.get("nickname")) + .email((String) response.get("email")) + .gender((String) response.get("gender")) + .ageRange((String) response.get("age")) + .build(); + + oAuth2Attribute.adaptNaverResponse(); + + return oAuth2Attribute; + } + + private static OAuth2Attribute ofApple(String attributeKey, + Map attributes) { + OAuth2Attribute oAuth2Attribute = OAuth2Attribute.builder() + .socialId(SocialProvider.APPLE + "@" + attributes.get(attributeKey)) + .provider(SocialProvider.APPLE) + .name((String) attributes.get("email")) + .nickname("undef") + .email((String) attributes.get("email")) + .gender("undef") + .ageRange("undef") + .build(); + + oAuth2Attribute.adaptAppleResponse(); + + return oAuth2Attribute; + } + + Map convertToMap() { + Map map = new HashMap<>(); + map.put("socialId", socialId); + map.put("provider", provider); + map.put("name", name); + map.put("nickname", nickname); + map.put("email", email); + map.put("gender", gender); + map.put("age", ageRange); + + return map; + } + + public void adaptNaverResponse() { + if (gender == null || gender.isBlank()) gender = "undef"; + else if (gender.equals("M")) gender = "male"; + else if (gender.equals("F")) gender = "female"; + else gender = "undef"; + + if (ageRange == null || ageRange.isBlank()) ageRange = "undef"; + if (email.length() > 50) email = email.substring(0, 50); + if (nickname.length() > 7) { + name = name.substring(0, 7); + nickname = nickname.substring(0, 7); + } + } + + public void adaptKakaoResponse() { + if (gender == null || gender.isBlank()) gender = "undef"; + if (ageRange == null || ageRange.isBlank()) ageRange = "undef"; + if (email.length() > 50) email = email.substring(0, 50); + if (nickname.length() > 7) { + name = name.substring(0, 7); + nickname = nickname.substring(0, 7); + } + } + + public void adaptGoogleResponse() { + if (email.length() > 50) email = email.substring(0, 50); + if (name.length() > 7) { + name = name.substring(0, 7); + nickname = nickname.substring(0, 7); + } + } + + public void adaptAppleResponse() { + if (email.length() > 50) email = email.substring(0, 50); + if (name.length() > 7) { + name = name.substring(0, 7); + nickname = nickname.substring(0, 7); + } + } +} diff --git a/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2FailureHandler.java b/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2FailureHandler.java new file mode 100644 index 00000000..3578e1d0 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2FailureHandler.java @@ -0,0 +1,38 @@ +package com.moing.backend.global.config.security.oauth; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.moing.backend.global.response.ErrorCode; +import com.moing.backend.global.response.ErrorResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Slf4j +@Component +@RequiredArgsConstructor +public class OAuth2FailureHandler implements AuthenticationFailureHandler { + + private final ObjectMapper objectMapper; + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { + log.error("[" + e.getClass().getSimpleName() + "] " + e.getMessage()); + + setErrorResponse(response, ErrorCode.INTERNAL_SERVER_ERROR); + } + + private void setErrorResponse(HttpServletResponse response, ErrorCode errorCode) throws IOException { + response.setStatus(500); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding("UTF-8"); + objectMapper.writeValue(response.getWriter(), new ErrorResponse<>(errorCode)); + } +} diff --git a/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2SuccessHandler.java b/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2SuccessHandler.java new file mode 100644 index 00000000..c5fc1130 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2SuccessHandler.java @@ -0,0 +1,62 @@ +package com.moing.backend.global.config.security.oauth; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.moing.backend.domain.auth.application.dto.response.SignInResponse; +import com.moing.backend.domain.member.domain.constant.RegistrationStatus; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberSaveService; +import com.moing.backend.global.config.security.jwt.TokenUtil; +import com.moing.backend.global.response.TokenInfoResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Slf4j +@RequiredArgsConstructor +@Component +public class OAuth2SuccessHandler implements AuthenticationSuccessHandler { + + private final MemberSaveService memberSaveService; + private final TokenUtil tokenUtil; + private final ObjectMapper objectMapper; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException { + OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal(); + Member member = Member.valueOf(oAuth2User); + + // 회원가입(가입 정보 없는 유저일 때만) 및 로그인 + Member signInMember = memberSaveService.saveMember(member); + + // 토큰 생성 + TokenInfoResponse token = tokenUtil.createToken(signInMember, signInMember.getRegistrationStatus().equals(RegistrationStatus.COMPLETED)); + log.info("{}", token); + + // Redis에 Refresh Token 저장 + tokenUtil.storeRefreshToken(signInMember.getSocialId(), token); + + // Response message 생성 + writeOauthResponse(response, SignInResponse.from(token, signInMember.getRegistrationStatus())); + } + + private void writeOauthResponse(HttpServletResponse response, SignInResponse signInResponse) + throws IOException { + + response.setContentType("application/json;charset=UTF-8"); + + // Httpbody에 json 형태로 로그인 내용 추가 + var writer = response.getWriter(); + writer.println(objectMapper.writeValueAsString(signInResponse)); + writer.flush(); + } + +} + diff --git a/src/main/java/com/moing/backend/global/config/security/util/AuthenticationUtil.java b/src/main/java/com/moing/backend/global/config/security/util/AuthenticationUtil.java new file mode 100644 index 00000000..bc7f91c2 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/security/util/AuthenticationUtil.java @@ -0,0 +1,56 @@ +package com.moing.backend.global.config.security.util; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.global.config.security.dto.User; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@Component +public class AuthenticationUtil { + + + public static String getCurrentUserEmail() { + User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + return user.getEmail(); + } + + public static String getCurrentUserSocialId() { + User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + return user.getSocialId(); + } + + public static Authentication getAuthentication(User user) { + + List grantedAuthorities = user.getRoles().stream() + .map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + + return new UsernamePasswordAuthenticationToken(user, "", + grantedAuthorities); + } + + public static void makeAuthentication(Member member) { + // Authentication 정보 만들기 + User user = User.builder() + .socialId(member.getSocialId()) + .email(member.getEmail()) + .roles(Arrays.asList(member.getRole().getKey())) + .build(); + + // ContextHolder 에 Authentication 정보 저장 + Authentication auth = AuthenticationUtil.getAuthentication(user); + SecurityContextHolder.getContext().setAuthentication(auth); + } +} + + diff --git a/src/main/java/com/moing/backend/global/config/webclient/WebClientConfig.java b/src/main/java/com/moing/backend/global/config/webclient/WebClientConfig.java new file mode 100644 index 00000000..b757600f --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/webclient/WebClientConfig.java @@ -0,0 +1,77 @@ +package com.moing.backend.global.config.webclient; + +import io.netty.channel.ChannelOption; +import io.netty.handler.timeout.ReadTimeoutHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.http.codec.LoggingCodecSupport; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.client.ExchangeStrategies; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClient; +import reactor.netty.tcp.TcpClient; + +import java.util.concurrent.TimeUnit; + +@Configuration +@Slf4j +public class WebClientConfig { + + @Bean + public WebClient webClient() { + ExchangeStrategies exchangeStrategies = configureExchangeStrategies(); + HttpClient httpClient = configureHttpClient(); + + return WebClient.builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .exchangeStrategies(exchangeStrategies) + .filter(logRequest()) + .filter(logResponse()) + .defaultHeader("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.3") + .build(); + } + + private ExchangeStrategies configureExchangeStrategies() { + ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() + .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024 * 1024 * 50)) + .build(); + enableLoggingRequestDetails(exchangeStrategies); + return exchangeStrategies; + } + + private void enableLoggingRequestDetails(ExchangeStrategies strategies) { + strategies.messageWriters().stream() + .filter(LoggingCodecSupport.class::isInstance) + .forEach(writer -> ((LoggingCodecSupport) writer).setEnableLoggingRequestDetails(true)); + } + + private HttpClient configureHttpClient() { + return HttpClient.from( + TcpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) + .doOnConnected(conn -> conn.addHandler(new ReadTimeoutHandler(3000, TimeUnit.MILLISECONDS))) + ); + } + + private ExchangeFilterFunction logRequest() { + return ExchangeFilterFunction.ofRequestProcessor( + clientRequest -> { + log.debug("Request: {} {}", clientRequest.method(), clientRequest.url()); + clientRequest.headers().forEach((name, values) -> values.forEach(value -> log.debug("{} : {}", name, value))); + return Mono.just(clientRequest); + } + ); + } + + private ExchangeFilterFunction logResponse() { + return ExchangeFilterFunction.ofResponseProcessor( + clientResponse -> { + clientResponse.headers().asHttpHeaders().forEach((name, values) -> values.forEach(value -> log.debug("{} : {}", name, value))); + return Mono.just(clientResponse); + } + ); + } +} diff --git a/src/main/java/com/moing/backend/global/config/exception/ApplicationException.java b/src/main/java/com/moing/backend/global/exception/ApplicationException.java similarity index 74% rename from src/main/java/com/moing/backend/global/config/exception/ApplicationException.java rename to src/main/java/com/moing/backend/global/exception/ApplicationException.java index af382e42..48b1b728 100644 --- a/src/main/java/com/moing/backend/global/config/exception/ApplicationException.java +++ b/src/main/java/com/moing/backend/global/exception/ApplicationException.java @@ -1,6 +1,6 @@ -package com.moing.backend.global.config.exception; +package com.moing.backend.global.exception; -import com.moing.backend.global.config.response.ErrorCode; +import com.moing.backend.global.response.ErrorCode; import org.springframework.http.HttpStatus; public abstract class ApplicationException extends RuntimeException { @@ -8,8 +8,7 @@ public abstract class ApplicationException extends RuntimeException { private final ErrorCode errorCode; private final HttpStatus httpStatus; - protected ApplicationException(ErrorCode errorCode, HttpStatus httpStatus, String message) { - super(message); + protected ApplicationException(ErrorCode errorCode, HttpStatus httpStatus) { this.errorCode = errorCode; this.httpStatus = httpStatus; } diff --git a/src/main/java/com/moing/backend/global/config/exception/GlobalExceptionHandler.java b/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java similarity index 93% rename from src/main/java/com/moing/backend/global/config/exception/GlobalExceptionHandler.java rename to src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java index cedd87f0..7eb7fa2e 100644 --- a/src/main/java/com/moing/backend/global/config/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java @@ -1,7 +1,7 @@ -package com.moing.backend.global.config.exception; +package com.moing.backend.global.exception; -import com.moing.backend.global.config.response.ErrorCode; -import com.moing.backend.global.config.response.ErrorResponse; +import com.moing.backend.global.response.ErrorCode; +import com.moing.backend.global.response.ErrorResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -51,7 +51,7 @@ public ResponseEntity internalServerErrorHandler(Exception ex) { private ResponseEntity handleException(Exception ex, ErrorCode errorCode, String message, HttpStatus httpStatus, Consumer logger) { logger.accept(String.format(LOG_FORMAT, ex.getClass().getSimpleName(), errorCode.getErrorCode(), ex.getMessage())); - ErrorResponse errorResponse = new ErrorResponse(errorCode.getErrorCode(), message); + ErrorResponse errorResponse = new ErrorResponse(errorCode); return ResponseEntity.status(httpStatus.value()).body(errorResponse); } diff --git a/src/main/java/com/moing/backend/global/exception/InternalServerErrorException.java b/src/main/java/com/moing/backend/global/exception/InternalServerErrorException.java new file mode 100644 index 00000000..47916666 --- /dev/null +++ b/src/main/java/com/moing/backend/global/exception/InternalServerErrorException.java @@ -0,0 +1,6 @@ +package com.moing.backend.global.exception; + +public class InternalServerErrorException extends RuntimeException{ + + public InternalServerErrorException(String message){ super(message); } +} diff --git a/src/main/java/com/moing/backend/global/interceptor/AuthInterceptor.java b/src/main/java/com/moing/backend/global/interceptor/AuthInterceptor.java new file mode 100644 index 00000000..ae0e1cc2 --- /dev/null +++ b/src/main/java/com/moing/backend/global/interceptor/AuthInterceptor.java @@ -0,0 +1,35 @@ +package com.moing.backend.global.interceptor; + +import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.global.config.security.dto.User; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Slf4j +@RequiredArgsConstructor +@Component +public class AuthInterceptor implements HandlerInterceptor { + + private final MemberQueryService memberQueryService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null && authentication.isAuthenticated()) { + User user = (User) authentication.getPrincipal(); + String socialId = user.getSocialId(); + + // socialId 를 갖는 사용자 존재 여부 + memberQueryService.getMemberBySocialId(socialId); + } + return true; + } +} + diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java new file mode 100644 index 00000000..c95683bd --- /dev/null +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -0,0 +1,24 @@ +package com.moing.backend.global.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum ErrorCode { + + BAD_REQUEST("400", "올바른 패턴을 입력하세요."), + METHOD_NOT_ALLOWED("405", "클라이언트가 사용한 HTTP 메서드가 리소스에서 허용되지 않습니다."), + INTERNAL_SERVER_ERROR("500", "서버에서 요청을 처리하는 동안 오류가 발생했습니다."), + + //유저 관련 에러 코드 + NOT_FOUND_BY_SOCIAL_ID_ERROR( "U0001", "해당 socialId인 유저가 존재하지 않습니다."), + NOT_FOUND_REFRESH_TOKEN_ERROR( "J0008", "유효하지 않는 RefreshToken 입니다."), + ACCOUNT_ALREADY_EXIST("AU0001", "이미 다른 소셜 플랫폼으로 가입하였습니다."), + TOKEN_INVALID_ERROR("AU0002", "입력 토큰이 유효하지 않습니다."), + APPID_INVALID_ERROR("AU0003", "appId가 유효하지 않습니다"); + private String errorCode; + private String message; + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/response/ErrorResponse.java b/src/main/java/com/moing/backend/global/response/ErrorResponse.java similarity index 60% rename from src/main/java/com/moing/backend/global/config/response/ErrorResponse.java rename to src/main/java/com/moing/backend/global/response/ErrorResponse.java index ce1f9c87..7705f7b4 100644 --- a/src/main/java/com/moing/backend/global/config/response/ErrorResponse.java +++ b/src/main/java/com/moing/backend/global/response/ErrorResponse.java @@ -1,4 +1,4 @@ -package com.moing.backend.global.config.response; +package com.moing.backend.global.response; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -7,7 +7,7 @@ @Getter @RequiredArgsConstructor -public class ErrorResponse { +public class ErrorResponse { private Boolean isSuccess; private LocalDateTime timeStamp; private String errorCode; @@ -19,4 +19,11 @@ public ErrorResponse(String errorCode, String message) { this.errorCode = errorCode; this.message = message; } + + public ErrorResponse(ErrorCode errorCode) { + this.isSuccess=false; + this.timeStamp = LocalDateTime.now().withNano(0); + this.errorCode=errorCode.getErrorCode(); + this.message=errorCode.getMessage(); + } } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/response/SuccessResponse.java b/src/main/java/com/moing/backend/global/response/SuccessResponse.java similarity index 92% rename from src/main/java/com/moing/backend/global/config/response/SuccessResponse.java rename to src/main/java/com/moing/backend/global/response/SuccessResponse.java index 7f8609e0..2b787b9d 100644 --- a/src/main/java/com/moing/backend/global/config/response/SuccessResponse.java +++ b/src/main/java/com/moing/backend/global/response/SuccessResponse.java @@ -1,4 +1,4 @@ -package com.moing.backend.global.config.response; +package com.moing.backend.global.response; import com.fasterxml.jackson.annotation.JsonInclude; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/moing/backend/global/response/TokenInfoResponse.java b/src/main/java/com/moing/backend/global/response/TokenInfoResponse.java new file mode 100644 index 00000000..d0edd5a8 --- /dev/null +++ b/src/main/java/com/moing/backend/global/response/TokenInfoResponse.java @@ -0,0 +1,29 @@ +package com.moing.backend.global.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +@AllArgsConstructor +public class TokenInfoResponse { + private String grantType; + private String accessToken; + private String refreshToken; + private Long refreshTokenExpirationTime; + + public static TokenInfoResponse from(String grantType, String accessToken, String refreshToken, Long refreshTokenExpirationTime) { + return TokenInfoResponse.builder() + .grantType(grantType) + .accessToken(accessToken) + .refreshToken(refreshToken) + .refreshTokenExpirationTime(refreshTokenExpirationTime) + .build(); + } + + public void updateRefreshToken(String refreshToken){ + this.refreshToken=refreshToken; + } +} + diff --git a/src/main/java/com/moing/backend/global/util/AesConverter.java b/src/main/java/com/moing/backend/global/util/AesConverter.java new file mode 100644 index 00000000..5da9aa0c --- /dev/null +++ b/src/main/java/com/moing/backend/global/util/AesConverter.java @@ -0,0 +1,31 @@ +package com.moing.backend.global.util; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; + +@Converter +public class AesConverter implements AttributeConverter { + private final AesUtil aesUtil; + + public AesConverter(AesUtil aesUtil) { + this.aesUtil = aesUtil; + } + + @Override + public String convertToDatabaseColumn(String attribute) { + try { + return aesUtil.encrypt(attribute); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to encrypt attribute", e); + } + } + + @Override + public String convertToEntityAttribute(String dbData) { + try { + return aesUtil.decrypt(dbData); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to decrypt dbData", e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/util/AesUtil.java b/src/main/java/com/moing/backend/global/util/AesUtil.java index a003a0bd..7ada8b89 100644 --- a/src/main/java/com/moing/backend/global/util/AesUtil.java +++ b/src/main/java/com/moing/backend/global/util/AesUtil.java @@ -7,24 +7,26 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.Base64; @Component public class AesUtil { - private final SecretKeySpec secretKeySpec; - private final IvParameterSpec ivParameterSpec; + private final String key; + private final String alg; + private final String iv; public AesUtil(@Value("${aes.secret.key}") String key, @Value("${aes.secret.alg}") String alg) { - this.secretKeySpec = createSecretKeySpec(key, alg); - this.ivParameterSpec = createIvParameterSpec(key); + this.key = key; + this.alg = alg; + this.iv = key.substring(0, 16); } public String encrypt(String text) { try { - Cipher cipher = Cipher.getInstance(secretKeySpec.getAlgorithm()); - cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); + Cipher cipher = Cipher.getInstance(alg); + SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"); + IvParameterSpec ivParamSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8)); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParamSpec); byte[] encrypted = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encrypted); } catch (Exception e) { @@ -34,8 +36,11 @@ public String encrypt(String text) { public String decrypt(String cipherText) { try { - Cipher cipher = Cipher.getInstance(secretKeySpec.getAlgorithm()); - cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); + Cipher cipher = Cipher.getInstance(alg); + SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES"); + IvParameterSpec ivParamSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8)); + cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParamSpec); + byte[] decodedBytes = Base64.getDecoder().decode(cipherText); byte[] decrypted = cipher.doFinal(decodedBytes); return new String(decrypted, StandardCharsets.UTF_8); @@ -43,21 +48,4 @@ public String decrypt(String cipherText) { throw new RuntimeException("Failed to decrypt cipherText: " + e.getMessage(), e); } } - - private SecretKeySpec createSecretKeySpec(String key, String alg) { - try { - byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); - MessageDigest sha = MessageDigest.getInstance("SHA-256"); - byte[] hash = sha.digest(keyBytes); - return new SecretKeySpec(hash, alg); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("Failed to create SecretKeySpec: " + e.getMessage(), e); - } - } - - private IvParameterSpec createIvParameterSpec(String key) { - byte[] iv = key.substring(0, 16).getBytes(StandardCharsets.UTF_8); - return new IvParameterSpec(iv); - } } - diff --git a/src/main/java/com/moing/backend/global/util/SecurityUtils.java b/src/main/java/com/moing/backend/global/util/SecurityUtils.java new file mode 100644 index 00000000..8c9620ad --- /dev/null +++ b/src/main/java/com/moing/backend/global/util/SecurityUtils.java @@ -0,0 +1,25 @@ +package com.moing.backend.global.util; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.global.config.security.oauth.CustomUserDetails; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Objects; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Transactional +public class SecurityUtils { + + public static Member getLoggedInUser() { + try { + return + ((CustomUserDetails) Objects.requireNonNull(SecurityContextHolder.getContext().getAuthentication()).getPrincipal()).getMember(); + } catch (NullPointerException e) { + throw new RuntimeException(); + } + } + +} diff --git a/src/main/resources/static/docs/Auth-API.html b/src/main/resources/static/docs/Auth-API.html new file mode 100644 index 00000000..50fa9972 --- /dev/null +++ b/src/main/resources/static/docs/Auth-API.html @@ -0,0 +1,1166 @@ + + + + + + + +Auth API + + + + +

+
+
+

Auth API

+
+
+

Auth Kakao 소셜 로그인 회원가입 전

+
+

HTTP request

+
+
+
POST /auth/signIn/kakao HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 36
+Host: localhost:8080
+
+{
+  "token" : "KAKAO_ACCESS_TOKEN"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

token

String

카카오 액세스 토큰

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 206
+
+{
+  "isSuccess" : true,
+  "message" : "로그인을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : false
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

로그인을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 : false

+
+
+
+

Auth Kakao 소셜 로그인 회원가입 후

+
+

HTTP request

+
+
+
POST /auth/signIn/kakao HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 36
+Host: localhost:8080
+
+{
+  "token" : "KAKAO_ACCESS_TOKEN"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

token

String

카카오 액세스 토큰

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 205
+
+{
+  "isSuccess" : true,
+  "message" : "로그인을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : true
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

로그인을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 :true

+
+
+
+
+

Auth Apple 소셜 로그인 회원가입 전

+
+

HTTP request

+
+
+
POST /auth/signIn/apple HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 38
+Host: localhost:8080
+
+{
+  "token" : "APPLE_IDENTITY_TOKEN"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

token

String

애플 아이디 토큰

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 206
+
+{
+  "isSuccess" : true,
+  "message" : "로그인을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : false
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

로그인을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 :false

+
+
+
+

Auth Apple 소셜 로그인 회원가입 후

+
+

HTTP request

+
+
+
POST /auth/signIn/apple HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 38
+Host: localhost:8080
+
+{
+  "token" : "APPLE_IDENTITY_TOKEN"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

token

String

애플 아이디 토큰

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 205
+
+{
+  "isSuccess" : true,
+  "message" : "로그인을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : true
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

로그인을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 :true

+
+
+
+

Auth 회원가입

+
+

HTTP request

+
+
+
PUT /auth/signUp HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: ACCESS_TOKEN
+Content-Length: 29
+Host: localhost:8080
+
+{
+  "nickName" : "NICKNAME"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

nickName

String

유저 닉네임

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 209
+
+{
+  "isSuccess" : true,
+  "message" : "회원 가입을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : true
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

회원 가입을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 : true

+
+
+
+

Auth 회원가입

+
+

HTTP request

+
+
+
PUT /auth/signUp HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: ACCESS_TOKEN
+Content-Length: 29
+Host: localhost:8080
+
+{
+  "nickName" : "NICKNAME"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

nickName

String

유저 닉네임

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 209
+
+{
+  "isSuccess" : true,
+  "message" : "회원 가입을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : true
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

회원 가입을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 : true

+
+
+
+

Auth 토큰 재발급

+
+

HTTP request

+
+
+
GET /auth/reissue HTTP/1.1
+RefreshToken: REFRESH_TOKEN
+Host: localhost:8080
+
+
+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 178
+
+{
+  "isSuccess" : true,
+  "message" : "토큰을 재발급했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN"
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

성공 여부 : true

message

String

토큰을 재발급했습니다

data.accessToken

String

서버 접근용 Token

data.refreshToken

String

서버 접근용 Refresh Token

+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/Overview.html b/src/main/resources/static/docs/Overview.html new file mode 100644 index 00000000..3b68948b --- /dev/null +++ b/src/main/resources/static/docs/Overview.html @@ -0,0 +1,591 @@ + + + + + + + +ErrorCode + + + + + +
+
+

ErrorCode

+
+
+

Error Response DTO

+ ++++++ + + + + + + + + +

isSuccess(Boolean)

timeStamp(LocalDateTime)

errorCode(String)

message(String)

+
+
+

Common ErrorCode

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ErrorCodeScopeDescription

400

전체

요청 형식 자체가 틀리거나 권한이 없음

403

전체

접근 권한이 존재하지 않음 (로그인 안한 경우)

405

전체

HTTP 메서드가 리소스에서 허용되지 않음

500

전체

서버오류

J0001

전체

예상치 못한 오류

J0002

전체

잘못된 JWT 서명

J0003

전체

만료된 토큰

J0004

전체

지원되지 않는 토큰

J0005

전체

접근이 거부됨

J0006

전체

토큰이 잘못됨

J0007

전체

추가 정보 입력 (닉네임) 안함

J0008

재발급 시

유효하지 않은 refresh Token

+
+
+

User / Auth ErrorCode

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

ErrorCode

Scope

Description

U0001

전체

해당 유저 존재하지 않음

AU0001

로그인할 때

이미 다른 소셜 플랫폼으로 가입함

AU0002

로그인할 때

입력 토큰이 유효하지 않음

AU0003

로그인할 때

appId가 일치하지 않음 (유효하지 않음)

+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html new file mode 100644 index 00000000..0738e9d2 --- /dev/null +++ b/src/main/resources/static/docs/api.html @@ -0,0 +1,1337 @@ + + + + + + + +Moing API Doc + + + + + + +
+
+

ErrorCode

+
+
+

Error Response DTO

+ ++++++ + + + + + + + + +

isSuccess(Boolean)

timeStamp(LocalDateTime)

errorCode(String)

message(String)

+
+
+

Common ErrorCode

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ErrorCodeScopeDescription

400

전체

요청 형식 자체가 틀리거나 권한이 없음

403

전체

접근 권한이 존재하지 않음 (로그인 안한 경우)

405

전체

HTTP 메서드가 리소스에서 허용되지 않음

500

전체

서버오류

J0001

전체

예상치 못한 오류

J0002

전체

잘못된 JWT 서명

J0003

전체

만료된 토큰

J0004

전체

지원되지 않는 토큰

J0005

전체

접근이 거부됨

J0006

전체

토큰이 잘못됨

J0007

전체

추가 정보 입력 (닉네임) 안함

J0008

재발급 시

유효하지 않은 refresh Token

+
+
+

User / Auth ErrorCode

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

ErrorCode

Scope

Description

U0001

전체

해당 유저 존재하지 않음

AU0001

로그인할 때

이미 다른 소셜 플랫폼으로 가입함

AU0002

로그인할 때

입력 토큰이 유효하지 않음

AU0003

로그인할 때

appId가 일치하지 않음 (유효하지 않음)

+
+
+
+
+

Auth API

+
+
+

Auth Kakao 소셜 로그인 회원가입 전

+
+

HTTP request

+
+
+
POST /auth/signIn/kakao HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 36
+Host: localhost:8080
+
+{
+  "token" : "KAKAO_ACCESS_TOKEN"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

token

String

카카오 액세스 토큰

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 206
+
+{
+  "isSuccess" : true,
+  "message" : "로그인을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : false
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

로그인을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 : false

+
+
+
+

Auth Kakao 소셜 로그인 회원가입 후

+
+

HTTP request

+
+
+
POST /auth/signIn/kakao HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 36
+Host: localhost:8080
+
+{
+  "token" : "KAKAO_ACCESS_TOKEN"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

token

String

카카오 액세스 토큰

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 205
+
+{
+  "isSuccess" : true,
+  "message" : "로그인을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : true
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

로그인을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 :true

+
+
+
+
+

Auth Apple 소셜 로그인 회원가입 전

+
+

HTTP request

+
+
+
POST /auth/signIn/apple HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 38
+Host: localhost:8080
+
+{
+  "token" : "APPLE_IDENTITY_TOKEN"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

token

String

애플 아이디 토큰

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 206
+
+{
+  "isSuccess" : true,
+  "message" : "로그인을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : false
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

로그인을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 :false

+
+
+
+

Auth Apple 소셜 로그인 회원가입 후

+
+

HTTP request

+
+
+
POST /auth/signIn/apple HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Content-Length: 38
+Host: localhost:8080
+
+{
+  "token" : "APPLE_IDENTITY_TOKEN"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

token

String

애플 아이디 토큰

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 205
+
+{
+  "isSuccess" : true,
+  "message" : "로그인을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : true
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

로그인을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 :true

+
+
+
+

Auth 회원가입

+
+

HTTP request

+
+
+
PUT /auth/signUp HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: ACCESS_TOKEN
+Content-Length: 29
+Host: localhost:8080
+
+{
+  "nickName" : "NICKNAME"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

nickName

String

유저 닉네임

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 209
+
+{
+  "isSuccess" : true,
+  "message" : "회원 가입을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : true
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

회원 가입을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 : true

+
+
+
+

Auth 회원가입

+
+

HTTP request

+
+
+
PUT /auth/signUp HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Authorization: ACCESS_TOKEN
+Content-Length: 29
+Host: localhost:8080
+
+{
+  "nickName" : "NICKNAME"
+}
+
+
+
+
+

Request fields

+ +++++ + + + + + + + + + + + + + + +
PathTypeDescription

nickName

String

유저 닉네임

+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 209
+
+{
+  "isSuccess" : true,
+  "message" : "회원 가입을 했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN",
+    "registrationStatus" : true
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

true

message

String

회원 가입을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

data.registrationStatus

Boolean

회원가입 여부 : true

+
+
+
+

Auth 토큰 재발급

+
+

HTTP request

+
+
+
GET /auth/reissue HTTP/1.1
+RefreshToken: REFRESH_TOKEN
+Host: localhost:8080
+
+
+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
+Content-Type: application/json;charset=UTF-8
+Content-Length: 178
+
+{
+  "isSuccess" : true,
+  "message" : "토큰을 재발급했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN"
+  }
+}
+
+
+
+
+

Response fields

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PathTypeDescription

isSuccess

Boolean

성공 여부 : true

message

String

토큰을 재발급했습니다

data.accessToken

String

서버 접근용 Token

data.refreshToken

String

서버 접근용 Refresh Token

+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/src/test/java/com/moing/backend/BackendApplicationTests.java b/src/test/java/com/moing/backend/BackendApplicationTests.java index 9a6d1dd7..0170d440 100644 --- a/src/test/java/com/moing/backend/BackendApplicationTests.java +++ b/src/test/java/com/moing/backend/BackendApplicationTests.java @@ -3,7 +3,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -@SpringBootTest +//@SpringBootTest class BackendApplicationTests { @Test diff --git a/src/test/java/com/moing/backend/config/CommonControllerTest.java b/src/test/java/com/moing/backend/config/CommonControllerTest.java new file mode 100644 index 00000000..49387fc7 --- /dev/null +++ b/src/test/java/com/moing/backend/config/CommonControllerTest.java @@ -0,0 +1,80 @@ +package com.moing.backend.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.moing.backend.domain.member.domain.constant.Role; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.global.config.security.filter.JwtAccessDeniedHandler; +import com.moing.backend.global.config.security.filter.JwtAuthenticationEntryPoint; +import com.moing.backend.global.config.security.jwt.TokenUtil; +import com.moing.backend.global.config.security.util.AuthenticationUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; +import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.restdocs.RestDocumentationExtension; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.filter.CharacterEncodingFilter; + +@AutoConfigureRestDocs +@Import(RestDocsConfig.class) +@MockBean(JpaMetamodelMappingContext.class) +@ExtendWith({RestDocumentationExtension.class, SpringExtension.class}) +public class CommonControllerTest { + @Autowired + protected RestDocumentationResultHandler restDocs; + + @Autowired + protected MockMvc mockMvc; + + @Autowired + protected ObjectMapper objectMapper; + + @MockBean + public TokenUtil tokenUtil; + + @MockBean + public JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; + + @MockBean + public ClientRegistrationRepository clientRegistrationRepository; + + @MockBean + public JwtAccessDeniedHandler jwtAccessDeniedHandler; + + @MockBean + public MemberQueryService memberQueryService; + + @BeforeEach + public void setUp(final WebApplicationContext context, final RestDocumentationContextProvider provider) throws Exception { + + Member member = Member.builder() + .memberId(1L) + .email("test@test.com") + .role(Role.USER) + .socialId("KAKAO@123") + .build(); + + // user.getSocialId() 에서 NullPointerException 방지를 위한 Authentication 생성 + AuthenticationUtil.makeAuthentication(member); + + this.mockMvc = MockMvcBuilders.webAppContextSetup(context) + .apply(MockMvcRestDocumentation.documentationConfiguration(provider)) // rest docs 설정 주입 + .alwaysDo(MockMvcResultHandlers.print()) // andDo(print()) 코드 포함 + .alwaysDo(restDocs) // pretty 패턴과 문서 디렉토리 명 정해준것 적용 + .addFilters(new CharacterEncodingFilter("UTF-8", true)) // 한글 깨짐 방지 + .build(); + } +} + diff --git a/src/test/java/com/moing/backend/config/RestDocsConfig.java b/src/test/java/com/moing/backend/config/RestDocsConfig.java new file mode 100644 index 00000000..3fb4a9f1 --- /dev/null +++ b/src/test/java/com/moing/backend/config/RestDocsConfig.java @@ -0,0 +1,19 @@ +package com.moing.backend.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.operation.preprocess.Preprocessors; + +@TestConfiguration +public class RestDocsConfig { + @Bean + public RestDocumentationResultHandler write(){ + return MockMvcRestDocumentation.document( + "{class-name}/{method-name}", + Preprocessors.preprocessRequest(Preprocessors.prettyPrint()), + Preprocessors.preprocessResponse(Preprocessors.prettyPrint()) + ); + } +} diff --git a/src/test/java/com/moing/backend/domain/auth/representation/AuthControllerTest.java b/src/test/java/com/moing/backend/domain/auth/representation/AuthControllerTest.java new file mode 100644 index 00000000..b809e13e --- /dev/null +++ b/src/test/java/com/moing/backend/domain/auth/representation/AuthControllerTest.java @@ -0,0 +1,293 @@ +package com.moing.backend.domain.auth.representation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.auth.application.dto.request.SignInRequest; +import com.moing.backend.domain.auth.application.dto.request.SignUpRequest; +import com.moing.backend.domain.auth.application.dto.response.ReissueTokenResponse; +import com.moing.backend.domain.auth.application.dto.response.SignInResponse; +import com.moing.backend.domain.auth.application.service.ReissueTokenUserCase; +import com.moing.backend.domain.auth.application.service.SignInUserCase; +import com.moing.backend.domain.auth.application.service.SignUpUserCase; +import com.moing.backend.domain.auth.presentation.AuthController; +import com.moing.backend.global.response.TokenInfoResponse; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.ResultActions; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(AuthController.class) +class AuthControllerTest extends CommonControllerTest { + + @MockBean + private SignInUserCase authService; + + @MockBean + private SignUpUserCase signUpUserCase; + + @MockBean + private ReissueTokenUserCase reissueTokenUserCase; + + @Test + public void Kakao_소셜_로그인_회원가입_전() throws Exception { + //given + SignInRequest input = SignInRequest.builder() + .token("KAKAO_ACCESS_TOKEN") + .build(); + + String body = objectMapper.writeValueAsString(input); + + SignInResponse output = SignInResponse.builder() + .accessToken("SERVER_ACCESS_TOKEN") + .refreshToken("SERVER_REFRESH_TOKEN") + .registrationStatus(false) + .build(); + + given(authService.signIn(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + post("/auth/signIn/kakao") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestFields( + fieldWithPath("token").description("카카오 액세스 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("로그인을 했습니다"), + fieldWithPath("data.accessToken").description("서버 접근용 Access Token"), + fieldWithPath("data.refreshToken").description("서버 접근용 Refresh Token"), + fieldWithPath("data.registrationStatus").description("회원가입 여부 : false") + ) + ) + ); + } + + @Test + public void Kakao_소셜_로그인_회원가입_후() throws Exception { + //given + SignInRequest input = SignInRequest.builder() + .token("KAKAO_ACCESS_TOKEN") + .build(); + + String body = objectMapper.writeValueAsString(input); + + SignInResponse output = SignInResponse.builder() + .accessToken("SERVER_ACCESS_TOKEN") + .refreshToken("SERVER_REFRESH_TOKEN") + .registrationStatus(true) + .build(); + + given(authService.signIn(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + post("/auth/signIn/kakao") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestFields( + fieldWithPath("token").description("카카오 액세스 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("로그인을 했습니다"), + fieldWithPath("data.accessToken").description("서버 접근용 Access Token"), + fieldWithPath("data.refreshToken").description("서버 접근용 Refresh Token"), + fieldWithPath("data.registrationStatus").description("회원가입 여부 :true") + ) + ) + ); + } + + @Test + public void Apple_소셜_로그인_회원가입_전() throws Exception { + //given + SignInRequest input = SignInRequest.builder() + .token("APPLE_IDENTITY_TOKEN") + .build(); + + String body = objectMapper.writeValueAsString(input); + + SignInResponse output = SignInResponse.builder() + .accessToken("SERVER_ACCESS_TOKEN") + .refreshToken("SERVER_REFRESH_TOKEN") + .registrationStatus(false) + .build(); + + given(authService.signIn(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + post("/auth/signIn/apple") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestFields( + fieldWithPath("token").description("애플 아이디 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("로그인을 했습니다"), + fieldWithPath("data.accessToken").description("서버 접근용 Access Token"), + fieldWithPath("data.refreshToken").description("서버 접근용 Refresh Token"), + fieldWithPath("data.registrationStatus").description("회원가입 여부 :false") + ) + ) + ); + } + + @Test + public void Apple_소셜_로그인_회원가입_후() throws Exception { + //given + SignInRequest input = SignInRequest.builder() + .token("APPLE_IDENTITY_TOKEN") + .build(); + + String body = objectMapper.writeValueAsString(input); + + SignInResponse output = SignInResponse.builder() + .accessToken("SERVER_ACCESS_TOKEN") + .refreshToken("SERVER_REFRESH_TOKEN") + .registrationStatus(true) + .build(); + + given(authService.signIn(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + post("/auth/signIn/apple") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestFields( + fieldWithPath("token").description("애플 아이디 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("로그인을 했습니다"), + fieldWithPath("data.accessToken").description("서버 접근용 Access Token"), + fieldWithPath("data.refreshToken").description("서버 접근용 Refresh Token"), + fieldWithPath("data.registrationStatus").description("회원가입 여부 :true") + ) + ) + ); + } + + + @Test + public void sign_up() throws Exception { + //given + SignUpRequest input = SignUpRequest.builder() + .nickName("NICKNAME") + .build(); + + String body = objectMapper.writeValueAsString(input); + + SignInResponse output = SignInResponse.builder() + .accessToken("SERVER_ACCESS_TOKEN") + .refreshToken("SERVER_REFRESH_TOKEN") + .registrationStatus(true) + .build(); + + + given(signUpUserCase.signUp(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + put("/auth/signUp") + .header("Authorization","ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestFields( + fieldWithPath("nickName").description("유저 닉네임") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("회원 가입을 했습니다"), + fieldWithPath("data.accessToken").description("서버 접근용 Access Token"), + fieldWithPath("data.refreshToken").description("서버 접근용 Refresh Token"), + fieldWithPath("data.registrationStatus").description("회원가입 여부 : true") + ) + ) + ); + } + + @Test + public void reissue_token() throws Exception { + //given + ReissueTokenResponse output = ReissueTokenResponse.builder() + .accessToken("SERVER_ACCESS_TOKEN") + .refreshToken("SERVER_REFRESH_TOKEN") + .build(); + + given(reissueTokenUserCase.reissueToken(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + get("/auth/reissue") + .header("RefreshToken", "REFRESH_TOKEN") + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("RefreshToken").description("토큰 재발급용 RefreshToken") + ), + responseFields( + fieldWithPath("isSuccess").description("성공 여부 : true"), + fieldWithPath("message").description("토큰을 재발급했습니다"), + fieldWithPath("data.accessToken").description("서버 접근용 Token"), + fieldWithPath("data.refreshToken").description("서버 접근용 Refresh Token") + ) + ) + ); + } + + +} \ No newline at end of file From ebc08536d6a58ce8ec86716c3788913b9a11eb26 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Tue, 8 Aug 2023 05:33:01 +0900 Subject: [PATCH 005/619] =?UTF-8?q?fix:=20=EC=A0=84=EB=9E=B5=20=ED=8C=A8?= =?UTF-8?q?=ED=84=B4=20=EC=9D=B4=EC=9A=A9=ED=95=B4=EC=84=9C=20OCP=20?= =?UTF-8?q?=EC=A4=80=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/service/SignInProvider.java | 7 +++++++ .../auth/application/service/SignInUserCase.java | 13 +++++++------ .../service/apple/AppleSignInUserCase.java | 6 ++++-- .../service/kakao/KakaoSignInUserCase.java | 5 +++-- .../auth/exception/UnknownProviderException.java | 4 ++++ .../member/domain/service/MemberSaveService.java | 7 +++++-- 6 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/SignInProvider.java create mode 100644 src/main/java/com/moing/backend/domain/auth/exception/UnknownProviderException.java diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignInProvider.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignInProvider.java new file mode 100644 index 00000000..7b56a977 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignInProvider.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.auth.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; + +public interface SignInProvider { + Member getUserData(String accessToken); +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java index 8c4491bd..5b001b27 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java @@ -1,8 +1,6 @@ package com.moing.backend.domain.auth.application.service; import com.moing.backend.domain.auth.application.dto.response.SignInResponse; -import com.moing.backend.domain.auth.application.service.apple.AppleSignInUserCase; -import com.moing.backend.domain.auth.application.service.kakao.KakaoSignInUserCase; import com.moing.backend.domain.member.domain.constant.RegistrationStatus; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.global.config.security.jwt.TokenUtil; @@ -12,6 +10,7 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.util.Map; @Service @Transactional @@ -20,8 +19,7 @@ public class SignInUserCase { private final MemberAuthUserCase internalAuthService; private final TokenUtil tokenUtil; - private final KakaoSignInUserCase kakaoSignInUserCase; - private final AppleSignInUserCase appleSignInUserCase; + private final Map signInProviders; public SignInResponse signIn(String token, String providerInfo) { //1. 사용자 정보 가져오기 @@ -39,7 +37,10 @@ public SignInResponse signIn(String token, String providerInfo) { } private Member getUserDataFromPlatform(String accessToken, String providerInfo) { - if (providerInfo.contains("kakao")) return kakaoSignInUserCase.getUserData(accessToken); - else return appleSignInUserCase.getUserData(accessToken); + SignInProvider signInProvider = signInProviders.get(providerInfo); + if (signInProvider == null) { + throw new IllegalArgumentException("Unknown provider: " + providerInfo); + } + return signInProvider.getUserData(accessToken); } } diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java index b22ca1aa..2f512ee2 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.auth.application.service.apple; +import com.moing.backend.domain.auth.application.service.SignInProvider; import com.moing.backend.domain.member.application.mapper.MemberMapper; import com.moing.backend.domain.member.domain.entity.Member; import io.jsonwebtoken.Claims; @@ -7,13 +8,14 @@ import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; -@Service +@Service("apple") @AllArgsConstructor -public class AppleSignInUserCase { +public class AppleSignInUserCase implements SignInProvider { private final AppleTokenUserCase appleTokenUserCase; private final MemberMapper memberMapper; + public Member getUserData(String identityToken) { Jws oidcTokenJws = appleTokenUserCase.sigVerificationAndGetJws(identityToken); diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java index fde2e577..77b163d0 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.auth.application.service.kakao; import com.moing.backend.domain.auth.application.dto.response.KakaoUserResponse; +import com.moing.backend.domain.auth.application.service.SignInProvider; import com.moing.backend.domain.member.application.mapper.MemberMapper; import com.moing.backend.domain.auth.exception.TokenInvalidException; import com.moing.backend.domain.member.domain.entity.Member; @@ -11,9 +12,9 @@ import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; -@Service +@Service("kakao") @RequiredArgsConstructor -public class KakaoSignInUserCase { +public class KakaoSignInUserCase implements SignInProvider { private final WebClient webClient; private final MemberMapper memberMapper; diff --git a/src/main/java/com/moing/backend/domain/auth/exception/UnknownProviderException.java b/src/main/java/com/moing/backend/domain/auth/exception/UnknownProviderException.java new file mode 100644 index 00000000..baeec5ac --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/exception/UnknownProviderException.java @@ -0,0 +1,4 @@ +package com.moing.backend.domain.auth.exception; + +public class UnknownProviderException { +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java index 34dc324a..29d42608 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java @@ -6,6 +6,7 @@ import lombok.AllArgsConstructor; import javax.transaction.Transactional; +import java.util.Optional; @DomainService @Transactional @@ -15,9 +16,11 @@ public class MemberSaveService { private final MemberRepository memberRepository; public Member saveMember(Member member) { - if(memberRepository.findBySocialIdNotDeleted(member.getSocialId()).isEmpty()){ + OptionalfindMember=memberRepository.findBySocialIdNotDeleted(member.getSocialId()); + if(findMember.isEmpty()){ return memberRepository.save(member); + } else { + return findMember.get(); } - return memberRepository.findBySocialIdNotDeleted(member.getSocialId()).get(); } } From 8d681f3a2c3c4cd932c6d1c1aaad8418c92659e9 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Fri, 11 Aug 2023 02:27:31 +0900 Subject: [PATCH 006/619] docs: Create Dockerfile --- Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..351dda2c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:11-jdk +ARG JAR_FILE=./build/libs/backend-0.0.1-SNAPSHOT.jar +COPY ${JAR_FILE} app.jar +ENTRYPOINT ["java","-jar","/app.jar"] From 14bf4071924941283bb07d4aa9b87633cebdfd7f Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Fri, 11 Aug 2023 02:47:40 +0900 Subject: [PATCH 007/619] docs: Create ci-cd.yml --- .github/workflows/ci-cd.yml | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 .github/workflows/ci-cd.yml diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml new file mode 100644 index 00000000..5a31d157 --- /dev/null +++ b/.github/workflows/ci-cd.yml @@ -0,0 +1,87 @@ +name: CI/CD + +on: + push: + branches: [ "master" ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + env : + working-directory: ./ + APPLICATION: ${{ secrets.APPLICATION }} + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - uses: actions/checkout@v2 + - run: | + mkdir ./src/main/resources + cd ./src/main/resources + touch ./application.yml + echo "${{env.APPLICATION}}" > ./application.yml + touch ./firebase-key.json + echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.jso + + - uses: actions/upload-artifact@v2 + with: + name: application.yml + path: ./src/main/resources/application.yml + + - uses: actions/upload-artifact@v2 + with: + name: firebase-key.json + path: ./src/main/resources/firebase-key.json + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + working-directory: ${{ env.working-directory }} + + - name: Build with Gradle + run: ./gradlew build + working-directory: ${{ env.working-directory }} + + - name: Cleanup Gradle Cache + if: ${{ always() }} + run: | + rm -f ~/.gradle/caches/modules-2/modules-2.lock + rm -f ~/.gradle/caches/modules-2/gc.properties + + - name: Docker build + run: | + docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} + docker build -t ${{ secrets.DOCKER_USERNAME }}/moing:green . + docker build -t ${{ secrets.DOCKER_USERNAME }}/moing:blue . + docker push ${{ secrets.DOCKER_USERNAME }}/moingt:green + docker push ${{ secrets.DOCKER_USERNAME }}/moing:blue + + - name: Deploy + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.EC2_SERVER_HOST }} + username: ec2-user + key: ${{ secrets.PRIVATE_KEY }} + envs: GITHUB_SHA + script: | + docker pull ${{ secrets.DOCKER_USERNAME }}/moing:green + docker pull ${{ secrets.DOCKER_USERNAME }}/moing:blue + ./deploy.sh From 9ee3895e198f64461d418b46fb51f2b3261fb3bc Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Fri, 11 Aug 2023 02:50:05 +0900 Subject: [PATCH 008/619] docs: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 5a31d157..5c36f626 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -2,7 +2,7 @@ name: CI/CD on: push: - branches: [ "master" ] + branches: [ "main" ] permissions: contents: read From a50d405bdd02917589c5fb85e5e3d2442424e25e Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Fri, 11 Aug 2023 02:51:32 +0900 Subject: [PATCH 009/619] docs: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 5c36f626..cabac015 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -35,7 +35,6 @@ jobs: - uses: actions/checkout@v2 - run: | - mkdir ./src/main/resources cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml From 4f8eff9ba1f72b1a65fadb46b0acb9c983da97cf Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Fri, 11 Aug 2023 02:54:31 +0900 Subject: [PATCH 010/619] docs: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index cabac015..9d583a77 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -70,7 +70,7 @@ jobs: docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} docker build -t ${{ secrets.DOCKER_USERNAME }}/moing:green . docker build -t ${{ secrets.DOCKER_USERNAME }}/moing:blue . - docker push ${{ secrets.DOCKER_USERNAME }}/moingt:green + docker push ${{ secrets.DOCKER_USERNAME }}/moing:green docker push ${{ secrets.DOCKER_USERNAME }}/moing:blue - name: Deploy From fb6c1bc4d79e42b8f5db46fb2e774c7b7e46082a Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Fri, 11 Aug 2023 13:23:09 +0900 Subject: [PATCH 011/619] dcos: Create deploy.sh --- deploy.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 deploy.sh diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 00000000..8db595a0 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,44 @@ +DOCKER_APP_NAME=meetup +DOCKER_USERNAME=modagbul + +# 현재 실행 중인 컨테이너를 확인 (blue 또는 green) +EXIST_BLUE=$(docker ps --filter name=${DOCKER_APP_NAME}-blue --filter status=running -q) +EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --filter status=running -q) + +# 둘 다 실행 중이지 않을 경우 blue 실행 +if [ -z "$EXIST_BLUE" ] && [ -z "$EXIST_GREEN" ]; then + echo "No containers running. Starting blue up" + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 ${DOCKER_USERNAME}/moing:blue + BEFORE_COMPOSE_COLOR="green" + AFTER_COMPOSE_COLOR="blue" +elif [ -z "$EXIST_BLUE" ]; then + echo "blue up" + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 ${DOCKER_USERNAME}/moing:blue + BEFORE_COMPOSE_COLOR="green" + AFTER_COMPOSE_COLOR="blue" +else + echo "green up" + docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 ${DOCKER_USERNAME}/moing:green + BEFORE_COMPOSE_COLOR="blue" + AFTER_COMPOSE_COLOR="green" +fi + +sleep 10 + +# 새로운 컨테이너가 제대로 실행되었는지 확인 +EXIST_AFTER=$(docker ps --filter name=${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} --filter status=running -q) +if [ -n "$EXIST_AFTER" ]; then + # nginx.config를 컨테이너에 맞게 변경해주고 reload 한다 + cp ./nginx.${AFTER_COMPOSE_COLOR}.conf /etc/nginx/nginx.conf + sudo nginx -s reload + + # 이전 컨테이너 종료 + docker stop ${DOCKER_APP_NAME}-${BEFORE_COMPOSE_COLOR} + docker rm ${DOCKER_APP_NAME}-${BEFORE_COMPOSE_COLOR} + echo "$BEFORE_COMPOSE_COLOR down" +else + # Docker logs + LOGS=$(docker logs ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} 2>&1) + echo "Error: ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} failed to start." + echo "$LOGS" +fi From 8ae72807c4c4939364ee10487f9d4fae3e7d5a59 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Fri, 11 Aug 2023 13:23:38 +0900 Subject: [PATCH 012/619] docs: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 9d583a77..3499815a 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -9,20 +9,23 @@ permissions: jobs: build: - runs-on: ubuntu-latest - env : + env: working-directory: ./ APPLICATION: ${{ secrets.APPLICATION }} steps: + # 소스 코드 체크아웃 - uses: actions/checkout@v2 + + # JDK 11 설정 - name: Set up JDK 11 uses: actions/setup-java@v2 with: java-version: '11' distribution: 'adopt' - + + # Gradle 패키지 캐시 - name: Cache Gradle packages uses: actions/cache@v2 with: @@ -32,15 +35,16 @@ jobs: key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | ${{ runner.os }}-gradle- - - - uses: actions/checkout@v2 + + # 설정 파일 생성 - run: | cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml touch ./firebase-key.json - echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.jso + echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json + # 설정 파일을 작업공간에 저장 - uses: actions/upload-artifact@v2 with: name: application.yml @@ -50,21 +54,25 @@ jobs: with: name: firebase-key.json path: ./src/main/resources/firebase-key.json - + + # gradlew 권한 설정 - name: Grant execute permission for gradlew run: chmod +x gradlew working-directory: ${{ env.working-directory }} - + + # Gradle로 빌드 - name: Build with Gradle run: ./gradlew build working-directory: ${{ env.working-directory }} - + + # Gradle 캐시 정리 - name: Cleanup Gradle Cache if: ${{ always() }} run: | rm -f ~/.gradle/caches/modules-2/modules-2.lock rm -f ~/.gradle/caches/modules-2/gc.properties + # Docker 이미지 빌드 및 푸시 - name: Docker build run: | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} @@ -73,7 +81,13 @@ jobs: docker push ${{ secrets.DOCKER_USERNAME }}/moing:green docker push ${{ secrets.DOCKER_USERNAME }}/moing:blue - - name: Deploy + # EC2로 deploy.sh 전송 + - name: SCP deploy.sh to EC2 + run: | + scp -i ${{ secrets.PRIVATE_KEY }} deploy.sh ec2-user@${{ secrets.EC2_SERVER_HOST }}:/home/ec2-user/ + + # 배포 스크립트 실행 + - name: Make deploy.sh executable and Deploy uses: appleboy/ssh-action@master with: host: ${{ secrets.EC2_SERVER_HOST }} @@ -81,6 +95,7 @@ jobs: key: ${{ secrets.PRIVATE_KEY }} envs: GITHUB_SHA script: | + chmod +x /home/ec2-user/deploy.sh docker pull ${{ secrets.DOCKER_USERNAME }}/moing:green docker pull ${{ secrets.DOCKER_USERNAME }}/moing:blue - ./deploy.sh + /home/ec2-user/deploy.sh From e01c911249571f299558501030ca0527d99c726a Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Fri, 11 Aug 2023 13:34:24 +0900 Subject: [PATCH 013/619] docs: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 3499815a..c47cefff 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -82,12 +82,17 @@ jobs: docker push ${{ secrets.DOCKER_USERNAME }}/moing:blue # EC2로 deploy.sh 전송 - - name: SCP deploy.sh to EC2 - run: | - scp -i ${{ secrets.PRIVATE_KEY }} deploy.sh ec2-user@${{ secrets.EC2_SERVER_HOST }}:/home/ec2-user/ + - name: Deploy deploy.sh to EC2 + uses: appleboy/scp-action@master + with: + host: ${{ secrets.EC2_SERVER_HOST }} + username: ec2-user + key: ${{ secrets.PRIVATE_KEY }} + source: "./deploy.sh" + target: "/home/ec2-user/" # 배포 스크립트 실행 - - name: Make deploy.sh executable and Deploy + - name: Deploy on EC2 uses: appleboy/ssh-action@master with: host: ${{ secrets.EC2_SERVER_HOST }} @@ -96,6 +101,4 @@ jobs: envs: GITHUB_SHA script: | chmod +x /home/ec2-user/deploy.sh - docker pull ${{ secrets.DOCKER_USERNAME }}/moing:green - docker pull ${{ secrets.DOCKER_USERNAME }}/moing:blue /home/ec2-user/deploy.sh From 79cb659d6f3cf193548ef4b4b23023341394386f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 18 Aug 2023 00:36:55 +0900 Subject: [PATCH 014/619] =?UTF-8?q?feat=20:=20=EC=B6=94=EA=B0=80=20Mission?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20Entity=20=EC=B6=94=EA=B0=80=20Mission,M?= =?UTF-8?q?issionArchive=20Entity=20=EC=B6=94=EA=B0=80=20Resove=20:=20#6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 + .../domain/mission/domain/entity/Mission.java | 49 +++++ .../domain/entity/constant/MissionStatus.java | 14 ++ .../domain/entity/constant/MissionType.java | 6 + .../domain/entity/constant/MissionWay.java | 9 + .../domain/repository/MissionRepository.java | 7 + .../domain/entity/MissionArchive.java | 40 ++++ .../backend/global/entity/BaseTimeEntity.java | 34 ++++ .../domain/mission/MissionCreateTest.java | 176 ++++++++++++++++++ 9 files changed, 339 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java create mode 100644 src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java create mode 100644 src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionType.java create mode 100644 src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionWay.java create mode 100644 src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java create mode 100644 src/main/java/com/moing/backend/global/entity/BaseTimeEntity.java create mode 100644 src/test/java/com/moing/backend/domain/mission/MissionCreateTest.java diff --git a/.gitignore b/.gitignore index 87cefe4e..5eea307e 100644 --- a/.gitignore +++ b/.gitignore @@ -38,5 +38,9 @@ out/ ### yml ### application.yml +application-local.yml .DS_Store firebase-key.json +src/test/resources/ + +.jpb diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java new file mode 100644 index 00000000..7767ef94 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -0,0 +1,49 @@ +package com.moing.backend.domain.mission.domain.entity; + +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class Mission extends BaseTimeEntity { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "mission_id") + private Long id; + + private String title; + private LocalDateTime dueTo; + private String rule; + private String content; + private Long number; + + @Enumerated(value = EnumType.STRING) + private MissionType type; + + @Enumerated(value = EnumType.STRING) + private MissionStatus status; + + @Enumerated(value = EnumType.STRING) + private MissionWay way; + + @OneToMany(mappedBy = "mission") + List missionArchiveList = new ArrayList<>(); + + + +} diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java new file mode 100644 index 00000000..62382308 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.mission.domain.entity.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum MissionStatus { + WAIT, + DONE, + ONGOING, + SKIP; + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionType.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionType.java new file mode 100644 index 00000000..453a0a1f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionType.java @@ -0,0 +1,6 @@ +package com.moing.backend.domain.mission.domain.entity.constant; + +public enum MissionType { + + ONCE,REPEAT; +} diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionWay.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionWay.java new file mode 100644 index 00000000..7fa9100b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionWay.java @@ -0,0 +1,9 @@ +package com.moing.backend.domain.mission.domain.entity.constant; + +public enum MissionWay { + TEXT, + LINK, + PHOTO; + + private String name; +} diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java new file mode 100644 index 00000000..ec8b779d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.mission.domain.repository; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MissionRepository extends JpaRepository { +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java new file mode 100644 index 00000000..f54e4721 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -0,0 +1,40 @@ +package com.moing.backend.domain.missionArchive.domain.entity; + + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 하는 저장소 + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "missionArchive_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + private Mission mission; + + @Enumerated(value = EnumType.STRING) + private MissionStatus status; + + private String archive; //링크, 글, 사진 뭐든 가능 + + + +} diff --git a/src/main/java/com/moing/backend/global/entity/BaseTimeEntity.java b/src/main/java/com/moing/backend/global/entity/BaseTimeEntity.java new file mode 100644 index 00000000..985e6bff --- /dev/null +++ b/src/main/java/com/moing/backend/global/entity/BaseTimeEntity.java @@ -0,0 +1,34 @@ +package com.moing.backend.global.entity; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters.LocalDateTimeConverter; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import java.time.LocalDateTime; + +@EntityListeners(AuditingEntityListener.class) +@MappedSuperclass +@Getter +@Setter +public class BaseTimeEntity { + + @CreatedDate + @Column(updatable = false) + @Convert(converter = LocalDateTimeConverter.class) + private LocalDateTime createdDate; + + @LastModifiedDate + @Column + @Convert(converter = LocalDateTimeConverter.class) + private LocalDateTime lastModifiedDate; + + +} + diff --git a/src/test/java/com/moing/backend/domain/mission/MissionCreateTest.java b/src/test/java/com/moing/backend/domain/mission/MissionCreateTest.java new file mode 100644 index 00000000..f1d4625a --- /dev/null +++ b/src/test/java/com/moing/backend/domain/mission/MissionCreateTest.java @@ -0,0 +1,176 @@ +//package com.moing.backend.domain.mission; +// +//import com.moing.backend.domain.mission.domain.entity.Mission; +//import com.moing.backend.domain.mission.domain.repository.MissionRepository; +//import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +//import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +//import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +//import org.junit.jupiter.api.Test; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.test.annotation.Rollback; +// +//import javax.transaction.Transactional; +//import java.time.LocalDateTime; +//import java.util.ArrayList; +//import java.util.List; +// +//import static org.assertj.core.api.Assertions.assertThat; +// +//@Rollback(value=false) +//@Transactional +//@SpringBootTest(properties = { "spring.config.location=classpath:application-test.yml" }) +////@SpringBootTest +//public class MissionCreateTest { +// +// @Autowired +// private TeamRepository teamRepository; +// @Autowired +// private TeamMemberRepository teamMemberRepository; +// @Autowired +// private OnceMissionRepository onceMissionRepository; +// @Autowired +// private MissionRepository missionRepository; +// @Autowired +// private TestMemberRepository testMemberRepository; +// @Autowired +// private RepeatMissionRepository repeatMissionRepository; +// +// @Test +// public void 한번미션_생셩() { +// Mission mission = new Mission(); +// +// Team makeTeam = Team.builder() +// .name("hi") +// .build(); +// +//// teamRepository.save(makeTeam); +// +// for (int i = 0; i < 3; i++) { +// TestMember newMember = new TestMember("name"+i); +// testMemberRepository.save(newMember); +// +// TeamMember newTeams = TeamMember.builder() +// .member(newMember) +// .team(makeTeam) +// .build(); +//// teamMemberRepository.save(newTeams); +// } +//// assertThat(teamRepository.findAll().size()).isEqualTo(1); +//// +// List missionArchives = new ArrayList<>(); +// +// // fetch 주의 +// Team newTeam = teamRepository.findById(2L).get(); +// List teamMembers = newTeam.getTeamMembers(); +// +//// List teamMembers = makeTeam.getTeamMembers(); +// +//// assertThat(teamMembers.size()).isEqualTo(3); +// +// for (TeamMember teamMember : teamMembers) { +// MissionArchive newMissionArchive = MissionArchive.builder() +// .member(teamMember.getMember()) +// .status(MissionStatus.WAITING) +// .build(); +// +// missionArchives.add(newMissionArchive); +// } +// +// OnceMission newOnceMission = OnceMission.builder() +// .missionArchives(missionArchives) +// .build(); +//// onceMissionRepository.save(newOnceMission); +// +// Mission newMission = Mission.builder() +// .title("new") +// .team(newTeam) +// .dueTo(LocalDateTime.now()) +// .rule("rule") +// .content("content") +// .type(MissionType.ONCE) +// .onceMission(newOnceMission) +// .build(); +// +// missionRepository.save(newMission); +// +// System.out.println("title : " + newMission.getTitle()); +// System.out.println("title : " + newMission.getRule()); +// System.out.println("user " + newMission.getTeam().getTeamMembers().size()); +// +// } +// +// @Test +// public void 반복미션_생성() { +// +// +// Team makeTeam = Team.builder() +// .name("hi") +// .build(); +// +// teamRepository.save(makeTeam); +// +// +// for (int i = 0; i < 3; i++) { +// TestMember newMember = new TestMember("name"+i); +// testMemberRepository.save(newMember); +// +// TeamMember newTeams = TeamMember.builder() +// .member(newMember) +// .team(makeTeam) +// .build(); +// } +// +// // 미션 생성 +// +// List missionArchives = new ArrayList<>(); +// +// // fetch 주의 +// Team newTeam = teamRepository.findById(2L).get(); +// List teamMembers = newTeam.getTeamMembers(); +// +// +// for (TeamMember teamMember : teamMembers) { +// MissionArchive newMissionArchive = MissionArchive.builder() +// .member(teamMember.getMember()) +// .status(MissionStatus.WAITING) +// .build(); +// +// missionArchives.add(newMissionArchive); +// } +// +// OnceMission newOnceMission = OnceMission.builder() +// .missionArchives(missionArchives) +// .build(); +// +// onceMissionRepository.save(newOnceMission); +// List repeat = new ArrayList<>(); +// +// for (int i=0;i<2;i++){ +// repeat.add(newOnceMission); +// } +// +// RepeatMission save = repeatMissionRepository.save(RepeatMission.builder() +// .times(2L) +// .dayMissions(repeat) +// .build()); +// +// +// Mission newMission = Mission.builder() +// .title("new") +// .team(newTeam) +// .dueTo(LocalDateTime.now()) +// .rule("rule") +// .content("content") +// .type(MissionType.REPEAT) +// .repeatMission(save) +// .build(); +// +// missionRepository.save(newMission); +// +// System.out.println("title : " + newMission.getTitle()); +// System.out.println("title : " + newMission.getRule()); +// System.out.println("user " + newMission.getTeam().getTeamMembers().size()); +// System.out.println("misison" + newMission.getRepeatMission().getDayMissions().size()); +// } +//} \ No newline at end of file From be6f47e343039d5025b4b272843df7c0655ee39f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 18 Aug 2023 00:45:40 +0900 Subject: [PATCH 015/619] =?UTF-8?q?feat=20:=20MissionCreateTest=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20mis?= =?UTF-8?q?sionCreateTest=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mission/MissionCreateTest.java | 176 ------------------ 1 file changed, 176 deletions(-) delete mode 100644 src/test/java/com/moing/backend/domain/mission/MissionCreateTest.java diff --git a/src/test/java/com/moing/backend/domain/mission/MissionCreateTest.java b/src/test/java/com/moing/backend/domain/mission/MissionCreateTest.java deleted file mode 100644 index f1d4625a..00000000 --- a/src/test/java/com/moing/backend/domain/mission/MissionCreateTest.java +++ /dev/null @@ -1,176 +0,0 @@ -//package com.moing.backend.domain.mission; -// -//import com.moing.backend.domain.mission.domain.entity.Mission; -//import com.moing.backend.domain.mission.domain.repository.MissionRepository; -//import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -//import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -//import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -//import org.junit.jupiter.api.Test; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.boot.test.context.SpringBootTest; -//import org.springframework.test.annotation.Rollback; -// -//import javax.transaction.Transactional; -//import java.time.LocalDateTime; -//import java.util.ArrayList; -//import java.util.List; -// -//import static org.assertj.core.api.Assertions.assertThat; -// -//@Rollback(value=false) -//@Transactional -//@SpringBootTest(properties = { "spring.config.location=classpath:application-test.yml" }) -////@SpringBootTest -//public class MissionCreateTest { -// -// @Autowired -// private TeamRepository teamRepository; -// @Autowired -// private TeamMemberRepository teamMemberRepository; -// @Autowired -// private OnceMissionRepository onceMissionRepository; -// @Autowired -// private MissionRepository missionRepository; -// @Autowired -// private TestMemberRepository testMemberRepository; -// @Autowired -// private RepeatMissionRepository repeatMissionRepository; -// -// @Test -// public void 한번미션_생셩() { -// Mission mission = new Mission(); -// -// Team makeTeam = Team.builder() -// .name("hi") -// .build(); -// -//// teamRepository.save(makeTeam); -// -// for (int i = 0; i < 3; i++) { -// TestMember newMember = new TestMember("name"+i); -// testMemberRepository.save(newMember); -// -// TeamMember newTeams = TeamMember.builder() -// .member(newMember) -// .team(makeTeam) -// .build(); -//// teamMemberRepository.save(newTeams); -// } -//// assertThat(teamRepository.findAll().size()).isEqualTo(1); -//// -// List missionArchives = new ArrayList<>(); -// -// // fetch 주의 -// Team newTeam = teamRepository.findById(2L).get(); -// List teamMembers = newTeam.getTeamMembers(); -// -//// List teamMembers = makeTeam.getTeamMembers(); -// -//// assertThat(teamMembers.size()).isEqualTo(3); -// -// for (TeamMember teamMember : teamMembers) { -// MissionArchive newMissionArchive = MissionArchive.builder() -// .member(teamMember.getMember()) -// .status(MissionStatus.WAITING) -// .build(); -// -// missionArchives.add(newMissionArchive); -// } -// -// OnceMission newOnceMission = OnceMission.builder() -// .missionArchives(missionArchives) -// .build(); -//// onceMissionRepository.save(newOnceMission); -// -// Mission newMission = Mission.builder() -// .title("new") -// .team(newTeam) -// .dueTo(LocalDateTime.now()) -// .rule("rule") -// .content("content") -// .type(MissionType.ONCE) -// .onceMission(newOnceMission) -// .build(); -// -// missionRepository.save(newMission); -// -// System.out.println("title : " + newMission.getTitle()); -// System.out.println("title : " + newMission.getRule()); -// System.out.println("user " + newMission.getTeam().getTeamMembers().size()); -// -// } -// -// @Test -// public void 반복미션_생성() { -// -// -// Team makeTeam = Team.builder() -// .name("hi") -// .build(); -// -// teamRepository.save(makeTeam); -// -// -// for (int i = 0; i < 3; i++) { -// TestMember newMember = new TestMember("name"+i); -// testMemberRepository.save(newMember); -// -// TeamMember newTeams = TeamMember.builder() -// .member(newMember) -// .team(makeTeam) -// .build(); -// } -// -// // 미션 생성 -// -// List missionArchives = new ArrayList<>(); -// -// // fetch 주의 -// Team newTeam = teamRepository.findById(2L).get(); -// List teamMembers = newTeam.getTeamMembers(); -// -// -// for (TeamMember teamMember : teamMembers) { -// MissionArchive newMissionArchive = MissionArchive.builder() -// .member(teamMember.getMember()) -// .status(MissionStatus.WAITING) -// .build(); -// -// missionArchives.add(newMissionArchive); -// } -// -// OnceMission newOnceMission = OnceMission.builder() -// .missionArchives(missionArchives) -// .build(); -// -// onceMissionRepository.save(newOnceMission); -// List repeat = new ArrayList<>(); -// -// for (int i=0;i<2;i++){ -// repeat.add(newOnceMission); -// } -// -// RepeatMission save = repeatMissionRepository.save(RepeatMission.builder() -// .times(2L) -// .dayMissions(repeat) -// .build()); -// -// -// Mission newMission = Mission.builder() -// .title("new") -// .team(newTeam) -// .dueTo(LocalDateTime.now()) -// .rule("rule") -// .content("content") -// .type(MissionType.REPEAT) -// .repeatMission(save) -// .build(); -// -// missionRepository.save(newMission); -// -// System.out.println("title : " + newMission.getTitle()); -// System.out.println("title : " + newMission.getRule()); -// System.out.println("user " + newMission.getTeam().getTeamMembers().size()); -// System.out.println("misison" + newMission.getRepeatMission().getDayMissions().size()); -// } -//} \ No newline at end of file From 75b203f1dec549230d9d8076d9e72c5dc8a4cd99 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Fri, 18 Aug 2023 10:56:44 +0900 Subject: [PATCH 016/619] =?UTF-8?q?feat:=20BaseTimeEntity=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/presentation/AuthController.java | 1 + .../domain/member/domain/entity/Member.java | 11 ++------ .../mypage/presentation/MyPageController.java | 6 ++++ .../config/webclient/WebClientConfig.java | 2 +- .../backend/global/entity/BaseTimeEntity.java | 28 +++++++++++++++++++ 5 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java create mode 100644 src/main/java/com/moing/backend/global/entity/BaseTimeEntity.java diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java index 484e7af7..428e228d 100644 --- a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java @@ -68,4 +68,5 @@ public ResponseEntity> reissue(HttpServlet return ResponseEntity.ok(SuccessResponse.create(REISSUE_TOKEN_SUCCESS.getMessage(), reissueToken)); } + //TODO 닉네임 중복검사 } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index a18f85ea..79842766 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.member.domain.constant.RegistrationStatus; import com.moing.backend.domain.member.domain.constant.Role; import com.moing.backend.domain.member.domain.constant.SocialProvider; +import com.moing.backend.global.entity.BaseTimeEntity; import com.moing.backend.global.util.AesConverter; import lombok.AllArgsConstructor; import lombok.Builder; @@ -18,7 +19,7 @@ @NoArgsConstructor @AllArgsConstructor @Getter -public class Member { +public class Member extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "member_id") @@ -41,11 +42,10 @@ public class Member { @Convert(converter = AesConverter.class) private String profileImage; //없으면 undef - private String gender; //없으면 undef - private String ageRange; //없으면 undef + private boolean isDeleted; // 추가정보 @@ -59,11 +59,8 @@ public class Member { @Convert(converter = AesConverter.class) private String introduction; //없으면 undef - private String fcmToken; //없으면 undef - private String reasonToDelete; //없으면 undef - @ColumnDefault("true") private boolean isNewUploadPush; @@ -97,7 +94,6 @@ public void prePersist() { if (nickName == null) nickName = "undef"; if (introduction == null) introduction = "undef"; if (fcmToken == null) fcmToken = "undef"; - if (reasonToDelete == null) reasonToDelete = "undef"; if (registrationStatus == null) registrationStatus = RegistrationStatus.UNCOMPLETED; } @@ -132,7 +128,6 @@ public void updateMypage(String nickName, String introduction) { public void deleteAccount(String reasonToDelete) { this.isDeleted = true; - this.reasonToDelete = reasonToDelete; } public void updateNewUploadPush(boolean newUploadPush) { diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java new file mode 100644 index 00000000..8ec64479 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java @@ -0,0 +1,6 @@ +package com.moing.backend.domain.mypage.presentation; + +public class MyPageController { + + //TODO 회원탍퇴, 로그아웃, 마이페이지 조회, 수정, 알림설정 수정 +} diff --git a/src/main/java/com/moing/backend/global/config/webclient/WebClientConfig.java b/src/main/java/com/moing/backend/global/config/webclient/WebClientConfig.java index b757600f..06739876 100644 --- a/src/main/java/com/moing/backend/global/config/webclient/WebClientConfig.java +++ b/src/main/java/com/moing/backend/global/config/webclient/WebClientConfig.java @@ -30,7 +30,7 @@ public WebClient webClient() { .exchangeStrategies(exchangeStrategies) .filter(logRequest()) .filter(logResponse()) - .defaultHeader("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.3") + .defaultHeader("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") .build(); } diff --git a/src/main/java/com/moing/backend/global/entity/BaseTimeEntity.java b/src/main/java/com/moing/backend/global/entity/BaseTimeEntity.java new file mode 100644 index 00000000..cf736bdd --- /dev/null +++ b/src/main/java/com/moing/backend/global/entity/BaseTimeEntity.java @@ -0,0 +1,28 @@ +package com.moing.backend.global.entity; + +import jodd.typeconverter.impl.LocalDateTimeConverter; +import lombok.Getter; +import lombok.Setter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import java.time.LocalDateTime; + +@Getter +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public class BaseTimeEntity { + + @CreatedDate + @Column(updatable = false) + private LocalDateTime createdDate; + + @LastModifiedDate + private LocalDateTime lastModifiedDate; + +} \ No newline at end of file From fb8bfb34d71d0d6ab9565dd7a6b4c4fccab9e04c Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Tue, 22 Aug 2023 23:22:29 +0900 Subject: [PATCH 017/619] =?UTF-8?q?feat:=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Auth-API.adoc | 37 ++- .../dto/request/SignInRequest.java | 11 +- .../dto/request/SignUpRequest.java | 10 +- .../dto/response/CheckNicknameResponse.java | 14 + .../response/KakaoAccessTokenResponse.java | 7 +- .../dto/response/KakaoUserResponse.java | 11 +- .../service/CheckNicknameUserCase.java | 20 ++ .../application/service/SignUpUserCase.java | 11 +- .../NicknameDuplicationException.java | 11 + .../auth/presentation/AuthController.java | 35 ++- .../constant/AuthResponseMessage.java | 3 +- .../domain/member/domain/entity/Member.java | 2 +- .../repository/MemberCustomRepository.java | 1 + .../MemberCustomRepositoryImpl.java | 9 + .../domain/service/MemberCheckService.java | 18 ++ ...ueryService.java => MemberGetService.java} | 2 +- .../dto/request/WithdrawRequest.java | 19 ++ .../application/service/SignOutUserCase.java | 18 ++ .../application/service/WithdrawUserCase.java | 27 ++ .../domain/mypage/domain/entity/Feedback.java | 31 ++ .../domain/repository/FeedbackRepository.java | 7 + .../domain/service/FeedbackSaveService.java | 22 ++ .../mypage/presentation/MyPageController.java | 51 +++- .../constant/MypageResponseMessage.java | 12 + .../config/security/SecurityConfig.java | 7 +- .../config/security/filter/JwtAuthFilter.java | 4 +- .../security/jwt/JwtSecurityConfig.java | 4 +- .../global/config/security/jwt/TokenUtil.java | 4 +- .../oauth/CustomUserDetailsService.java | 4 +- .../global/interceptor/AuthInterceptor.java | 4 +- .../backend/global/response/ErrorCode.java | 3 +- src/main/resources/static/docs/Auth-API.html | 264 ++++++++--------- src/main/resources/static/docs/api.html | 271 ++++++++---------- .../backend/config/CommonControllerTest.java | 4 +- .../representation/AuthControllerTest.java | 79 ++++- 35 files changed, 650 insertions(+), 387 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/auth/application/dto/response/CheckNicknameResponse.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/exception/NicknameDuplicationException.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/service/MemberCheckService.java rename src/main/java/com/moing/backend/domain/member/domain/service/{MemberQueryService.java => MemberGetService.java} (95%) create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/dto/request/WithdrawRequest.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/domain/entity/Feedback.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/domain/repository/FeedbackRepository.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/domain/service/FeedbackSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java diff --git a/src/docs/asciidoc/Auth-API.adoc b/src/docs/asciidoc/Auth-API.adoc index 37e3779f..ab75db50 100644 --- a/src/docs/asciidoc/Auth-API.adoc +++ b/src/docs/asciidoc/Auth-API.adoc @@ -1,31 +1,44 @@ [[Auth-API]] -== Auth API += Auth API [[Auth-Kako-소셜-로그인]] -=== Auth Kakao 소셜 로그인 회원가입 전 -operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-request,request-fields,http-response,response-fields'] +=== Auth Kakao 소셜 로그인 요청 +operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-request,request-fields'] -=== Auth Kakao 소셜 로그인 회원가입 후 -operation::auth-controller-test/kakao_소셜_로그인_회원가입_후[snippets='http-request,request-fields,http-response,response-fields'] +=== Auth Kakao 소셜 로그인 회원가입 전 응답 +operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-response,response-fields'] + +=== Auth Kakao 소셜 로그인 회원가입 후 응답 +operation::auth-controller-test/kakao_소셜_로그인_회원가입_후[snippets='http-response,response-fields'] --- [[Auth-Apple-소셜-로그인]] -=== Auth Apple 소셜 로그인 회원가입 전 -operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-request,request-fields,http-response,response-fields'] +=== Auth Apple 소셜 로그인 요청 +operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-request,request-fields'] -=== Auth Apple 소셜 로그인 회원가입 후 -operation::auth-controller-test/apple_소셜_로그인_회원가입_후[snippets='http-request,request-fields,http-response,response-fields'] +=== Auth Apple 소셜 로그인 회원가입 전 응답 +operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-response,response-fields'] +=== Auth Apple 소셜 로그인 회원가입 후 응답 +operation::auth-controller-test/apple_소셜_로그인_회원가입_후[snippets='http-response,response-fields'] -[[Auth-회원가입]] -=== Auth 회원가입 -operation::auth-controller-test/sign_up[snippets='http-request,request-fields,http-response,response-fields'] [[Auth-회원가입]] === Auth 회원가입 operation::auth-controller-test/sign_up[snippets='http-request,request-fields,http-response,response-fields'] + [[Auth-토큰-재발급]] === Auth 토큰 재발급 operation::auth-controller-test/reissue_token[snippets='http-request,http-response,response-fields'] + +[[Auth-닉네임-검사]] +=== Auth 닉네임 중복검사 요청 +operation::auth-controller-test/check_nickname_중복o[snippets='http-request'] + +=== Auth 닉네임 중복인 경우 +operation::auth-controller-test/check_nickname_중복o[snippets='http-response,response-fields'] + +=== Auth 닉네임 중복이 아닌 경우 +operation::auth-controller-test/check_nickname_중복x[snippets='http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java index 0a11219f..980fa113 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java @@ -1,16 +1,15 @@ package com.moing.backend.domain.auth.application.dto.request; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; + +import javax.validation.constraints.NotBlank; @Builder @AllArgsConstructor @NoArgsConstructor -@Data +@Getter public class SignInRequest { - + @NotBlank(message="token 을 입력해주세요.") private String token; } diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java index 33877ec9..0b892ae7 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java @@ -1,14 +1,14 @@ package com.moing.backend.domain.auth.application.dto.request; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; + +import javax.validation.constraints.NotBlank; @Builder @AllArgsConstructor @NoArgsConstructor -@Data +@Getter public class SignUpRequest { + @NotBlank(message = "nickName 을 입력해주세요.") private String nickName; } diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/CheckNicknameResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/CheckNicknameResponse.java new file mode 100644 index 00000000..e1a6b886 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/CheckNicknameResponse.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.auth.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class CheckNicknameResponse { + private Boolean isDuplicated; +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java index 87fb3ca0..a04370f0 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java @@ -2,15 +2,12 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.annotation.JsonNaming; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; @Builder @NoArgsConstructor @AllArgsConstructor -@Data +@Getter @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) public class KakaoAccessTokenResponse { diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java index a8e484a8..cf8d8be3 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java @@ -2,22 +2,19 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.annotation.JsonNaming; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; @Builder @NoArgsConstructor @AllArgsConstructor -@Data +@Getter @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) public class KakaoUserResponse { private Long id; private Properties properties; private KakaoAccount kakaoAccount; - @Data + @Getter @NoArgsConstructor @AllArgsConstructor @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) @@ -25,7 +22,7 @@ public static class Properties { private String nickname; } - @Data + @Getter @NoArgsConstructor @AllArgsConstructor public static class KakaoAccount { diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUserCase.java new file mode 100644 index 00000000..73b80f8c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUserCase.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.auth.application.service; + +import com.moing.backend.domain.auth.application.dto.response.CheckNicknameResponse; +import com.moing.backend.domain.member.domain.service.MemberCheckService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class CheckNicknameUserCase { + + private final MemberCheckService memberCheckService; + public CheckNicknameResponse checkNickname(String nickname){ + boolean isDuplicated=memberCheckService.checkNickname(nickname); + return new CheckNicknameResponse(isDuplicated); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java index 6509a057..263437f4 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java @@ -2,9 +2,11 @@ import com.moing.backend.domain.auth.application.dto.request.SignUpRequest; import com.moing.backend.domain.auth.application.dto.response.SignInResponse; +import com.moing.backend.domain.auth.exception.NicknameDuplicationException; import com.moing.backend.domain.member.domain.constant.RegistrationStatus; import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.domain.member.domain.service.MemberCheckService; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.global.config.security.jwt.TokenUtil; import com.moing.backend.global.config.security.util.AuthenticationUtil; import com.moing.backend.global.response.TokenInfoResponse; @@ -19,7 +21,8 @@ public class SignUpUserCase { private final TokenUtil tokenUtil; - private final MemberQueryService memberQueryService; + private final MemberGetService memberQueryService; + private final MemberCheckService memberCheckService; public SignInResponse signUp(String token, SignUpRequest signUpRequest) { @@ -27,7 +30,9 @@ public SignInResponse signUp(String token, SignUpRequest signUpRequest) { String socialId = tokenUtil.getSocialId(token); Member member = memberQueryService.getMemberBySocialId(socialId); //2. signUp 처리 - member.signUp(signUpRequest.getNickName()); + String nickName=signUpRequest.getNickName(); + if(memberCheckService.checkNickname(nickName)) throw new NicknameDuplicationException(); //닉네임 중복검사 (이중체크) + member.signUp(nickName); //3. security 처리 AuthenticationUtil.makeAuthentication(member); //4. token 만들기 diff --git a/src/main/java/com/moing/backend/domain/auth/exception/NicknameDuplicationException.java b/src/main/java/com/moing/backend/domain/auth/exception/NicknameDuplicationException.java new file mode 100644 index 00000000..957d9de9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/exception/NicknameDuplicationException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.auth.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NicknameDuplicationException extends AuthException { + public NicknameDuplicationException(){ + super(ErrorCode.NICKNAME_DUPLICATION_ERROR, + HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java index 428e228d..5d4c96d4 100644 --- a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java @@ -2,8 +2,10 @@ import com.moing.backend.domain.auth.application.dto.request.SignInRequest; import com.moing.backend.domain.auth.application.dto.request.SignUpRequest; +import com.moing.backend.domain.auth.application.dto.response.CheckNicknameResponse; import com.moing.backend.domain.auth.application.dto.response.ReissueTokenResponse; import com.moing.backend.domain.auth.application.dto.response.SignInResponse; +import com.moing.backend.domain.auth.application.service.CheckNicknameUserCase; import com.moing.backend.domain.auth.application.service.ReissueTokenUserCase; import com.moing.backend.domain.auth.application.service.SignInUserCase; import com.moing.backend.domain.auth.application.service.SignUpUserCase; @@ -20,7 +22,7 @@ @RestController @AllArgsConstructor -@RequestMapping("/auth") +@RequestMapping("/api/auth") public class AuthController { private final SignInUserCase authService; @@ -28,10 +30,11 @@ public class AuthController { private final SignUpUserCase signUpService; private final ReissueTokenUserCase reissueTokenService; + private final CheckNicknameUserCase checkNicknameService; /** * 소셜 로그인 (애플/ 카카오) - * [POST] /auth/signIn/kakao||apple + * [POST] api/auth/signIn/kakao||apple * 작성자 : 김민수 */ @PostMapping("/signIn/{provider}") @@ -42,31 +45,33 @@ public ResponseEntity> signIn(@PathVariable Stri /** * 회원가입 (초기 로그인한 사용자 닉네임 입력) - * [PUT] /auth/signUp + * [PUT] api/auth/signUp * 작성자 : 김민수 */ @PutMapping("/signUp") - public ResponseEntity> signUp(HttpServletRequest request, @Valid @RequestBody SignUpRequest signUpRequest) { - String token = request.getHeader("Authorization"); + public ResponseEntity> signUp(@RequestHeader(value = "Authorization") String token, + @Valid @RequestBody SignUpRequest signUpRequest) { + token = (token != null && token.startsWith("Bearer ")) ? token.substring(7) : token; return ResponseEntity.ok(SuccessResponse.create(SIGN_UP_SUCCESS.getMessage(), this.signUpService.signUp(token, signUpRequest))); } - - /** * 토큰 재발급 - * [GET] /auth/reissue + * [GET] api/auth/reissue * 작성자 : 김민수 */ @GetMapping("/reissue") - public ResponseEntity> reissue(HttpServletRequest request) { - - // 헤더로부터 RefreshToken 추출. - String token = request.getHeader("RefreshToken"); - // 토큰 재발행 + public ResponseEntity> reissue(@RequestHeader(value = "RefreshToken") String token) { ReissueTokenResponse reissueToken = reissueTokenService.reissueToken(token); - return ResponseEntity.ok(SuccessResponse.create(REISSUE_TOKEN_SUCCESS.getMessage(), reissueToken)); } - //TODO 닉네임 중복검사 + /** + * 닉네임 중복검사 + * [GET] api/auth/nickname + * 작성자 : 김민수 + */ + @GetMapping("/nickname/{nickname}") + public ResponseEntity> checkNickname(@PathVariable String nickname){ + return ResponseEntity.ok(SuccessResponse.create(CHECK_NICKNAME_SUCCESS.getMessage(), checkNicknameService.checkNickname(nickname))); + } } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/constant/AuthResponseMessage.java b/src/main/java/com/moing/backend/domain/auth/presentation/constant/AuthResponseMessage.java index 1eb7f046..e86f5204 100644 --- a/src/main/java/com/moing/backend/domain/auth/presentation/constant/AuthResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/auth/presentation/constant/AuthResponseMessage.java @@ -8,7 +8,8 @@ public enum AuthResponseMessage { SIGN_IN_SUCCESS("로그인을 했습니다"), SIGN_UP_SUCCESS("회원 가입을 했습니다"), - REISSUE_TOKEN_SUCCESS("토큰을 재발급했습니다"); + REISSUE_TOKEN_SUCCESS("토큰을 재발급했습니다"), + CHECK_NICKNAME_SUCCESS("닉네임 중복검사를 했습니다"); private final String message; } diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index 79842766..0338cb7d 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -126,7 +126,7 @@ public void updateMypage(String nickName, String introduction) { this.introduction = introduction; } - public void deleteAccount(String reasonToDelete) { + public void deleteAccount() { this.isDeleted = true; } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java index cb097741..151fb815 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java @@ -6,4 +6,5 @@ public interface MemberCustomRepository { Optional findBySocialIdNotDeleted(String socialId); + boolean checkNickname(String nickname); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java index 219349f7..de95f305 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java @@ -23,4 +23,13 @@ public Optional findBySocialIdNotDeleted(String socialId) { .where(member.isDeleted.eq(false)) .fetchFirst()); } + + @Override + public boolean checkNickname(String nickname) { + return queryFactory + .selectOne() + .from(member) + .where(member.nickName.eq(nickname)) + .fetchFirst() != null; + } } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberCheckService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberCheckService.java new file mode 100644 index 00000000..299dceb2 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberCheckService.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.member.domain.service; + +import com.moing.backend.domain.member.domain.repository.MemberRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MemberCheckService { + private final MemberRepository memberRepository; + public boolean checkNickname(String nickname) { + return memberRepository.checkNickname(nickname); + } + +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberQueryService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java similarity index 95% rename from src/main/java/com/moing/backend/domain/member/domain/service/MemberQueryService.java rename to src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java index e82e5238..09342d61 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberQueryService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java @@ -11,7 +11,7 @@ @DomainService @Transactional @RequiredArgsConstructor -public class MemberQueryService { +public class MemberGetService { private final MemberRepository memberRepository; public Member getMemberBySocialId(String socialId){ diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/request/WithdrawRequest.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/request/WithdrawRequest.java new file mode 100644 index 00000000..78067857 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/request/WithdrawRequest.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.mypage.application.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class WithdrawRequest { + @NotBlank(message = "reason 을 입력해주세요.") + @Size(min = 1, max = 500, message="reason 은 최소 1개, 최대 500개의 문자만 입력 가능합니다.") + private String reason; +} diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java new file mode 100644 index 00000000..abce0334 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.mypage.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.global.config.security.jwt.TokenUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class SignOutUserCase { + + private final TokenUtil tokenUtil; + + public void signOut(String socialId){ + tokenUtil.expireRefreshToken(socialId); + } +} diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java new file mode 100644 index 00000000..daf6ef32 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.mypage.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; +import com.moing.backend.domain.mypage.domain.service.FeedbackSaveService; +import com.moing.backend.global.config.security.jwt.TokenUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class WithdrawUserCase { + private final MemberGetService memberGetService; + private final FeedbackSaveService feedbackSaveService; + private final TokenUtil tokenUtil; + + public void withdraw(String socialId, WithdrawRequest withdrawRequest) { + //1. 멤버 상태 변화 + Member member = memberGetService.getMemberBySocialId(socialId); + member.deleteAccount(); + //2. 피드백 저장 + feedbackSaveService.saveFeedback(member, withdrawRequest); + //3. 리프레시 토큰 만료 + tokenUtil.expireRefreshToken(socialId); + } +} diff --git a/src/main/java/com/moing/backend/domain/mypage/domain/entity/Feedback.java b/src/main/java/com/moing/backend/domain/mypage/domain/entity/Feedback.java new file mode 100644 index 00000000..26ee5648 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/domain/entity/Feedback.java @@ -0,0 +1,31 @@ +package com.moing.backend.domain.mypage.domain.entity; + +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; + +import javax.persistence.*; + +@NoArgsConstructor +@RequiredArgsConstructor +@Entity +public class Feedback extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "feedback_id") + private Long feedbackId; + + @Column(nullable = false) + private Long memberId; + + @Column(nullable = false, length = 500) + private String reason; + + public Feedback(Long memberId, String reason){ + this.memberId=memberId; + this.reason=reason; + } +} diff --git a/src/main/java/com/moing/backend/domain/mypage/domain/repository/FeedbackRepository.java b/src/main/java/com/moing/backend/domain/mypage/domain/repository/FeedbackRepository.java new file mode 100644 index 00000000..857fb7b2 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/domain/repository/FeedbackRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.mypage.domain.repository; + +import com.moing.backend.domain.mypage.domain.entity.Feedback; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FeedbackRepository extends JpaRepository { +} diff --git a/src/main/java/com/moing/backend/domain/mypage/domain/service/FeedbackSaveService.java b/src/main/java/com/moing/backend/domain/mypage/domain/service/FeedbackSaveService.java new file mode 100644 index 00000000..2548ef1f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/domain/service/FeedbackSaveService.java @@ -0,0 +1,22 @@ +package com.moing.backend.domain.mypage.domain.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; +import com.moing.backend.domain.mypage.domain.entity.Feedback; +import com.moing.backend.domain.mypage.domain.repository.FeedbackRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class FeedbackSaveService { + private final FeedbackRepository feedbackRepository; + + public void saveFeedback(Member member, WithdrawRequest withdrawRequest){ + Feedback feedback=new Feedback(member.getMemberId(), withdrawRequest.getReason()); + feedbackRepository.save(feedback); + } +} diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java index 8ec64479..7c971147 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java @@ -1,6 +1,55 @@ package com.moing.backend.domain.mypage.presentation; +import com.moing.backend.domain.auth.application.dto.response.SignInResponse; +import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; +import com.moing.backend.domain.mypage.application.service.SignOutUserCase; +import com.moing.backend.domain.mypage.application.service.WithdrawUserCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +import static com.moing.backend.domain.mypage.presentation.constant.MypageResponseMessage.SIGN_OUT_SUCCESS; +import static com.moing.backend.domain.mypage.presentation.constant.MypageResponseMessage.WITHDRAWAL_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/mypage") public class MyPageController { - //TODO 회원탍퇴, 로그아웃, 마이페이지 조회, 수정, 알림설정 수정 + private final SignOutUserCase signOutService; + private final WithdrawUserCase withdrawService; + + //TODO 마이페이지 조회, 수정, 알림설정 수정 + + /** + * 로그아웃 + * [DELETE] api/auth/mypage/signOut + * 작성자 : 김민수 + */ + @PostMapping("/signOut") + public ResponseEntity signOut(@AuthenticationPrincipal User user) { + this.signOutService.signOut(user.getSocialId()); + return ResponseEntity.ok(SuccessResponse.create(SIGN_OUT_SUCCESS.getMessage())); + } + + /** + * 회원탈퇴 + * [DELETE] api/auth/mypage/withdrawal + * 작성자 : 김민수 + */ + @PostMapping("/withdrawal") + public ResponseEntity withdraw(@AuthenticationPrincipal User user, + @Valid @RequestBody WithdrawRequest withdrawRequest) { + this.withdrawService.withdraw(user.getSocialId(), withdrawRequest); + return ResponseEntity.ok(SuccessResponse.create(WITHDRAWAL_SUCCESS.getMessage())); + } + } diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java b/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java new file mode 100644 index 00000000..f1d4429d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mypage.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum MypageResponseMessage { + SIGN_OUT_SUCCESS("로그아웃을 했습니다"), + WITHDRAWAL_SUCCESS("회원탈퇴를 했습니다"); + private final String message; +} diff --git a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java index c1e18b11..e89f7fce 100644 --- a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java +++ b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java @@ -1,6 +1,6 @@ package com.moing.backend.global.config.security; -import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.global.config.security.filter.JwtAccessDeniedHandler; import com.moing.backend.global.config.security.filter.JwtAuthenticationEntryPoint; import com.moing.backend.global.config.security.jwt.JwtSecurityConfig; @@ -26,7 +26,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { private final TokenUtil tokenUtil; private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; private final JwtAccessDeniedHandler jwtAccessDeniedHandler; - private final MemberQueryService memberQueryService; + private final MemberGetService memberQueryService; @Override public void configure(WebSecurity web) throws Exception { @@ -49,7 +49,8 @@ protected void configure(HttpSecurity http) throws Exception { .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //Spring Security에서 세션을 사용하지 않도록 설정 .and() .authorizeRequests() - .antMatchers("/auth/**", "/docs/**").permitAll() + .antMatchers(HttpMethod.GET,"/api/auth/signUp").authenticated() + .antMatchers("/api/auth/**", "/docs/**").permitAll() .anyRequest().authenticated() .and() .apply(new JwtSecurityConfig(tokenUtil, memberQueryService)); diff --git a/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthFilter.java b/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthFilter.java index 9f744a3d..7b4f0642 100644 --- a/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthFilter.java +++ b/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthFilter.java @@ -1,7 +1,7 @@ package com.moing.backend.global.config.security.filter; import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.global.config.security.jwt.JwtExceptionList; import com.moing.backend.global.config.security.jwt.TokenUtil; import com.moing.backend.global.config.security.util.AuthenticationUtil; @@ -26,7 +26,7 @@ public class JwtAuthFilter extends OncePerRequestFilter { public static final String AUTHORIZATION_HEADER = "Authorization"; private final TokenUtil tokenUtil; - private final MemberQueryService memberQueryService; + private final MemberGetService memberQueryService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException, JwtException { diff --git a/src/main/java/com/moing/backend/global/config/security/jwt/JwtSecurityConfig.java b/src/main/java/com/moing/backend/global/config/security/jwt/JwtSecurityConfig.java index 9d1f751b..bca70ba3 100644 --- a/src/main/java/com/moing/backend/global/config/security/jwt/JwtSecurityConfig.java +++ b/src/main/java/com/moing/backend/global/config/security/jwt/JwtSecurityConfig.java @@ -1,6 +1,6 @@ package com.moing.backend.global.config.security.jwt; -import com.moing.backend.domain.member.domain.service.MemberQueryService; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.global.config.security.filter.JwtAuthFilter; import lombok.RequiredArgsConstructor; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; @@ -13,7 +13,7 @@ public class JwtSecurityConfig extends SecurityConfigurerAdapter - +
-
-

Auth API

-
-

Auth Kakao 소셜 로그인 회원가입 전

+

Auth Kakao 소셜 로그인 요청

HTTP request

-
POST /auth/signIn/kakao HTTP/1.1
+
POST /api/auth/signIn/kakao HTTP/1.1
 Content-Type: application/json;charset=UTF-8
 Content-Length: 36
 Host: localhost:8080
@@ -484,8 +485,11 @@ 

Request fields

+
+
+

Auth Kakao 소셜 로그인 회원가입 전 응답

-

HTTP response

+

HTTP response

HTTP/1.1 200 OK
@@ -505,7 +509,7 @@ 

HTTP response

-

Response fields

+

Response fields

@@ -550,48 +554,9 @@

Response fields

-

Auth Kakao 소셜 로그인 회원가입 후

+

Auth Kakao 소셜 로그인 회원가입 후 응답

-

HTTP request

-
-
-
POST /auth/signIn/kakao HTTP/1.1
-Content-Type: application/json;charset=UTF-8
-Content-Length: 36
-Host: localhost:8080
-
-{
-  "token" : "KAKAO_ACCESS_TOKEN"
-}
-
-
-
-
-

Request fields

-
----- - - - - - - - - - - - - - - -
PathTypeDescription

token

String

카카오 액세스 토큰

-
-
-

HTTP response

+

HTTP response

HTTP/1.1 200 OK
@@ -611,7 +576,7 @@ 

HTTP respon

-

Response fields

+

Response fields

@@ -657,12 +622,12 @@

Response
-

Auth Apple 소셜 로그인 회원가입 전

+

Auth Apple 소셜 로그인 요청

HTTP request

-
POST /auth/signIn/apple HTTP/1.1
+
POST /api/auth/signIn/apple HTTP/1.1
 Content-Type: application/json;charset=UTF-8
 Content-Length: 38
 Host: localhost:8080
@@ -697,8 +662,11 @@ 

Request fields

+
+
+

Auth Apple 소셜 로그인 회원가입 전 응답

-

HTTP response

+

HTTP response

HTTP/1.1 200 OK
@@ -718,7 +686,7 @@ 

HTTP response

-

Response fields

+

Response fields

@@ -763,48 +731,9 @@

Response fields

-

Auth Apple 소셜 로그인 회원가입 후

+

Auth Apple 소셜 로그인 회원가입 후 응답

-

HTTP request

-
-
-
POST /auth/signIn/apple HTTP/1.1
-Content-Type: application/json;charset=UTF-8
-Content-Length: 38
-Host: localhost:8080
-
-{
-  "token" : "APPLE_IDENTITY_TOKEN"
-}
-
-
-
-
-

Request fields

-
----- - - - - - - - - - - - - - - -
PathTypeDescription

token

String

애플 아이디 토큰

-
-
-

HTTP response

+

HTTP response

HTTP/1.1 200 OK
@@ -824,7 +753,7 @@ 

HTTP respon

-

Response fields

+

Response fields

@@ -874,9 +803,9 @@

Auth 회원가입

HTTP request

-
PUT /auth/signUp HTTP/1.1
+
PUT /api/auth/signUp HTTP/1.1
 Content-Type: application/json;charset=UTF-8
-Authorization: ACCESS_TOKEN
+Authorization: Bearer ACCESS_TOKEN
 Content-Length: 29
 Host: localhost:8080
 
@@ -976,25 +905,38 @@ 

Response fields

-

Auth 회원가입

+

Auth 토큰 재발급

-

HTTP request

+

HTTP request

-
PUT /auth/signUp HTTP/1.1
+
GET /api/auth/reissue HTTP/1.1
+RefreshToken: REFRESH_TOKEN
+Host: localhost:8080
+
+
+
+
+

HTTP response

+
+
+
HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
-Authorization: ACCESS_TOKEN
-Content-Length: 29
-Host: localhost:8080
+Content-Length: 178
 
 {
-  "nickName" : "NICKNAME"
+  "isSuccess" : true,
+  "message" : "토큰을 재발급했습니다",
+  "data" : {
+    "accessToken" : "SERVER_ACCESS_TOKEN",
+    "refreshToken" : "SERVER_REFRESH_TOKEN"
+  }
 }
-

Request fields

+

Response fields

@@ -1010,35 +952,74 @@

Request fields

- + + + + + + - + + + + + + + + + + +

nickName

isSuccess

Boolean

성공 여부 : true

message

String

유저 닉네임

토큰을 재발급했습니다

data.accessToken

String

서버 접근용 Token

data.refreshToken

String

서버 접근용 Refresh Token

+
+
+

Auth 닉네임 중복검사 요청

-

HTTP response

+

HTTP request

+
+
+
GET /api/auth/nickname/NICKNAME HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Host: localhost:8080
+
+
+
+
+
+

Auth 닉네임 중복인 경우

+
+

HTTP request

+
+
+
GET /api/auth/nickname/NICKNAME HTTP/1.1
+Content-Type: application/json;charset=UTF-8
+Host: localhost:8080
+
+
+
+
+

HTTP response

HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
-Content-Length: 209
+Content-Length: 124
 
 {
   "isSuccess" : true,
-  "message" : "회원 가입을 했습니다",
+  "message" : "닉네임 중복검사를 했습니다",
   "data" : {
-    "accessToken" : "SERVER_ACCESS_TOKEN",
-    "refreshToken" : "SERVER_REFRESH_TOKEN",
-    "registrationStatus" : true
+    "isDuplicated" : true
   }
 }
-

Response fields

+

Response fields

@@ -1056,65 +1037,53 @@

Response fields

- + - - - - - - - - - - - + - + - +

isSuccess

Boolean

true

성공 여부 : true

message

String

회원 가입을 했습니다

data.accessToken

String

서버 접근용 Access Token

data.refreshToken

String

서버 접근용 Refresh Token

닉네임 중복검사를 했습니다

data.registrationStatus

data.isDuplicated

Boolean

회원가입 여부 : true

닉네임 중복 여부 : ture

-

Auth 토큰 재발급

+

Auth 닉네임 중복이 아닌 경우

-

HTTP request

+

HTTP request

-
GET /auth/reissue HTTP/1.1
-RefreshToken: REFRESH_TOKEN
+
GET /api/auth/nickname/NICKNAME HTTP/1.1
 Host: localhost:8080
-

HTTP response

+

HTTP response

HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
-Content-Length: 178
+Content-Length: 125
 
 {
   "isSuccess" : true,
-  "message" : "토큰을 재발급했습니다",
+  "message" : "닉네임 중복검사를 했습니다",
   "data" : {
-    "accessToken" : "SERVER_ACCESS_TOKEN",
-    "refreshToken" : "SERVER_REFRESH_TOKEN"
+    "isDuplicated" : false
   }
 }
-

Response fields

+

Response fields

@@ -1137,29 +1106,22 @@

Response fields

- + - - - - - - - - + + +

message

String

토큰을 재발급했습니다

닉네임 중복검사를 했습니다

data.accessToken

String

서버 접근용 Token

data.refreshToken

String

서버 접근용 Refresh Token

data.isDuplicated

Boolean

닉네임 중복 여부 : false

-
-
diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html index 0738e9d2..5c6fb30f 100644 --- a/src/main/resources/static/docs/api.html +++ b/src/main/resources/static/docs/api.html @@ -455,13 +455,17 @@

Moing API Doc

  • Auth API
  • @@ -608,16 +612,14 @@

    User

    -
    -

    Auth API

    -
    +

    Auth API

    -

    Auth Kakao 소셜 로그인 회원가입 전

    +

    Auth Kakao 소셜 로그인 요청

    HTTP request

    -
    POST /auth/signIn/kakao HTTP/1.1
    +
    POST /api/auth/signIn/kakao HTTP/1.1
     Content-Type: application/json;charset=UTF-8
     Content-Length: 36
     Host: localhost:8080
    @@ -652,8 +654,11 @@ 

    +

    Auth Kakao 소셜 로그인 회원가입 전 응답

    -

    HTTP response

    +

    HTTP response

    HTTP/1.1 200 OK
    @@ -673,7 +678,7 @@ 

    -

    Response fields

    +

    Response fields

    @@ -718,48 +723,9 @@

    -

    Auth Kakao 소셜 로그인 회원가입 후

    +

    Auth Kakao 소셜 로그인 회원가입 후 응답

    -

    HTTP request

    -
    -
    -
    POST /auth/signIn/kakao HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 36
    -Host: localhost:8080
    -
    -{
    -  "token" : "KAKAO_ACCESS_TOKEN"
    -}
    -
    -
    -
    -
    ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    token

    String

    카카오 액세스 토큰

    -
    -
    -

    HTTP response

    +

    HTTP response

    HTTP/1.1 200 OK
    @@ -779,7 +745,7 @@ 

    -

    Response fields

    +

    Response fields

    @@ -825,12 +791,12 @@

    -

    Auth Apple 소셜 로그인 회원가입 전

    +

    Auth Apple 소셜 로그인 요청

    HTTP request

    -
    POST /auth/signIn/apple HTTP/1.1
    +
    POST /api/auth/signIn/apple HTTP/1.1
     Content-Type: application/json;charset=UTF-8
     Content-Length: 38
     Host: localhost:8080
    @@ -865,8 +831,11 @@ 

    +

    Auth Apple 소셜 로그인 회원가입 전 응답

    -

    HTTP response

    +

    HTTP response

    HTTP/1.1 200 OK
    @@ -886,7 +855,7 @@ 

    -

    Response fields

    +

    Response fields

    @@ -931,48 +900,9 @@

    -

    Auth Apple 소셜 로그인 회원가입 후

    -
    -

    HTTP request

    -
    -
    -
    POST /auth/signIn/apple HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 38
    -Host: localhost:8080
    -
    -{
    -  "token" : "APPLE_IDENTITY_TOKEN"
    -}
    -
    -
    -
    +

    Auth Apple 소셜 로그인 회원가입 후 응답

    ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    token

    String

    애플 아이디 토큰

    -
    -
    -

    HTTP response

    +

    HTTP response

    HTTP/1.1 200 OK
    @@ -992,7 +922,7 @@ 

    -

    Response fields

    +

    Response fields

    @@ -1042,9 +972,9 @@

    Auth 회원

    HTTP request

    -
    PUT /auth/signUp HTTP/1.1
    +
    PUT /api/auth/signUp HTTP/1.1
     Content-Type: application/json;charset=UTF-8
    -Authorization: ACCESS_TOKEN
    +Authorization: Bearer ACCESS_TOKEN
     Content-Length: 29
     Host: localhost:8080
     
    @@ -1144,25 +1074,38 @@ 

    -

    Auth 회원가입

    +

    Auth 토큰 재발급

    -

    HTTP request

    +

    HTTP request

    -
    PUT /auth/signUp HTTP/1.1
    +
    GET /api/auth/reissue HTTP/1.1
    +RefreshToken: REFRESH_TOKEN
    +Host: localhost:8080
    +
    +
    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
    -Authorization: ACCESS_TOKEN
    -Content-Length: 29
    -Host: localhost:8080
    +Content-Length: 178
     
     {
    -  "nickName" : "NICKNAME"
    +  "isSuccess" : true,
    +  "message" : "토큰을 재발급했습니다",
    +  "data" : {
    +    "accessToken" : "SERVER_ACCESS_TOKEN",
    +    "refreshToken" : "SERVER_REFRESH_TOKEN"
    +  }
     }

    @@ -1178,35 +1121,74 @@

    nickName

    +

    + + + + + - + + + + + + + + + + +

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    유저 닉네임

    토큰을 재발급했습니다

    data.accessToken

    String

    서버 접근용 Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    +
    +
    +

    Auth 닉네임 중복검사 요청

    -

    HTTP response

    +

    HTTP request

    +
    +
    +
    GET /api/auth/nickname/NICKNAME HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Host: localhost:8080
    +
    +
    +
    +
    +
    +

    Auth 닉네임 중복인 경우

    +
    +

    HTTP request

    +
    +
    +
    GET /api/auth/nickname/NICKNAME HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Host: localhost:8080
    +
    +
    +
    +
    +

    HTTP response

    HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
    -Content-Length: 209
    +Content-Length: 124
     
     {
       "isSuccess" : true,
    -  "message" : "회원 가입을 했습니다",
    +  "message" : "닉네임 중복검사를 했습니다",
       "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : true
    +    "isDuplicated" : true
       }
     }
    -

    Response fields

    +

    Response fields

    @@ -1224,65 +1206,53 @@

    isSuccess

    - + - - - - - - - - - - - + - + - +

    Boolean

    true

    성공 여부 : true

    message

    String

    회원 가입을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    닉네임 중복검사를 했습니다

    data.registrationStatus

    data.isDuplicated

    Boolean

    회원가입 여부 : true

    닉네임 중복 여부 : ture

    -

    Auth 토큰 재발급

    +

    Auth 닉네임 중복이 아닌 경우

    -

    HTTP request

    +

    HTTP request

    -
    GET /auth/reissue HTTP/1.1
    -RefreshToken: REFRESH_TOKEN
    +
    GET /api/auth/nickname/NICKNAME HTTP/1.1
     Host: localhost:8080
    -

    HTTP response

    +

    HTTP response

    HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
    -Content-Length: 178
    +Content-Length: 125
     
     {
       "isSuccess" : true,
    -  "message" : "토큰을 재발급했습니다",
    +  "message" : "닉네임 중복검사를 했습니다",
       "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN"
    +    "isDuplicated" : false
       }
     }
    -

    Response fields

    +

    Response fields

    @@ -1305,25 +1275,18 @@

    message

    - + - - - - - - - - + + +

    String

    토큰을 재발급했습니다

    닉네임 중복검사를 했습니다

    data.accessToken

    String

    서버 접근용 Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.isDuplicated

    Boolean

    닉네임 중복 여부 : false

    -
    -

    -
    -

    [[Mypage-회원탈퇴_ request_fields]] -== request fields

    -
    -

    Snippet request-fields not found for operation::mypage-controller-test/withdraw

    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + +
    PathTypeDescription

    reason

    String

    회원탈퇴하는 이유

    -
    -

    [[Mypage-회원탈퇴_ http_response]] -== http response

    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 70
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "회원탈퇴를 했습니다"
    +}
    -
    -

    Snippet http-response not found for operation::mypage-controller-test/withdraw

    @@ -569,7 +594,7 @@

    Response fields

    diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html index 4a1b7592..b3159844 100644 --- a/src/main/resources/static/docs/api.html +++ b/src/main/resources/static/docs/api.html @@ -1350,19 +1350,44 @@

    -

    [[Mypage-회원탈퇴_ request_fields]] -== request fields

    -
    -

    Snippet request-fields not found for operation::mypage-controller-test/withdraw

    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + +
    PathTypeDescription

    reason

    String

    회원탈퇴하는 이유

    -
    -

    [[Mypage-회원탈퇴_ http_response]] -== http response

    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 70
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "회원탈퇴를 했습니다"
    +}
    -
    -

    Snippet http-response not found for operation::mypage-controller-test/withdraw

    From 81940d72202573ecded78b101fdae3e3a58c32ac Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Wed, 23 Aug 2023 02:29:21 +0900 Subject: [PATCH 023/619] deploy: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index c47cefff..3bd742b1 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -76,8 +76,8 @@ jobs: - name: Docker build run: | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} - docker build -t ${{ secrets.DOCKER_USERNAME }}/moing:green . - docker build -t ${{ secrets.DOCKER_USERNAME }}/moing:blue . + docker build --no-cache -t ${{ secrets.DOCKER_USERNAME }}/moing:green . + docker build --no-cache -t ${{ secrets.DOCKER_USERNAME }}/moing:blue . docker push ${{ secrets.DOCKER_USERNAME }}/moing:green docker push ${{ secrets.DOCKER_USERNAME }}/moing:blue From f85ee4f7cc0d0f8e488a0a459e09f50134358e0b Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Wed, 23 Aug 2023 02:50:26 +0900 Subject: [PATCH 024/619] deploy: Update Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 351dda2c..3f9f0aa8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,5 @@ FROM openjdk:11-jdk +ARG CACHEBREAKER=1 ARG JAR_FILE=./build/libs/backend-0.0.1-SNAPSHOT.jar COPY ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"] From 0344fc7bda6c7d7878b853f2191d6b585febcb9f Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Wed, 23 Aug 2023 03:01:20 +0900 Subject: [PATCH 025/619] deploy: Update deploy.sh --- deploy.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deploy.sh b/deploy.sh index 8db595a0..6d3fed4d 100644 --- a/deploy.sh +++ b/deploy.sh @@ -1,6 +1,10 @@ DOCKER_APP_NAME=meetup DOCKER_USERNAME=modagbul +# 최신 이미지 가져오기 +docker pull ${DOCKER_USERNAME}/moing:blue +docker pull ${DOCKER_USERNAME}/moing:green + # 현재 실행 중인 컨테이너를 확인 (blue 또는 green) EXIST_BLUE=$(docker ps --filter name=${DOCKER_APP_NAME}-blue --filter status=running -q) EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --filter status=running -q) From 6b03dfbec96f133512de080a771d933e0abf6532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 23 Aug 2023 17:32:46 +0900 Subject: [PATCH 026/619] =?UTF-8?q?fix=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98,=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9C=84=ED=95=9C=20mapper=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mission/application/mapper/MissionMapper.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java index a781818a..31dee3cb 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java +++ b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java @@ -27,13 +27,11 @@ public static Mission mapToMission(MissionReq missionReq, Team team, Member memb .rule(missionReq.getRule()) .content(missionReq.getContent()) .way(MissionWay.valueOf(missionReq.getWay())) - .type(type) - .number(1) + .type(MissionType.valueOf(missionReq.getType())) + .number(missionReq.getNumber()) .status(MissionStatus.WAIT) .build(); - - } public static MissionCreateRes mapToMissionCreateRes(Mission mission) { From 82985ffc1d3153ca606ab3c184743b1e0ca1ba47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 23 Aug 2023 19:13:30 +0900 Subject: [PATCH 027/619] =?UTF-8?q?fix=20:=20test=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/MissionCreateRes.java | 2 +- .../representation/MissionControllerTest.java | 21 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java index 4bf467dc..dce5e67d 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java @@ -12,7 +12,7 @@ public class MissionCreateRes { private String rule; private String content; - private Long number; + private int number; private String type; private String status; diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index 3e378d2e..cfdd2f3c 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -9,6 +9,7 @@ import com.moing.backend.domain.mission.application.service.MissionReadUseCase; import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; import com.moing.backend.domain.mission.domain.repository.MissionRepository; +import com.moing.backend.domain.mission.presentation.MissionController; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -26,27 +27,29 @@ import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -@WebMvcTest +@WebMvcTest(MissionController.class) public class MissionControllerTest extends CommonControllerTest { @MockBean private MissionCreateUseCase missionCreateUseCase; + @MockBean private MissionUpdateUseCase missionUpdateUseCase; + @MockBean private MissionReadUseCase missionReadUseCase; + @MockBean private MissionDeleteUseCase missionDeleteUseCase; - @Autowired - private MissionRepository missionRepository; + @Test public void 미션_생성() throws Exception { //given MissionReq input = MissionReq.builder() .title("title") - .dueTo("dueTo") + .dueTo("2023-12-31 23:39:22 333") .rule("rule") .content("content") .number(1) @@ -61,7 +64,7 @@ public class MissionControllerTest extends CommonControllerTest { .dueTo("dueTo") .rule("rule") .content("content") - .number(1L) + .number(1) .type("TEXT") .status("WAIT") .way("TEXT") @@ -119,7 +122,7 @@ public class MissionControllerTest extends CommonControllerTest { .dueTo("dueTo") .rule("rule") .content("content") - .number(1L) + .number(1) .type("TEXT") .status("WAIT") .way("TEXT") @@ -175,7 +178,7 @@ public class MissionControllerTest extends CommonControllerTest { //when ResultActions actions = mockMvc.perform( - get("/mission/{missionId}") + get("/mission/{missionId}",1) .contentType(MediaType.APPLICATION_JSON) ); @@ -214,7 +217,7 @@ public class MissionControllerTest extends CommonControllerTest { .dueTo("dueTo") .rule("rule") .content("content") - .number(1L) + .number(1) .type("TEXT") .status("WAIT") .way("TEXT") @@ -224,7 +227,7 @@ public class MissionControllerTest extends CommonControllerTest { //when ResultActions actions = mockMvc.perform( - delete("/mission/{missionId}") + delete("/mission/{missionId}",1) .contentType(MediaType.APPLICATION_JSON) ); From 41af520ad020a9c46cbcf1b801f5e70009d53d00 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Fri, 25 Aug 2023 15:29:01 +0900 Subject: [PATCH 028/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Overview.adoc | 9 + src/docs/asciidoc/Team-API.adoc | 28 + src/docs/asciidoc/api.adoc | 2 + .../domain/member/domain/entity/Member.java | 27 +- .../dto/request/CreateTeamRequest.java | 37 + .../dto/response/CreateTeamResponse.java | 14 + .../team/application/mapper/TeamMapper.java | 9 + .../service/CreateTeamUserCase.java | 33 + .../team/domain/constant/ApprovalStatus.java | 14 + .../domain/team/domain/constant/Category.java | 18 + .../domain/team/domain/entity/Team.java | 91 ++ .../repository/TeamCustomRepository.java | 4 + .../repository/TeamCustomRepositoryImpl.java | 4 + .../domain/repository/TeamRepository.java | 7 + .../team/domain/service/TeamSaveService.java | 15 + .../presentation/AdminTeamController.java | 16 + .../team/presentation/TeamController.java | 36 + .../constant/TeamResponseMessage.java | 11 + .../teamMember/domain/entity/TeamMember.java | 48 + .../TeamMemberCustomRepository.java | 7 + .../TeamMemberCustomRepositoryImpl.java | 25 + .../repository/TeamMemberRepository.java | 7 + .../domain/service/TeamMemberGetService.java | 17 + .../domain/service/TeamMemberSaveService.java | 20 + .../exception/TeamMemberException.java | 11 + .../exception/TooManyTeamMemberException.java | 11 + .../config/security/SecurityConfig.java | 2 +- .../backend/global/response/ErrorCode.java | 8 +- src/main/resources/static/docs/Overview.html | 24 +- src/main/resources/static/docs/Team-API.html | 615 ++++++++++++ src/main/resources/static/docs/api.html | 876 ++---------------- .../team/presentation/TeamControllerTest.java | 79 ++ 32 files changed, 1315 insertions(+), 810 deletions(-) create mode 100644 src/docs/asciidoc/Team-API.adoc create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/request/CreateTeamRequest.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/CreateTeamResponse.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/team/domain/constant/ApprovalStatus.java create mode 100644 src/main/java/com/moing/backend/domain/team/domain/constant/Category.java create mode 100644 src/main/java/com/moing/backend/domain/team/domain/entity/Team.java create mode 100644 src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/team/domain/repository/TeamRepository.java create mode 100644 src/main/java/com/moing/backend/domain/team/domain/service/TeamSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java create mode 100644 src/main/java/com/moing/backend/domain/team/presentation/TeamController.java create mode 100644 src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java create mode 100644 src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java create mode 100644 src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java create mode 100644 src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java create mode 100644 src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/teamMember/exception/TeamMemberException.java create mode 100644 src/main/java/com/moing/backend/domain/teamMember/exception/TooManyTeamMemberException.java create mode 100644 src/main/resources/static/docs/Team-API.html create mode 100644 src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java diff --git a/src/docs/asciidoc/Overview.adoc b/src/docs/asciidoc/Overview.adoc index 1ba5a3e8..4461b8a4 100644 --- a/src/docs/asciidoc/Overview.adoc +++ b/src/docs/asciidoc/Overview.adoc @@ -80,4 +80,13 @@ | appId가 일치하지 않음 (유효하지 않음) |=== +=== Team / Team_member ErrorCode +|=== +| ErrorCode | Scope | Description +| `TM0001` +| 팀 개설할 때 +| 팀 최대 개수 3을 초과 +|=== + + diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc new file mode 100644 index 00000000..d17ccd0c --- /dev/null +++ b/src/docs/asciidoc/Team-API.adoc @@ -0,0 +1,28 @@ +[[Team-API]] += Team API + +[[Team-소모임-개설]] +=== Team 소모임 개설 +operation::team-controller-test/create_team[snippets='http-request,request-fields,http-response,response-fields'] + +=== 소모임 카테고리 +|=== +| Category | Description + +| `SPORTS` +| 스포츠/운동 + +| `HABIT` +| 생활습관 개선 + +| `TEST` +| 시험/취업준비 + +| `STUDY` +| 스터디/공부 + +| `READING` +| 독서 + +| `ETC` +| 그외 자기계발 \ No newline at end of file diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 8a41bcf5..b17fac77 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -12,4 +12,6 @@ include::Auth-API.adoc[] include::Mypage-API.adoc[] +include::Team-API.adoc[] + diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index dec48f15..5017d9b7 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.member.domain.constant.RegistrationStatus; import com.moing.backend.domain.member.domain.constant.Role; import com.moing.backend.domain.member.domain.constant.SocialProvider; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.entity.BaseTimeEntity; import com.moing.backend.global.util.AesConverter; import lombok.AllArgsConstructor; @@ -13,6 +14,8 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; @Entity @Builder @@ -33,6 +36,7 @@ public class Member extends BaseTimeEntity { private SocialProvider provider; @Enumerated(EnumType.STRING) + @Column(nullable = false) private RegistrationStatus registrationStatus; @Convert(converter = AesConverter.class) @@ -40,16 +44,20 @@ public class Member extends BaseTimeEntity { private String email; @Convert(converter = AesConverter.class) + @Column(nullable = false) private String profileImage; //없으면 undef + @Column(nullable = false, length = 6) private String gender; //없으면 undef + @Column(nullable = false, length = 10) private String ageRange; //없으면 undef private boolean isDeleted; // 추가정보 @Convert(converter = AesConverter.class) + @Column(nullable = false, unique = true) private String nickName; //없으면 undef @Column(nullable = false) @@ -57,8 +65,10 @@ public class Member extends BaseTimeEntity { private Role role; @Convert(converter = AesConverter.class) + @Column(nullable = false) private String introduction; //없으면 undef + @Column(nullable = false) private String fcmToken; //없으면 undef @ColumnDefault("true") @@ -70,6 +80,8 @@ public class Member extends BaseTimeEntity { @ColumnDefault("true") private boolean isFirePush; + @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) + private List teamMembers = new ArrayList<>(); //최대 3개이므로 양방향 //==생성 메서드==// public static Member valueOf(OAuth2User oAuth2User) { @@ -86,6 +98,7 @@ public static Member valueOf(OAuth2User oAuth2User) { .build(); } + //==초기화==// @PrePersist public void prePersist() { if (profileImage == null) profileImage = "undef"; @@ -121,7 +134,8 @@ public void updateMember(String nickName, String fcmToken) { this.fcmToken = fcmToken; } - public void updateMypage(String nickName, String introduction) { + public void updateProfile(String profileImage, String nickName, String introduction) { + this.profileImage = profileImage; this.nickName = nickName; this.introduction = introduction; } @@ -129,7 +143,10 @@ public void updateMypage(String nickName, String introduction) { public void deleteAccount() { this.isDeleted = true; } - public void reSignUp(){this.isDeleted=false;} + + public void reSignUp() { + this.isDeleted = false; + } public void updateNewUploadPush(boolean newUploadPush) { this.isNewUploadPush = newUploadPush; @@ -143,8 +160,10 @@ public void updateFirePush(boolean firePush) { this.isFirePush = firePush; } - public void updateProfile(String string) { - this.profileImage = string; + public void updateAllPush(boolean allPush) { + this.isNewUploadPush = allPush; + this.isRemindPush = allPush; + this.isFirePush = allPush; } } diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/request/CreateTeamRequest.java b/src/main/java/com/moing/backend/domain/team/application/dto/request/CreateTeamRequest.java new file mode 100644 index 00000000..a7f3ce33 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/request/CreateTeamRequest.java @@ -0,0 +1,37 @@ +package com.moing.backend.domain.team.application.dto.request; + +import com.moing.backend.domain.team.domain.constant.Category; +import com.moing.backend.global.annotation.Enum; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class CreateTeamRequest { + @NotBlank(message = "category 를 입력해 주세요.") + @Enum(enumClass = Category.class) + private String category; + + @NotBlank(message = "name 을 입력해 주세요.") + @Size(min = 1, max = 10, message = "name 은 최소 1개, 최대 10개의 문자만 입력 가능합니다.") + private String name; + + @NotBlank(message = "introduction 을 입력해 주세요.") + @Size(min = 1, max = 300, message = "introduction 은 최소 1개, 최대 300개의 문자만 입력 가능합니다.") + private String introduction; + + @NotBlank(message = "promise 를 입력해 주세요.") + @Size(min = 1, max = 100, message = "promise 는 최소 1개, 최대 100개의 문자만 입력 가능합니다.") + private String promise; + + @NotBlank(message = "profileImgUrl 을 입력해 주세요.") + private String profileImgUrl; + +} diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/CreateTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/CreateTeamResponse.java new file mode 100644 index 00000000..b87b04ce --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/CreateTeamResponse.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.team.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CreateTeamResponse { + private Long teamId; +} diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java new file mode 100644 index 00000000..2118d7f0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -0,0 +1,9 @@ +package com.moing.backend.domain.team.application.mapper; + +import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; +import com.moing.backend.domain.team.domain.entity.Team; +import org.springframework.stereotype.Component; + +@Component +public class TeamMapper { +} diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java new file mode 100644 index 00000000..9ab01cb6 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java @@ -0,0 +1,33 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; +import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamSaveService; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberSaveService; +import lombok.RequiredArgsConstructor; +import org.checkerframework.checker.units.qual.C; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class CreateTeamUserCase { + + private final MemberGetService memberGetService; + private final TeamSaveService teamSaveService; + private final TeamMemberSaveService teamMemberSaveService; + + public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String socialId){ + Member member = memberGetService.getMemberBySocialId(socialId); + Team team=Team.createTeam(createTeamRequest, member); + teamSaveService.saveTeam(team); + teamMemberSaveService.saveTeamMember(team, member); + return new CreateTeamResponse(team.getTeamId()); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/constant/ApprovalStatus.java b/src/main/java/com/moing/backend/domain/team/domain/constant/ApprovalStatus.java new file mode 100644 index 00000000..3a5695dd --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/domain/constant/ApprovalStatus.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.team.domain.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@AllArgsConstructor +public enum ApprovalStatus { + NO_CONFIRMATION("확인안함"), + APPROVAL("승인"), + REJECTION("거절"); + private final String message; +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/constant/Category.java b/src/main/java/com/moing/backend/domain/team/domain/constant/Category.java new file mode 100644 index 00000000..79f02adb --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/domain/constant/Category.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.team.domain.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum Category{ + SPORTS("스포츠/운동"), + HABIT("생활습관 개선"), + TEST("시험/취업준비"), + STUDY("스터디/공부"), + READING("독서"), + ETC("그외 자기계발"); + + private final String message; +} + diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java new file mode 100644 index 00000000..79a47187 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -0,0 +1,91 @@ +package com.moing.backend.domain.team.domain.entity; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; +import com.moing.backend.domain.team.domain.constant.ApprovalStatus; +import com.moing.backend.domain.team.domain.constant.Category; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.time.LocalDateTime; +import java.time.ZoneId; + +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Entity +public class Team extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "team_id") + private Long teamId; + + @Enumerated(EnumType.STRING) + @Column(nullable = false, length = 10) + private Category category; + + @Column(nullable = false, length = 10) + private String name; + + @Column(nullable = false) + private String profileImgUrl; + + @Column(nullable = false, length = 300) + private String introduction; + + @Column(nullable = false, length = 100) + private String promise; + + @Column(nullable = false) + private Long leaderId; + + private String invitationCode; + + @Column(nullable = false, length = 16) + @Enumerated(EnumType.STRING) + private ApprovalStatus approvalStatus; + + private LocalDateTime approvalTime; + + private boolean isDeleted; + + private LocalDateTime deletionTime; + + public static Team createTeam(CreateTeamRequest createTeamRequest, Member member) { + return Team.builder() + .category(Enum.valueOf(Category.class, createTeamRequest.getCategory())) + .name(createTeamRequest.getName()) + .introduction(createTeamRequest.getIntroduction()) + .promise(createTeamRequest.getPromise()) + .profileImgUrl(createTeamRequest.getProfileImgUrl()) + .approvalStatus(ApprovalStatus.NO_CONFIRMATION) + .leaderId(member.getMemberId()) + .build(); + } + + public void approveTeam() { + this.approvalStatus = ApprovalStatus.APPROVAL; + this.approvalTime = LocalDateTime.now(ZoneId.of("Asia/Seoul")).withNano(0); + } + + public void rejectTeam() { + this.approvalStatus = ApprovalStatus.REJECTION; + } + + public void updateTeam(String name, String introduction, String profileImgUrl) { + this.name = name; + this.introduction = introduction; + this.profileImgUrl = profileImgUrl; + } + + public void deleteTeam() { + this.isDeleted = true; + this.deletionTime = LocalDateTime.now(ZoneId.of("Asia/Seoul")).withNano(0); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java new file mode 100644 index 00000000..0acfe4cf --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -0,0 +1,4 @@ +package com.moing.backend.domain.team.domain.repository; + +public interface TeamCustomRepository { +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java new file mode 100644 index 00000000..adaf2525 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -0,0 +1,4 @@ +package com.moing.backend.domain.team.domain.repository; + +public class TeamCustomRepositoryImpl implements TeamCustomRepository{ +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamRepository.java new file mode 100644 index 00000000..46d64c1b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.team.domain.repository; + +import com.moing.backend.domain.team.domain.entity.Team; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TeamRepository extends JpaRepository, TeamCustomRepository { +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamSaveService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamSaveService.java new file mode 100644 index 00000000..11a48024 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamSaveService.java @@ -0,0 +1,15 @@ +package com.moing.backend.domain.team.domain.service; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.repository.TeamRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class TeamSaveService { + private final TeamRepository teamRepository; + public void saveTeam(Team team){ + teamRepository.save(team); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java new file mode 100644 index 00000000..ec73d377 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.team.presentation; + +import com.moing.backend.domain.team.application.service.CreateTeamUserCase; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/admin/team") +public class AdminTeamController { + + //TODO 소모임 승인, 반려하기 + + private final CreateTeamUserCase createTeamService; +} diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java new file mode 100644 index 00000000..3f198df9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -0,0 +1,36 @@ +package com.moing.backend.domain.team.presentation; + +import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; +import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; +import com.moing.backend.domain.team.application.service.CreateTeamUserCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +import static com.moing.backend.domain.team.presentation.constant.TeamResponseMessage.CREATE_TEAM_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/team") +public class TeamController { + private final CreateTeamUserCase createTeamService; + + /** + * 소모임 생성 (only 개설만) + * [POST] api/team + * 작성자 : 김민수 + */ + @PostMapping + public ResponseEntity> createTeam(@AuthenticationPrincipal User user, + @Valid @RequestBody CreateTeamRequest createTeamRequest) { + return ResponseEntity.ok(SuccessResponse.create(CREATE_TEAM_SUCCESS.getMessage(), this.createTeamService.createTeam(createTeamRequest,user.getSocialId()))); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java new file mode 100644 index 00000000..34f74c20 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.team.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum TeamResponseMessage { + CREATE_TEAM_SUCCESS("소모임을 생성하였습니다"); + private final String message; +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java new file mode 100644 index 00000000..16d96bb5 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java @@ -0,0 +1,48 @@ +package com.moing.backend.domain.teamMember.domain.entity; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.exception.TooManyTeamMemberException; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class TeamMember extends BaseTimeEntity { + + @Id + @GeneratedValue + @Column(name="team_member_id") + private Long teamMemberId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team_id") + private Team team; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + //==연관관계 메서드==// + public void updateTeam(Team team){ + this.team=team; + } + + public void updateMember(Member member){ + if(member.getTeamMembers().size()<3) { + this.member = member; + member.getTeamMembers().add(this); + }else{ + throw new TooManyTeamMemberException(); + } + } + +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java new file mode 100644 index 00000000..25422e2b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.teamMember.domain.repository; + +import java.util.List; + +public interface TeamMemberCustomRepository { + List getMemberIdsByTeamId(Long teamId); +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java new file mode 100644 index 00000000..0c84aebf --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -0,0 +1,25 @@ +package com.moing.backend.domain.teamMember.domain.repository; + +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.util.List; + +import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; + +public class TeamMemberCustomRepositoryImpl implements TeamMemberCustomRepository { + private final JPAQueryFactory queryFactory; + + public TeamMemberCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + @Override + public List getMemberIdsByTeamId(Long teamId) { + return queryFactory + .select(teamMember.member.memberId) + .from(teamMember) + .where(teamMember.team.teamId.eq(teamId)) + .fetch(); + } +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java new file mode 100644 index 00000000..77049443 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.teamMember.domain.repository; + +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TeamMemberRepository extends JpaRepository, TeamMemberCustomRepository{ +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java new file mode 100644 index 00000000..b3cb6b31 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.teamMember.domain.service; + +import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@DomainService +@RequiredArgsConstructor +public class TeamMemberGetService { + private final TeamMemberRepository teamMemberRepository; + + public List getTeamMemberIds(Long teamId){ + return teamMemberRepository.getMemberIdsByTeamId(teamId); + } +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java new file mode 100644 index 00000000..82baab9e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.teamMember.domain.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class TeamMemberSaveService { + private final TeamMemberRepository teamMemberRepository; + public void saveTeamMember(Team team, Member member){ + TeamMember teamMember=new TeamMember(); + teamMember.updateMember(member); + teamMember.updateTeam(team); + this.teamMemberRepository.save(teamMember); + } +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/exception/TeamMemberException.java b/src/main/java/com/moing/backend/domain/teamMember/exception/TeamMemberException.java new file mode 100644 index 00000000..d47d2e21 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamMember/exception/TeamMemberException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.teamMember.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class TeamMemberException extends ApplicationException { + protected TeamMemberException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/exception/TooManyTeamMemberException.java b/src/main/java/com/moing/backend/domain/teamMember/exception/TooManyTeamMemberException.java new file mode 100644 index 00000000..d8047bc5 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamMember/exception/TooManyTeamMemberException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.teamMember.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class TooManyTeamMemberException extends TeamMemberException{ + public TooManyTeamMemberException(){ + super(ErrorCode.TOO_MANY_TEAM_MEMBER_ERROR, + HttpStatus.FORBIDDEN); + } +} diff --git a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java index 068fe0f6..efcafd2e 100644 --- a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java +++ b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java @@ -7,7 +7,6 @@ import com.moing.backend.global.config.security.jwt.TokenUtil; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; @@ -50,6 +49,7 @@ protected void configure(HttpSecurity http) throws Exception { .and() .authorizeRequests() .antMatchers("/api/auth/**", "/docs/**").permitAll() + .antMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .apply(new JwtSecurityConfig(tokenUtil, memberQueryService)); diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 0ce41764..16041802 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -11,14 +11,18 @@ public enum ErrorCode { BAD_REQUEST("400", "올바른 패턴을 입력하세요."), METHOD_NOT_ALLOWED("405", "클라이언트가 사용한 HTTP 메서드가 리소스에서 허용되지 않습니다."), INTERNAL_SERVER_ERROR("500", "서버에서 요청을 처리하는 동안 오류가 발생했습니다."), + NOT_FOUND_REFRESH_TOKEN_ERROR( "J0008", "유효하지 않는 RefreshToken 입니다."), //유저 관련 에러 코드 NOT_FOUND_BY_SOCIAL_ID_ERROR( "U0001", "해당 socialId인 유저가 존재하지 않습니다."), - NOT_FOUND_REFRESH_TOKEN_ERROR( "J0008", "유효하지 않는 RefreshToken 입니다."), ACCOUNT_ALREADY_EXIST("AU0001", "이미 다른 소셜 플랫폼으로 가입하였습니다."), TOKEN_INVALID_ERROR("AU0002", "입력 토큰이 유효하지 않습니다."), APPID_INVALID_ERROR("AU0003", "appId가 유효하지 않습니다"), - NICKNAME_DUPLICATION_ERROR("AU0003", "닉네임이 중복됩니다."); + NICKNAME_DUPLICATION_ERROR("AU0003", "닉네임이 중복됩니다."), + + //팀멤버 에러 코드 + TOO_MANY_TEAM_MEMBER_ERROR("TM0001", "팀 최대 개수 3을 초과했습니다"); + private String errorCode; private String message; diff --git a/src/main/resources/static/docs/Overview.html b/src/main/resources/static/docs/Overview.html index 3b68948b..667acaae 100644 --- a/src/main/resources/static/docs/Overview.html +++ b/src/main/resources/static/docs/Overview.html @@ -578,13 +578,35 @@

    User / Auth ErrorCode

    +
    +

    Team / Team_member ErrorCode

    + +++++ + + + + + + + + + + + + +

    ErrorCode

    Scope

    Description

    TM0001

    팀 개설할 때

    팀 최대 개수 3을 초과

    +
    diff --git a/src/main/resources/static/docs/Team-API.html b/src/main/resources/static/docs/Team-API.html new file mode 100644 index 00000000..d25e0771 --- /dev/null +++ b/src/main/resources/static/docs/Team-API.html @@ -0,0 +1,615 @@ + + + + + + + +Team API + + + + + +
    +
    +

    Team 소모임 개설

    +
    +

    HTTP request

    +
    +
    +
    POST /api/team HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Content-Length: 182
    +Host: localhost:8080
    +
    +{
    +  "category" : "ETC",
    +  "name" : "소모임 이름",
    +  "introduction" : "소모임 소개글",
    +  "promise" : "소모임 각오",
    +  "profileImgUrl" : "소모임 대표 사진 URL"
    +}
    +
    +
    +
    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    category

    String

    카테고리

    name

    String

    소모임 이름

    introduction

    String

    소모임 소개글

    profileImgUrl

    String

    소모임 대표 사진

    promise

    String

    소모임 각오

    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 111
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "소모임을 생성하였습니다",
    +  "data" : {
    +    "teamId" : 1
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    소모임을 생성하였습니다

    data.teamId

    Number

    생성한 teamId

    +
    +
    +
    +

    소모임 카테고리

    + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CategoryDescription

    SPORTS

    스포츠/운동

    HABIT

    생활습관 개선

    TEST

    시험/취업준비

    STUDY

    스터디/공부

    READING

    독서

    ETC

    그외 자기계발

    +
    +
    + + + \ No newline at end of file diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html index b3159844..76a690d6 100644 --- a/src/main/resources/static/docs/api.html +++ b/src/main/resources/static/docs/api.html @@ -451,27 +451,7 @@

    Moing API Doc

  • Error Response DTO
  • Common ErrorCode
  • User / Auth ErrorCode
  • - - -
  • Auth API - -
  • -
  • Mypage API -
  • @@ -616,815 +596,107 @@

    User

    -
    -
    -

    Auth API

    -
    -

    Auth Kakao 소셜 로그인 요청

    -
    -

    HTTP request

    -
    -
    -
    POST /api/auth/signIn/kakao HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 36
    -Host: localhost:8080
    -
    -{
    -  "token" : "KAKAO_ACCESS_TOKEN"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    token

    String

    카카오 액세스 토큰

    -
    -
    -
    -

    Auth Kakao 소셜 로그인 회원가입 전 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 206
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : false
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 : false

    -
    -
    -
    -

    Auth Kakao 소셜 로그인 회원가입 후 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 205
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :true

    -
    -
    -
    -
    -

    Auth Apple 소셜 로그인 요청

    -
    -

    HTTP request

    -
    -
    -
    POST /api/auth/signIn/apple HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 38
    -Host: localhost:8080
    -
    -{
    -  "token" : "APPLE_IDENTITY_TOKEN"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    token

    String

    애플 아이디 토큰

    -
    -
    -
    -

    Auth Apple 소셜 로그인 회원가입 전 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 206
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : false
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :false

    -
    -
    -
    -

    Auth Apple 소셜 로그인 회원가입 후 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 205
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :true

    -
    -
    -
    -

    Auth 회원가입

    -
    -

    HTTP request

    -
    -
    -
    PUT /api/auth/signUp HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 29
    -Host: localhost:8080
    -
    -{
    -  "nickName" : "NICKNAME"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    nickName

    String

    유저 닉네임

    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 209
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "회원 가입을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    회원 가입을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 : true

    -
    -
    -
    -

    Auth 토큰 재발급

    -
    -

    HTTP request

    -
    -
    -
    GET /api/auth/reissue HTTP/1.1
    -RefreshToken: REFRESH_TOKEN
    -Host: localhost:8080
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 178
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "토큰을 재발급했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN"
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    토큰을 재발급했습니다

    data.accessToken

    String

    서버 접근용 Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    -
    -
    -
    -

    Auth 닉네임 중복검사 요청

    -
    -

    HTTP request

    -
    -
    -
    GET /api/auth/nickname/NICKNAME HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Host: localhost:8080
    -
    -
    -
    -
    -
    -

    Auth 닉네임 중복인 경우

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 124
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "닉네임 중복검사를 했습니다",
    -  "data" : {
    -    "isDuplicated" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    닉네임 중복검사를 했습니다

    data.isDuplicated

    Boolean

    닉네임 중복 여부 : ture

    -
    -
    -

    Auth 닉네임 중복이 아닌 경우

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 125
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "닉네임 중복검사를 했습니다",
    -  "data" : {
    -    "isDuplicated" : false
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    닉네임 중복검사를 했습니다

    data.isDuplicated

    Boolean

    닉네임 중복 여부 : false

    -
    -
    -

    Mypage API

    -
    -

    Mypage 로그아웃

    -
    -

    HTTP request

    -
    -
    -
    POST /api/mypage/signOut HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Host: localhost:8080
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 70
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그아웃을 했습니다"
    -}
    -
    -
    -
    -
    -

    Response fields

    +

    Team / Team_member ErrorCode

    - - - - - - - - - - + + + - - - + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    ErrorCode

    Scope

    Description

    message

    String

    로그아웃을 했습니다

    TM0001

    팀 개설할 때

    팀 최대 개수 3을 초과

    +

    += Auth API

    +

    +=== Auth Kakao 소셜 로그인 요청 +operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-request,request-fields']

    +

    === Auth Kakao 소셜 로그인 회원가입 전 응답 +operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-response,response-fields']

    +

    === Auth Kakao 소셜 로그인 회원가입 후 응답 +operation::auth-controller-test/kakao_소셜_로그인_회원가입_후[snippets='http-response,response-fields']

    +

    ---

    +

    +=== Auth Apple 소셜 로그인 요청 +operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-request,request-fields']

    +

    === Auth Apple 소셜 로그인 회원가입 전 응답 +operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-response,response-fields']

    +

    === Auth Apple 소셜 로그인 회원가입 후 응답 +operation::auth-controller-test/apple_소셜_로그인_회원가입_후[snippets='http-response,response-fields']

    +

    +=== Auth 회원가입 +operation::auth-controller-test/sign_up[snippets='http-request,request-fields,http-response,response-fields']

    +

    +=== Auth 토큰 재발급 +operation::auth-controller-test/reissue_token[snippets='http-request,http-response,response-fields']

    +

    +=== Auth 닉네임 중복검사 요청 +operation::auth-controller-test/check_nickname_중복o[snippets='http-request']

    +

    === Auth 닉네임 중복인 경우 +operation::auth-controller-test/check_nickname_중복o[snippets='http-response,response-fields']

    +

    === Auth 닉네임 중복이 아닌 경우 +operation::auth-controller-test/check_nickname_중복x[snippets='http-response,response-fields']

    +

    += Mypage API

    +

    +=== Mypage 로그아웃 +operation::mypage-controller-test/sign_out[snippets='http-request,http-response,response-fields']

    +

    ---

    +

    +=== Mypage 회원탈퇴 +operation::mypage-controller-test/withdraw[snippets='http-request,request-fields,http-response,response-fields']

    +

    += Team API

    +

    +=== Team 소모임 개설 +operation::team-controller-test/create_team[snippets='http-request,request-fields,http-response,response-fields']

    +

    === 소모임 카테고리

    +
    +

    | Category | Description

    -
    +
    +

    | SPORTS +| 스포츠/운동

    -
    -

    Mypage 회원탈퇴

    -
    -

    HTTP request

    -
    -
    -
    DELETE /api/mypage/withdrawal HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 34
    -Host: localhost:8080
    -
    -{
    -  "reason" : "REASON_TO_LEAVE"
    -}
    +
    +

    | HABIT +| 생활습관 개선

    +
    +

    | TEST +| 시험/취업준비

    +
    +

    | STUDY +| 스터디/공부

    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    reason

    String

    회원탈퇴하는 이유

    +
    +

    | READING +| 독서

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 70
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "회원탈퇴를 했습니다"
    -}
    +
    +

    | ETC +| 그외 자기계발

    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    회원탈퇴를 했습니다

    -
    diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java new file mode 100644 index 00000000..4134766d --- /dev/null +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -0,0 +1,79 @@ +package com.moing.backend.domain.team.presentation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; +import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; +import com.moing.backend.domain.team.application.service.CreateTeamUserCase; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.ResultActions; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(TeamController.class) +public class TeamControllerTest extends CommonControllerTest { + @MockBean + private CreateTeamUserCase createTeamService; + + @Test + public void create_team() throws Exception { + + //given + CreateTeamRequest input = CreateTeamRequest.builder() + .category("ETC") + .name("소모임 이름") + .introduction("소모임 소개글") + .profileImgUrl("소모임 대표 사진 URL") + .promise("소모임 각오") + .build(); + + String body = objectMapper.writeValueAsString(input); + + CreateTeamResponse output = CreateTeamResponse.builder() + .teamId(1L) + .build(); + + given(createTeamService.createTeam(any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform( + post("/api/team") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + requestFields( + fieldWithPath("category").description("카테고리"), + fieldWithPath("name").description("소모임 이름"), + fieldWithPath("introduction").description("소모임 소개글"), + fieldWithPath("profileImgUrl").description("소모임 대표 사진"), + fieldWithPath("promise").description("소모임 각오") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("소모임을 생성하였습니다"), + fieldWithPath("data.teamId").description("생성한 teamId") + ) + ) + ); + } +} From e3526723bb64fc38b19990ce00017b39a190f613 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Fri, 25 Aug 2023 23:10:32 +0900 Subject: [PATCH 029/619] docs: Update api.adoc --- src/docs/asciidoc/api.adoc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index b17fac77..afc5cc1b 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -14,4 +14,3 @@ include::Mypage-API.adoc[] include::Team-API.adoc[] - From 73deb3afcaf98751c395fd436f02be159c630a80 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Fri, 25 Aug 2023 23:14:09 +0900 Subject: [PATCH 030/619] =?UTF-8?q?docs:=20api.html=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/api.adoc | 1 - .../presentation/AdminTeamController.java | 2 + src/main/resources/static/docs/Overview.html | 2 +- src/main/resources/static/docs/api.html | 1052 +++++++++++++++-- 4 files changed, 988 insertions(+), 69 deletions(-) diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index b17fac77..afc5cc1b 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -14,4 +14,3 @@ include::Mypage-API.adoc[] include::Team-API.adoc[] - diff --git a/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java index ec73d377..3241479e 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java @@ -13,4 +13,6 @@ public class AdminTeamController { //TODO 소모임 승인, 반려하기 private final CreateTeamUserCase createTeamService; + + } diff --git a/src/main/resources/static/docs/Overview.html b/src/main/resources/static/docs/Overview.html index 667acaae..27e12002 100644 --- a/src/main/resources/static/docs/Overview.html +++ b/src/main/resources/static/docs/Overview.html @@ -606,7 +606,7 @@

    Team / Team_member ErrorCode

    diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html index 76a690d6..5cd5701a 100644 --- a/src/main/resources/static/docs/api.html +++ b/src/main/resources/static/docs/api.html @@ -454,6 +454,33 @@

    Moing API Doc

  • Team / Team_member ErrorCode
  • +
  • Auth API + +
  • +
  • Mypage API + +
  • +
  • Team API + +
  • @@ -613,90 +640,981 @@

    TM0001

    팀 개설할 때

    -

    팀 최대 개수 3을 초과

    -

    -= Auth API

    -

    -=== Auth Kakao 소셜 로그인 요청 -operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-request,request-fields']

    -

    === Auth Kakao 소셜 로그인 회원가입 전 응답 -operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-response,response-fields']

    -

    === Auth Kakao 소셜 로그인 회원가입 후 응답 -operation::auth-controller-test/kakao_소셜_로그인_회원가입_후[snippets='http-response,response-fields']

    -

    ---

    -

    -=== Auth Apple 소셜 로그인 요청 -operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-request,request-fields']

    -

    === Auth Apple 소셜 로그인 회원가입 전 응답 -operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-response,response-fields']

    -

    === Auth Apple 소셜 로그인 회원가입 후 응답 -operation::auth-controller-test/apple_소셜_로그인_회원가입_후[snippets='http-response,response-fields']

    -

    -=== Auth 회원가입 -operation::auth-controller-test/sign_up[snippets='http-request,request-fields,http-response,response-fields']

    -

    -=== Auth 토큰 재발급 -operation::auth-controller-test/reissue_token[snippets='http-request,http-response,response-fields']

    -

    -=== Auth 닉네임 중복검사 요청 -operation::auth-controller-test/check_nickname_중복o[snippets='http-request']

    -

    === Auth 닉네임 중복인 경우 -operation::auth-controller-test/check_nickname_중복o[snippets='http-response,response-fields']

    -

    === Auth 닉네임 중복이 아닌 경우 -operation::auth-controller-test/check_nickname_중복x[snippets='http-response,response-fields']

    -

    -= Mypage API

    -

    -=== Mypage 로그아웃 -operation::mypage-controller-test/sign_out[snippets='http-request,http-response,response-fields']

    -

    ---

    -

    -=== Mypage 회원탈퇴 -operation::mypage-controller-test/withdraw[snippets='http-request,request-fields,http-response,response-fields']

    -

    -= Team API

    -

    -=== Team 소모임 개설 -operation::team-controller-test/create_team[snippets='http-request,request-fields,http-response,response-fields']

    -

    === 소모임 카테고리

    +

    팀 최대 개수 3을 초과

    + + + +

    +
    +
    +

    Auth API

    +
    +

    Auth Kakao 소셜 로그인 요청

    +
    +

    HTTP request

    +
    +
    +
    POST /api/auth/signIn/kakao HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 36
    +Host: localhost:8080
    +
    +{
    +  "token" : "KAKAO_ACCESS_TOKEN"
    +}
    +
    +
    +
    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + +
    PathTypeDescription

    token

    String

    카카오 액세스 토큰

    +
    +
    +
    +

    Auth Kakao 소셜 로그인 회원가입 전 응답

    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 206
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "로그인을 했습니다",
    +  "data" : {
    +    "accessToken" : "SERVER_ACCESS_TOKEN",
    +    "refreshToken" : "SERVER_REFRESH_TOKEN",
    +    "registrationStatus" : false
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 : false

    +
    +
    +
    +

    Auth Kakao 소셜 로그인 회원가입 후 응답

    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 205
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "로그인을 했습니다",
    +  "data" : {
    +    "accessToken" : "SERVER_ACCESS_TOKEN",
    +    "refreshToken" : "SERVER_REFRESH_TOKEN",
    +    "registrationStatus" : true
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :true

    +
    +
    +
    +
    +

    Auth Apple 소셜 로그인 요청

    +
    +

    HTTP request

    +
    +
    +
    POST /api/auth/signIn/apple HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 38
    +Host: localhost:8080
    +
    +{
    +  "token" : "APPLE_IDENTITY_TOKEN"
    +}
    +
    +
    +
    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + +
    PathTypeDescription

    token

    String

    애플 아이디 토큰

    +
    +
    +
    +

    Auth Apple 소셜 로그인 회원가입 전 응답

    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 206
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "로그인을 했습니다",
    +  "data" : {
    +    "accessToken" : "SERVER_ACCESS_TOKEN",
    +    "refreshToken" : "SERVER_REFRESH_TOKEN",
    +    "registrationStatus" : false
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :false

    +
    +
    +
    +

    Auth Apple 소셜 로그인 회원가입 후 응답

    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 205
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "로그인을 했습니다",
    +  "data" : {
    +    "accessToken" : "SERVER_ACCESS_TOKEN",
    +    "refreshToken" : "SERVER_REFRESH_TOKEN",
    +    "registrationStatus" : true
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :true

    +
    +
    +
    +

    Auth 회원가입

    +
    +

    HTTP request

    +
    +
    +
    PUT /api/auth/signUp HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Content-Length: 29
    +Host: localhost:8080
    +
    +{
    +  "nickName" : "NICKNAME"
    +}
    +
    +
    +
    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + +
    PathTypeDescription

    nickName

    String

    유저 닉네임

    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 209
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "회원 가입을 했습니다",
    +  "data" : {
    +    "accessToken" : "SERVER_ACCESS_TOKEN",
    +    "refreshToken" : "SERVER_REFRESH_TOKEN",
    +    "registrationStatus" : true
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    회원 가입을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 : true

    +
    +
    +
    +

    Auth 토큰 재발급

    +
    +

    HTTP request

    +
    +
    +
    GET /api/auth/reissue HTTP/1.1
    +RefreshToken: REFRESH_TOKEN
    +Host: localhost:8080
    +
    +
    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 178
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "토큰을 재발급했습니다",
    +  "data" : {
    +    "accessToken" : "SERVER_ACCESS_TOKEN",
    +    "refreshToken" : "SERVER_REFRESH_TOKEN"
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    토큰을 재발급했습니다

    data.accessToken

    String

    서버 접근용 Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    +
    +
    +
    +

    Auth 닉네임 중복검사 요청

    +
    +

    HTTP request

    +
    +
    +
    GET /api/auth/nickname/NICKNAME HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Host: localhost:8080
    +
    +
    +
    +
    +
    +

    Auth 닉네임 중복인 경우

    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 124
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "닉네임 중복검사를 했습니다",
    +  "data" : {
    +    "isDuplicated" : true
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    닉네임 중복검사를 했습니다

    data.isDuplicated

    Boolean

    닉네임 중복 여부 : ture

    -
    -

    | Category | Description

    -
    -

    | SPORTS -| 스포츠/운동

    -
    -

    | HABIT -| 생활습관 개선

    +
    +

    Auth 닉네임 중복이 아닌 경우

    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 125
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "닉네임 중복검사를 했습니다",
    +  "data" : {
    +    "isDuplicated" : false
    +  }
    +}
    -
    -

    | TEST -| 시험/취업준비

    -
    -

    | STUDY -| 스터디/공부

    -
    -

    | READING -| 독서

    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    닉네임 중복검사를 했습니다

    data.isDuplicated

    Boolean

    닉네임 중복 여부 : false

    +
    +
    +

    Mypage API

    +
    +

    Mypage 로그아웃

    +
    +

    HTTP request

    +
    +
    +
    POST /api/mypage/signOut HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Host: localhost:8080
    -
    -

    | ETC -| 그외 자기계발

    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 70
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "로그아웃을 했습니다"
    +}
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그아웃을 했습니다

    +
    +
    +
    +
    +

    Mypage 회원탈퇴

    +
    +

    HTTP request

    +
    +
    +
    DELETE /api/mypage/withdrawal HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Content-Length: 34
    +Host: localhost:8080
    +
    +{
    +  "reason" : "REASON_TO_LEAVE"
    +}
    +
    +
    +
    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + +
    PathTypeDescription

    reason

    String

    회원탈퇴하는 이유

    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 70
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "회원탈퇴를 했습니다"
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    회원탈퇴를 했습니다

    +
    +
    +

    Team API

    +
    +

    Team 소모임 개설

    +
    +

    HTTP request

    +
    +
    +
    POST /api/team HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Content-Length: 182
    +Host: localhost:8080
    +
    +{
    +  "category" : "ETC",
    +  "name" : "소모임 이름",
    +  "introduction" : "소모임 소개글",
    +  "promise" : "소모임 각오",
    +  "profileImgUrl" : "소모임 대표 사진 URL"
    +}
    +
    +
    +
    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    category

    String

    카테고리

    name

    String

    소모임 이름

    introduction

    String

    소모임 소개글

    profileImgUrl

    String

    소모임 대표 사진

    promise

    String

    소모임 각오

    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 111
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "소모임을 생성하였습니다",
    +  "data" : {
    +    "teamId" : 1
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    소모임을 생성하였습니다

    data.teamId

    Number

    생성한 teamId

    +
    +
    +
    +

    소모임 카테고리

    + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CategoryDescription

    SPORTS

    스포츠/운동

    HABIT

    생활습관 개선

    TEST

    시험/취업준비

    STUDY

    스터디/공부

    READING

    독서

    ETC

    그외 자기계발

    +
    +
    From 7bfd72dd02cf63c636979d9475ff56e64e5c1e90 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sat, 26 Aug 2023 00:18:50 +0900 Subject: [PATCH 031/619] =?UTF-8?q?deploy:=20data.sql=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-cd.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 3bd742b1..5997bc97 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -41,6 +41,8 @@ jobs: cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml + touch ./data.sql + echo "${{env.DATA_SQL}}" > ./data.sql touch ./firebase-key.json echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json @@ -50,6 +52,13 @@ jobs: name: application.yml path: ./src/main/resources/application.yml + + - uses: actions/upload-artifact@v2 + with: + name: data.sql + path: ./src/main/resources/data.sql + + - uses: actions/upload-artifact@v2 with: name: firebase-key.json From 02d310ee26395c7e5f182f81e74923e81caf04d3 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sat, 26 Aug 2023 00:28:47 +0900 Subject: [PATCH 032/619] deploy: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 5997bc97..3bd742b1 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -41,8 +41,6 @@ jobs: cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml - touch ./data.sql - echo "${{env.DATA_SQL}}" > ./data.sql touch ./firebase-key.json echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json @@ -52,13 +50,6 @@ jobs: name: application.yml path: ./src/main/resources/application.yml - - - uses: actions/upload-artifact@v2 - with: - name: data.sql - path: ./src/main/resources/data.sql - - - uses: actions/upload-artifact@v2 with: name: firebase-key.json From fa510ebbedcdad058c51d1860f9f341fcaa4d721 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sat, 26 Aug 2023 00:38:19 +0900 Subject: [PATCH 033/619] deploy: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 3bd742b1..4853c661 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -41,6 +41,8 @@ jobs: cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml + touch ./data.sql + echo "${{env.DATA_SQL}}" > ./data.sql touch ./firebase-key.json echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json @@ -50,6 +52,12 @@ jobs: name: application.yml path: ./src/main/resources/application.yml + - uses: actions/upload-artifact@v2 + with: + name: data.sql + path: ./src/main/resources/data.sql + + - uses: actions/upload-artifact@v2 with: name: firebase-key.json From 5b2887ee4c686a1cf5c0244959aaaee6ac7b2ca5 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sat, 26 Aug 2023 00:43:06 +0900 Subject: [PATCH 034/619] docs: Update deploy.sh --- deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy.sh b/deploy.sh index 6d3fed4d..57dee070 100644 --- a/deploy.sh +++ b/deploy.sh @@ -27,7 +27,7 @@ else AFTER_COMPOSE_COLOR="green" fi -sleep 10 +sleep 40 # 새로운 컨테이너가 제대로 실행되었는지 확인 EXIST_AFTER=$(docker ps --filter name=${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} --filter status=running -q) From be463c192cbd44f32368a726c84dfff621792e64 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sat, 26 Aug 2023 00:46:09 +0900 Subject: [PATCH 035/619] docs: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 4853c661..b59a65a5 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -36,32 +36,25 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - # 설정 파일 생성 - - run: | - cd ./src/main/resources - touch ./application.yml - echo "${{env.APPLICATION}}" > ./application.yml - touch ./data.sql - echo "${{env.DATA_SQL}}" > ./data.sql - touch ./firebase-key.json - echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json - - # 설정 파일을 작업공간에 저장 + - uses: actions/checkout@v2 + - run: touch ./src/main/resources/application.yml + - run: echo "${{env.APPLICATION}}" > ./src/main/resources/application.yml - uses: actions/upload-artifact@v2 with: name: application.yml path: ./src/main/resources/application.yml - - - uses: actions/upload-artifact@v2 - with: - name: data.sql - path: ./src/main/resources/data.sql - - + - run: touch ./src/main/resources/firebase-key.json + - run: echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./src/main/resources/firebase-key.json - uses: actions/upload-artifact@v2 with: name: firebase-key.json path: ./src/main/resources/firebase-key.json + - run: touch ./src/main/resources/data.sql + - run: echo "${{env.DATA_SQL}" > ./src/main/resources/data.sql + - uses: actions/upload-artifact@v2 + with: + name: data.sql + path: ./src/main/resources/data.sql # gradlew 권한 설정 - name: Grant execute permission for gradlew From fd1ec49ea5b86f106cc6260d0bc8eeb4b43eae2d Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sat, 26 Aug 2023 00:48:24 +0900 Subject: [PATCH 036/619] docs: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index b59a65a5..5702bdab 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -50,7 +50,7 @@ jobs: name: firebase-key.json path: ./src/main/resources/firebase-key.json - run: touch ./src/main/resources/data.sql - - run: echo "${{env.DATA_SQL}" > ./src/main/resources/data.sql + - run: echo "${{env.DATA_SQL}}" > ./src/main/resources/data.sql - uses: actions/upload-artifact@v2 with: name: data.sql From 339eacc9d8c6f2b363c116095de78a3073138fb4 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sat, 26 Aug 2023 00:55:42 +0900 Subject: [PATCH 037/619] docs: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 5702bdab..05110882 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -13,6 +13,8 @@ jobs: env: working-directory: ./ APPLICATION: ${{ secrets.APPLICATION }} + GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }} + DATA_SQL: ${{ secrets.DATA_SQl }} steps: # 소스 코드 체크아웃 From 2ef8694fc21c78bb1fad71a0edafccd503c11a28 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sat, 26 Aug 2023 01:06:05 +0900 Subject: [PATCH 038/619] deploy: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 05110882..fbc4964f 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -38,25 +38,33 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - - uses: actions/checkout@v2 - - run: touch ./src/main/resources/application.yml - - run: echo "${{env.APPLICATION}}" > ./src/main/resources/application.yml + # 설정 파일 생성 + - run: | + cd ./src/main/resources + touch ./application.yml + echo "${{env.APPLICATION}}" > ./application.yml + touch ./data.sql + echo "${{env.DATA_SQL}}" > ./data.sql + touch ./firebase-key.json + echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json + + # 설정 파일을 작업공간에 저장 - uses: actions/upload-artifact@v2 with: name: application.yml path: ./src/main/resources/application.yml - - run: touch ./src/main/resources/firebase-key.json - - run: echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./src/main/resources/firebase-key.json - - uses: actions/upload-artifact@v2 - with: - name: firebase-key.json - path: ./src/main/resources/firebase-key.json - - run: touch ./src/main/resources/data.sql - - run: echo "${{env.DATA_SQL}}" > ./src/main/resources/data.sql + + - uses: actions/upload-artifact@v2 with: name: data.sql path: ./src/main/resources/data.sql + + + - uses: actions/upload-artifact@v2 + with: + name: firebase-key.json + path: ./src/main/resources/firebase-key.json # gradlew 권한 설정 - name: Grant execute permission for gradlew From cc9fb4c9fe17e40ae509098e25bd1e84cd5edf3e Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sat, 26 Aug 2023 01:14:34 +0900 Subject: [PATCH 039/619] docs: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index fbc4964f..777e041e 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -43,8 +43,6 @@ jobs: cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml - touch ./data.sql - echo "${{env.DATA_SQL}}" > ./data.sql touch ./firebase-key.json echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json @@ -54,13 +52,6 @@ jobs: name: application.yml path: ./src/main/resources/application.yml - - - uses: actions/upload-artifact@v2 - with: - name: data.sql - path: ./src/main/resources/data.sql - - - uses: actions/upload-artifact@v2 with: name: firebase-key.json From e5f8324a6b94a385d38a72159f92c2d5cd69ff97 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sat, 26 Aug 2023 01:31:57 +0900 Subject: [PATCH 040/619] docs: Update deploy.sh --- deploy.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/deploy.sh b/deploy.sh index 57dee070..9179e352 100644 --- a/deploy.sh +++ b/deploy.sh @@ -12,6 +12,12 @@ EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --filter status=r # 둘 다 실행 중이지 않을 경우 blue 실행 if [ -z "$EXIST_BLUE" ] && [ -z "$EXIST_GREEN" ]; then echo "No containers running. Starting blue up" + + # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. + if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-blue -q)" ]; then + docker rm ${DOCKER_APP_NAME}-blue + fi + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 ${DOCKER_USERNAME}/moing:blue BEFORE_COMPOSE_COLOR="green" AFTER_COMPOSE_COLOR="blue" From 49f5c24dc166b50f326b7d95f2b9f0b4b8267460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 26 Aug 2023 02:27:10 +0900 Subject: [PATCH 041/619] =?UTF-8?q?feat=20:=20MissionControllerTest=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=A1=B0=ED=9A=8C,=EC=88=98=EC=A0=95,?= =?UTF-8?q?=EC=9E=91=EC=84=B1,=EC=A1=B0=ED=9A=8C=20test=20OK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mission/domain/entity/Team.java | 4 - .../representation/MissionControllerTest.java | 122 ++++++++++++------ 2 files changed, 83 insertions(+), 43 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/mission/domain/entity/Team.java diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Team.java deleted file mode 100644 index 41d27c15..00000000 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Team.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.moing.backend.domain.mission.domain.entity; - -public class Team { -} diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index cfdd2f3c..4b6801b3 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -15,12 +15,17 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.restdocs.payload.JsonFieldType; import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.http.ResponseEntity.status; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.payload.PayloadDocumentation.*; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; @@ -49,7 +54,7 @@ public class MissionControllerTest extends CommonControllerTest { //given MissionReq input = MissionReq.builder() .title("title") - .dueTo("2023-12-31 23:39:22 333") + .dueTo("2023-12-31 23:39:22.333") .rule("rule") .content("content") .number(1) @@ -70,11 +75,13 @@ public class MissionControllerTest extends CommonControllerTest { .way("TEXT") .build(); - given(missionCreateUseCase.createMission(any())).willReturn(output); + given(missionCreateUseCase.createMission(any(),any())).willReturn(output); + Long teamId = 2L; //when - ResultActions actions = mockMvc.perform( - post("/mission") + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + post("/api/{teamId}/mission",teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) .content(body) ); @@ -84,8 +91,20 @@ public class MissionControllerTest extends CommonControllerTest { .andExpect(MockMvcResultMatchers.status().isOk()) .andDo( restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), requestFields( - fieldWithPath("token").description("카카오 액세스 토큰") + fieldWithPath("title").description("미션 제목"), + fieldWithPath("dueTo").description("미션 마감 날짜"), + fieldWithPath("rule").description("미션 규칙"), + fieldWithPath("content").description("미션 내용"), + fieldWithPath("number").description("미션 반복 횟수"), + fieldWithPath("type").description("미션 타입"), + fieldWithPath("way").description("미션 진행 방법") ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -96,10 +115,13 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.content").description("미션 내용"), fieldWithPath("data.number").description("미션 반복 횟수"), fieldWithPath("data.type").description("미션 타입"), - fieldWithPath("data.way").description("미션 진행 방법") + fieldWithPath("data.way").description("미션 진행 방법"), + fieldWithPath("data.status").description("미션 진행 상태") ) ) - ); + ) + .andReturn(); + } @Test @@ -128,11 +150,14 @@ public class MissionControllerTest extends CommonControllerTest { .way("TEXT") .build(); - given(missionCreateUseCase.createMission(any())).willReturn(output); + given(missionUpdateUseCase.updateMission(any(),any())).willReturn(output); + Long teamId = 2L; + Long missionId = 2L; //when - ResultActions actions = mockMvc.perform( - put("/mission") + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + put("/api/{teamId}/mission/{missionId}",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) .content(body) ); @@ -142,8 +167,21 @@ public class MissionControllerTest extends CommonControllerTest { .andExpect(MockMvcResultMatchers.status().isOk()) .andDo( restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), requestFields( - fieldWithPath("token").description("카카오 액세스 토큰") + fieldWithPath("title").description("미션 제목"), + fieldWithPath("dueTo").description("미션 마감 날짜"), + fieldWithPath("rule").description("미션 규칙"), + fieldWithPath("content").description("미션 내용"), + fieldWithPath("number").description("미션 반복 횟수"), + fieldWithPath("type").description("미션 타입"), + fieldWithPath("way").description("미션 진행 방법") ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -154,10 +192,14 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.content").description("미션 내용"), fieldWithPath("data.number").description("미션 반복 횟수"), fieldWithPath("data.type").description("미션 타입"), - fieldWithPath("data.way").description("미션 진행 방법") + fieldWithPath("data.way").description("미션 진행 방법"), + fieldWithPath("data.status").description("미션 진행 상태") + ) ) - ); + ) + .andReturn(); + } @Test @@ -176,10 +218,14 @@ public class MissionControllerTest extends CommonControllerTest { given(missionReadUseCase.getMission(any())).willReturn(output); + Long teamId = 2L; + Long missionId = 1L; //when - ResultActions actions = mockMvc.perform( - get("/mission/{missionId}",1) + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/mission/{missionId}",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) + ); //then @@ -187,11 +233,12 @@ public class MissionControllerTest extends CommonControllerTest { .andExpect(MockMvcResultMatchers.status().isOk()) .andDo( restDocs.document( - pathParameters( - parameterWithName("missionId").description("미션 아이디") + requestHeaders( + headerWithName("Authorization").description("접근 토큰") ), - requestFields( - fieldWithPath("token").description("카카오 액세스 토큰") + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -205,29 +252,22 @@ public class MissionControllerTest extends CommonControllerTest { ) ) - ); + ) + .andReturn(); + } @Test public void 미션_삭제() throws Exception { //given - MissionCreateRes output = MissionCreateRes.builder() - .title("title") - .dueTo("dueTo") - .rule("rule") - .content("content") - .number(1) - .type("TEXT") - .status("WAIT") - .way("TEXT") - .build(); - - given(missionCreateUseCase.createMission(any())).willReturn(output); + Long teamId = 2L; + Long missionId = 1L; //when - ResultActions actions = mockMvc.perform( - delete("/mission/{missionId}",1) + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/{teamId}/mission/{missionId}",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) ); @@ -236,16 +276,20 @@ public class MissionControllerTest extends CommonControllerTest { .andExpect(MockMvcResultMatchers.status().isOk()) .andDo( restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), pathParameters( + parameterWithName("teamId").description("팀 아이디"), parameterWithName("missionId").description("삭제할 미션 아이디") ), - requestFields( - fieldWithPath("token").description("카카오 액세스 토큰") - ), responseFields( - fieldWithPath("missionId").description("삭제된 미션 아이디") + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("미션을 삭제 했습니다"), + fieldWithPath("data").description("삭제된 미션 아이디") ) ) - ); + ) + .andReturn(); } } From 41978e5d7428dbffc87b2348da2dc4a5d6b9ef39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 27 Aug 2023 19:16:53 +0900 Subject: [PATCH 042/619] =?UTF-8?q?fix=20:=20mission=20=EC=83=9D=EC=84=B1,?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=ED=99=95=EC=9D=B8?= =?UTF-8?q?=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/mapper/MissionMapper.java | 4 +-- .../service/MissionCreateUseCase.java | 19 ++++++++----- .../service/MissionDeleteUseCase.java | 8 +++++- .../service/MissionReadUseCase.java | 8 ++++-- .../service/MissionUpdateUseCase.java | 11 ++++---- .../domain/mission/domain/entity/Mission.java | 20 ++++++++++--- .../domain/service/MissionUpdateService.java | 2 +- .../presentation/MissionController.java | 28 ++++++++++--------- 8 files changed, 64 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java index 31dee3cb..c56902ef 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java +++ b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java @@ -5,10 +5,10 @@ import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.Team; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; +import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.annotation.Mapper; import java.time.LocalDateTime; @@ -17,7 +17,7 @@ @Mapper public class MissionMapper { - public static Mission mapToMission(MissionReq missionReq, Team team, Member member, MissionType type) { + public static Mission mapToMission(MissionReq missionReq, Member member, MissionType type) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index 2da2b6eb..cd40b2ed 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -2,13 +2,15 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.repository.MemberRepository; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.application.dto.req.MissionReq; import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; import com.moing.backend.domain.mission.application.mapper.MissionMapper; import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.Team; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionSaveService; +import com.moing.backend.domain.team.domain.repository.TeamRepository; +import com.moing.backend.global.util.SecurityUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,15 +21,18 @@ public class MissionCreateUseCase { private final MissionSaveService missionSaveService; - private final MemberRepository memberRepository; + private final TeamRepository teamRepository; + private final MemberGetService memberGetService; - public MissionCreateRes createMission(MissionReq missionReq) { + public MissionCreateRes createMission(String userSocialId, Long teamId, MissionReq missionReq) { - Team team = new Team(); -// Member member = SecurityUtils.getLoggedInUser(); - Member member = memberRepository.findById(1L).orElseThrow(); - Mission mission = MissionMapper.mapToMission(missionReq, team, member, MissionType.ONCE); + Member member = memberGetService.getMemberBySocialId(userSocialId); + + Mission mission = MissionMapper.mapToMission(missionReq, member, MissionType.valueOf(missionReq.getType())); + // teamRepository 변경 예정 + mission.setTeam(teamRepository.findById(teamId).orElseThrow()); + missionSaveService.save(mission); return MissionMapper.mapToMissionCreateRes(mission); diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java index 2c9a51f4..b68bf10d 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java @@ -1,5 +1,7 @@ package com.moing.backend.domain.mission.application.service; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.mission.domain.service.MissionDeleteService; import lombok.RequiredArgsConstructor; @@ -12,8 +14,12 @@ public class MissionDeleteUseCase { private final MissionDeleteService missionDeleteService; + private final MemberGetService memberGetService; + + public Long deleteMission(String userSocialId,Long missionId) { + + Member member = memberGetService.getMemberBySocialId(userSocialId); - public Long deleteMission(Long missionId) { return missionDeleteService.deleteMission(missionId); } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java index f02d4a8c..5d9ce7f0 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.mission.application.service; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; import com.moing.backend.domain.mission.application.mapper.MissionMapper; @@ -17,9 +18,12 @@ public class MissionReadUseCase { MissionQueryService missionQueryService; + MemberGetService memberGetService; + + public MissionReadRes getMission(String userSocialId, Long missionId) { + + Member member = memberGetService.getMemberBySocialId(userSocialId); - public MissionReadRes getMission(Long missionId) { - Member member = SecurityUtils.getLoggedInUser(); Mission mission = missionQueryService.findMissionById(missionId); return MissionMapper.mapToMissionReadRes(mission); } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index d75ef9a5..6f9a772c 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -1,11 +1,11 @@ package com.moing.backend.domain.mission.application.service; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.application.dto.req.MissionReq; import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; import com.moing.backend.domain.mission.application.mapper.MissionMapper; import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.Team; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.mission.domain.service.MissionSaveService; @@ -21,18 +21,17 @@ public class MissionUpdateUseCase { private final MissionSaveService missionSaveService; private final MissionQueryService missionQueryService; + private final MemberGetService memberGetService; - public MissionCreateRes updateMission(Long missionId, MissionReq missionReq) { + public MissionCreateRes updateMission(String userSocialId,Long missionId, MissionReq missionReq) { - Team team = new Team(); - Member member = SecurityUtils.getLoggedInUser(); - Mission mission = MissionMapper.mapToMission(missionReq, team, member, MissionType.ONCE); + Member member = memberGetService.getMemberBySocialId(userSocialId); Mission findMission = missionQueryService.findMissionById(missionId); findMission.updateMission(missionReq); - return MissionMapper.mapToMissionCreateRes(mission); + return MissionMapper.mapToMissionCreateRes(findMission); } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index 27b28f30..a6b070ef 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; import lombok.Builder; @@ -13,6 +14,7 @@ import javax.persistence.*; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; @@ -32,6 +34,10 @@ public class Mission extends BaseTimeEntity { private String content; private int number; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team_id") + private Team team; + @Enumerated(value = EnumType.STRING) private MissionType type; @@ -45,27 +51,33 @@ public class Mission extends BaseTimeEntity { List missionArchiveList = new ArrayList<>(); @Builder - public Mission(String title, LocalDateTime dueTo, String rule, String content, int number, MissionType type, MissionStatus status, MissionWay way) { + public Mission(String title, LocalDateTime dueTo, String rule, String content, int number, Team team, MissionType type, MissionStatus status, MissionWay way) { this.title = title; this.dueTo = dueTo; this.rule = rule; this.content = content; this.number = number; + this.team = team; this.type = type; this.status = status; this.way = way; } - public Mission updateMission(MissionReq missionReq) { + public void updateMission(MissionReq missionReq) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + this.title = missionReq.getTitle(); - this.dueTo = LocalDateTime.parse(missionReq.getDueTo()); + this.dueTo = LocalDateTime.parse(missionReq.getDueTo(), formatter); this.rule = missionReq.getRule(); this.content = missionReq.getContent(); this.number = missionReq.getNumber(); this.type = MissionType.valueOf(missionReq.getType()); this.way = MissionWay.valueOf(missionReq.getWay()); - return this; + } + + public void setTeam(Team team) { + this.team = team; } } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionUpdateService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionUpdateService.java index ccc52e19..db3e7cff 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionUpdateService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionUpdateService.java @@ -13,7 +13,7 @@ public class MissionUpdateService { private final MissionRepository missionRepository; - public void update(Mission mission) { + public void updateMission(Mission mission) { missionRepository.save(mission); } } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index a7e1814f..a7f298f8 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -8,9 +8,11 @@ import com.moing.backend.domain.mission.application.service.MissionReadUseCase; import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; import com.moing.backend.domain.mission.domain.service.MissionDeleteService; +import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.*; @@ -18,7 +20,7 @@ @RestController @AllArgsConstructor -@RequestMapping("/mission") +@RequestMapping("/api/{teamId}/mission") public class MissionController { @@ -29,43 +31,43 @@ public class MissionController { /** * 미션 조회 - * [GET] /mission/{missionId} + * [GET] {teamId}/mission/{missionId} * 작성자 : 정승연 */ @GetMapping("/{missionId}") - public ResponseEntity> getMission(@PathVariable Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(READ_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getMission(missionId))); + public ResponseEntity> getMission(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(READ_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getMission(user.getSocialId(),missionId))); } /** * 미션 생성 - * [POST] /mission + * [POST] {teamId}/mission * 작성자 : 정승연 */ @PostMapping() - public ResponseEntity> createMission(@RequestBody MissionReq missionReq) { - return ResponseEntity.ok(SuccessResponse.create(CREATE_MISSION_SUCCESS.getMessage(), this.missionCreateUseCase.createMission(missionReq))); + public ResponseEntity> createMission(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId, @RequestBody MissionReq missionReq) { + return ResponseEntity.ok(SuccessResponse.create(CREATE_MISSION_SUCCESS.getMessage(), this.missionCreateUseCase.createMission(user.getSocialId(),teamId,missionReq))); } /** * 미션 수정 - * [PUT] /mission/{missionId} + * [PUT] {teamId}/mission/{missionId} * 작성자 : 정승연 */ @PutMapping("/{missionId}") - public ResponseEntity> updateMission(@PathVariable Long missionId, @RequestBody MissionReq missionReq) { - return ResponseEntity.ok(SuccessResponse.create(UPDATE_MISSION_SUCCESS.getMessage(), this.missionUpdateUseCase.updateMission(missionId, missionReq))); + public ResponseEntity> updateMission(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId, @RequestBody MissionReq missionReq) { + return ResponseEntity.ok(SuccessResponse.create(UPDATE_MISSION_SUCCESS.getMessage(), this.missionUpdateUseCase.updateMission(user.getSocialId(),missionId, missionReq))); } /** * 미션 삭제 - * [DELETE] /mission/{missionId} + * [DELETE] {teamId}/mission/{missionId} * 작성자 : 정승연 */ @DeleteMapping("/{missionId}") - public ResponseEntity> deleteMission(@PathVariable Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(DELETE_MISSION_SUCCESS.getMessage(), this.missionDeleteUseCase.deleteMission(missionId))); + public ResponseEntity> deleteMission(@AuthenticationPrincipal User user,@PathVariable Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(DELETE_MISSION_SUCCESS.getMessage(), this.missionDeleteUseCase.deleteMission(user.getSocialId(),missionId))); } From 409b250525a8d8693cdd599186dd4d0e92ff33b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 27 Aug 2023 23:12:20 +0900 Subject: [PATCH 043/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionCreateUseCase.java | 2 ++ .../application/service/MissionUpdateUseCase.java | 2 ++ .../domain/mission/presentation/MissionController.java | 10 ++++++++++ 3 files changed, 14 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index cd40b2ed..f067a245 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -29,6 +29,8 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR Member member = memberGetService.getMemberBySocialId(userSocialId); + // 소모임장 확인 로직 추가 + Mission mission = MissionMapper.mapToMission(missionReq, member, MissionType.valueOf(missionReq.getType())); // teamRepository 변경 예정 mission.setTeam(teamRepository.findById(teamId).orElseThrow()); diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index 6f9a772c..7cbca253 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -28,6 +28,8 @@ public MissionCreateRes updateMission(String userSocialId,Long missionId, Missio Member member = memberGetService.getMemberBySocialId(userSocialId); + // 소모임장 확인 로직 추가 + Mission findMission = missionQueryService.findMissionById(missionId); findMission.updateMission(missionReq); diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index a7f298f8..58f50484 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -39,6 +39,16 @@ public class MissionController { public ResponseEntity> getMission(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId) { return ResponseEntity.ok(SuccessResponse.create(READ_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getMission(user.getSocialId(),missionId))); } + /** + * 미션 리스트 조회 + * [GET] {teamId}/mission/{missionId} + * 작성자 : 정승연 + */ + + @GetMapping("") + public ResponseEntity> getMissionList(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(READ_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getMission(user.getSocialId(),teamId))); + } /** * 미션 생성 From ac4e53c308538a9c042374ca6cd5b480b7aa0242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:45:31 +0900 Subject: [PATCH 044/619] =?UTF-8?q?fesat=20:=20missionArchiveCreate=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/req/MissionArchiveReq.java | 12 ++++ .../dto/res/MissionArchiveRes.java | 32 +++++++++ .../dto/res/MissionArchiveResImg.java | 5 ++ .../mapper/MissionArchiveMapper.java | 44 ++++++++++++ .../service/MissionArchiveCreateUseCase.java | 68 +++++++++++++++++++ .../repository/MissionArchiveRepository.java | 17 +++++ .../service/MissionArchiveDeleteService.java | 13 ++++ .../service/MissionArchiveQueryService.java | 39 +++++++++++ .../service/MissionArchiveSaveService.java | 20 ++++++ .../exception/MissionArchiveException.java | 13 ++++ .../NotFoundMissionArchiveException.java | 12 ++++ 11 files changed, 275 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveResImg.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/exception/MissionArchiveException.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java new file mode 100644 index 00000000..81cc1e0b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.missionArchive.application.dto.req; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class MissionArchiveReq { + + private String status; + private String archive; //사진일 경우 파일명, 이외에는 text,link +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java new file mode 100644 index 00000000..a3d82e6e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -0,0 +1,32 @@ +package com.moing.backend.domain.missionArchive.application.dto.res; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Builder +@Getter +@Setter +public class MissionArchiveRes { + + private String title; + private String status; + private String dueTo; + + private int totalPerson; + private int donePerson; + + + private String rule; + private String content; + + private String archive; + + private String createdDate; + + + + + + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveResImg.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveResImg.java new file mode 100644 index 00000000..fa1de2b2 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveResImg.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.missionArchive.application.dto.res; + +public class MissionArchiveResImg { + private String s3URL; +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java new file mode 100644 index 00000000..a155ba23 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -0,0 +1,44 @@ +package com.moing.backend.domain.missionArchive.application.mapper; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.global.annotation.Mapper; + +@Mapper +public class MissionArchiveMapper { + + public static MissionArchive mapToMissionArchive(MissionArchiveReq missionArchiveReq, Member member, Mission mission) { + return MissionArchive.builder() + .archive(missionArchiveReq.getArchive()) + .status(MissionStatus.valueOf(missionArchiveReq.getStatus())) + .member(member) + .mission(mission) + .build(); + } + + public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArchive) { + Mission mission = missionArchive.getMission(); + Team team = mission.getTeam(); + + return MissionArchiveRes.builder() + .title(mission.getTitle()) + .status(mission.getStatus().name()) + .dueTo(mission.getDueTo().toString()) + .totalPerson(10) + .donePerson(mission.getMissionArchiveList().size()) + .rule(mission.getRule()) + .content(mission.getContent()) + .archive(missionArchive.getArchive()) + .createdDate(missionArchive.getCreatedDate().toString()) + .build(); + + } + + + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java new file mode 100644 index 00000000..ed8af35c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -0,0 +1,68 @@ +package com.moing.backend.domain.missionArchive.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.application.dto.req.MissionReq; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; +import com.moing.backend.domain.mission.domain.service.MissionDeleteService; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; +import com.moing.backend.domain.team.domain.entity.Team; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionArchiveCreateUseCase { + + private final MissionArchiveSaveService missionArchiveSaveService; + private final MissionArchiveQueryService missionArchiveQueryService; + private final MissionArchiveDeleteService missionArchiveDeleteService; + private final MissionQueryService missionQueryService; + private final MemberGetService memberGetService; + + public MissionArchiveRes createArchiveCreate(String userSocialId, Long missionId, MissionArchiveReq missionReq) { + + Member member = memberGetService.getMemberBySocialId(userSocialId); + Mission mission = missionQueryService.findMissionById(missionId); + Team team = mission.getTeam(); + + + // 사진 제출 했다면, + if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(member.getMemberId(), missionId)) { + + //s3삭제 + //archive set presignedURL + + String url = null; + missionReq.setArchive(url); + + return saveArchive(mission, missionReq,member); + + } + + return saveArchive(mission, missionReq,member); + + } + + + public MissionArchiveRes saveArchive(Mission mission,MissionArchiveReq missionReq,Member member) { + MissionArchive save = missionArchiveSaveService.save(MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission)); + + if (mission.getMissionArchiveList().size() == 3) { + mission.setStatus(MissionStatus.DONE); + } + return MissionArchiveMapper.mapToMissionArchiveRes(save); + } + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java new file mode 100644 index 00000000..1f9723a9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.missionArchive.domain.repository; + +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.Optional; + +public interface MissionArchiveRepository extends JpaRepository { + + @Query("select m from MissionArchive as m where m.member =: memberId") + public Optional findByMemberId(Long memberId); + + @Query("select m from MissionArchive as m where m.mission.id =: missionId and m.member.memberId =: memberId") + public Optional findByMissionIdAndMemberId(Long memberId, Long missionId); + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java new file mode 100644 index 00000000..8189476c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.missionArchive.domain.service; + +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; + +public class MissionArchiveDeleteService { + + private MissionArchiveRepository missionArchiveRepository; + + public void deleteMissionArchive(MissionArchive missionArchive) { + missionArchiveRepository.delete(missionArchive); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java new file mode 100644 index 00000000..6d0cb933 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -0,0 +1,39 @@ +package com.moing.backend.domain.missionArchive.domain.service; + +import com.moing.backend.domain.mission.domain.repository.MissionRepository; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; +import com.moing.backend.domain.missionArchive.exception.NotFoundMissionArchiveException; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionArchiveQueryService { + + private final MissionRepository missionRepository; + private final MissionArchiveRepository missionArchiveRepository; + +// public List findByMissionId(Long missionId) { +// +// } + + public MissionArchive findByMemberId(Long memberId) { + return missionArchiveRepository.findByMemberId(memberId).orElseThrow(NotFoundMissionArchiveException::new); + } + + public Boolean isDone(Long memberId, Long missionId) { + Optional byMemberId = missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId); + if (byMemberId.isPresent()) { + return Boolean.TRUE; + } + else{ + return Boolean.FALSE; + } + } +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveSaveService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveSaveService.java new file mode 100644 index 00000000..bf8a53ac --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveSaveService.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.missionArchive.domain.service; + +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionArchiveSaveService { + + private final MissionArchiveRepository missionArchiveRepository; + + public MissionArchive save(MissionArchive missionArchive) { + return missionArchiveRepository.save(missionArchive); + } + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/exception/MissionArchiveException.java b/src/main/java/com/moing/backend/domain/missionArchive/exception/MissionArchiveException.java new file mode 100644 index 00000000..a6711c3d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/exception/MissionArchiveException.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.missionArchive.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class MissionArchiveException extends ApplicationException { + + protected MissionArchiveException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java b/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java new file mode 100644 index 00000000..007aa0d5 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.missionArchive.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundMissionArchiveException extends MissionArchiveException { + + public NotFoundMissionArchiveException() { + super(ErrorCode.TOKEN_INVALID_ERROR, + HttpStatus.BAD_REQUEST); + } +} From 61a9b34c02956125fbb28f625fa0d32d8fced9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:49:33 +0900 Subject: [PATCH 045/619] =?UTF-8?q?fix=20:=20mapper=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mission/application/dto/req/MissionReq.java | 1 + .../domain/mission/application/mapper/MissionMapper.java | 2 +- .../moing/backend/domain/mission/domain/entity/Mission.java | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java index 98962c87..bc28dcd6 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java @@ -16,5 +16,6 @@ public class MissionReq { private String type; private String way; + private String status; } diff --git a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java index c56902ef..30257f18 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java +++ b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java @@ -29,7 +29,7 @@ public static Mission mapToMission(MissionReq missionReq, Member member, Mission .way(MissionWay.valueOf(missionReq.getWay())) .type(MissionType.valueOf(missionReq.getType())) .number(missionReq.getNumber()) - .status(MissionStatus.WAIT) + .status(MissionStatus.valueOf(missionReq.getStatus())) .build(); } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index a6b070ef..39aece59 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -80,4 +80,8 @@ public void updateMission(MissionReq missionReq) { public void setTeam(Team team) { this.team = team; } + + public void setStatus(MissionStatus missionStatus) { + this.status = missionStatus; + } } From bed7303076e22cfbabdcb4f54f9c030336cb3fff Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Wed, 30 Aug 2023 01:45:55 +0900 Subject: [PATCH 046/619] deploy: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 777e041e..418de118 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -45,6 +45,8 @@ jobs: echo "${{env.APPLICATION}}" > ./application.yml touch ./firebase-key.json echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json + touch ./data.sql + echo "${{env.DATA_SQL}}" > ./data.sql # 설정 파일을 작업공간에 저장 - uses: actions/upload-artifact@v2 @@ -57,6 +59,11 @@ jobs: name: firebase-key.json path: ./src/main/resources/firebase-key.json + - uses: actions/upload-artifact@v2 + with: + name: data.sql + path: ./src/main/resources/data.sql + # gradlew 권한 설정 - name: Grant execute permission for gradlew run: chmod +x gradlew From 41d795d1275eae842516545e4a977532633dcd53 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Wed, 30 Aug 2023 02:07:00 +0900 Subject: [PATCH 047/619] Update ci-cd.yml --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 418de118..176a902c 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -46,7 +46,7 @@ jobs: touch ./firebase-key.json echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json touch ./data.sql - echo "${{env.DATA_SQL}}" > ./data.sql + echo "${{env.DATA_SQL}}" | base64 --decode > ./data.sql # 설정 파일을 작업공간에 저장 - uses: actions/upload-artifact@v2 From c98ea351b1925345e686ab703c972fb417348e12 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Wed, 30 Aug 2023 02:24:30 +0900 Subject: [PATCH 048/619] Update deploy.sh --- deploy.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/deploy.sh b/deploy.sh index 9179e352..59c6402d 100644 --- a/deploy.sh +++ b/deploy.sh @@ -23,16 +23,29 @@ if [ -z "$EXIST_BLUE" ] && [ -z "$EXIST_GREEN" ]; then AFTER_COMPOSE_COLOR="blue" elif [ -z "$EXIST_BLUE" ]; then echo "blue up" + + # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. + if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-blue -q)" ]; then + docker rm ${DOCKER_APP_NAME}-blue + fi + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 ${DOCKER_USERNAME}/moing:blue BEFORE_COMPOSE_COLOR="green" AFTER_COMPOSE_COLOR="blue" else echo "green up" + + # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. + if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-green -q)" ]; then + docker rm ${DOCKER_APP_NAME}-green + fi + docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 ${DOCKER_USERNAME}/moing:green BEFORE_COMPOSE_COLOR="blue" AFTER_COMPOSE_COLOR="green" fi + sleep 40 # 새로운 컨테이너가 제대로 실행되었는지 확인 From c2479021740bc7a99c7022226c1cf32332db4621 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Wed, 30 Aug 2023 02:59:24 +0900 Subject: [PATCH 049/619] feat: add AuthRedirectController --- .gitignore | 1 + .../auth/presentation/AuthController.java | 7 ++++ .../presentation/AuthRedirectController.java | 42 +++++++++++++++++++ .../TeamMemberCustomRepositoryImpl.java | 2 + 4 files changed, 52 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/auth/presentation/AuthRedirectController.java diff --git a/.gitignore b/.gitignore index 87cefe4e..14010ef5 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ out/ application.yml .DS_Store firebase-key.json +data.sql diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java index 5d4c96d4..84e66da2 100644 --- a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java @@ -12,12 +12,18 @@ import com.moing.backend.global.response.SuccessResponse; import com.moing.backend.global.response.TokenInfoResponse; import lombok.AllArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; +import java.net.URI; +import java.net.URISyntaxException; + import static com.moing.backend.domain.auth.presentation.constant.AuthResponseMessage.*; @RestController @@ -74,4 +80,5 @@ public ResponseEntity> reissue(@RequestHea public ResponseEntity> checkNickname(@PathVariable String nickname){ return ResponseEntity.ok(SuccessResponse.create(CHECK_NICKNAME_SUCCESS.getMessage(), checkNicknameService.checkNickname(nickname))); } + } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthRedirectController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthRedirectController.java new file mode 100644 index 00000000..1b27bdb4 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthRedirectController.java @@ -0,0 +1,42 @@ +package com.moing.backend.domain.auth.presentation; + +import lombok.AllArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.net.URI; +import java.net.URISyntaxException; + +@RestController +@AllArgsConstructor +public class AuthRedirectController { + @Value("${android.package}") + private String androidPackage; + + @Value("${android.scheme}") + private String androidScheme; + + /** + * 애플 로그인 리다이렉트 + */ + @CrossOrigin(origins = "https://appleid.apple.com") + @PostMapping(value = "/auth/apple/callback", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + public ResponseEntity userLoginAppleCallback(@RequestParam("code") String code, + @RequestParam("id_token") String idToken) throws URISyntaxException { + // Deep link 생성 + String callback = String.format("intent://callback?code=%s&id_token=%s#Intent;package=%s;scheme=%s;end", + code, idToken, androidPackage, androidScheme); + + // 리다이렉트 + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setLocation(new URI(callback)); + return new ResponseEntity<>(httpHeaders, HttpStatus.TEMPORARY_REDIRECT); + } +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index 0c84aebf..0e2e1854 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.teamMember.domain.repository; +import com.moing.backend.domain.team.domain.entity.QTeam; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -20,6 +21,7 @@ public List getMemberIdsByTeamId(Long teamId) { .select(teamMember.member.memberId) .from(teamMember) .where(teamMember.team.teamId.eq(teamId)) + .where(teamMember.team.isDeleted.eq(false)) .fetch(); } } From 4c516cc4871543a555b82f3acb115b0287819190 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sun, 3 Sep 2023 13:40:52 +0900 Subject: [PATCH 050/619] =?UTF-8?q?feat:=20presigned=20url=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=ED=95=98=EA=B8=B0=20/=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=EC=95=8C=EB=A6=BC=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 5 ++ .../dto/request/SignUpRequest.java | 3 + .../application/service/SignUpUserCase.java | 2 +- .../presentation/AuthRedirectController.java | 52 ++++++++-------- .../application/dto/ImageFileExtension.java | 15 +++++ .../image/application/dto/ImageUrlDto.java | 17 +++++ .../dto/request/IssuePresignedUrlRequest.java | 26 ++++++++ .../response/IssuePresignedUrlResponse.java | 25 ++++++++ .../service/IssuePresignedUrlUseCase.java | 23 +++++++ .../image/presentation/ImageController.java | 33 ++++++++++ .../constant/EImageResponseMessage.java | 12 ++++ .../domain/member/domain/entity/Member.java | 16 +---- .../repository/MemberCustomRepository.java | 1 - .../MemberCustomRepositoryImpl.java | 8 --- .../domain/service/MemberDeleteService.java | 20 ++++++ .../domain/service/MemberGetService.java | 2 +- .../domain/service/MemberSaveService.java | 4 -- .../dto/request/UpdateProfileRequest.java | 17 +++++ .../dto/response/GetAlarmResponse.java | 18 ++++++ .../dto/response/GetProfileResponse.java | 16 +++++ .../application/service/AlarmUserCase.java | 24 +++++++ .../application/service/ProfileUserCase.java | 37 +++++++++++ .../application/service/WithdrawUserCase.java | 7 ++- .../mypage/presentation/MyPageController.java | 45 +++++++++++++- .../constant/MypageResponseMessage.java | 6 +- .../moing/backend/global/annotation/Util.java | 15 +++++ .../backend/global/annotation/ValidEnum.java | 21 +++++++ .../global/config/s3/ImageUrlUtil.java | 14 +++++ .../backend/global/config/s3/S3Config.java | 33 ++++++++++ .../backend/global/config/s3/S3Service.java | 62 +++++++++++++++++++ .../config/security/SecurityConfig.java | 2 +- .../security/oauth/CustomUserDetails.java | 8 +-- src/main/resources/static/docs/Auth-API.html | 10 ++- src/main/resources/static/docs/api.html | 10 ++- .../auth/presentation/AuthControllerTest.java | 4 +- .../presentation/MypageControllerTest.java | 8 +++ 36 files changed, 550 insertions(+), 71 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/infra/image/application/dto/ImageFileExtension.java create mode 100644 src/main/java/com/moing/backend/domain/infra/image/application/dto/ImageUrlDto.java create mode 100644 src/main/java/com/moing/backend/domain/infra/image/application/dto/request/IssuePresignedUrlRequest.java create mode 100644 src/main/java/com/moing/backend/domain/infra/image/application/dto/response/IssuePresignedUrlResponse.java create mode 100644 src/main/java/com/moing/backend/domain/infra/image/application/service/IssuePresignedUrlUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/infra/image/presentation/ImageController.java create mode 100644 src/main/java/com/moing/backend/domain/infra/image/presentation/constant/EImageResponseMessage.java create mode 100644 src/main/java/com/moing/backend/domain/member/domain/service/MemberDeleteService.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/dto/request/UpdateProfileRequest.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetAlarmResponse.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetProfileResponse.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java create mode 100644 src/main/java/com/moing/backend/global/annotation/Util.java create mode 100644 src/main/java/com/moing/backend/global/annotation/ValidEnum.java create mode 100644 src/main/java/com/moing/backend/global/config/s3/ImageUrlUtil.java create mode 100644 src/main/java/com/moing/backend/global/config/s3/S3Config.java create mode 100644 src/main/java/com/moing/backend/global/config/s3/S3Service.java diff --git a/build.gradle b/build.gradle index 587b2a34..cc102aad 100644 --- a/build.gradle +++ b/build.gradle @@ -77,6 +77,11 @@ dependencies { implementation 'javax.cache:cache-api:1.1.1' implementation 'org.redisson:redisson:3.19.0' + // S3 + implementation("org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE") + implementation platform('software.amazon.awssdk:bom:2.17.230') + implementation 'software.amazon.awssdk:s3' + } tasks.named('test') { diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java index 8ac4de72..8d7170a6 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java @@ -13,4 +13,7 @@ public class SignUpRequest { @NotBlank(message = "nickName 을 입력해주세요.") @Size(min = 1, max = 10, message="nickName 은 최소 1개, 최대 10개의 문자만 입력 가능합니다.") private String nickName; + + @NotBlank(message = "fcmToken 을 입력해주세요.") + private String fcmToken; } diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java index 263437f4..f73b36d9 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java @@ -32,7 +32,7 @@ public SignInResponse signUp(String token, SignUpRequest signUpRequest) { //2. signUp 처리 String nickName=signUpRequest.getNickName(); if(memberCheckService.checkNickname(nickName)) throw new NicknameDuplicationException(); //닉네임 중복검사 (이중체크) - member.signUp(nickName); + member.signUp(nickName, signUpRequest.getFcmToken()); //3. security 처리 AuthenticationUtil.makeAuthentication(member); //4. token 만들기 diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthRedirectController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthRedirectController.java index 1b27bdb4..36b1f66b 100644 --- a/src/main/java/com/moing/backend/domain/auth/presentation/AuthRedirectController.java +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthRedirectController.java @@ -14,29 +14,29 @@ import java.net.URI; import java.net.URISyntaxException; -@RestController -@AllArgsConstructor -public class AuthRedirectController { - @Value("${android.package}") - private String androidPackage; - - @Value("${android.scheme}") - private String androidScheme; - - /** - * 애플 로그인 리다이렉트 - */ - @CrossOrigin(origins = "https://appleid.apple.com") - @PostMapping(value = "/auth/apple/callback", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - public ResponseEntity userLoginAppleCallback(@RequestParam("code") String code, - @RequestParam("id_token") String idToken) throws URISyntaxException { - // Deep link 생성 - String callback = String.format("intent://callback?code=%s&id_token=%s#Intent;package=%s;scheme=%s;end", - code, idToken, androidPackage, androidScheme); - - // 리다이렉트 - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.setLocation(new URI(callback)); - return new ResponseEntity<>(httpHeaders, HttpStatus.TEMPORARY_REDIRECT); - } -} +//@RestController +//@AllArgsConstructor +//public class AuthRedirectController { +// @Value("${android.package}") +// private String androidPackage; +// +// @Value("${android.scheme}") +// private String androidScheme; +// +// /** +// * 애플 로그인 리다이렉트 +// */ +// @CrossOrigin(origins = "https://appleid.apple.com") +// @PostMapping(value = "/auth/apple/callback", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) +// public ResponseEntity userLoginAppleCallback(@RequestParam("code") String code, +// @RequestParam("id_token") String idToken) throws URISyntaxException { +// // Deep link 생성 +// String callback = String.format("intent://callback?code=%s&id_token=%s#Intent;package=%s;scheme=%s;end", +// code, idToken, androidPackage, androidScheme); +// +// // 리다이렉트 +// HttpHeaders httpHeaders = new HttpHeaders(); +// httpHeaders.setLocation(new URI(callback)); +// return new ResponseEntity<>(httpHeaders, HttpStatus.TEMPORARY_REDIRECT); +// } +//} diff --git a/src/main/java/com/moing/backend/domain/infra/image/application/dto/ImageFileExtension.java b/src/main/java/com/moing/backend/domain/infra/image/application/dto/ImageFileExtension.java new file mode 100644 index 00000000..b93a1bdc --- /dev/null +++ b/src/main/java/com/moing/backend/domain/infra/image/application/dto/ImageFileExtension.java @@ -0,0 +1,15 @@ +package com.moing.backend.domain.infra.image.application.dto; + + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum ImageFileExtension { + JPEG("jpeg"), + JPG("jpg"), + PNG("png"); + + private final String uploadExtension; +} diff --git a/src/main/java/com/moing/backend/domain/infra/image/application/dto/ImageUrlDto.java b/src/main/java/com/moing/backend/domain/infra/image/application/dto/ImageUrlDto.java new file mode 100644 index 00000000..8b96e15a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/infra/image/application/dto/ImageUrlDto.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.infra.image.application.dto; + + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class ImageUrlDto { + + private final String presignedUrl; + private final String key; + + public static ImageUrlDto of(String url, String key) { + return ImageUrlDto.builder().presignedUrl(url).key(key).build(); + } +} diff --git a/src/main/java/com/moing/backend/domain/infra/image/application/dto/request/IssuePresignedUrlRequest.java b/src/main/java/com/moing/backend/domain/infra/image/application/dto/request/IssuePresignedUrlRequest.java new file mode 100644 index 00000000..f123d803 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/infra/image/application/dto/request/IssuePresignedUrlRequest.java @@ -0,0 +1,26 @@ +package com.moing.backend.domain.infra.image.application.dto.request; + + +import com.moing.backend.domain.infra.image.application.dto.ImageFileExtension; +import com.moing.backend.global.annotation.ValidEnum; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +@Builder +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class IssuePresignedUrlRequest { + + + @NotBlank(message = "파일 확장자를 입력해주세요.") + @ValidEnum( + enumClass = ImageFileExtension.class, + message = "유효하지 않은 ImageFileExtension 파라미터입니다.") + private ImageFileExtension imageFileExtension; + +} diff --git a/src/main/java/com/moing/backend/domain/infra/image/application/dto/response/IssuePresignedUrlResponse.java b/src/main/java/com/moing/backend/domain/infra/image/application/dto/response/IssuePresignedUrlResponse.java new file mode 100644 index 00000000..4b01271c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/infra/image/application/dto/response/IssuePresignedUrlResponse.java @@ -0,0 +1,25 @@ +package com.moing.backend.domain.infra.image.application.dto.response; + + +import com.moing.backend.domain.infra.image.application.dto.ImageUrlDto; +import com.moing.backend.global.config.s3.ImageUrlUtil; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class IssuePresignedUrlResponse { + + private final String presignedUrl; + + private final String imgUrl; + + public static IssuePresignedUrlResponse from(ImageUrlDto urlDto) { + String imgUrl = ImageUrlUtil.prefix +"/"+ urlDto.getKey(); + + return IssuePresignedUrlResponse.builder() + .presignedUrl(urlDto.getPresignedUrl()) + .imgUrl(imgUrl) + .build(); + } +} diff --git a/src/main/java/com/moing/backend/domain/infra/image/application/service/IssuePresignedUrlUseCase.java b/src/main/java/com/moing/backend/domain/infra/image/application/service/IssuePresignedUrlUseCase.java new file mode 100644 index 00000000..b95af55c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/infra/image/application/service/IssuePresignedUrlUseCase.java @@ -0,0 +1,23 @@ +package com.moing.backend.domain.infra.image.application.service; + + +import com.moing.backend.domain.infra.image.application.dto.request.IssuePresignedUrlRequest; +import com.moing.backend.domain.infra.image.application.dto.response.IssuePresignedUrlResponse; +import com.moing.backend.global.config.s3.S3Service; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + + +@Service +@RequiredArgsConstructor +public class IssuePresignedUrlUseCase { + + private final S3Service s3Service; + + public IssuePresignedUrlResponse execute(IssuePresignedUrlRequest issuePresignedUrlRequest) { + + return IssuePresignedUrlResponse.from( + s3Service.issuePreSignedUrl( + issuePresignedUrlRequest.getImageFileExtension())); + } +} diff --git a/src/main/java/com/moing/backend/domain/infra/image/presentation/ImageController.java b/src/main/java/com/moing/backend/domain/infra/image/presentation/ImageController.java new file mode 100644 index 00000000..28c973ac --- /dev/null +++ b/src/main/java/com/moing/backend/domain/infra/image/presentation/ImageController.java @@ -0,0 +1,33 @@ +package com.moing.backend.domain.infra.image.presentation; + +import com.moing.backend.domain.infra.image.application.dto.request.IssuePresignedUrlRequest; +import com.moing.backend.domain.infra.image.application.dto.response.IssuePresignedUrlResponse; +import com.moing.backend.domain.infra.image.application.service.IssuePresignedUrlUseCase; +import com.moing.backend.domain.infra.image.presentation.constant.EImageResponseMessage; +import com.moing.backend.global.annotation.ValidEnum; +import com.moing.backend.global.response.SuccessResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + + +@RestController +@RequestMapping("/api/image") +@RequiredArgsConstructor +public class ImageController { + + private final IssuePresignedUrlUseCase getPresignedUrlUseCase; + + + @PostMapping("/presigned") + public ResponseEntity> createPresigned(@RequestBody IssuePresignedUrlRequest issuePresignedUrlRequest) { + + return ResponseEntity.ok(SuccessResponse.create(EImageResponseMessage.ISSUE_PRESIGNED_URL_SUCCESS.getMessage(), getPresignedUrlUseCase.execute(issuePresignedUrlRequest))); + } +} diff --git a/src/main/java/com/moing/backend/domain/infra/image/presentation/constant/EImageResponseMessage.java b/src/main/java/com/moing/backend/domain/infra/image/presentation/constant/EImageResponseMessage.java new file mode 100644 index 00000000..be3e14c0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/infra/image/presentation/constant/EImageResponseMessage.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.infra.image.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum EImageResponseMessage { + ISSUE_PRESIGNED_URL_SUCCESS("presignedUrl을 발급하였습니다"); + + private final String message; +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index 5017d9b7..28c1bde2 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -53,7 +53,6 @@ public class Member extends BaseTimeEntity { @Column(nullable = false, length = 10) private String ageRange; //없으면 undef - private boolean isDeleted; // 추가정보 @Convert(converter = AesConverter.class) @@ -110,13 +109,10 @@ public void prePersist() { if (registrationStatus == null) registrationStatus = RegistrationStatus.UNCOMPLETED; } - public void signUp(String nickName) { + public void signUp(String nickName, String fcmToken) { this.nickName = nickName; - this.registrationStatus = RegistrationStatus.COMPLETED; - } - - public void updateFcmToken(String fcmToken) { this.fcmToken = fcmToken; + this.registrationStatus = RegistrationStatus.COMPLETED; } @Builder @@ -140,14 +136,6 @@ public void updateProfile(String profileImage, String nickName, String introduct this.introduction = introduction; } - public void deleteAccount() { - this.isDeleted = true; - } - - public void reSignUp() { - this.isDeleted = false; - } - public void updateNewUploadPush(boolean newUploadPush) { this.isNewUploadPush = newUploadPush; } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java index 151fb815..c1b27c23 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java @@ -5,6 +5,5 @@ import java.util.Optional; public interface MemberCustomRepository { - Optional findBySocialIdNotDeleted(String socialId); boolean checkNickname(String nickname); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java index de95f305..2126f3b1 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java @@ -16,14 +16,6 @@ public MemberCustomRepositoryImpl(EntityManager em) { this.queryFactory = new JPAQueryFactory(em); } - @Override - public Optional findBySocialIdNotDeleted(String socialId) { - return Optional.ofNullable(queryFactory.selectFrom(member) - .where(member.socialId.eq(socialId)) - .where(member.isDeleted.eq(false)) - .fetchFirst()); - } - @Override public boolean checkNickname(String nickname) { return queryFactory diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberDeleteService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberDeleteService.java new file mode 100644 index 00000000..843fcde5 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberDeleteService.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.member.domain.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.repository.MemberRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MemberDeleteService { + + private final MemberRepository memberRepository; + + public void deleteMember(Member member){ + this.memberRepository.delete(member); + } +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java index 09342d61..dc88284d 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java @@ -15,6 +15,6 @@ public class MemberGetService { private final MemberRepository memberRepository; public Member getMemberBySocialId(String socialId){ - return memberRepository.findBySocialIdNotDeleted(socialId).orElseThrow(()->new NotFoundBySocialIdException()); + return memberRepository.findBySocialId(socialId).orElseThrow(()->new NotFoundBySocialIdException()); } } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java index 2d974a92..71f01159 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java @@ -18,10 +18,6 @@ public class MemberSaveService { public Member saveMember(Member member) { OptionalfindMember=memberRepository.findBySocialId(member.getSocialId()); if(findMember.isEmpty()){ - //회원탈퇴회원이라면 재가입 - if(member.isDeleted()){ - member.reSignUp(); - } return memberRepository.save(member); } else { return findMember.get(); diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/request/UpdateProfileRequest.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/request/UpdateProfileRequest.java new file mode 100644 index 00000000..578f59d0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/request/UpdateProfileRequest.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.mypage.application.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class UpdateProfileRequest { + + private String profileImage; + private String nickName; + private String introduction; +} diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetAlarmResponse.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetAlarmResponse.java new file mode 100644 index 00000000..8d7e602c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetAlarmResponse.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.mypage.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class GetAlarmResponse { + + private boolean isNewUploadPush; + private boolean isRemindPush; + private boolean isFirePush; +} diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetProfileResponse.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetProfileResponse.java new file mode 100644 index 00000000..5b6d2e79 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetProfileResponse.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.mypage.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class GetProfileResponse { + private String profileImage; + private String nickName; + private String introduction; +} diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java new file mode 100644 index 00000000..b535db5f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.mypage.application.service; + +import com.moing.backend.domain.member.application.mapper.MemberMapper; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mypage.application.dto.response.GetAlarmResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RequestBody; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class AlarmUserCase { + + private MemberGetService memberGetService; + + public GetAlarmResponse getAlarm(String socialId){ + Member member=memberGetService.getMemberBySocialId(socialId); + return new GetAlarmResponse(member.isNewUploadPush(),member.isRemindPush(), member.isFirePush()); + } +} diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java new file mode 100644 index 00000000..fdaa3f4a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java @@ -0,0 +1,37 @@ +package com.moing.backend.domain.mypage.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mypage.application.dto.request.UpdateProfileRequest; +import com.moing.backend.domain.mypage.application.dto.response.GetProfileResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@RequiredArgsConstructor +public class ProfileUserCase { + + private final MemberGetService memberGetService; + + public GetProfileResponse getProfile(String socialId){ + Member member=memberGetService.getMemberBySocialId(socialId); + return new GetProfileResponse(member.getProfileImage(), member.getNickName(), member.getIntroduction()); + } + + @Transactional + public void updateProfile(String socialId, UpdateProfileRequest updateProfileRequest) { + Member member = memberGetService.getMemberBySocialId(socialId); + member.updateProfile( + getUpdatedValue(updateProfileRequest.getProfileImage(), member.getProfileImage()), + getUpdatedValue(updateProfileRequest.getNickName(), member.getNickName()), + getUpdatedValue(updateProfileRequest.getIntroduction(), member.getIntroduction()) + ); + } + + private String getUpdatedValue(String newValue, String currentValue) { + return newValue != null ? newValue : currentValue; + } + +} diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java index daf6ef32..54931f44 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.mypage.application.service; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberDeleteService; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; import com.moing.backend.domain.mypage.domain.service.FeedbackSaveService; @@ -14,11 +15,13 @@ public class WithdrawUserCase { private final MemberGetService memberGetService; private final FeedbackSaveService feedbackSaveService; private final TokenUtil tokenUtil; + private final MemberDeleteService memberDeleteService; public void withdraw(String socialId, WithdrawRequest withdrawRequest) { - //1. 멤버 상태 변화 + //1. 멤버 삭제 Member member = memberGetService.getMemberBySocialId(socialId); - member.deleteAccount(); + memberDeleteService.deleteMember(member); + //TODO: 애플과 카카오 회원탈퇴 //2. 피드백 저장 feedbackSaveService.saveFeedback(member, withdrawRequest); //3. 리프레시 토큰 만료 diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java index c3cc6adc..bfc89771 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java @@ -1,6 +1,11 @@ package com.moing.backend.domain.mypage.presentation; +import com.moing.backend.domain.mypage.application.dto.request.UpdateProfileRequest; import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; +import com.moing.backend.domain.mypage.application.dto.response.GetAlarmResponse; +import com.moing.backend.domain.mypage.application.dto.response.GetProfileResponse; +import com.moing.backend.domain.mypage.application.service.AlarmUserCase; +import com.moing.backend.domain.mypage.application.service.ProfileUserCase; import com.moing.backend.domain.mypage.application.service.SignOutUserCase; import com.moing.backend.domain.mypage.application.service.WithdrawUserCase; import com.moing.backend.global.config.security.dto.User; @@ -12,8 +17,7 @@ import javax.validation.Valid; -import static com.moing.backend.domain.mypage.presentation.constant.MypageResponseMessage.SIGN_OUT_SUCCESS; -import static com.moing.backend.domain.mypage.presentation.constant.MypageResponseMessage.WITHDRAWAL_SUCCESS; +import static com.moing.backend.domain.mypage.presentation.constant.MypageResponseMessage.*; @RestController @AllArgsConstructor @@ -22,8 +26,10 @@ public class MyPageController { private final SignOutUserCase signOutService; private final WithdrawUserCase withdrawService; + private final ProfileUserCase profileUserCase; + private final AlarmUserCase alarmUserCase; - //TODO 마이페이지 조회, 수정, 알림설정 수정 + //TODO 마이페이지 조회, 알림설정 수정 /** * 로그아웃 @@ -47,4 +53,37 @@ public ResponseEntity withdraw(@AuthenticationPrincipal User us this.withdrawService.withdraw(user.getSocialId(), withdrawRequest); return ResponseEntity.ok(SuccessResponse.create(WITHDRAWAL_SUCCESS.getMessage())); } + + /** + * 프로필 조회 + * [GET] api/mypage/profile + * 작성자 : 김민수 + */ + @GetMapping("/profile") + public ResponseEntity> getProfile(@AuthenticationPrincipal User user){ + return ResponseEntity.ok(SuccessResponse.create(GET_PROFILE_SUCCESS.getMessage(), this.profileUserCase.getProfile(user.getSocialId()))); + } + + /** + * 프로필 수정 + * [PUT] api/mypage/profile + * 작성자 : 김민수 + */ + @PutMapping("/profile") + public ResponseEntity updatePorfile(@AuthenticationPrincipal User user, + @RequestBody UpdateProfileRequest updateProfileRequest){ + this.profileUserCase.updateProfile(user.getSocialId(), updateProfileRequest); + return ResponseEntity.ok(SuccessResponse.create(UPDATE_PROFILE_SUCCESS.getMessage())); + } + + /** + * 알림정보 조회 + * [GET] api/mypage/alarm + * 작성자 : 김민수 + */ + @GetMapping("/alarm") + public ResponseEntity> getAlarm(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(GET_ALARM_SUCCESS.getMessage(), this.alarmUserCase.getAlarm(user.getSocialId()))); + } + } diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java b/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java index f1d4429d..463f5ddb 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java @@ -7,6 +7,10 @@ @RequiredArgsConstructor public enum MypageResponseMessage { SIGN_OUT_SUCCESS("로그아웃을 했습니다"), - WITHDRAWAL_SUCCESS("회원탈퇴를 했습니다"); + WITHDRAWAL_SUCCESS("회원탈퇴를 했습니다"), + GET_PROFILE_SUCCESS("프로필을 조회했습니다"), + UPDATE_PROFILE_SUCCESS("프로필을 수정했습니다"), + GET_ALARM_SUCCESS("알람 정보를 조회했습니다"), + UPDATE_ALARM_SUCCESS("알람 정보를 수정했습니다"); private final String message; } diff --git a/src/main/java/com/moing/backend/global/annotation/Util.java b/src/main/java/com/moing/backend/global/annotation/Util.java new file mode 100644 index 00000000..20eb01b1 --- /dev/null +++ b/src/main/java/com/moing/backend/global/annotation/Util.java @@ -0,0 +1,15 @@ +package com.moing.backend.global.annotation; + +import org.springframework.core.annotation.AliasFor; +import org.springframework.stereotype.Component; + +import java.lang.annotation.*; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Component +public @interface Util { + @AliasFor(annotation = Component.class) + String value() default ""; +} diff --git a/src/main/java/com/moing/backend/global/annotation/ValidEnum.java b/src/main/java/com/moing/backend/global/annotation/ValidEnum.java new file mode 100644 index 00000000..a1c53508 --- /dev/null +++ b/src/main/java/com/moing/backend/global/annotation/ValidEnum.java @@ -0,0 +1,21 @@ +package com.moing.backend.global.annotation; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Constraint(validatedBy = {EnumValidator.class}) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ValidEnum { + String message() default "Invalid value. This is not permitted."; + + Class[] groups() default {}; + + Class[] payload() default {}; + + Class> enumClass(); +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/s3/ImageUrlUtil.java b/src/main/java/com/moing/backend/global/config/s3/ImageUrlUtil.java new file mode 100644 index 00000000..2e85b4fa --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/s3/ImageUrlUtil.java @@ -0,0 +1,14 @@ +package com.moing.backend.global.config.s3; + +import com.moing.backend.global.annotation.Util; +import org.springframework.beans.factory.annotation.Value; + +@Util +public class ImageUrlUtil { + public static String prefix; + + @Value("${image.prefix}") + public void setPrefix(String value) { + prefix = value; + } +} diff --git a/src/main/java/com/moing/backend/global/config/s3/S3Config.java b/src/main/java/com/moing/backend/global/config/s3/S3Config.java new file mode 100644 index 00000000..5b2078ae --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/s3/S3Config.java @@ -0,0 +1,33 @@ +package com.moing.backend.global.config.s3; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class S3Config { + + @Value("${cloud.aws.credentials.access-key}") + private String accessKey; + + @Value("${cloud.aws.credentials.secret-key}") + private String secretKey; + + @Value("${cloud.aws.region.static}") + private String region; + + @Bean + public AmazonS3Client amazonS3Client() { + AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); + return (AmazonS3Client) + AmazonS3ClientBuilder.standard() + .withCredentials(new AWSStaticCredentialsProvider(credentials)) + .withRegion(region) + .build(); + } +} diff --git a/src/main/java/com/moing/backend/global/config/s3/S3Service.java b/src/main/java/com/moing/backend/global/config/s3/S3Service.java new file mode 100644 index 00000000..a218a353 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/s3/S3Service.java @@ -0,0 +1,62 @@ +package com.moing.backend.global.config.s3; + +import com.amazonaws.HttpMethod; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.Headers; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; +import com.moing.backend.domain.infra.image.application.dto.ImageFileExtension; +import com.moing.backend.domain.infra.image.application.dto.ImageUrlDto; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class S3Service { + private final AmazonS3Client amazonS3; + + @Value("${cloud.aws.s3.bucket}") + private String bucket; + + + public ImageUrlDto issuePreSignedUrl(ImageFileExtension fileExtension) { + + String valueFileExtension = fileExtension.getUploadExtension(); + + String fileName = createFileName(valueFileExtension); + + GeneratePresignedUrlRequest request = getGeneratePreSignedUrlRequest(bucket, fileName, valueFileExtension); + String url = amazonS3.generatePresignedUrl(request).toString(); + + return ImageUrlDto.of(url, fileName); + } + + private String createFileName(String fileExtension) { + return UUID.randomUUID() + "." + fileExtension; + } + + // 업로드용 Pre-Signed URL을 생성하기 때문에, PUT을 지정 + private GeneratePresignedUrlRequest getGeneratePreSignedUrlRequest( + String bucket, String fileName, String fileExtension) { + GeneratePresignedUrlRequest generatePresignedUrlRequest = + new GeneratePresignedUrlRequest(bucket, fileName) + .withMethod(HttpMethod.PUT) + .withExpiration(getPreSignedUrlExpiration()); + generatePresignedUrlRequest.addRequestParameter( + Headers.S3_CANNED_ACL, CannedAccessControlList.PublicRead.toString()); + return generatePresignedUrlRequest; + } + + private Date getPreSignedUrlExpiration() { + Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Seoul")); + calendar.add(Calendar.MINUTE, 5); // 5분 추가 + return calendar.getTime(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java index efcafd2e..873811ae 100644 --- a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java +++ b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java @@ -48,7 +48,7 @@ protected void configure(HttpSecurity http) throws Exception { .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //Spring Security에서 세션을 사용하지 않도록 설정 .and() .authorizeRequests() - .antMatchers("/api/auth/**", "/docs/**").permitAll() + .antMatchers("/api/auth/**", "/docs/**", "/api/image/**").permitAll() .antMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() diff --git a/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetails.java b/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetails.java index a27370a0..0123fb99 100644 --- a/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetails.java +++ b/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetails.java @@ -34,22 +34,22 @@ public String getUsername() { @Override public boolean isAccountNonExpired() { - return !member.isDeleted(); + return true; } @Override public boolean isAccountNonLocked() { - return !member.isDeleted(); + return true; } @Override public boolean isCredentialsNonExpired() { - return !member.isDeleted(); + return true; } @Override public boolean isEnabled() { - return !member.isDeleted(); + return true; } public Member getMember() { diff --git a/src/main/resources/static/docs/Auth-API.html b/src/main/resources/static/docs/Auth-API.html index 12f4e702..4bf6e822 100644 --- a/src/main/resources/static/docs/Auth-API.html +++ b/src/main/resources/static/docs/Auth-API.html @@ -806,11 +806,12 @@

    HTTP request

    PUT /api/auth/signUp HTTP/1.1
     Content-Type: application/json;charset=UTF-8
     Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 29
    +Content-Length: 56
     Host: localhost:8080
     
     {
    -  "nickName" : "NICKNAME"
    +  "nickName" : "NICKNAME",
    +  "fcmToken" : "FCMTOKEN"
     }
    @@ -836,6 +837,11 @@

    Request fields

    String

    유저 닉네임

    + +

    fcmToken

    +

    String

    +

    FCM TOKEN

    + diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html index 5cd5701a..7ade9d32 100644 --- a/src/main/resources/static/docs/api.html +++ b/src/main/resources/static/docs/api.html @@ -1010,11 +1010,12 @@

    PUT /api/auth/signUp HTTP/1.1 Content-Type: application/json;charset=UTF-8 Authorization: Bearer ACCESS_TOKEN -Content-Length: 29 +Content-Length: 56 Host: localhost:8080 { - "nickName" : "NICKNAME" + "nickName" : "NICKNAME", + "fcmToken" : "FCMTOKEN" } @@ -1040,6 +1041,11 @@

    String

    유저 닉네임

    + +

    fcmToken

    +

    String

    +

    FCM TOKEN

    + diff --git a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java index 9a076d35..0a6a74cb 100644 --- a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java +++ b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java @@ -221,6 +221,7 @@ public void sign_up() throws Exception { //given SignUpRequest input = SignUpRequest.builder() .nickName("NICKNAME") + .fcmToken("FCMTOKEN") .build(); String body = objectMapper.writeValueAsString(input); @@ -252,7 +253,8 @@ public void sign_up() throws Exception { headerWithName("Authorization").description("접근 토큰") ), requestFields( - fieldWithPath("nickName").description("유저 닉네임") + fieldWithPath("nickName").description("유저 닉네임"), + fieldWithPath("fcmToken").description("FCM TOKEN") ), responseFields( fieldWithPath("isSuccess").description("true"), diff --git a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java index b6deef0a..ffe11983 100644 --- a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java @@ -2,6 +2,8 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; +import com.moing.backend.domain.mypage.application.service.AlarmUserCase; +import com.moing.backend.domain.mypage.application.service.ProfileUserCase; import com.moing.backend.domain.mypage.application.service.SignOutUserCase; import com.moing.backend.domain.mypage.application.service.WithdrawUserCase; import org.junit.jupiter.api.Test; @@ -24,6 +26,12 @@ public class MypageControllerTest extends CommonControllerTest { @MockBean private WithdrawUserCase withdrawService; + @MockBean + private ProfileUserCase profileUserCase; + + @MockBean + private AlarmUserCase alarmUserCase; + @Test public void sign_out() throws Exception { //when From 1a4b1c5a4d29be0597c3a3ab18e9c5dd5682cbfb Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sun, 3 Sep 2023 14:13:41 +0900 Subject: [PATCH 051/619] =?UTF-8?q?feat:=20presigned-URL=20adoc=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + src/docs/asciidoc/Image-API.adoc | 17 + src/docs/asciidoc/Team-API.adoc | 5 +- src/docs/asciidoc/api.adoc | 3 + .../image/presentation/ImageController.java | 4 - src/main/resources/static/docs/Image-API.html | 579 ++++++++++++++++++ src/main/resources/static/docs/Team-API.html | 4 +- src/main/resources/static/docs/api.html | 137 ++++- .../presentation/ImageControllerTest.java | 67 ++ 9 files changed, 808 insertions(+), 11 deletions(-) create mode 100644 src/docs/asciidoc/Image-API.adoc create mode 100644 src/main/resources/static/docs/Image-API.html create mode 100644 src/test/java/com/moing/backend/domain/infra/image/presentation/ImageControllerTest.java diff --git a/.gitignore b/.gitignore index 14010ef5..1cc184d2 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ application.yml .DS_Store firebase-key.json data.sql + +#### docs #### +!**/src/main/resources/static/docs/ \ No newline at end of file diff --git a/src/docs/asciidoc/Image-API.adoc b/src/docs/asciidoc/Image-API.adoc new file mode 100644 index 00000000..d2bb8996 --- /dev/null +++ b/src/docs/asciidoc/Image-API.adoc @@ -0,0 +1,17 @@ +[[Image-API]] += Image API + +[[Presigned-Url-발급]] +=== Presigned Url 발급 +operation::image-controller-test/create_presigned_url[snippets='http-request,http-response,request-fields,response-fields'] + +=== imageFileExtension +|=== +| input 형식 + +| `JPG` + +| `JPEG` + +| `PNG` +|=== \ No newline at end of file diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc index d17ccd0c..4afd2ca1 100644 --- a/src/docs/asciidoc/Team-API.adoc +++ b/src/docs/asciidoc/Team-API.adoc @@ -5,7 +5,7 @@ === Team 소모임 개설 operation::team-controller-test/create_team[snippets='http-request,request-fields,http-response,response-fields'] -=== 소모임 카테고리 +=== Team Category |=== | Category | Description @@ -25,4 +25,5 @@ operation::team-controller-test/create_team[snippets='http-request,request-field | 독서 | `ETC` -| 그외 자기계발 \ No newline at end of file +| 그외 자기계발 +|=== \ No newline at end of file diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index afc5cc1b..f4089838 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -8,9 +8,12 @@ include::Overview.adoc[] +include::Image-API.adoc[] + include::Auth-API.adoc[] include::Mypage-API.adoc[] include::Team-API.adoc[] + diff --git a/src/main/java/com/moing/backend/domain/infra/image/presentation/ImageController.java b/src/main/java/com/moing/backend/domain/infra/image/presentation/ImageController.java index 28c973ac..6499a141 100644 --- a/src/main/java/com/moing/backend/domain/infra/image/presentation/ImageController.java +++ b/src/main/java/com/moing/backend/domain/infra/image/presentation/ImageController.java @@ -4,18 +4,14 @@ import com.moing.backend.domain.infra.image.application.dto.response.IssuePresignedUrlResponse; import com.moing.backend.domain.infra.image.application.service.IssuePresignedUrlUseCase; import com.moing.backend.domain.infra.image.presentation.constant.EImageResponseMessage; -import com.moing.backend.global.annotation.ValidEnum; import com.moing.backend.global.response.SuccessResponse; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import javax.validation.Valid; - @RestController @RequestMapping("/api/image") diff --git a/src/main/resources/static/docs/Image-API.html b/src/main/resources/static/docs/Image-API.html new file mode 100644 index 00000000..c5881d22 --- /dev/null +++ b/src/main/resources/static/docs/Image-API.html @@ -0,0 +1,579 @@ + + + + + + + +Image API + + + + + +
    +
    +

    Presigned Url 발급

    +
    +

    HTTP request

    +
    +
    +
    POST /api/image/presigned HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 34
    +Host: localhost:8080
    +
    +{
    +  "imageFileExtension" : "JPG"
    +}
    +
    +
    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 162
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "presignedUrl을 발급하였습니다",
    +  "data" : {
    +    "presignedUrl" : "PRESIGNED_URL",
    +    "imgUrl" : "IMAGE_URL"
    +  }
    +}
    +
    +
    +
    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + +
    PathTypeDescription

    imageFileExtension

    String

    이미지 확장자

    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    presignedUrl을 발급하였습니다

    data.presignedUrl

    String

    이미지 업로드용 PresignedUrl

    data.imgUrl

    String

    업로드 후 이미지 URL

    +
    +
    +
    +

    imageFileExtension

    + +++ + + + + + + + + + + + + + + + + +
    input 형식

    JPG

    JPEG

    PNG

    +
    +
    + + + \ No newline at end of file diff --git a/src/main/resources/static/docs/Team-API.html b/src/main/resources/static/docs/Team-API.html index d25e0771..e9ec6d0e 100644 --- a/src/main/resources/static/docs/Team-API.html +++ b/src/main/resources/static/docs/Team-API.html @@ -564,7 +564,7 @@

    Response fields

    -

    소모임 카테고리

    +

    Team Category

    @@ -608,7 +608,7 @@

    소모임 카테고리

    diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html index 7ade9d32..bfc0ad40 100644 --- a/src/main/resources/static/docs/api.html +++ b/src/main/resources/static/docs/api.html @@ -454,6 +454,12 @@

    Moing API Doc

  • Team / Team_member ErrorCode
  • +
  • Image API + +
  • Auth API @@ -647,6 +653,131 @@

    Image API

    +
    +

    Presigned Url 발급

    +
    +

    HTTP request

    +
    +
    +
    POST /api/image/presigned HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 34
    +Host: localhost:8080
    +
    +{
    +  "imageFileExtension" : "JPG"
    +}
    +
    +
    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 162
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "presignedUrl을 발급하였습니다",
    +  "data" : {
    +    "presignedUrl" : "PRESIGNED_URL",
    +    "imgUrl" : "IMAGE_URL"
    +  }
    +}
    +
    +
    +
    +
  • +++++ + + + + + + + + + + + + + + +
    PathTypeDescription

    imageFileExtension

    String

    이미지 확장자

    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    presignedUrl을 발급하였습니다

    data.presignedUrl

    String

    이미지 업로드용 PresignedUrl

    data.imgUrl

    String

    업로드 후 이미지 URL

    +
    + +
    +

    imageFileExtension

    + +++ + + + + + + + + + + + + + + + + +
    input 형식

    JPG

    JPEG

    PNG

    +

    Auth API

    Auth Kakao 소셜 로그인 요청

    @@ -1576,7 +1707,7 @@

    -

    소모임 카테고리

    +

    Team Category

    @@ -1620,7 +1751,7 @@

    diff --git a/src/test/java/com/moing/backend/domain/infra/image/presentation/ImageControllerTest.java b/src/test/java/com/moing/backend/domain/infra/image/presentation/ImageControllerTest.java new file mode 100644 index 00000000..4777ff83 --- /dev/null +++ b/src/test/java/com/moing/backend/domain/infra/image/presentation/ImageControllerTest.java @@ -0,0 +1,67 @@ +package com.moing.backend.domain.infra.image.presentation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.infra.image.application.dto.ImageFileExtension; +import com.moing.backend.domain.infra.image.application.dto.request.IssuePresignedUrlRequest; +import com.moing.backend.domain.infra.image.application.dto.response.IssuePresignedUrlResponse; +import com.moing.backend.domain.infra.image.application.service.IssuePresignedUrlUseCase; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.ResultActions; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(ImageController.class) +class ImageControllerTest extends CommonControllerTest { + + @MockBean + private IssuePresignedUrlUseCase getPresignedUrlUseCase; + + @Test + public void create_presigned_url() throws Exception { + IssuePresignedUrlRequest input = IssuePresignedUrlRequest.builder() + .imageFileExtension(ImageFileExtension.JPG) + .build(); + + String body = objectMapper.writeValueAsString(input); + + IssuePresignedUrlResponse output = IssuePresignedUrlResponse.builder() + .presignedUrl("PRESIGNED_URL") + .imgUrl("IMAGE_URL") + .build(); + + + given(getPresignedUrlUseCase.execute(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + post("/api/image/presigned") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestFields( + fieldWithPath("imageFileExtension").description("이미지 확장자") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("presignedUrl을 발급하였습니다"), + fieldWithPath("data.presignedUrl").description("이미지 업로드용 PresignedUrl"), + fieldWithPath("data.imgUrl").description("업로드 후 이미지 URL") + ) + ) + ); + } +} \ No newline at end of file From 08313e3e1b3848b5512f97d6067c1e1a939f671d Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sun, 3 Sep 2023 14:56:14 +0900 Subject: [PATCH 052/619] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C,=20=EC=88=98=EC=A0=95=20adoc=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Mypage-API.adoc | 19 ++ .../resources/static/docs/Mypage-API.html | 215 ++++++++++++++++- src/main/resources/static/docs/api.html | 217 +++++++++++++++++- .../presentation/ImageControllerTest.java | 2 +- .../presentation/MypageControllerTest.java | 87 +++++++ 5 files changed, 537 insertions(+), 3 deletions(-) diff --git a/src/docs/asciidoc/Mypage-API.adoc b/src/docs/asciidoc/Mypage-API.adoc index 8bd64ca9..58e5ef94 100644 --- a/src/docs/asciidoc/Mypage-API.adoc +++ b/src/docs/asciidoc/Mypage-API.adoc @@ -10,3 +10,22 @@ operation::mypage-controller-test/sign_out[snippets='http-request,http-response, [[Mypage-회원탈퇴]] === Mypage 회원탈퇴 operation::mypage-controller-test/withdraw[snippets='http-request,request-fields,http-response,response-fields'] + +[[Mypage-프로필-조회]] +=== Mypage 프로필 조회 +operation::mypage-controller-test/get_profile[snippets='http-request,http-response,response-fields'] +IMPORTANT: Response Fields (profileImage, nickName, introduction)이 "undef" 인 경우는 사용자가 아직 입력을 안 한 경우임 + +[[Mypage-프로필-수정]] +=== Mypage 프로필 수정 +operation::mypage-controller-test/update_profile[snippets='http-request,http-response,request-fields,response-fields'] +IMPORTANT: Request Fileds는 반드시 세 값이 모두 들어가야 하는 것이 아니고, 업데이트할 값만 입력해도 됨, 따라서 아래와 같은 예시 가능 + + + PUT /api/mypage/profile HTTP/1.1 +Content-Type: application/json;charset=UTF-8 +Authorization: Bearer ACCESS_TOKEN +Content-Length: 104 +Host: localhost:8080 +{ +"profileImage" : "PROFILE_IMAGE_URL" +} diff --git a/src/main/resources/static/docs/Mypage-API.html b/src/main/resources/static/docs/Mypage-API.html index b1670a2f..b2710356 100644 --- a/src/main/resources/static/docs/Mypage-API.html +++ b/src/main/resources/static/docs/Mypage-API.html @@ -590,11 +590,224 @@

    Response fields

    +
    +

    Mypage 프로필 조회

    +
    +

    HTTP request

    +
    +
    +
    GET /api/mypage/profile HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Host: localhost:8080
    +
    +
    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 198
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "프로필을 조회했습니다",
    +  "data" : {
    +    "profileImage" : "PROFILE_IMAGE_URL",
    +    "nickName" : "NICKNAME",
    +    "introduction" : "INTRODUCTION"
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    프로필을 조회했습니다

    data.profileImage

    String

    프로필 이미지 URL

    data.nickName

    String

    닉네임

    data.introduction

    String

    한줄 소개

    +
    +
    + + + + + +
    +
    Important
    +
    +Response Fields (profileImage, nickName, introduction)이 "undef" 인 경우는 사용자가 아직 입력을 안 한 경우임 +
    +
    +
    +
    +

    Mypage 프로필 수정

    +
    +

    HTTP request

    +
    +
    +
    PUT /api/mypage/profile HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Content-Length: 104
    +Host: localhost:8080
    +
    +{
    +  "profileImage" : "PROFILE_IMAGE_URL",
    +  "nickName" : "NICKNAME",
    +  "introduction" : "INTRODUCTION"
    +}
    +
    +
    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 73
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "프로필을 수정했습니다"
    +}
    +
    +
    +
    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    profileImage

    String

    프로필 이미지 URL

    nickName

    String

    닉네임

    introduction

    String

    한줄 소개

    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    프로필을 수정했습니다.

    +
    +
    + + + + + +
    +
    Important
    +
    +Request Fileds는 반드시 세 값이 모두 들어가야 하는 것이 아니고, 업데이트할 값만 입력해도 됨, 따라서 아래와 같은 예시 가능
    +
    +
    +
    +
    +
     PUT /api/mypage/profile HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Content-Length: 104
    +Host: localhost:8080
    +{
    +"profileImage" : "PROFILE_IMAGE_URL"
    +}
    +
    +
    +
    diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html index bfc0ad40..1a46b6b4 100644 --- a/src/main/resources/static/docs/api.html +++ b/src/main/resources/static/docs/api.html @@ -479,6 +479,8 @@

    Moing API Doc

  • Team API @@ -1586,6 +1588,219 @@

    +

    Mypage 프로필 조회

    +
    +

    HTTP request

    +
    +
    +
    GET /api/mypage/profile HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Host: localhost:8080
    +
    +
    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 198
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "프로필을 조회했습니다",
    +  "data" : {
    +    "profileImage" : "PROFILE_IMAGE_URL",
    +    "nickName" : "NICKNAME",
    +    "introduction" : "INTRODUCTION"
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    프로필을 조회했습니다

    data.profileImage

    String

    프로필 이미지 URL

    data.nickName

    String

    닉네임

    data.introduction

    String

    한줄 소개

    +
    +
    + + + + + +
    + + +Response Fields (profileImage, nickName, introduction)이 "undef" 인 경우는 사용자가 아직 입력을 안 한 경우임 +
    +
    + +
    +

    Mypage 프로필 수정

    +
    +

    HTTP request

    +
    +
    +
    PUT /api/mypage/profile HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Content-Length: 104
    +Host: localhost:8080
    +
    +{
    +  "profileImage" : "PROFILE_IMAGE_URL",
    +  "nickName" : "NICKNAME",
    +  "introduction" : "INTRODUCTION"
    +}
    +
    +
    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 73
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "프로필을 수정했습니다"
    +}
    +
    +
    +
    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    profileImage

    String

    프로필 이미지 URL

    nickName

    String

    닉네임

    introduction

    String

    한줄 소개

    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    프로필을 수정했습니다.

    +
    +
    + + + + + +
    + + +Request Fileds는 반드시 세 값이 모두 들어가야 하는 것이 아니고, 업데이트할 값만 입력해도 됨, 따라서 아래와 같은 예시 가능
    +
    +
    +
    +
    +
     PUT /api/mypage/profile HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Content-Length: 104
    +Host: localhost:8080
    +{
    +"profileImage" : "PROFILE_IMAGE_URL"
    +}
    +
    +
    +

    Team API

    Team 소모임 개설

    @@ -1751,7 +1966,7 @@

    Team Category diff --git a/src/test/java/com/moing/backend/domain/infra/image/presentation/ImageControllerTest.java b/src/test/java/com/moing/backend/domain/infra/image/presentation/ImageControllerTest.java index 4777ff83..9465f1d9 100644 --- a/src/test/java/com/moing/backend/domain/infra/image/presentation/ImageControllerTest.java +++ b/src/test/java/com/moing/backend/domain/infra/image/presentation/ImageControllerTest.java @@ -59,7 +59,7 @@ public void create_presigned_url() throws Exception { fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("presignedUrl을 발급하였습니다"), fieldWithPath("data.presignedUrl").description("이미지 업로드용 PresignedUrl"), - fieldWithPath("data.imgUrl").description("업로드 후 이미지 URL") + fieldWithPath("data.imgUrl").description("업로드 후 이미지 URL") ) ) ); diff --git a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java index ffe11983..277100a0 100644 --- a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java @@ -1,17 +1,22 @@ package com.moing.backend.domain.mypage.presentation; import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.mypage.application.dto.request.UpdateProfileRequest; import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; +import com.moing.backend.domain.mypage.application.dto.response.GetProfileResponse; import com.moing.backend.domain.mypage.application.service.AlarmUserCase; import com.moing.backend.domain.mypage.application.service.ProfileUserCase; import com.moing.backend.domain.mypage.application.service.SignOutUserCase; import com.moing.backend.domain.mypage.application.service.WithdrawUserCase; +import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.ResultActions; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.payload.PayloadDocumentation.*; @@ -82,6 +87,9 @@ public void withdraw() throws Exception { .andExpect(status().isOk()) .andDo( restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), requestFields( fieldWithPath("reason").description("회원탈퇴하는 이유") ), @@ -92,4 +100,83 @@ public void withdraw() throws Exception { ) ); } + + @Test + public void get_profile() throws Exception { + //given + GetProfileResponse output = GetProfileResponse.builder() + .profileImage("PROFILE_IMAGE_URL") + .introduction("INTRODUCTION") + .nickName("NICKNAME") + .build(); + + given(profileUserCase.getProfile(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + get("/api/mypage/profile") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("프로필을 조회했습니다"), + fieldWithPath("data.profileImage").description("프로필 이미지 URL"), + fieldWithPath("data.nickName").description("닉네임"), + fieldWithPath("data.introduction").description("한줄 소개") + ) + ) + ); + } + + @Test + public void update_profile() throws Exception { + //given + UpdateProfileRequest input = UpdateProfileRequest.builder() + .profileImage("PROFILE_IMAGE_URL") + .introduction("INTRODUCTION") + .nickName("NICKNAME") + .build(); + + String body = objectMapper.writeValueAsString(input); + + //when + ResultActions actions = mockMvc.perform( + put("/api/mypage/profile") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + requestFields( + fieldWithPath("profileImage").description("프로필 이미지 URL"), + fieldWithPath("nickName").description("닉네임"), + fieldWithPath("introduction").description("한줄 소개") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("프로필을 수정했습니다.") + ) + ) + ); + } } From 771fb11cad0385a24c222a2c5bd205eae6e1d2dc Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sun, 3 Sep 2023 22:27:58 +0900 Subject: [PATCH 053/619] docs: delete src/main/resources/static/docs --- src/main/resources/static/docs/Auth-API.html | 1115 ---------- src/main/resources/static/docs/Image-API.html | 579 ----- .../resources/static/docs/Mypage-API.html | 814 ------- src/main/resources/static/docs/Overview.html | 613 ----- src/main/resources/static/docs/Team-API.html | 615 ----- src/main/resources/static/docs/api.html | 1976 ----------------- 6 files changed, 5712 deletions(-) delete mode 100644 src/main/resources/static/docs/Auth-API.html delete mode 100644 src/main/resources/static/docs/Image-API.html delete mode 100644 src/main/resources/static/docs/Mypage-API.html delete mode 100644 src/main/resources/static/docs/Overview.html delete mode 100644 src/main/resources/static/docs/Team-API.html delete mode 100644 src/main/resources/static/docs/api.html diff --git a/src/main/resources/static/docs/Auth-API.html b/src/main/resources/static/docs/Auth-API.html deleted file mode 100644 index 4bf6e822..00000000 --- a/src/main/resources/static/docs/Auth-API.html +++ /dev/null @@ -1,1115 +0,0 @@ - - - - - - - -Auth API - - - - - -
    -
    -

    Auth Kakao 소셜 로그인 요청

    -
    -

    HTTP request

    -
    -
    -
    POST /api/auth/signIn/kakao HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 36
    -Host: localhost:8080
    -
    -{
    -  "token" : "KAKAO_ACCESS_TOKEN"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    token

    String

    카카오 액세스 토큰

    -
    -
    -
    -

    Auth Kakao 소셜 로그인 회원가입 전 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 206
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : false
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 : false

    -
    -
    -
    -

    Auth Kakao 소셜 로그인 회원가입 후 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 205
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :true

    -
    -
    -
    -
    -

    Auth Apple 소셜 로그인 요청

    -
    -

    HTTP request

    -
    -
    -
    POST /api/auth/signIn/apple HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 38
    -Host: localhost:8080
    -
    -{
    -  "token" : "APPLE_IDENTITY_TOKEN"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    token

    String

    애플 아이디 토큰

    -
    -
    -
    -

    Auth Apple 소셜 로그인 회원가입 전 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 206
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : false
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :false

    -
    -
    -
    -

    Auth Apple 소셜 로그인 회원가입 후 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 205
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :true

    -
    -
    -
    -

    Auth 회원가입

    -
    -

    HTTP request

    -
    -
    -
    PUT /api/auth/signUp HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 56
    -Host: localhost:8080
    -
    -{
    -  "nickName" : "NICKNAME",
    -  "fcmToken" : "FCMTOKEN"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    nickName

    String

    유저 닉네임

    fcmToken

    String

    FCM TOKEN

    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 209
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "회원 가입을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    회원 가입을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 : true

    -
    -
    -
    -

    Auth 토큰 재발급

    -
    -

    HTTP request

    -
    -
    -
    GET /api/auth/reissue HTTP/1.1
    -RefreshToken: REFRESH_TOKEN
    -Host: localhost:8080
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 178
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "토큰을 재발급했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN"
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    토큰을 재발급했습니다

    data.accessToken

    String

    서버 접근용 Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    -
    -
    -
    -

    Auth 닉네임 중복검사 요청

    -
    -

    HTTP request

    -
    -
    -
    GET /api/auth/nickname/NICKNAME HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Host: localhost:8080
    -
    -
    -
    -
    -
    -

    Auth 닉네임 중복인 경우

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 124
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "닉네임 중복검사를 했습니다",
    -  "data" : {
    -    "isDuplicated" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    닉네임 중복검사를 했습니다

    data.isDuplicated

    Boolean

    닉네임 중복 여부 : ture

    -
    -
    -
    -

    Auth 닉네임 중복이 아닌 경우

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 125
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "닉네임 중복검사를 했습니다",
    -  "data" : {
    -    "isDuplicated" : false
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    닉네임 중복검사를 했습니다

    data.isDuplicated

    Boolean

    닉네임 중복 여부 : false

    -
    -
    -
    - - - \ No newline at end of file diff --git a/src/main/resources/static/docs/Image-API.html b/src/main/resources/static/docs/Image-API.html deleted file mode 100644 index c5881d22..00000000 --- a/src/main/resources/static/docs/Image-API.html +++ /dev/null @@ -1,579 +0,0 @@ - - - - - - - -Image API - - - - - -
    -
    -

    Presigned Url 발급

    -
    -

    HTTP request

    -
    -
    -
    POST /api/image/presigned HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 34
    -Host: localhost:8080
    -
    -{
    -  "imageFileExtension" : "JPG"
    -}
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 162
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "presignedUrl을 발급하였습니다",
    -  "data" : {
    -    "presignedUrl" : "PRESIGNED_URL",
    -    "imgUrl" : "IMAGE_URL"
    -  }
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    imageFileExtension

    String

    이미지 확장자

    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    presignedUrl을 발급하였습니다

    data.presignedUrl

    String

    이미지 업로드용 PresignedUrl

    data.imgUrl

    String

    업로드 후 이미지 URL

    -
    -
    -
    -

    imageFileExtension

    - --- - - - - - - - - - - - - - - - - -
    input 형식

    JPG

    JPEG

    PNG

    -
    -
    - - - \ No newline at end of file diff --git a/src/main/resources/static/docs/Mypage-API.html b/src/main/resources/static/docs/Mypage-API.html deleted file mode 100644 index b2710356..00000000 --- a/src/main/resources/static/docs/Mypage-API.html +++ /dev/null @@ -1,814 +0,0 @@ - - - - - - - -Mypage API - - - - - -
    -
    -

    Mypage 로그아웃

    -
    -

    HTTP request

    -
    -
    -
    POST /api/mypage/signOut HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Host: localhost:8080
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 70
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그아웃을 했습니다"
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그아웃을 했습니다

    -
    -
    -
    -
    -

    Mypage 회원탈퇴

    -
    -

    HTTP request

    -
    -
    -
    DELETE /api/mypage/withdrawal HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 34
    -Host: localhost:8080
    -
    -{
    -  "reason" : "REASON_TO_LEAVE"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    reason

    String

    회원탈퇴하는 이유

    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 70
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "회원탈퇴를 했습니다"
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    회원탈퇴를 했습니다

    -
    -
    -
    -

    Mypage 프로필 조회

    -
    -

    HTTP request

    -
    -
    -
    GET /api/mypage/profile HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Host: localhost:8080
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 198
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "프로필을 조회했습니다",
    -  "data" : {
    -    "profileImage" : "PROFILE_IMAGE_URL",
    -    "nickName" : "NICKNAME",
    -    "introduction" : "INTRODUCTION"
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    프로필을 조회했습니다

    data.profileImage

    String

    프로필 이미지 URL

    data.nickName

    String

    닉네임

    data.introduction

    String

    한줄 소개

    -
    -
    - - - - - -
    -
    Important
    -
    -Response Fields (profileImage, nickName, introduction)이 "undef" 인 경우는 사용자가 아직 입력을 안 한 경우임 -
    -
    -
    -
    -

    Mypage 프로필 수정

    -
    -

    HTTP request

    -
    -
    -
    PUT /api/mypage/profile HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 104
    -Host: localhost:8080
    -
    -{
    -  "profileImage" : "PROFILE_IMAGE_URL",
    -  "nickName" : "NICKNAME",
    -  "introduction" : "INTRODUCTION"
    -}
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 73
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "프로필을 수정했습니다"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    profileImage

    String

    프로필 이미지 URL

    nickName

    String

    닉네임

    introduction

    String

    한줄 소개

    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    프로필을 수정했습니다.

    -
    -
    - - - - - -
    -
    Important
    -
    -Request Fileds는 반드시 세 값이 모두 들어가야 하는 것이 아니고, 업데이트할 값만 입력해도 됨, 따라서 아래와 같은 예시 가능
    -
    -
    -
    -
    -
     PUT /api/mypage/profile HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 104
    -Host: localhost:8080
    -{
    -"profileImage" : "PROFILE_IMAGE_URL"
    -}
    -
    -
    -
    -
    - - - \ No newline at end of file diff --git a/src/main/resources/static/docs/Overview.html b/src/main/resources/static/docs/Overview.html deleted file mode 100644 index 27e12002..00000000 --- a/src/main/resources/static/docs/Overview.html +++ /dev/null @@ -1,613 +0,0 @@ - - - - - - - -ErrorCode - - - - - -
    -
    -

    ErrorCode

    -
    -
    -

    Error Response DTO

    - ------ - - - - - - - - -

    isSuccess(Boolean)

    timeStamp(LocalDateTime)

    errorCode(String)

    message(String)

    -
    -
    -

    Common ErrorCode

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ErrorCodeScopeDescription

    400

    전체

    요청 형식 자체가 틀리거나 권한이 없음

    403

    전체

    접근 권한이 존재하지 않음 (로그인 안한 경우)

    405

    전체

    HTTP 메서드가 리소스에서 허용되지 않음

    500

    전체

    서버오류

    J0001

    전체

    예상치 못한 오류

    J0002

    전체

    잘못된 JWT 서명

    J0003

    전체

    만료된 토큰

    J0004

    전체

    지원되지 않는 토큰

    J0005

    전체

    접근이 거부됨

    J0006

    전체

    토큰이 잘못됨

    J0007

    전체

    추가 정보 입력 (닉네임) 안함

    J0008

    재발급 시

    유효하지 않은 refresh Token

    -
    -
    -

    User / Auth ErrorCode

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    ErrorCode

    Scope

    Description

    U0001

    전체

    해당 유저 존재하지 않음

    AU0001

    로그인할 때

    이미 다른 소셜 플랫폼으로 가입함

    AU0002

    로그인할 때

    입력 토큰이 유효하지 않음

    AU0003

    로그인할 때

    appId가 일치하지 않음 (유효하지 않음)

    -
    -
    -

    Team / Team_member ErrorCode

    - ----- - - - - - - - - - - - - -

    ErrorCode

    Scope

    Description

    TM0001

    팀 개설할 때

    팀 최대 개수 3을 초과

    -
    -
    -
    -
    - - - \ No newline at end of file diff --git a/src/main/resources/static/docs/Team-API.html b/src/main/resources/static/docs/Team-API.html deleted file mode 100644 index e9ec6d0e..00000000 --- a/src/main/resources/static/docs/Team-API.html +++ /dev/null @@ -1,615 +0,0 @@ - - - - - - - -Team API - - - - - -
    -
    -

    Team 소모임 개설

    -
    -

    HTTP request

    -
    -
    -
    POST /api/team HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 182
    -Host: localhost:8080
    -
    -{
    -  "category" : "ETC",
    -  "name" : "소모임 이름",
    -  "introduction" : "소모임 소개글",
    -  "promise" : "소모임 각오",
    -  "profileImgUrl" : "소모임 대표 사진 URL"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    category

    String

    카테고리

    name

    String

    소모임 이름

    introduction

    String

    소모임 소개글

    profileImgUrl

    String

    소모임 대표 사진

    promise

    String

    소모임 각오

    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 111
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "소모임을 생성하였습니다",
    -  "data" : {
    -    "teamId" : 1
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    소모임을 생성하였습니다

    data.teamId

    Number

    생성한 teamId

    -
    -
    -
    -

    Team Category

    - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    CategoryDescription

    SPORTS

    스포츠/운동

    HABIT

    생활습관 개선

    TEST

    시험/취업준비

    STUDY

    스터디/공부

    READING

    독서

    ETC

    그외 자기계발

    -
    -
    - - - \ No newline at end of file diff --git a/src/main/resources/static/docs/api.html b/src/main/resources/static/docs/api.html deleted file mode 100644 index 1a46b6b4..00000000 --- a/src/main/resources/static/docs/api.html +++ /dev/null @@ -1,1976 +0,0 @@ - - - - - - - -Moing API Doc - - - - - - -
    -
    -

    ErrorCode

    -
    -
    -

    Error Response DTO

    - ------ - - - - - - - - -

    isSuccess(Boolean)

    timeStamp(LocalDateTime)

    errorCode(String)

    message(String)

    -
    -
    -

    Common ErrorCode

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ErrorCodeScopeDescription

    400

    전체

    요청 형식 자체가 틀리거나 권한이 없음

    403

    전체

    접근 권한이 존재하지 않음 (로그인 안한 경우)

    405

    전체

    HTTP 메서드가 리소스에서 허용되지 않음

    500

    전체

    서버오류

    J0001

    전체

    예상치 못한 오류

    J0002

    전체

    잘못된 JWT 서명

    J0003

    전체

    만료된 토큰

    J0004

    전체

    지원되지 않는 토큰

    J0005

    전체

    접근이 거부됨

    J0006

    전체

    토큰이 잘못됨

    J0007

    전체

    추가 정보 입력 (닉네임) 안함

    J0008

    재발급 시

    유효하지 않은 refresh Token

    -
    -
    -

    User / Auth ErrorCode

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    ErrorCode

    Scope

    Description

    U0001

    전체

    해당 유저 존재하지 않음

    AU0001

    로그인할 때

    이미 다른 소셜 플랫폼으로 가입함

    AU0002

    로그인할 때

    입력 토큰이 유효하지 않음

    AU0003

    로그인할 때

    appId가 일치하지 않음 (유효하지 않음)

    -
    -
    -

    Team / Team_member ErrorCode

    - ----- - - - - - - - - - - - - -

    ErrorCode

    Scope

    Description

    TM0001

    팀 개설할 때

    팀 최대 개수 3을 초과

    -
    -
    -
    -

    Image API

    -
    -

    Presigned Url 발급

    -
    -

    HTTP request

    -
    -
    -
    POST /api/image/presigned HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 34
    -Host: localhost:8080
    -
    -{
    -  "imageFileExtension" : "JPG"
    -}
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 162
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "presignedUrl을 발급하였습니다",
    -  "data" : {
    -    "presignedUrl" : "PRESIGNED_URL",
    -    "imgUrl" : "IMAGE_URL"
    -  }
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    imageFileExtension

    String

    이미지 확장자

    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    presignedUrl을 발급하였습니다

    data.presignedUrl

    String

    이미지 업로드용 PresignedUrl

    data.imgUrl

    String

    업로드 후 이미지 URL

    -
    -
    -
    -

    imageFileExtension

    - --- - - - - - - - - - - - - - - - - -
    input 형식

    JPG

    JPEG

    PNG

    -
    -

    Auth API

    -
    -

    Auth Kakao 소셜 로그인 요청

    -
    -

    HTTP request

    -
    -
    -
    POST /api/auth/signIn/kakao HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 36
    -Host: localhost:8080
    -
    -{
    -  "token" : "KAKAO_ACCESS_TOKEN"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    token

    String

    카카오 액세스 토큰

    -
    -
    -
    -

    Auth Kakao 소셜 로그인 회원가입 전 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 206
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : false
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 : false

    -
    -
    -
    -

    Auth Kakao 소셜 로그인 회원가입 후 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 205
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :true

    -
    -
    -
    -
    -

    Auth Apple 소셜 로그인 요청

    -
    -

    HTTP request

    -
    -
    -
    POST /api/auth/signIn/apple HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 38
    -Host: localhost:8080
    -
    -{
    -  "token" : "APPLE_IDENTITY_TOKEN"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    token

    String

    애플 아이디 토큰

    -
    -
    -
    -

    Auth Apple 소셜 로그인 회원가입 전 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 206
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : false
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :false

    -
    -
    -
    -

    Auth Apple 소셜 로그인 회원가입 후 응답

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 205
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그인을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 :true

    -
    -
    -
    -

    Auth 회원가입

    -
    -

    HTTP request

    -
    -
    -
    PUT /api/auth/signUp HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 56
    -Host: localhost:8080
    -
    -{
    -  "nickName" : "NICKNAME",
    -  "fcmToken" : "FCMTOKEN"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    nickName

    String

    유저 닉네임

    fcmToken

    String

    FCM TOKEN

    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 209
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "회원 가입을 했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN",
    -    "registrationStatus" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    회원 가입을 했습니다

    data.accessToken

    String

    서버 접근용 Access Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    data.registrationStatus

    Boolean

    회원가입 여부 : true

    -
    -
    -
    -

    Auth 토큰 재발급

    -
    -

    HTTP request

    -
    -
    -
    GET /api/auth/reissue HTTP/1.1
    -RefreshToken: REFRESH_TOKEN
    -Host: localhost:8080
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 178
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "토큰을 재발급했습니다",
    -  "data" : {
    -    "accessToken" : "SERVER_ACCESS_TOKEN",
    -    "refreshToken" : "SERVER_REFRESH_TOKEN"
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    토큰을 재발급했습니다

    data.accessToken

    String

    서버 접근용 Token

    data.refreshToken

    String

    서버 접근용 Refresh Token

    -
    -
    -
    -

    Auth 닉네임 중복검사 요청

    -
    -

    HTTP request

    -
    -
    -
    GET /api/auth/nickname/NICKNAME HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Host: localhost:8080
    -
    -
    -
    -
    -
    -

    Auth 닉네임 중복인 경우

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 124
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "닉네임 중복검사를 했습니다",
    -  "data" : {
    -    "isDuplicated" : true
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    닉네임 중복검사를 했습니다

    data.isDuplicated

    Boolean

    닉네임 중복 여부 : ture

    -
    -
    -
    -

    Auth 닉네임 중복이 아닌 경우

    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 125
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "닉네임 중복검사를 했습니다",
    -  "data" : {
    -    "isDuplicated" : false
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    성공 여부 : true

    message

    String

    닉네임 중복검사를 했습니다

    data.isDuplicated

    Boolean

    닉네임 중복 여부 : false

    -
    -
    -

    Mypage API

    -
    -

    Mypage 로그아웃

    -
    -

    HTTP request

    -
    -
    -
    POST /api/mypage/signOut HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Host: localhost:8080
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 70
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "로그아웃을 했습니다"
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그아웃을 했습니다

    -
    -
    -
    -
    -

    Mypage 회원탈퇴

    -
    -

    HTTP request

    -
    -
    -
    DELETE /api/mypage/withdrawal HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 34
    -Host: localhost:8080
    -
    -{
    -  "reason" : "REASON_TO_LEAVE"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    reason

    String

    회원탈퇴하는 이유

    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 70
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "회원탈퇴를 했습니다"
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    회원탈퇴를 했습니다

    -
    -
    -
    -

    Mypage 프로필 조회

    -
    -

    HTTP request

    -
    -
    -
    GET /api/mypage/profile HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Host: localhost:8080
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 198
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "프로필을 조회했습니다",
    -  "data" : {
    -    "profileImage" : "PROFILE_IMAGE_URL",
    -    "nickName" : "NICKNAME",
    -    "introduction" : "INTRODUCTION"
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    프로필을 조회했습니다

    data.profileImage

    String

    프로필 이미지 URL

    data.nickName

    String

    닉네임

    data.introduction

    String

    한줄 소개

    -
    -
    - - - - - -
    - - -Response Fields (profileImage, nickName, introduction)이 "undef" 인 경우는 사용자가 아직 입력을 안 한 경우임 -
    -
    -
    -
    -

    Mypage 프로필 수정

    -
    -

    HTTP request

    -
    -
    -
    PUT /api/mypage/profile HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 104
    -Host: localhost:8080
    -
    -{
    -  "profileImage" : "PROFILE_IMAGE_URL",
    -  "nickName" : "NICKNAME",
    -  "introduction" : "INTRODUCTION"
    -}
    -
    -
    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 73
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "프로필을 수정했습니다"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    profileImage

    String

    프로필 이미지 URL

    nickName

    String

    닉네임

    introduction

    String

    한줄 소개

    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    프로필을 수정했습니다.

    -
    -
    - - - - - -
    - - -Request Fileds는 반드시 세 값이 모두 들어가야 하는 것이 아니고, 업데이트할 값만 입력해도 됨, 따라서 아래와 같은 예시 가능
    -
    -
    -
    -
    -
     PUT /api/mypage/profile HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 104
    -Host: localhost:8080
    -{
    -"profileImage" : "PROFILE_IMAGE_URL"
    -}
    -
    -
    -
    -

    Team API

    -
    -

    Team 소모임 개설

    -
    -

    HTTP request

    -
    -
    -
    POST /api/team HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 182
    -Host: localhost:8080
    -
    -{
    -  "category" : "ETC",
    -  "name" : "소모임 이름",
    -  "introduction" : "소모임 소개글",
    -  "promise" : "소모임 각오",
    -  "profileImgUrl" : "소모임 대표 사진 URL"
    -}
    -
    -
    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    category

    String

    카테고리

    name

    String

    소모임 이름

    introduction

    String

    소모임 소개글

    profileImgUrl

    String

    소모임 대표 사진

    promise

    String

    소모임 각오

    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 111
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "소모임을 생성하였습니다",
    -  "data" : {
    -    "teamId" : 1
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    소모임을 생성하였습니다

    data.teamId

    Number

    생성한 teamId

    -
    -
    -
    -

    Team Category

    - ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    CategoryDescription

    SPORTS

    스포츠/운동

    HABIT

    생활습관 개선

    TEST

    시험/취업준비

    STUDY

    스터디/공부

    READING

    독서

    ETC

    그외 자기계발

    -
    -
    - - - - - - \ No newline at end of file From 012a6fbc36594de3184b49eb660484832d2a665b Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sun, 3 Sep 2023 22:30:48 +0900 Subject: [PATCH 054/619] deploy: resources mkdir --- .github/workflows/ci-cd.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 176a902c..3b975a41 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -40,6 +40,7 @@ jobs: # 설정 파일 생성 - run: | + mkdir ./src/main/resources cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml From 255af0e021978fb845e4d8e4ae486ac6e5fa1113 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sun, 3 Sep 2023 23:12:12 +0900 Subject: [PATCH 055/619] =?UTF-8?q?docs:=20tatic/docs/=EC=97=90=20html=20j?= =?UTF-8?q?ar=ED=8C=8C=EC=9D=BC=20=EC=95=88=EC=97=90=20=EB=B3=B5=EC=82=AC?= =?UTF-8?q?=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle b/build.gradle index cc102aad..bd351e8c 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,14 @@ repositories { google() } + +bootJar { + dependsOn asciidoctor + from ("${asciidoctor.outputDir}/html5") { + into 'static/docs' + } +} + dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' From 0cab90094f30ea4b4dbc941b0352374c47eccd04 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sun, 3 Sep 2023 23:47:01 +0900 Subject: [PATCH 056/619] deploy: show log --- .github/workflows/ci-cd.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 3b975a41..40e38a97 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -75,6 +75,18 @@ jobs: run: ./gradlew build working-directory: ${{ env.working-directory }} + ##### 문서 생성 확인 + - name: Check generated docs + run: | + echo "Listing generated docs:" + ls ${{ env.working-directory }}/build/docs/asciidoc + + ##### JAR 파일에서 문서 확인 + - name: Check docs in JAR + run: | + jar tf ${{ env.working-directory }}/build/libs/backend-0.0.1-SNAPSHOT.jar | grep "static/docs" + + # Gradle 캐시 정리 - name: Cleanup Gradle Cache if: ${{ always() }} From 2348b90244af4b5c8eb3ff88801f353155ef71cb Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sun, 3 Sep 2023 23:49:47 +0900 Subject: [PATCH 057/619] deploy:show log --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 40e38a97..5062117a 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -84,7 +84,7 @@ jobs: ##### JAR 파일에서 문서 확인 - name: Check docs in JAR run: | - jar tf ${{ env.working-directory }}/build/libs/backend-0.0.1-SNAPSHOT.jar | grep "static/docs" + jar tf ./build/libs/backend-0.0.1-SNAPSHOT.jar | grep "static/docs" # Gradle 캐시 정리 From cd7d8b49767a3ba7adb78e81963624009c928068 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Sun, 3 Sep 2023 23:57:36 +0900 Subject: [PATCH 058/619] =?UTF-8?q?deploy:=20cache=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-cd.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 5062117a..0a3e9c48 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -27,16 +27,16 @@ jobs: java-version: '11' distribution: 'adopt' - # Gradle 패키지 캐시 - - name: Cache Gradle packages - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- + # # Gradle 패키지 캐시 + # - name: Cache Gradle packages + # uses: actions/cache@v2 + # with: + # path: | + # ~/.gradle/caches + # ~/.gradle/wrapper + # key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + # restore-keys: | + # ${{ runner.os }}-gradle- # 설정 파일 생성 - run: | From 4a7b9894218bba8d5fecc977e51afc3369bf38e3 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Mon, 4 Sep 2023 00:03:21 +0900 Subject: [PATCH 059/619] deploy: Update ci-cd.yml --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 0a3e9c48..e2e57e7d 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -84,7 +84,7 @@ jobs: ##### JAR 파일에서 문서 확인 - name: Check docs in JAR run: | - jar tf ./build/libs/backend-0.0.1-SNAPSHOT.jar | grep "static/docs" + jar tf ./build/libs/backend-0.0.1-SNAPSHOT.jar # Gradle 캐시 정리 From 3c96d7a59cd2808c336ff7fb07ea1252f486bb78 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Mon, 4 Sep 2023 00:09:57 +0900 Subject: [PATCH 060/619] =?UTF-8?q?deploy:=20app.jar=EC=97=90=20html?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3f9f0aa8..01e0298e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,4 +2,9 @@ FROM openjdk:11-jdk ARG CACHEBREAKER=1 ARG JAR_FILE=./build/libs/backend-0.0.1-SNAPSHOT.jar COPY ${JAR_FILE} app.jar -ENTRYPOINT ["java","-jar","/app.jar"] + +# 문서를 이미지의 /static/docs 디렉토리에 복사 +COPY ./build/docs/asciidoc/static/docs/*.html /static/docs/ + +# 애플리케이션 실행 시 -cp 옵션을 사용하여 /static/docs 디렉토리를 클래스패스에 추가 +ENTRYPOINT ["java","-cp",".:/static/docs","-jar","/app.jar"] From 26cbfc299f82ffaeb2c63c0bbd81376f36912d92 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Mon, 4 Sep 2023 00:15:29 +0900 Subject: [PATCH 061/619] deploy: Update Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 01e0298e..24f680a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ ARG JAR_FILE=./build/libs/backend-0.0.1-SNAPSHOT.jar COPY ${JAR_FILE} app.jar # 문서를 이미지의 /static/docs 디렉토리에 복사 -COPY ./build/docs/asciidoc/static/docs/*.html /static/docs/ +COPY ./build/docs/asciidoc/*.html /static/docs/ # 애플리케이션 실행 시 -cp 옵션을 사용하여 /static/docs 디렉토리를 클래스패스에 추가 ENTRYPOINT ["java","-cp",".:/static/docs","-jar","/app.jar"] From e668a6d54b14db861b82768bbf4b250130254201 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Mon, 4 Sep 2023 00:21:56 +0900 Subject: [PATCH 062/619] =?UTF-8?q?docs:=20log=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-cd.yml | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index e2e57e7d..3b975a41 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -27,16 +27,16 @@ jobs: java-version: '11' distribution: 'adopt' - # # Gradle 패키지 캐시 - # - name: Cache Gradle packages - # uses: actions/cache@v2 - # with: - # path: | - # ~/.gradle/caches - # ~/.gradle/wrapper - # key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - # restore-keys: | - # ${{ runner.os }}-gradle- + # Gradle 패키지 캐시 + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- # 설정 파일 생성 - run: | @@ -75,18 +75,6 @@ jobs: run: ./gradlew build working-directory: ${{ env.working-directory }} - ##### 문서 생성 확인 - - name: Check generated docs - run: | - echo "Listing generated docs:" - ls ${{ env.working-directory }}/build/docs/asciidoc - - ##### JAR 파일에서 문서 확인 - - name: Check docs in JAR - run: | - jar tf ./build/libs/backend-0.0.1-SNAPSHOT.jar - - # Gradle 캐시 정리 - name: Cleanup Gradle Cache if: ${{ always() }} From 9e4ca2f9cf97c951d2a2c145b883ec5f90474a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 6 Sep 2023 13:29:51 +0900 Subject: [PATCH 063/619] =?UTF-8?q?feat=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=83=9D=EC=84=B1,=EC=A1=B0=ED=9A=8C,?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20=EB=AF=B8=EC=85=98=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=8B=9C=20presigendURL=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=95=B4=EC=95=BC=ED=95=A8=E3=85=81=20-=20=ED=8C=80=EC=9B=90?= =?UTF-8?q?=EC=9D=B4=20=EC=97=AC=EB=9F=AC=EB=AA=85=EC=9D=BC=20=EB=95=8C=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=EB=B0=8F=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=95=B4=EC=95=BC?= =?UTF-8?q?=ED=95=A8=20-=20=EB=AF=B8=EC=85=98=20=EC=9E=AC=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=8B=9C=20=EC=82=AC=EC=A7=84=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=EC=9D=98=20=EA=B2=BD=EC=9A=B0=20=EA=B8=B0=EC=A1=B4=20s3=20?= =?UTF-8?q?=EC=82=AC=EC=A7=84=20=EC=82=AD=EC=A0=9C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84=ED=95=B4=EC=95=BC?= =?UTF-8?q?=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/req/MissionReq.java | 1 - .../application/dto/res/MissionCreateRes.java | 2 + .../application/mapper/MissionMapper.java | 6 +- .../service/MissionCreateUseCase.java | 4 +- .../service/MissionReadUseCase.java | 4 +- .../service/MissionUpdateUseCase.java | 1 - .../presentation/MissionController.java | 10 ++- .../dto/res/MissionArchiveRes.java | 21 ++---- .../application/dto/res/PersonalArchive.java | 20 +++++ .../mapper/MissionArchiveMapper.java | 24 +++--- .../service/MissionArchiveCreateUseCase.java | 18 ++++- .../service/MissionArchiveReadUseCase.java | 59 +++++++++++++++ .../MissionArchiveResponseMessage.java | 16 ++++ .../repository/MissionArchiveRepository.java | 8 +- .../service/MissionArchiveDeleteService.java | 6 ++ .../service/MissionArchiveQueryService.java | 4 + .../MissionArchiveController.java | 75 +++++++++++++++++++ .../representation/MissionControllerTest.java | 6 +- 18 files changed, 240 insertions(+), 45 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java index bc28dcd6..98962c87 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java @@ -16,6 +16,5 @@ public class MissionReq { private String type; private String way; - private String status; } diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java index dce5e67d..59338e38 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java @@ -7,6 +7,8 @@ @Builder public class MissionCreateRes { + private Long missionId; + private String title; private String dueTo; diff --git a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java index 30257f18..756ac7e5 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java +++ b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java @@ -17,7 +17,7 @@ @Mapper public class MissionMapper { - public static Mission mapToMission(MissionReq missionReq, Member member, MissionType type) { + public static Mission mapToMission(MissionReq missionReq, Member member, MissionStatus status) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); @@ -29,7 +29,7 @@ public static Mission mapToMission(MissionReq missionReq, Member member, Mission .way(MissionWay.valueOf(missionReq.getWay())) .type(MissionType.valueOf(missionReq.getType())) .number(missionReq.getNumber()) - .status(MissionStatus.valueOf(missionReq.getStatus())) + .status(status) .build(); } @@ -38,6 +38,7 @@ public static MissionCreateRes mapToMissionCreateRes(Mission mission) { return MissionCreateRes.builder() + .missionId(mission.getId()) .title(mission.getTitle()) .dueTo(mission.getDueTo().toString()) .rule(mission.getRule()) @@ -45,6 +46,7 @@ public static MissionCreateRes mapToMissionCreateRes(Mission mission) { .content(mission.getContent()) .type(mission.getType().name()) .status(mission.getStatus().name()) + .number(mission.getNumber()) .build(); } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index f067a245..a0b13fac 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; import com.moing.backend.domain.mission.application.mapper.MissionMapper; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionSaveService; import com.moing.backend.domain.team.domain.repository.TeamRepository; @@ -31,7 +32,7 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR // 소모임장 확인 로직 추가 - Mission mission = MissionMapper.mapToMission(missionReq, member, MissionType.valueOf(missionReq.getType())); + Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.WAIT); // teamRepository 변경 예정 mission.setTeam(teamRepository.findById(teamId).orElseThrow()); @@ -41,5 +42,4 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR } - } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java index 5d9ce7f0..0bc52c51 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java @@ -17,8 +17,8 @@ @RequiredArgsConstructor public class MissionReadUseCase { - MissionQueryService missionQueryService; - MemberGetService memberGetService; + private final MissionQueryService missionQueryService; + private final MemberGetService memberGetService; public MissionReadRes getMission(String userSocialId, Long missionId) { diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index 7cbca253..fefc9c0c 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -29,7 +29,6 @@ public MissionCreateRes updateMission(String userSocialId,Long missionId, Missio Member member = memberGetService.getMemberBySocialId(userSocialId); // 소모임장 확인 로직 추가 - Mission findMission = missionQueryService.findMissionById(missionId); findMission.updateMission(missionReq); diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 58f50484..0079163b 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -39,22 +39,24 @@ public class MissionController { public ResponseEntity> getMission(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId) { return ResponseEntity.ok(SuccessResponse.create(READ_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getMission(user.getSocialId(),missionId))); } + /** * 미션 리스트 조회 * [GET] {teamId}/mission/{missionId} * 작성자 : 정승연 */ - @GetMapping("") - public ResponseEntity> getMissionList(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(READ_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getMission(user.getSocialId(),teamId))); - } +// @GetMapping() +// public ResponseEntity> getMissionList(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId) { +// return ResponseEntity.ok(SuccessResponse.create(READ_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getMission(user.getSocialId(),teamId))); +// } /** * 미션 생성 * [POST] {teamId}/mission * 작성자 : 정승연 */ + @PostMapping() public ResponseEntity> createMission(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId, @RequestBody MissionReq missionReq) { return ResponseEntity.ok(SuccessResponse.create(CREATE_MISSION_SUCCESS.getMessage(), this.missionCreateUseCase.createMission(user.getSocialId(),teamId,missionReq))); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index a3d82e6e..6cf5dab5 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -4,29 +4,20 @@ import lombok.Getter; import lombok.Setter; +import java.util.List; + @Builder @Getter @Setter public class MissionArchiveRes { - private String title; - private String status; - private String dueTo; - - private int totalPerson; - private int donePerson; - - - private String rule; - private String content; - private String archive; private String createdDate; + private List donePersonalArchives; - - - - + public void setPersonalArchives(List done) { + this.donePersonalArchives = done; + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java new file mode 100644 index 00000000..05adaaaa --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.missionArchive.application.dto.res; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class PersonalArchive { + + private String nickname; + private String profileImg; + + private String archive; + private String createdDate; + + private int likes; + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index a155ba23..61b4eed0 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -5,10 +5,14 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.annotation.Mapper; +import java.util.ArrayList; +import java.util.List; + @Mapper public class MissionArchiveMapper { @@ -22,21 +26,21 @@ public static MissionArchive mapToMissionArchive(MissionArchiveReq missionArchiv } public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArchive) { - Mission mission = missionArchive.getMission(); - Team team = mission.getTeam(); - return MissionArchiveRes.builder() - .title(mission.getTitle()) - .status(mission.getStatus().name()) - .dueTo(mission.getDueTo().toString()) - .totalPerson(10) - .donePerson(mission.getMissionArchiveList().size()) - .rule(mission.getRule()) - .content(mission.getContent()) .archive(missionArchive.getArchive()) .createdDate(missionArchive.getCreatedDate().toString()) .build(); + } + + public static PersonalArchive mapToPersonalArchive(MissionArchive missionArchive) { + Member member = missionArchive.getMember(); + return PersonalArchive.builder() + .nickname(member.getNickName()) + .profileImg(member.getProfileImage()) + .archive(missionArchive.getArchive()) + .createdDate(missionArchive.getCreatedDate().toString()) + .build(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index ed8af35c..b643fd3e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -10,6 +10,7 @@ import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; @@ -20,6 +21,11 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; + +import static com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper.mapToPersonalArchive; + @Service @Transactional @RequiredArgsConstructor @@ -28,10 +34,13 @@ public class MissionArchiveCreateUseCase { private final MissionArchiveSaveService missionArchiveSaveService; private final MissionArchiveQueryService missionArchiveQueryService; private final MissionArchiveDeleteService missionArchiveDeleteService; + private final MissionQueryService missionQueryService; + private final MemberGetService memberGetService; - public MissionArchiveRes createArchiveCreate(String userSocialId, Long missionId, MissionArchiveReq missionReq) { + // 미션 인증 및 재인증 (수정하기도 포함됨) + public MissionArchiveRes createArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); Mission mission = missionQueryService.findMissionById(missionId); @@ -59,10 +68,15 @@ public MissionArchiveRes createArchiveCreate(String userSocialId, Long missionId public MissionArchiveRes saveArchive(Mission mission,MissionArchiveReq missionReq,Member member) { MissionArchive save = missionArchiveSaveService.save(MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission)); - if (mission.getMissionArchiveList().size() == 3) { + // 미션 완료 처리 + if (mission.getMissionArchiveList().size() == 3-1) { mission.setStatus(MissionStatus.DONE); } + return MissionArchiveMapper.mapToMissionArchiveRes(save); + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java new file mode 100644 index 00000000..9bbd1d7d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java @@ -0,0 +1,59 @@ +package com.moing.backend.domain.missionArchive.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; +import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; + +import static com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper.mapToPersonalArchive; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionArchiveReadUseCase { + + //미션 아치브 읽어오기 + private final MemberGetService memberGetService; + private final MissionQueryService missionQueryService; + private final MissionArchiveQueryService missionArchiveQueryService; + + + // 나의 인증 목록 + public MissionArchiveRes getMyArchive(String userSocialId, Long missionId) { + MissionArchive myArchive = getArchive(userSocialId, missionId); + return MissionArchiveMapper.mapToMissionArchiveRes(myArchive); + } + + // 팀원들 인증 목록 + public List getPersonalArchive(String userSocialId, Long missionId) { + Mission mission = missionQueryService.findMissionById(missionId); + + List done = new ArrayList<>(); + + mission.getMissionArchiveList() + .forEach(missionArchive1 -> done.add(mapToPersonalArchive(missionArchive1))); + + return done; + } + + // memberId, missionId로 archive 꺼내기 + public MissionArchive getArchive(String userSocialId, Long missionId) { + Member member = memberGetService.getMemberBySocialId(userSocialId); + Mission mission = missionQueryService.findMissionById(missionId); + + return missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java new file mode 100644 index 00000000..3296c80e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.missionArchive.domain.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum MissionArchiveResponseMessage { + + CREATE_ARCHIVE_SUCCESS("미션 인증을 완료 했습니다"), + READ_MY_ARCHIVE_SUCCESS("나의 미션 인증 현황 조회를 완료 했습니다"), + READ_TEAM_ARCHIVE_SUCCESS("팀원 미션 인증 현황 조회를 완료 했습니다"); + + private final String message; + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java index 1f9723a9..d03c3f85 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -1,6 +1,8 @@ package com.moing.backend.domain.missionArchive.domain.repository; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import feign.Param; +import org.hibernate.annotations.Parameter; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -8,10 +10,10 @@ public interface MissionArchiveRepository extends JpaRepository { - @Query("select m from MissionArchive as m where m.member =: memberId") + @Query("select m from MissionArchive as m where m.member =:memberId") public Optional findByMemberId(Long memberId); - @Query("select m from MissionArchive as m where m.mission.id =: missionId and m.member.memberId =: memberId") - public Optional findByMissionIdAndMemberId(Long memberId, Long missionId); + @Query("select m from MissionArchive as m where m.mission.id = :missionId and m.member.memberId =:memberId") + public Optional findByMissionIdAndMemberId(@Param("memberId") Long memberId, @Param("missionId")Long missionId); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java index 8189476c..a616fe10 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java @@ -2,7 +2,13 @@ import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; +@DomainService +@Transactional +@RequiredArgsConstructor public class MissionArchiveDeleteService { private MissionArchiveRepository missionArchiveRepository; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 6d0cb933..d2cffcd7 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -36,4 +36,8 @@ public Boolean isDone(Long memberId, Long missionId) { return Boolean.FALSE; } } + + public MissionArchive findMyArchive(Long memberId, Long missionId) { + return missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId).orElseThrow(NotFoundMissionArchiveException::new); + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java new file mode 100644 index 00000000..08fc1b14 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -0,0 +1,75 @@ +package com.moing.backend.domain.missionArchive.presentation; + +import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; +import com.moing.backend.domain.mission.application.service.MissionCreateUseCase; +import com.moing.backend.domain.mission.application.service.MissionDeleteUseCase; +import com.moing.backend.domain.mission.application.service.MissionReadUseCase; +import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateUseCase; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveReadUseCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.READ_MISSION_SUCCESS; +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; + + +@RestController +@AllArgsConstructor +@RequestMapping("/api/{teamId}/{missionId}/archive") +public class MissionArchiveController { + + private final MissionArchiveCreateUseCase missionArchiveCreateUseCase; + private final MissionArchiveReadUseCase missionArchiveReadUseCase; + + /** + * 미션 인증 하기 + * [POST] {teamId}/{missionId}/missionArchive + * 작성자 : 정승연 + */ + + @PostMapping() + public ResponseEntity> createArchive(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId, + @RequestBody MissionArchiveReq missionArchiveReq) { + return ResponseEntity.ok(SuccessResponse.create(CREATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveCreateUseCase.createArchive(user.getSocialId(), missionId,missionArchiveReq))); + } + + /** + * 미션 인증 조회 + * [GET] {teamId}/{missionId}/archiveㅡ + * 작성자 : 정승연 + */ + + @GetMapping() + public ResponseEntity> getArchives(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId, + @RequestBody MissionArchiveReq missionArchiveReq) { + return ResponseEntity.ok(SuccessResponse.create(READ_MY_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getMyArchive(user.getSocialId(), missionId))); + } + + /** + * 모임원 미션 인증 목록 조회 + * [GET] {teamId}/{missionId}/archive/done + * 작성자 : 정승연 + */ + @GetMapping("/done") + public ResponseEntity>> getDoneArchives(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId, + @RequestBody MissionArchiveReq missionArchiveReq) { + return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getPersonalArchive(user.getSocialId(), missionId))); + } + +} \ No newline at end of file diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index 4b6801b3..795837a9 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -75,7 +75,7 @@ public class MissionControllerTest extends CommonControllerTest { .way("TEXT") .build(); - given(missionCreateUseCase.createMission(any(),any())).willReturn(output); + given(missionCreateUseCase.createMission(any(),any(),any())).willReturn(output); Long teamId = 2L; //when @@ -150,7 +150,7 @@ public class MissionControllerTest extends CommonControllerTest { .way("TEXT") .build(); - given(missionUpdateUseCase.updateMission(any(),any())).willReturn(output); + given(missionUpdateUseCase.updateMission(any(),any(),any())).willReturn(output); Long teamId = 2L; Long missionId = 2L; @@ -216,7 +216,7 @@ public class MissionControllerTest extends CommonControllerTest { .way("TEXT") .build(); - given(missionReadUseCase.getMission(any())).willReturn(output); + given(missionReadUseCase.getMission(any(),any())).willReturn(output); Long teamId = 2L; Long missionId = 1L; From f590cff2cdac2a5ab3f95736b00f81ef046403f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 6 Sep 2023 14:35:20 +0900 Subject: [PATCH 064/619] =?UTF-8?q?feat=20:=20mission=20CRUD=20rest=20docs?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Mission-API.adoc | 29 + .../resources/static/docs/Mission-API.html | 657 ++++++++++++++++++ .../representation/MissionControllerTest.java | 4 + 3 files changed, 690 insertions(+) create mode 100644 src/docs/asciidoc/Mission-API.adoc create mode 100644 src/main/resources/static/docs/Mission-API.html diff --git a/src/docs/asciidoc/Mission-API.adoc b/src/docs/asciidoc/Mission-API.adoc new file mode 100644 index 00000000..cedcde65 --- /dev/null +++ b/src/docs/asciidoc/Mission-API.adoc @@ -0,0 +1,29 @@ + + +[[Mission-API]] += Mission API + +[[Mission-생성]] +=== Mission 생성 +operation::mission-controller-test/미션_생성[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[Mission-조회]] +=== Mission 생성 +operation::mission-controller-test/미션_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[Mission-수정]] +=== Mission 수정 +operation::mission-controller-test/미션_수정[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[Mission-수정]] +=== Mission 수정 +operation::mission-controller-test/미션_삭제[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + diff --git a/src/main/resources/static/docs/Mission-API.html b/src/main/resources/static/docs/Mission-API.html new file mode 100644 index 00000000..4a377611 --- /dev/null +++ b/src/main/resources/static/docs/Mission-API.html @@ -0,0 +1,657 @@ + + + + + + + +Mission API + + + + + +
    +
    +

    Mission 생성

    +
    +

    HTTP request

    +
    +
    +
    POST /api/2/mission HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer ACCESS_TOKEN
    +Content-Length: 159
    +Host: localhost:8080
    +
    +{
    +  "title" : "title",
    +  "dueTo" : "2023-12-31 23:39:22.333",
    +  "rule" : "rule",
    +  "content" : "content",
    +  "number" : 1,
    +  "type" : "ONCE",
    +  "way" : "TEXT"
    +}
    +
    +
    +
    +
    +

    Path parameters

    + + ++++ + + + + + + + + + + + + +
    Table 1. /api/{teamId}/mission
    ParameterDescription

    teamId

    팀 아이디

    +
    +
    +

    Request fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    title

    String

    미션 제목

    dueTo

    String

    미션 마감 날짜

    rule

    String

    미션 규칙

    content

    String

    미션 내용

    number

    Number

    미션 반복 횟수

    type

    String

    미션 타입

    way

    String

    미션 진행 방법

    +
    +
    +

    HTTP response

    +
    +
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json;charset=UTF-8
    +Content-Length: 292
    +
    +{
    +  "isSuccess" : true,
    +  "message" : "미션 생성을 완료 했습니다",
    +  "data" : {
    +    "missionId" : 1,
    +    "title" : "title",
    +    "dueTo" : "dueTo",
    +    "rule" : "rule",
    +    "content" : "content",
    +    "number" : 1,
    +    "type" : "TEXT",
    +    "status" : "WAIT",
    +    "way" : "TEXT"
    +  }
    +}
    +
    +
    +
    +
    +

    Response fields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.missionId

    Number

    미션 아이디

    data.title

    String

    미션 제목

    data.dueTo

    String

    미션 마감 날짜

    data.rule

    String

    미션 규칙

    data.content

    String

    미션 내용

    data.number

    Number

    미션 반복 횟수

    data.type

    String

    미션 타입

    data.way

    String

    미션 진행 방법

    data.status

    String

    미션 진행 상태

    +
    +
    +
    +
    + + + \ No newline at end of file diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index 795837a9..c4fd0b0d 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -65,6 +65,7 @@ public class MissionControllerTest extends CommonControllerTest { String body = objectMapper.writeValueAsString(input); MissionCreateRes output = MissionCreateRes.builder() + .missionId(1L) .title("title") .dueTo("dueTo") .rule("rule") @@ -109,6 +110,7 @@ public class MissionControllerTest extends CommonControllerTest { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("로그인을 했습니다"), + fieldWithPath("data.missionId").description("미션 아이디"), fieldWithPath("data.title").description("미션 제목"), fieldWithPath("data.dueTo").description("미션 마감 날짜"), fieldWithPath("data.rule").description("미션 규칙"), @@ -140,6 +142,7 @@ public class MissionControllerTest extends CommonControllerTest { String body = objectMapper.writeValueAsString(input); MissionCreateRes output = MissionCreateRes.builder() + .missionId(1L) .title("title") .dueTo("dueTo") .rule("rule") @@ -186,6 +189,7 @@ public class MissionControllerTest extends CommonControllerTest { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("로그인을 했습니다"), + fieldWithPath("data.missionId").description("미션 아이디"), fieldWithPath("data.title").description("미션 제목"), fieldWithPath("data.dueTo").description("미션 마감 날짜"), fieldWithPath("data.rule").description("미션 규칙"), From 3463321e151e85e82415a894f6d5da95cb3fde85 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Thu, 7 Sep 2023 06:19:20 +0900 Subject: [PATCH 065/619] feat: Delete src/main/resources/static/docs/Mission-API.html --- .../resources/static/docs/Mission-API.html | 657 ------------------ 1 file changed, 657 deletions(-) delete mode 100644 src/main/resources/static/docs/Mission-API.html diff --git a/src/main/resources/static/docs/Mission-API.html b/src/main/resources/static/docs/Mission-API.html deleted file mode 100644 index 4a377611..00000000 --- a/src/main/resources/static/docs/Mission-API.html +++ /dev/null @@ -1,657 +0,0 @@ - - - - - - - -Mission API - - - - - -
    -
    -

    Mission 생성

    -
    -

    HTTP request

    -
    -
    -
    POST /api/2/mission HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer ACCESS_TOKEN
    -Content-Length: 159
    -Host: localhost:8080
    -
    -{
    -  "title" : "title",
    -  "dueTo" : "2023-12-31 23:39:22.333",
    -  "rule" : "rule",
    -  "content" : "content",
    -  "number" : 1,
    -  "type" : "ONCE",
    -  "way" : "TEXT"
    -}
    -
    -
    -
    -
    -

    Path parameters

    - - ---- - - - - - - - - - - - - -
    Table 1. /api/{teamId}/mission
    ParameterDescription

    teamId

    팀 아이디

    -
    -
    -

    Request fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    title

    String

    미션 제목

    dueTo

    String

    미션 마감 날짜

    rule

    String

    미션 규칙

    content

    String

    미션 내용

    number

    Number

    미션 반복 횟수

    type

    String

    미션 타입

    way

    String

    미션 진행 방법

    -
    -
    -

    HTTP response

    -
    -
    -
    HTTP/1.1 200 OK
    -Content-Type: application/json;charset=UTF-8
    -Content-Length: 292
    -
    -{
    -  "isSuccess" : true,
    -  "message" : "미션 생성을 완료 했습니다",
    -  "data" : {
    -    "missionId" : 1,
    -    "title" : "title",
    -    "dueTo" : "dueTo",
    -    "rule" : "rule",
    -    "content" : "content",
    -    "number" : 1,
    -    "type" : "TEXT",
    -    "status" : "WAIT",
    -    "way" : "TEXT"
    -  }
    -}
    -
    -
    -
    -
    -

    Response fields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    isSuccess

    Boolean

    true

    message

    String

    로그인을 했습니다

    data.missionId

    Number

    미션 아이디

    data.title

    String

    미션 제목

    data.dueTo

    String

    미션 마감 날짜

    data.rule

    String

    미션 규칙

    data.content

    String

    미션 내용

    data.number

    Number

    미션 반복 횟수

    data.type

    String

    미션 타입

    data.way

    String

    미션 진행 방법

    data.status

    String

    미션 진행 상태

    -
    -
    -
    -
    - - - \ No newline at end of file From e8157e1597c4aea82cb77f66888f10241decae37 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sun, 10 Sep 2023 20:19:15 +0900 Subject: [PATCH 066/619] =?UTF-8?q?feat:=20google=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Auth-API.adoc | 11 +++ .../dto/response/GoogleUserResponse.java | 25 ++++++ .../service/google/GoogleSignInUserCase.java | 43 ++++++++++ .../service/google/GoogleTokenUserCase.java | 25 ++++++ .../auth/presentation/AuthController.java | 4 +- .../application/mapper/MemberMapper.java | 15 ++++ .../domain/constant/SocialProvider.java | 2 +- .../team/presentation/TeamController.java | 8 ++ .../teamMember/domain/entity/TeamMember.java | 4 +- .../security/oauth/OAuth2Attribute.java | 23 ----- .../auth/presentation/AuthControllerTest.java | 86 +++++++++++++++++++ 11 files changed, 219 insertions(+), 27 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/auth/application/dto/response/GoogleUserResponse.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java diff --git a/src/docs/asciidoc/Auth-API.adoc b/src/docs/asciidoc/Auth-API.adoc index ab75db50..45380bc1 100644 --- a/src/docs/asciidoc/Auth-API.adoc +++ b/src/docs/asciidoc/Auth-API.adoc @@ -24,6 +24,17 @@ operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets operation::auth-controller-test/apple_소셜_로그인_회원가입_후[snippets='http-response,response-fields'] +[[Auth-Google-소셜-로그인]] +=== Auth Google 소셜 로그인 요청 +operation::auth-controller-test/google_소셜_로그인_회원가입_전[snippets='http-request,request-fields'] + +=== Auth Google 소셜 로그인 회원가입 전 응답 +operation::auth-controller-test/google_소셜_로그인_회원가입_전[snippets='http-response,response-fields'] + +=== Auth Google 소셜 로그인 회원가입 후 응답 +operation::auth-controller-test/google_소셜_로그인_회원가입_후[snippets='http-response,response-fields'] + + [[Auth-회원가입]] === Auth 회원가입 operation::auth-controller-test/sign_up[snippets='http-request,request-fields,http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/GoogleUserResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/GoogleUserResponse.java new file mode 100644 index 00000000..5d5388c0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/GoogleUserResponse.java @@ -0,0 +1,25 @@ +package com.moing.backend.domain.auth.application.dto.response; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class GoogleUserResponse { + + private String aud; + private String sub; + private String email; + private String name; + private String picture; + + public void adaptResponse() { + if(email.length() > 50) email = email.substring(0, 50); + if(name.length() > 7) name = name.substring(0, 7); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java new file mode 100644 index 00000000..9dac6637 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java @@ -0,0 +1,43 @@ +package com.moing.backend.domain.auth.application.service.google; + +import com.moing.backend.domain.auth.application.dto.response.GoogleUserResponse; +import com.moing.backend.domain.auth.application.service.SignInProvider; +import com.moing.backend.domain.auth.exception.AppIdInvalidException; +import com.moing.backend.domain.auth.exception.TokenInvalidException; +import com.moing.backend.domain.member.application.mapper.MemberMapper; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.global.exception.InternalServerErrorException; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.Arrays; + +@Service("google") +@RequiredArgsConstructor +public class GoogleSignInUserCase implements SignInProvider { + + private final MemberMapper memberMapper; + private final WebClient webClient; + private final GoogleTokenUserCase googleTokenUserCase; + + public Member getUserData(String accessToken) { + GoogleUserResponse googleUserResponse = webClient.get() + .uri("https://oauth2.googleapis.com/tokeninfo", builder -> builder.queryParam("id_token", accessToken).build()) + .retrieve() + .onStatus(HttpStatus::is4xxClientError, response -> Mono.error(new TokenInvalidException())) + .onStatus(HttpStatus::is5xxServerError, response -> Mono.error(new InternalServerErrorException("Google Internal Server Error "))) + .bodyToMono(GoogleUserResponse.class) + .block(); + + googleTokenUserCase.verifyAccessToken(googleUserResponse.getAud()); + + googleUserResponse.adaptResponse(); + return memberMapper.createGoogleMember(googleUserResponse); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java new file mode 100644 index 00000000..167889f3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java @@ -0,0 +1,25 @@ +package com.moing.backend.domain.auth.application.service.google; + +import com.moing.backend.domain.auth.exception.AppIdInvalidException; +import com.moing.backend.domain.auth.exception.TokenInvalidException; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Arrays; + +@Component +@RequiredArgsConstructor +public class GoogleTokenUserCase { + + @Value("${app-id.google}") + private String appId; + + public void verifyAccessToken(String aud) { + String extractedAppId = Arrays.stream(aud.split("-")) + .findFirst() + .orElseThrow(() -> new TokenInvalidException()); + + if (!appId.equals(extractedAppId)) throw new AppIdInvalidException(); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java index 84e66da2..bd80611c 100644 --- a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java @@ -39,8 +39,8 @@ public class AuthController { private final CheckNicknameUserCase checkNicknameService; /** - * 소셜 로그인 (애플/ 카카오) - * [POST] api/auth/signIn/kakao||apple + * 소셜 로그인 (애플/ 카카오/구글) + * [POST] api/auth/signIn/kakao||apple||google * 작성자 : 김민수 */ @PostMapping("/signIn/{provider}") diff --git a/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java b/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java index 4dc96a31..df55b8a7 100644 --- a/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java +++ b/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java @@ -1,11 +1,15 @@ package com.moing.backend.domain.member.application.mapper; +import com.moing.backend.domain.auth.application.dto.response.GoogleUserResponse; import com.moing.backend.domain.auth.application.dto.response.KakaoUserResponse; import com.moing.backend.domain.member.domain.constant.Role; import com.moing.backend.domain.member.domain.constant.SocialProvider; import com.moing.backend.domain.member.domain.entity.Member; import org.springframework.stereotype.Component; +import java.time.LocalDate; +import java.time.LocalDateTime; + @Component public class MemberMapper { @@ -33,4 +37,15 @@ public Member createAppleMember(String socialId, String email) { return newMember; } + + public Member createGoogleMember(GoogleUserResponse googleUserResponse){ + Member newMember= Member.builder() + .socialId(SocialProvider.GOOGLE + "@" + googleUserResponse.getSub()) + .provider(SocialProvider.GOOGLE) + .email(googleUserResponse.getEmail()) + .role(Role.USER) + .build(); + + return newMember; + } } diff --git a/src/main/java/com/moing/backend/domain/member/domain/constant/SocialProvider.java b/src/main/java/com/moing/backend/domain/member/domain/constant/SocialProvider.java index 400ffc8e..8779d851 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/constant/SocialProvider.java +++ b/src/main/java/com/moing/backend/domain/member/domain/constant/SocialProvider.java @@ -6,5 +6,5 @@ @AllArgsConstructor @Getter public enum SocialProvider { - GOOGLE, NAVER, APPLE, KAKAO; + GOOGLE, APPLE, KAKAO; } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index 3f198df9..7c096ac5 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -33,4 +33,12 @@ public ResponseEntity> createTeam(@Authentic @Valid @RequestBody CreateTeamRequest createTeamRequest) { return ResponseEntity.ok(SuccessResponse.create(CREATE_TEAM_SUCCESS.getMessage(), this.createTeamService.createTeam(createTeamRequest,user.getSocialId()))); } + + /** + * 소모임 생성 (only 개설만) + * [POST] api/team + * 작성자 : 김민수 + */ + + } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java index 16d96bb5..64bdfb9f 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java @@ -31,7 +31,9 @@ public class TeamMember extends BaseTimeEntity { @JoinColumn(name = "member_id") private Member member; - //==연관관계 메서드==// + private boolean isDeleted; //소모임 삭제여부, 마이페이지에서는 상관 없이 모두 조회 + + //==연관관계 메서드 ==// public void updateTeam(Team team){ this.team=team; } diff --git a/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2Attribute.java b/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2Attribute.java index 275e2e6c..0c5ba658 100644 --- a/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2Attribute.java +++ b/src/main/java/com/moing/backend/global/config/security/oauth/OAuth2Attribute.java @@ -31,8 +31,6 @@ static OAuth2Attribute of(String provider, String attributeKey, return ofGoogle(attributeKey, attributes); case "kakao": return ofKakao("id", attributes); - case "naver": - return ofNaver("id", attributes); case "apple": return ofApple("id", attributes); default: @@ -77,27 +75,6 @@ private static OAuth2Attribute ofKakao(String attributeKey, return oAuth2Attribute; } - private static OAuth2Attribute ofNaver(String attributeKey, - Map attributes) { - Map response = (Map) attributes.get("response"); - - System.out.println(response); - - OAuth2Attribute oAuth2Attribute = OAuth2Attribute.builder() - .socialId(SocialProvider.NAVER + "@" + response.get(attributeKey)) - .provider(SocialProvider.NAVER) - .name((String) response.get("nickname")) - .nickname((String) response.get("nickname")) - .email((String) response.get("email")) - .gender((String) response.get("gender")) - .ageRange((String) response.get("age")) - .build(); - - oAuth2Attribute.adaptNaverResponse(); - - return oAuth2Attribute; - } - private static OAuth2Attribute ofApple(String attributeKey, Map attributes) { OAuth2Attribute oAuth2Attribute = OAuth2Attribute.builder() diff --git a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java index 0a6a74cb..03d1eaa2 100644 --- a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java +++ b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java @@ -215,6 +215,92 @@ class AuthControllerTest extends CommonControllerTest { ); } + @Test + public void GOOGLE_소셜_로그인_회원가입_전() throws Exception { + //given + SignInRequest input = SignInRequest.builder() + .token("APPLE_IDENTITY_TOKEN") + .build(); + + String body = objectMapper.writeValueAsString(input); + + SignInResponse output = SignInResponse.builder() + .accessToken("SERVER_ACCESS_TOKEN") + .refreshToken("SERVER_REFRESH_TOKEN") + .registrationStatus(false) + .build(); + + given(authService.signIn(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + post("/api/auth/signIn/google") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestFields( + fieldWithPath("token").description("구글 아이디 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("로그인을 했습니다"), + fieldWithPath("data.accessToken").description("서버 접근용 Access Token"), + fieldWithPath("data.refreshToken").description("서버 접근용 Refresh Token"), + fieldWithPath("data.registrationStatus").description("회원가입 여부 :false") + ) + ) + ); + } + + @Test + public void GOOGLE_소셜_로그인_회원가입_후() throws Exception { + //given + SignInRequest input = SignInRequest.builder() + .token("APPLE_IDENTITY_TOKEN") + .build(); + + String body = objectMapper.writeValueAsString(input); + + SignInResponse output = SignInResponse.builder() + .accessToken("SERVER_ACCESS_TOKEN") + .refreshToken("SERVER_REFRESH_TOKEN") + .registrationStatus(true) + .build(); + + given(authService.signIn(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + post("/api/auth/signIn/google") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestFields( + fieldWithPath("token").description("구글 아이디 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("로그인을 했습니다"), + fieldWithPath("data.accessToken").description("서버 접근용 Access Token"), + fieldWithPath("data.refreshToken").description("서버 접근용 Refresh Token"), + fieldWithPath("data.registrationStatus").description("회원가입 여부 :true") + ) + ) + ); + } + @Test public void sign_up() throws Exception { From 3fcec940c5b07289d54b6085a9289d8191e39c8e Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Mon, 11 Sep 2023 01:22:59 +0900 Subject: [PATCH 067/619] =?UTF-8?q?feat:=20=ED=99=88=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=86=8C=EB=AA=A8=EC=9E=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=98=EA=B8=B0=20=EB=B0=8F=20=EC=86=8C=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=B9=BC=EB=9F=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + src/docs/asciidoc/Team-API.adoc | 6 +- .../dto/response/GetTeamResponse.java | 29 +++++++ .../application/dto/response/TeamBlock.java | 47 +++++++++++ .../service/CreateTeamUserCase.java | 6 +- .../application/service/GetTeamUserCase.java | 23 ++++++ .../domain/team/domain/entity/Team.java | 9 +++ .../repository/TeamCustomRepository.java | 3 + .../repository/TeamCustomRepositoryImpl.java | 44 +++++++++- .../team/domain/service/TeamGetService.java | 19 +++++ .../team/presentation/TeamController.java | 17 ++-- .../constant/TeamResponseMessage.java | 3 +- .../domain/service/TeamMemberSaveService.java | 3 +- .../exception/ApplicationException.java | 1 + .../team/presentation/TeamControllerTest.java | 81 ++++++++++++++++++- 15 files changed, 278 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamResponse.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java diff --git a/.gitignore b/.gitignore index 89579405..74e6afc1 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,4 @@ data.sql #### docs #### !**/src/main/resources/static/docs/ +*.html diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc index 4afd2ca1..83ee6609 100644 --- a/src/docs/asciidoc/Team-API.adoc +++ b/src/docs/asciidoc/Team-API.adoc @@ -26,4 +26,8 @@ operation::team-controller-test/create_team[snippets='http-request,request-field | `ETC` | 그외 자기계발 -|=== \ No newline at end of file +|=== + +[[Team-소모임-조회]] +=== Team 소모임 조회 +operation::team-controller-test/get_team[snippets='http-request,http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamResponse.java new file mode 100644 index 00000000..bad378b3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamResponse.java @@ -0,0 +1,29 @@ +package com.moing.backend.domain.team.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class GetTeamResponse { + private String memberNickName; + private Integer numOfTeam; + private List teamBlocks = new ArrayList<>(); + + public GetTeamResponse(Integer numOfTeam, List teamBlocks) { + this.numOfTeam=numOfTeam; + this.teamBlocks = teamBlocks; + } + public void updateMemberNickName(String memberNickName) { + this.memberNickName=memberNickName; + } +} + + diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java new file mode 100644 index 00000000..ace5ebcc --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java @@ -0,0 +1,47 @@ +package com.moing.backend.domain.team.application.dto.response; + +import com.moing.backend.domain.team.domain.constant.Category; +import com.querydsl.core.annotations.QueryProjection; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; + +@Getter +@AllArgsConstructor +@Builder +@NoArgsConstructor +public class TeamBlock { + private Long teamId; + private Long duration; //걸린시간(단위:hour) + private Integer levelOfFire; //불꽃 레벨 + private String teamName; + private Integer numOfMember; + private String category; + private String startDate; + + @QueryProjection + public TeamBlock(Long teamId, LocalDateTime approvalTime, Integer levelOfFire, String teamName, Integer numOfMember, Category category){ + this.teamId=teamId; + this.duration=calculateDuration(approvalTime); + this.levelOfFire=levelOfFire; + this.teamName=teamName; + this.numOfMember=numOfMember; + this.category=category.getMessage(); + this.startDate=approvalTime.toLocalDate().format(DateTimeFormatter.ofPattern("yyyy.MM.dd")); + } + + private Long calculateDuration(LocalDateTime approvalTime) { + ZoneId seoulZoneId = ZoneId.of("Asia/Seoul"); + LocalDateTime currentSeoulTime = LocalDateTime.now(seoulZoneId).withSecond(0).withNano(0); + LocalDateTime adjustedApprovalTime = approvalTime.withSecond(0).withNano(0); + return ChronoUnit.HOURS.between(adjustedApprovalTime, currentSeoulTime); + } +} + diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java index 9ab01cb6..5167ebfb 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java @@ -6,10 +6,8 @@ import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamSaveService; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.domain.teamMember.domain.service.TeamMemberSaveService; import lombok.RequiredArgsConstructor; -import org.checkerframework.checker.units.qual.C; import org.springframework.stereotype.Service; import javax.transaction.Transactional; @@ -27,7 +25,9 @@ public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String Member member = memberGetService.getMemberBySocialId(socialId); Team team=Team.createTeam(createTeamRequest, member); teamSaveService.saveTeam(team); - teamMemberSaveService.saveTeamMember(team, member); + teamMemberSaveService.addTeamMember(team, member); + //지워야 함 (테스트 용) + team.approveTeam(); return new CreateTeamResponse(team.getTeamId()); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java new file mode 100644 index 00000000..383a7f8e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java @@ -0,0 +1,23 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class GetTeamUserCase { + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + + public GetTeamResponse getTeam(String socialId) { + Member member = memberGetService.getMemberBySocialId(socialId); + return teamGetService.getTeam(member); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java index 79a47187..039ed756 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -57,6 +57,9 @@ public class Team extends BaseTimeEntity { private LocalDateTime deletionTime; + private Integer numOfMember; //반정규화 + private Integer levelOfFire; + public static Team createTeam(CreateTeamRequest createTeamRequest, Member member) { return Team.builder() .category(Enum.valueOf(Category.class, createTeamRequest.getCategory())) @@ -66,6 +69,8 @@ public static Team createTeam(CreateTeamRequest createTeamRequest, Member member .profileImgUrl(createTeamRequest.getProfileImgUrl()) .approvalStatus(ApprovalStatus.NO_CONFIRMATION) .leaderId(member.getMemberId()) + .numOfMember(0) + .levelOfFire(1) .build(); } @@ -88,4 +93,8 @@ public void deleteTeam() { this.isDeleted = true; this.deletionTime = LocalDateTime.now(ZoneId.of("Asia/Seoul")).withNano(0); } + + public void addTeamMember(){ + numOfMember++; + } } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index 0acfe4cf..cf1e1985 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -1,4 +1,7 @@ package com.moing.backend.domain.team.domain.repository; +import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; + public interface TeamCustomRepository { + GetTeamResponse findTeamByMemberId(Long memberId); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index adaf2525..ea68db94 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -1,4 +1,46 @@ package com.moing.backend.domain.team.domain.repository; -public class TeamCustomRepositoryImpl implements TeamCustomRepository{ +import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.team.application.dto.response.QTeamBlock; +import com.moing.backend.domain.team.application.dto.response.TeamBlock; +import com.moing.backend.domain.team.domain.constant.ApprovalStatus; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.util.List; + +import static com.moing.backend.domain.team.domain.entity.QTeam.team; +import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; + +public class TeamCustomRepositoryImpl implements TeamCustomRepository { + + private final JPAQueryFactory queryFactory; + + public TeamCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + @Override + public GetTeamResponse findTeamByMemberId(Long memberId) { + List teamBlocks = getTeamBlock(memberId); + Integer numOfTeam = teamBlocks.size(); + return new GetTeamResponse(numOfTeam, teamBlocks); + } + + private List getTeamBlock(Long memberId) { + return queryFactory + .select(new QTeamBlock(team.teamId, + team.approvalTime, + team.levelOfFire, + team.name, + team.numOfMember, + team.category)) + .from(teamMember) + .innerJoin(teamMember.team, team) + .on(teamMember.member.memberId.eq(memberId)) + .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) + .orderBy(team.approvalTime.asc()) + .fetch(); + } + } diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java new file mode 100644 index 00000000..d04fbdad --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.team.domain.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.team.domain.repository.TeamRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class TeamGetService { + private final TeamRepository teamRepository; + + public GetTeamResponse getTeam(Member member) { + GetTeamResponse getTeamResponse = teamRepository.findTeamByMemberId(member.getMemberId()); + getTeamResponse.updateMemberNickName(member.getNickName()); + return getTeamResponse; + } +} diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index 7c096ac5..c9078d96 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -2,26 +2,27 @@ import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; +import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.application.service.CreateTeamUserCase; +import com.moing.backend.domain.team.application.service.GetTeamUserCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import static com.moing.backend.domain.team.presentation.constant.TeamResponseMessage.CREATE_TEAM_SUCCESS; +import static com.moing.backend.domain.team.presentation.constant.TeamResponseMessage.GET_TEAM_SUCCESS; @RestController @AllArgsConstructor @RequestMapping("/api/team") public class TeamController { private final CreateTeamUserCase createTeamService; + private final GetTeamUserCase getTeamUserCase; /** * 소모임 생성 (only 개설만) @@ -35,10 +36,14 @@ public ResponseEntity> createTeam(@Authentic } /** - * 소모임 생성 (only 개설만) - * [POST] api/team + * 소모임 조회하기 (소모임 홈화면) : 인증사진 제외 + * [GET] api/team * 작성자 : 김민수 */ + @GetMapping + public ResponseEntity> getTeam(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_SUCCESS.getMessage(), this.getTeamUserCase.getTeam(user.getSocialId()))); + } } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 34f74c20..72ac878e 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -6,6 +6,7 @@ @Getter @RequiredArgsConstructor public enum TeamResponseMessage { - CREATE_TEAM_SUCCESS("소모임을 생성하였습니다"); + CREATE_TEAM_SUCCESS("소모임을 생성하였습니다"), + GET_TEAM_SUCCESS("홈 화면에서 내 소모임을 모두 조회했습니다."); private final String message; } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java index 82baab9e..13e6851a 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java @@ -11,10 +11,11 @@ @RequiredArgsConstructor public class TeamMemberSaveService { private final TeamMemberRepository teamMemberRepository; - public void saveTeamMember(Team team, Member member){ + public void addTeamMember(Team team, Member member){ TeamMember teamMember=new TeamMember(); teamMember.updateMember(member); teamMember.updateTeam(team); + team.addTeamMember(); this.teamMemberRepository.save(teamMember); } } diff --git a/src/main/java/com/moing/backend/global/exception/ApplicationException.java b/src/main/java/com/moing/backend/global/exception/ApplicationException.java index 48b1b728..c79eb581 100644 --- a/src/main/java/com/moing/backend/global/exception/ApplicationException.java +++ b/src/main/java/com/moing/backend/global/exception/ApplicationException.java @@ -9,6 +9,7 @@ public abstract class ApplicationException extends RuntimeException { private final HttpStatus httpStatus; protected ApplicationException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode.getMessage()); this.errorCode = errorCode; this.httpStatus = httpStatus; } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 4134766d..179d6e2b 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -3,25 +3,34 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; +import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.team.application.dto.response.TeamBlock; import com.moing.backend.domain.team.application.service.CreateTeamUserCase; +import com.moing.backend.domain.team.application.service.GetTeamUserCase; import org.junit.jupiter.api.Test; +import org.mockito.Mock; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.ResultActions; +import java.util.ArrayList; +import java.util.List; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.payload.PayloadDocumentation.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(TeamController.class) public class TeamControllerTest extends CommonControllerTest { @MockBean private CreateTeamUserCase createTeamService; + @MockBean + private GetTeamUserCase getTeamUserCase; @Test public void create_team() throws Exception { @@ -76,4 +85,74 @@ public void create_team() throws Exception { ) ); } + @Test + public void get_team() throws Exception { + //given + List teamBlocks=new ArrayList<>(); + + TeamBlock teamBlock1=TeamBlock.builder() + .teamId(1L) + .duration(5L) + .levelOfFire(3) + .teamName("소모임 예시1") + .numOfMember(10) + .category("ETC") + .startDate("2023.09.05") + .build(); + + TeamBlock teamBlock2=TeamBlock.builder() + .teamId(2L) + .duration(10L) + .levelOfFire(3) + .teamName("소모임 예시2") + .numOfMember(8) + .category("SPORTS") + .startDate("2023.09.01") + .build(); + + teamBlocks.add(teamBlock1); + teamBlocks.add(teamBlock2); + + GetTeamResponse output = GetTeamResponse.builder() + .numOfTeam(1) + .memberNickName("유저 닉네임") + .teamBlocks(teamBlocks) + .build(); + + given(getTeamUserCase.getTeam(any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform( + get("/api/team") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("홈 화면에서 내 소모임을 모두 조회했습니다."), + fieldWithPath("data.numOfTeam").description("소모임 개수(최대 3개)"), + fieldWithPath("data.memberNickName").description("유저 닉네임"), + fieldWithPath("data.teamBlocks[0].teamId").description("소모임 아이디"), + fieldWithPath("data.teamBlocks[0].duration").description("소모임과 함께한 시간"), + fieldWithPath("data.teamBlocks[0].levelOfFire").description("불꽃 레벨"), + fieldWithPath("data.teamBlocks[0].teamName").description("소모임 이름"), + fieldWithPath("data.teamBlocks[0].numOfMember").description("소모임원 숫자"), + fieldWithPath("data.teamBlocks[0].category").description("소모임 카테고리"), + fieldWithPath("data.teamBlocks[0].startDate").description("소모임 시작일") + ) + + ) + ); + } } From ce6ba57988f5d456c4473eb956291676ea9f8adc Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Wed, 13 Sep 2023 21:35:03 +0900 Subject: [PATCH 068/619] =?UTF-8?q?fix:=20=EB=8B=A4=EB=A5=B8=20=ED=94=8C?= =?UTF-8?q?=EB=9E=AB=ED=8F=BC=EC=9C=BC=EB=A1=9C=20=EA=B0=80=EC=9E=85?= =?UTF-8?q?=ED=96=88=EC=9D=84=20=EB=95=8C=20=EC=97=90=EB=9F=AC=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/domain/repository/MemberRepository.java | 2 ++ .../domain/member/domain/service/MemberSaveService.java | 2 +- .../domain/team/application/service/CreateTeamUserCase.java | 3 ++- src/main/java/com/moing/backend/global/response/ErrorCode.java | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java index ab81d900..20cb1f23 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java @@ -9,4 +9,6 @@ public interface MemberRepository extends JpaRepository, MemberCus Optional findBySocialId(String socialId); + Optional findByEmail(String email); + } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java index 71f01159..6427010a 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java @@ -16,7 +16,7 @@ public class MemberSaveService { private final MemberRepository memberRepository; public Member saveMember(Member member) { - OptionalfindMember=memberRepository.findBySocialId(member.getSocialId()); + OptionalfindMember=memberRepository.findByEmail(member.getEmail()); if(findMember.isEmpty()){ return memberRepository.save(member); } else { diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java index 5167ebfb..b5b3f423 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java @@ -26,8 +26,9 @@ public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String Team team=Team.createTeam(createTeamRequest, member); teamSaveService.saveTeam(team); teamMemberSaveService.addTeamMember(team, member); - //지워야 함 (테스트 용) + //====지워야 함 (테스트 용)===== team.approveTeam(); + //====지워야 함 (테스트 용)===== return new CreateTeamResponse(team.getTeamId()); } } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 16041802..005893ff 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -15,7 +15,7 @@ public enum ErrorCode { //유저 관련 에러 코드 NOT_FOUND_BY_SOCIAL_ID_ERROR( "U0001", "해당 socialId인 유저가 존재하지 않습니다."), - ACCOUNT_ALREADY_EXIST("AU0001", "이미 다른 소셜 플랫폼으로 가입하였습니다."), + ACCOUNT_ALREADY_EXIST("AU0001", "해당 email로 다른 소셜 플랫폼으로 가입하였습니다."), TOKEN_INVALID_ERROR("AU0002", "입력 토큰이 유효하지 않습니다."), APPID_INVALID_ERROR("AU0003", "appId가 유효하지 않습니다"), NICKNAME_DUPLICATION_ERROR("AU0003", "닉네임이 중복됩니다."), From 0baff1bfdcdc643d0430c3f739f2ca1b712c004e Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Thu, 14 Sep 2023 06:40:26 +0900 Subject: [PATCH 069/619] =?UTF-8?q?fix:=20=EB=8B=A4=EB=A5=B8=20=ED=94=8C?= =?UTF-8?q?=EB=9E=AB=ED=8F=BC=EC=9C=BC=EB=A1=9C=20=EA=B0=80=EC=9E=85?= =?UTF-8?q?=ED=96=88=EC=9D=84=20=EB=96=84=20=EC=98=A4=EB=A5=98=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MemberAuthUserCase.java | 5 ++--- .../dto/response/DeleteTeamResponse.java | 14 ++++++++++++++ .../application/dto/response/TeamBlock.java | 5 ++--- .../service/DisbandTeamUserCase.java | 19 +++++++++++++++++++ .../repository/TeamCustomRepositoryImpl.java | 4 +++- .../team/presentation/TeamController.java | 17 ++++++++++++++--- .../constant/TeamResponseMessage.java | 3 ++- .../team/presentation/TeamControllerTest.java | 4 ++++ 8 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java index 5de09d77..b8cc7982 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java @@ -26,9 +26,8 @@ public Member auth(Member member, String providerInfo) { // 다른 플랫폼으로 가입했으면 에러 출력 private void checkRegistration(Member signInMember, String providerInfo) { - Optional.of(signInMember) - .filter(m -> providerInfo.contains(m.getProvider().name().toLowerCase())) - .orElseThrow(()->new AccountAlreadyExistedException()); + if(!providerInfo.contains((signInMember.getProvider().name().toLowerCase()))) + throw new AccountAlreadyExistedException(); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java new file mode 100644 index 00000000..92ed9017 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.team.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class DeleteTeamResponse { + private Long teamId; +} diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java index ace5ebcc..763d9248 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java @@ -7,7 +7,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; @@ -19,7 +18,7 @@ @NoArgsConstructor public class TeamBlock { private Long teamId; - private Long duration; //걸린시간(단위:hour) + private Long duration; //걸린시간(단위:날짜) private Integer levelOfFire; //불꽃 레벨 private String teamName; private Integer numOfMember; @@ -41,7 +40,7 @@ private Long calculateDuration(LocalDateTime approvalTime) { ZoneId seoulZoneId = ZoneId.of("Asia/Seoul"); LocalDateTime currentSeoulTime = LocalDateTime.now(seoulZoneId).withSecond(0).withNano(0); LocalDateTime adjustedApprovalTime = approvalTime.withSecond(0).withNano(0); - return ChronoUnit.HOURS.between(adjustedApprovalTime, currentSeoulTime); + return ChronoUnit.DAYS.between(adjustedApprovalTime, currentSeoulTime); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java new file mode 100644 index 00000000..5045bc93 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class DisbandTeamUserCase { + + public DeleteTeamResponse disbandTeam(String socialId, Long teamId){ + // 1. 소모임장인지 확인 -> 아니면 오류 + // 2. 소모임 강제 종료 + return null; + } +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index ea68db94..b3718742 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -38,7 +38,9 @@ private List getTeamBlock(Long memberId) { .from(teamMember) .innerJoin(teamMember.team, team) .on(teamMember.member.memberId.eq(memberId)) - .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) + .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) //승인 되었고 + .where(team.isDeleted.eq(false)) //강제종료되었는지 + .where(teamMember.isDeleted.eq(false)) //탈퇴했는지 .orderBy(team.approvalTime.asc()) .fetch(); } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index c9078d96..72d09626 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -2,8 +2,10 @@ import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; +import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.application.service.CreateTeamUserCase; +import com.moing.backend.domain.team.application.service.DisbandTeamUserCase; import com.moing.backend.domain.team.application.service.GetTeamUserCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; @@ -14,8 +16,7 @@ import javax.validation.Valid; -import static com.moing.backend.domain.team.presentation.constant.TeamResponseMessage.CREATE_TEAM_SUCCESS; -import static com.moing.backend.domain.team.presentation.constant.TeamResponseMessage.GET_TEAM_SUCCESS; +import static com.moing.backend.domain.team.presentation.constant.TeamResponseMessage.*; @RestController @AllArgsConstructor @@ -23,6 +24,7 @@ public class TeamController { private final CreateTeamUserCase createTeamService; private final GetTeamUserCase getTeamUserCase; + private final DisbandTeamUserCase disbandTeamUserCase; /** * 소모임 생성 (only 개설만) @@ -45,5 +47,14 @@ public ResponseEntity> getTeam(@AuthenticationP return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_SUCCESS.getMessage(), this.getTeamUserCase.getTeam(user.getSocialId()))); } - + /** + * 소모임 강제 종료 (소모임 권한) + * [DELETE] api/team/{teamId}/disband + * 작성자:김민수 + */ + @DeleteMapping("/{teamId}/disband") + public ResponseEntity> disbandTeam(@AuthenticationPrincipal User user, + @PathVariable Long teamId){ + return ResponseEntity.ok(SuccessResponse.create(DISBAND_TEAM_SUCCESS.getMessage(), this.disbandTeamUserCase.disbandTeam(user.getSocialId(), teamId))); + } } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 72ac878e..9dfff563 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -7,6 +7,7 @@ @RequiredArgsConstructor public enum TeamResponseMessage { CREATE_TEAM_SUCCESS("소모임을 생성하였습니다"), - GET_TEAM_SUCCESS("홈 화면에서 내 소모임을 모두 조회했습니다."); + GET_TEAM_SUCCESS("홈 화면에서 내 소모임을 모두 조회했습니다."), + DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."); private final String message; } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 179d6e2b..6d7c00a2 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -6,6 +6,7 @@ import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.application.dto.response.TeamBlock; import com.moing.backend.domain.team.application.service.CreateTeamUserCase; +import com.moing.backend.domain.team.application.service.DisbandTeamUserCase; import com.moing.backend.domain.team.application.service.GetTeamUserCase; import org.junit.jupiter.api.Test; import org.mockito.Mock; @@ -32,6 +33,9 @@ public class TeamControllerTest extends CommonControllerTest { @MockBean private GetTeamUserCase getTeamUserCase; + @MockBean + private DisbandTeamUserCase disbandTeamUserCase; + @Test public void create_team() throws Exception { From 89a6abd79eba58f982d9db5a321174aa300f7631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:49:49 +0900 Subject: [PATCH 070/619] =?UTF-8?q?fix=20:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=EC=9E=A5=20=ED=99=95=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionCreateUseCase.java | 19 +++++++++++++------ .../exception/NoAccessCreateMission.java | 12 ++++++++++++ .../presentation/MissionController.java | 2 +- ...a => SingleMissionArchiveReadUseCase.java} | 2 +- .../backend/global/response/ErrorCode.java | 6 +++++- 5 files changed, 32 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/exception/NoAccessCreateMission.java rename src/main/java/com/moing/backend/domain/missionArchive/application/service/{MissionArchiveReadUseCase.java => SingleMissionArchiveReadUseCase.java} (98%) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index a0b13fac..d5343370 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -10,6 +10,8 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionSaveService; +import com.moing.backend.domain.mission.exception.NoAccessCreateMission; +import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.repository.TeamRepository; import com.moing.backend.global.util.SecurityUtils; import lombok.RequiredArgsConstructor; @@ -27,18 +29,23 @@ public class MissionCreateUseCase { public MissionCreateRes createMission(String userSocialId, Long teamId, MissionReq missionReq) { - Member member = memberGetService.getMemberBySocialId(userSocialId); + Team team = teamRepository.findById(teamId).orElseThrow(); // 소모임장 확인 로직 추가 + if (member.getMemberId() == team.getLeaderId()) { + Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.ONGOING); + // teamRepository 변경 예정 + mission.setTeam(team); + missionSaveService.save(mission); - Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.WAIT); - // teamRepository 변경 예정 - mission.setTeam(teamRepository.findById(teamId).orElseThrow()); + return MissionMapper.mapToMissionCreateRes(mission); + } + else{ + throw new NoAccessCreateMission(); + } - missionSaveService.save(mission); - return MissionMapper.mapToMissionCreateRes(mission); } diff --git a/src/main/java/com/moing/backend/domain/mission/exception/NoAccessCreateMission.java b/src/main/java/com/moing/backend/domain/mission/exception/NoAccessCreateMission.java new file mode 100644 index 00000000..d8fa3346 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/exception/NoAccessCreateMission.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mission.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NoAccessCreateMission extends MissionException { + + public NoAccessCreateMission() { + super(ErrorCode.NO_ACCESS_CREATE_MISSION, + HttpStatus.UNAUTHORIZED); + } +} diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 0079163b..4c235f14 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -20,7 +20,7 @@ @RestController @AllArgsConstructor -@RequestMapping("/api/{teamId}/mission") +@RequestMapping("/api/{teamId}/missions") public class MissionController { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java similarity index 98% rename from src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java rename to src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java index 9bbd1d7d..b5f9cf76 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java @@ -21,7 +21,7 @@ @Service @Transactional @RequiredArgsConstructor -public class MissionArchiveReadUseCase { +public class SingleMissionArchiveReadUseCase { //미션 아치브 읽어오기 private final MemberGetService memberGetService; diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 16041802..9f546aef 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -21,7 +21,11 @@ public enum ErrorCode { NICKNAME_DUPLICATION_ERROR("AU0003", "닉네임이 중복됩니다."), //팀멤버 에러 코드 - TOO_MANY_TEAM_MEMBER_ERROR("TM0001", "팀 최대 개수 3을 초과했습니다"); + TOO_MANY_TEAM_MEMBER_ERROR("TM0001", "팀 최대 개수 3을 초과했습니다"), + + //미션 생성 에러코드 + NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."); + private String errorCode; private String message; From 7ef2410256d215ae948fd9460b470cbebbd1c458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:51:30 +0900 Subject: [PATCH 071/619] =?UTF-8?q?fix=20:=20MissionStatus,=20MissionArchi?= =?UTF-8?q?veStatus=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/entity/constant/MissionStatus.java | 5 +---- .../mapper/MissionArchiveMapper.java | 18 +++++++++++++++++- .../domain/entity/MissionArchive.java | 2 +- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java index 62382308..e561994a 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java @@ -6,9 +6,6 @@ @Getter @AllArgsConstructor public enum MissionStatus { - WAIT, - DONE, + END, ONGOING, - SKIP; - } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 61b4eed0..1c54a7e9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -1,12 +1,14 @@ package com.moing.backend.domain.missionArchive.application.mapper; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.annotation.Mapper; @@ -19,7 +21,7 @@ public class MissionArchiveMapper { public static MissionArchive mapToMissionArchive(MissionArchiveReq missionArchiveReq, Member member, Mission mission) { return MissionArchive.builder() .archive(missionArchiveReq.getArchive()) - .status(MissionStatus.valueOf(missionArchiveReq.getStatus())) + .status(MissionArchiveStatus.valueOf(missionArchiveReq.getStatus())) .member(member) .mission(mission) .build(); @@ -44,5 +46,19 @@ public static PersonalArchive mapToPersonalArchive(MissionArchive missionArchive } + public static SingleMissionBoardRes mapToSingleMissionBoardRes(MissionArchive missionArchive) { + Member member = missionArchive.getMember(); + Mission mission = missionArchive.getMission(); + return SingleMissionBoardRes.builder() + .missionId(mission.getId()) + .title(mission.getTitle()) + .missionType(mission.getType().name()) + .dueTo(mission.getDueTo().toString()) + .status(missionArchive.getStatus().name()) + .build(); + + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index f54e4721..c72f62dc 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -31,7 +31,7 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 private Mission mission; @Enumerated(value = EnumType.STRING) - private MissionStatus status; + private MissionArchiveStatus status; private String archive; //링크, 글, 사진 뭐든 가능 From 01aff883bee79a5acf48c1b26a17bfcd5c76817a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:52:18 +0900 Subject: [PATCH 072/619] =?UTF-8?q?fix=20:=20mission=20crud=20url=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20test=20url?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/representation/MissionControllerTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index c4fd0b0d..8ac524c7 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -81,7 +81,7 @@ public class MissionControllerTest extends CommonControllerTest { Long teamId = 2L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - post("/api/{teamId}/mission",teamId) + post("/api/{teamId}/missions",teamId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) .content(body) @@ -159,7 +159,7 @@ public class MissionControllerTest extends CommonControllerTest { //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - put("/api/{teamId}/mission/{missionId}",teamId,missionId) + put("/api/{teamId}/missions/{missionId}",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) .content(body) @@ -226,7 +226,7 @@ public class MissionControllerTest extends CommonControllerTest { Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/{teamId}/mission/{missionId}",teamId,missionId) + get("/api/{teamId}/missions/{missionId}",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) @@ -270,7 +270,7 @@ public class MissionControllerTest extends CommonControllerTest { Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - delete("/api/{teamId}/mission/{missionId}",teamId,missionId) + delete("/api/{teamId}/missions/{missionId}",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) ); From 02ccf2c7d2165f9a75bb08faa696fbfaa8232477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:53:21 +0900 Subject: [PATCH 073/619] =?UTF-8?q?entity=20:=20team=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=EC=97=90=EC=84=9C=20List=20=EC=B0=B8=EC=A1=B0=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moing/backend/domain/team/domain/entity/Team.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java index 79a47187..0b393587 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.team.domain.entity; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.moing.backend.domain.team.domain.constant.Category; @@ -13,6 +14,8 @@ import javax.persistence.*; import java.time.LocalDateTime; import java.time.ZoneId; +import java.util.ArrayList; +import java.util.List; @Builder @NoArgsConstructor @@ -57,6 +60,9 @@ public class Team extends BaseTimeEntity { private LocalDateTime deletionTime; + @OneToMany(mappedBy = "team") + List missions = new ArrayList<>(); + public static Team createTeam(CreateTeamRequest createTeamRequest, Member member) { return Team.builder() .category(Enum.valueOf(Category.class, createTeamRequest.getCategory())) From db5fc6e19b117f99c20eb6a2afc8a4dfc092b31b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:56:11 +0900 Subject: [PATCH 074/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EA=B3=BC=20=EC=9E=AC=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveCreateUseCase.java | 39 +++++-------- .../service/MissionArchiveUpdateUseCase.java | 56 +++++++++++++++++++ .../MissionArchiveController.java | 44 +++++++++------ 3 files changed, 98 insertions(+), 41 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index b643fd3e..b768198a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.application.service; +import com.moing.backend.domain.infra.image.application.service.IssuePresignedUrlUseCase; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.application.dto.req.MissionReq; @@ -39,42 +40,32 @@ public class MissionArchiveCreateUseCase { private final MemberGetService memberGetService; - // 미션 인증 및 재인증 (수정하기도 포함됨) + private final MissionArchiveScoreService missionArchiveScoreService; + + // 미션 인증 public MissionArchiveRes createArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); + MissionArchive missionArchive = missionArchiveSaveService.save(MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission)); - - // 사진 제출 했다면, - if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(member.getMemberId(), missionId)) { - - //s3삭제 - //archive set presignedURL - - String url = null; - missionReq.setArchive(url); - - return saveArchive(mission, missionReq,member); - + if (isDoneSingleMission(mission)) { + missionArchiveScoreService.addScore(team); } - return saveArchive(mission, missionReq,member); + return MissionArchiveMapper.mapToMissionArchiveRes(missionArchive); } - - public MissionArchiveRes saveArchive(Mission mission,MissionArchiveReq missionReq,Member member) { - MissionArchive save = missionArchiveSaveService.save(MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission)); - - // 미션 완료 처리 - if (mission.getMissionArchiveList().size() == 3-1) { - mission.setStatus(MissionStatus.DONE); + // 모든 모임원이 단일 미션을 완료하였는지 + public Boolean isDoneSingleMission(Mission mission) { + Team team = mission.getTeam(); + if (mission.getMissionArchiveList().size() == team.getLeaderId()-1) { + mission.setStatus(MissionStatus.END); + return true; } - - return MissionArchiveMapper.mapToMissionArchiveRes(save); - + return false; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java new file mode 100644 index 00000000..adb6dca4 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -0,0 +1,56 @@ +package com.moing.backend.domain.missionArchive.application.service; + +import com.moing.backend.domain.infra.image.application.service.IssuePresignedUrlUseCase; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; +import com.moing.backend.domain.team.domain.entity.Team; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionArchiveUpdateUseCase { + + private final MissionArchiveSaveService missionArchiveSaveService; + private final MissionArchiveQueryService missionArchiveQueryService; + private final MissionArchiveDeleteService missionArchiveDeleteService; + + private final MissionQueryService missionQueryService; + + private final MemberGetService memberGetService; + + private final IssuePresignedUrlUseCase getPresignedUrlUseCase; + + + // 미션 인증 및 재인증 (수정하기도 포함됨) + public MissionArchiveRes updateArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { + + Member member = memberGetService.getMemberBySocialId(userSocialId); + Mission mission = missionQueryService.findMissionById(missionId); + Team team = mission.getTeam(); + + // 사진 제출 했다면, + if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(member.getMemberId(), missionId)) { + //s3삭제 + + } + + MissionArchive missionArchive = missionArchiveSaveService.save(MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission)); + return MissionArchiveMapper.mapToMissionArchiveRes(missionArchive); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 08fc1b14..0d8b824c 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -1,15 +1,11 @@ package com.moing.backend.domain.missionArchive.presentation; -import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; -import com.moing.backend.domain.mission.application.service.MissionCreateUseCase; -import com.moing.backend.domain.mission.application.service.MissionDeleteUseCase; -import com.moing.backend.domain.mission.application.service.MissionReadUseCase; -import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateUseCase; -import com.moing.backend.domain.missionArchive.application.service.MissionArchiveReadUseCase; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveUpdateUseCase; +import com.moing.backend.domain.missionArchive.application.service.SingleMissionArchiveReadUseCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -19,21 +15,21 @@ import java.util.List; -import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.READ_MISSION_SUCCESS; import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; @RestController @AllArgsConstructor -@RequestMapping("/api/{teamId}/{missionId}/archive") +@RequestMapping("/api/{teamId}/missions/{missionId}/archive") public class MissionArchiveController { private final MissionArchiveCreateUseCase missionArchiveCreateUseCase; - private final MissionArchiveReadUseCase missionArchiveReadUseCase; + private final MissionArchiveUpdateUseCase missionArchiveUpdateUseCase; + private final SingleMissionArchiveReadUseCase singleMissionArchiveReadUseCase; /** * 미션 인증 하기 - * [POST] {teamId}/{missionId}/missionArchive + * [POST] {teamId}/missions/{missionId}/archive * 작성자 : 정승연 */ @@ -45,31 +41,45 @@ public ResponseEntity> createArchive(@Authent return ResponseEntity.ok(SuccessResponse.create(CREATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveCreateUseCase.createArchive(user.getSocialId(), missionId,missionArchiveReq))); } + /** + * 미션 재인증 하기 + * [POST] {teamId}/missions/{missionId}/archive + * 작성자 : 정승연 + */ + + @PutMapping() + public ResponseEntity> updateArchive(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId, + @RequestBody MissionArchiveReq missionArchiveReq) { + return ResponseEntity.ok(SuccessResponse.create(CREATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveUpdateUseCase.updateArchive(user.getSocialId(), missionId,missionArchiveReq))); + } + /** * 미션 인증 조회 - * [GET] {teamId}/{missionId}/archiveㅡ + * [GET] {teamId}/missions/{missionId}/archive * 작성자 : 정승연 */ @GetMapping() - public ResponseEntity> getArchives(@AuthenticationPrincipal User user, + public ResponseEntity>> getMyArchives(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId, @RequestBody MissionArchiveReq missionArchiveReq) { - return ResponseEntity.ok(SuccessResponse.create(READ_MY_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getMyArchive(user.getSocialId(), missionId))); + return ResponseEntity.ok(SuccessResponse.create(READ_MY_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getMyArchive(user.getSocialId(), missionId))); } /** * 모임원 미션 인증 목록 조회 - * [GET] {teamId}/{missionId}/archive/done + * [GET] {teamId}/missions/{missionId}/archive/others * 작성자 : 정승연 */ - @GetMapping("/done") - public ResponseEntity>> getDoneArchives(@AuthenticationPrincipal User user, + @GetMapping("/others") + public ResponseEntity>> getOtherPeopleArchives(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId, @RequestBody MissionArchiveReq missionArchiveReq) { - return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getPersonalArchive(user.getSocialId(), missionId))); + return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(user.getSocialId(), missionId))); } } \ No newline at end of file From 285a47b5944c2760fd4b6118280c7b294bd26427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:58:52 +0900 Subject: [PATCH 075/619] =?UTF-8?q?feat=20:=20=EB=8B=A8=EC=9D=BC=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A1=B0=ED=9A=8C=20=EB=B3=B4=EB=93=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/FinishMissionBoardRes.java | 10 +++ .../dto/res/SingleMissionBoardRes.java | 17 +++++ .../service/MissionArchiveBoardUseCase.java | 69 +++++++++++++++++++ .../SingleMissionArchiveReadUseCase.java | 12 ++-- .../repository/MissionArchiveRepository.java | 22 +++++- .../service/MissionArchiveQueryService.java | 48 +++++++++++-- 6 files changed, 165 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java create mode 100644 src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java new file mode 100644 index 00000000..30e48acd --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java @@ -0,0 +1,10 @@ +package com.moing.backend.domain.mission.application.dto.res; + +public class FinishMissionBoardRes { + private Long missionId; + private String dueTo; // 날짜 + private String title; + private String status; + private String missionType; + +} diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java new file mode 100644 index 00000000..e7d1ad93 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.mission.application.dto.res; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class SingleMissionBoardRes { + private Long missionId; + private String dueTo; // 날짜 + private String title; + private String status; + private String missionType; + +} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java new file mode 100644 index 00000000..d20bfb9d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java @@ -0,0 +1,69 @@ +package com.moing.backend.domain.mission.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.repository.TeamRepository; +import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; + +// 모아보기 +@Service +@Transactional +@RequiredArgsConstructor +public class MissionArchiveBoardUseCase { + + private final MissionArchiveQueryService missionArchiveQueryService; + + private final MemberGetService memberGetService; + private final TeamRepository teamRepository; + + public List getActiveSingleMissions(Long teamId, String memberId,Long missionId) { + + Team team = teamRepository.findById(teamId).orElseThrow(); + Member member = memberGetService.getMemberBySocialId(memberId); + + // 인증상태 가져올 미션 배열 + List missionIds = new ArrayList<>(); + team.getMissions().forEach(mission -> missionIds.add(mission.getId())); + + List singleMissionBoardResList = new ArrayList<>(); + missionArchiveQueryService.findMySingleMissionArchives(member.getMemberId(), missionIds, MissionStatus.ONGOING).forEach( + missionArchive -> singleMissionBoardResList.add(MissionArchiveMapper.mapToSingleMissionBoardRes(missionArchive)) + ); + + return singleMissionBoardResList; + + } + +// public List getActiveRepeatMissions(Long teamId, String memberId) { +// +// Team team = teamRepository.findById(teamId).orElseThrow(); +// Member member = memberGetService.getMemberBySocialId(memberId); +// +// missionArchiveQueryService.findRepeatMissionMyArchive(memberId, ); +// } +// +// public List getFinishMissions(Long teamId, Long memberId) { +// +// +// +// } +// public List getFinishRepeatMissions(Long teamId, Long memberId) { +// +// } +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java index b5f9cf76..c5df70bc 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java @@ -30,9 +30,13 @@ public class SingleMissionArchiveReadUseCase { // 나의 인증 목록 - public MissionArchiveRes getMyArchive(String userSocialId, Long missionId) { - MissionArchive myArchive = getArchive(userSocialId, missionId); - return MissionArchiveMapper.mapToMissionArchiveRes(myArchive); + public List getMyArchive(String userSocialId, Long missionId) { + List myArchives = getArchive(userSocialId, missionId); + + List archiveRes = new ArrayList<>(); + myArchives.forEach(myArchive -> archiveRes.add(MissionArchiveMapper.mapToMissionArchiveRes(myArchive))); + + return archiveRes; } // 팀원들 인증 목록 @@ -48,7 +52,7 @@ public List getPersonalArchive(String userSocialId, Long missio } // memberId, missionId로 archive 꺼내기 - public MissionArchive getArchive(String userSocialId, Long missionId) { + public List getArchive(String userSocialId, Long missionId) { Member member = memberGetService.getMemberBySocialId(userSocialId); Mission mission = missionQueryService.findMissionById(missionId); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java index d03c3f85..727e51c6 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -1,19 +1,35 @@ package com.moing.backend.domain.missionArchive.domain.repository; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import feign.Param; import org.hibernate.annotations.Parameter; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import java.util.List; import java.util.Optional; public interface MissionArchiveRepository extends JpaRepository { - @Query("select m from MissionArchive as m where m.member =:memberId") - public Optional findByMemberId(Long memberId); + @Query("select m from MissionArchive as m where m.member =:memberId" ) + Optional findByMemberId(@Param("memberId") Long memberId); @Query("select m from MissionArchive as m where m.mission.id = :missionId and m.member.memberId =:memberId") - public Optional findByMissionIdAndMemberId(@Param("memberId") Long memberId, @Param("missionId")Long missionId); + Optional> findByMissionIdAndMemberId(@Param("memberId") Long memberId, @Param("missionId")Long missionId); + + + @Query("select m from MissionArchive as m " + + "where m.mission.id IN :missionIds " + + "and m.member.memberId =:memberId " + + "and m.mission.status =:status " + + "and m.status =:archiveStatus") + Optional> findSingleMissionArchivesByMemberId (@Param("memberId") Long memberId, + @Param("missionIds") List missionIds, + @Param("status")String status, + @Param("archiveStatus")String archiveStatus); + @Query("select m from MissionArchive as m where m.mission.id IN :missionIds and m.member.memberId =:memberId") + Optional> findRepeatMissionArchivesByMission (@Param("memberId") Long memberId, @Param("missionIds") List missionIds); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index d2cffcd7..318604ea 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -1,16 +1,23 @@ package com.moing.backend.domain.missionArchive.domain.service; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; import com.moing.backend.domain.missionArchive.exception.NotFoundMissionArchiveException; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Optional; +import static com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus.*; +import static com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus.INCOMPLETE; + @DomainService @Transactional @RequiredArgsConstructor @@ -19,16 +26,16 @@ public class MissionArchiveQueryService { private final MissionRepository missionRepository; private final MissionArchiveRepository missionArchiveRepository; -// public List findByMissionId(Long missionId) { -// -// } + public List findMyArchive(Long memberId, Long missionId) { + return missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId).orElseThrow(); + } public MissionArchive findByMemberId(Long memberId) { return missionArchiveRepository.findByMemberId(memberId).orElseThrow(NotFoundMissionArchiveException::new); } public Boolean isDone(Long memberId, Long missionId) { - Optional byMemberId = missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId); + Optional> byMemberId = missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId); if (byMemberId.isPresent()) { return Boolean.TRUE; } @@ -37,7 +44,36 @@ public Boolean isDone(Long memberId, Long missionId) { } } - public MissionArchive findMyArchive(Long memberId, Long missionId) { - return missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId).orElseThrow(NotFoundMissionArchiveException::new); + // team의 mission id 들 가져와서 나의 mission archive 리턴 + public List findMySingleMissionArchives(Long memberId, List missionIds, MissionStatus missionStatus) { + // INCOMPLETE + List incompleteList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), INCOMPLETE.name()) + .orElseThrow(NotFoundMissionArchiveException::new); + Collections.sort(incompleteList, new Comparator() { + @Override + public int compare(MissionArchive missionArchive1, MissionArchive missionArchive2) { + // missionArchive1의 dueTo와 missionArchive2의 dueTo를 비교하여 오름차순으로 정렬 + return missionArchive1.getMission().getDueTo().compareTo(missionArchive2.getMission().getDueTo()); + } + }); + + List completeList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), COMPLETE.name()) + .orElseThrow(NotFoundMissionArchiveException::new); + Collections.sort(completeList, new Comparator() { + @Override + public int compare(MissionArchive missionArchive1, MissionArchive missionArchive2) { + // missionArchive1의 dueTo와 missionArchive2의 dueTo를 비교하여 오름차순으로 정렬 + return missionArchive2.getMission().getDueTo().compareTo(missionArchive1.getMission().getDueTo()); + } + }); + incompleteList.addAll(completeList); + return incompleteList; + } + public List findMyRepeatMissionArchives(Long memberId, List missionIds) { + return missionArchiveRepository.findRepeatMissionArchivesByMission(memberId, missionIds).orElseThrow(NotFoundMissionArchiveException::new); } + + + + } From e9548842f4d19917f2dab7d56902c2588dd66b2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:59:20 +0900 Subject: [PATCH 076/619] =?UTF-8?q?feat=20:=20mission=20archive=20status?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC=20:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionArchive/domain/entity/MissionArchiveStatus.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchiveStatus.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchiveStatus.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchiveStatus.java new file mode 100644 index 00000000..2fe72b45 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchiveStatus.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.missionArchive.domain.entity; + +public enum MissionArchiveStatus { + INCOMPLETE,COMPLETE,SKIP +} From d3c3b5a4930787442c81bdaf46e63d6ec42ea25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:59:49 +0900 Subject: [PATCH 077/619] =?UTF-8?q?feat=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A1=B0=ED=9A=8C=20=EB=B3=B4=EB=93=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/RepeatMissionBoardRes.java | 12 ++++ .../RepeatMissionArchiveReadUseCase.java | 63 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java new file mode 100644 index 00000000..ddef3b56 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mission.application.dto.res; + +public class RepeatMissionBoardRes { + private Long missionId; + private String dueTo; //요일 + private String title; + private String status; + private int num; + private int done; + + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java new file mode 100644 index 00000000..7690445a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java @@ -0,0 +1,63 @@ +package com.moing.backend.domain.missionArchive.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; +import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; + +import static com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper.mapToPersonalArchive; + +@Service +@Transactional +@RequiredArgsConstructor +public class RepeatMissionArchiveReadUseCase { + + //미션 아치브 읽어오기 + private final MemberGetService memberGetService; + private final MissionQueryService missionQueryService; + private final MissionArchiveQueryService missionArchiveQueryService; + + + // 나의 인증 목록 + public List getMyArchive(String userSocialId, Long missionId) { + List myArchives = getArchive(userSocialId, missionId); + + List archiveRes = new ArrayList<>(); + myArchives.forEach(myArchive -> archiveRes.add(MissionArchiveMapper.mapToMissionArchiveRes(myArchive))); + + return archiveRes; + } + + // 팀원들 인증 목록 + public List getPersonalArchive(String userSocialId, Long missionId) { + Mission mission = missionQueryService.findMissionById(missionId); + + List done = new ArrayList<>(); + + mission.getMissionArchiveList() + .forEach(missionArchive1 -> done.add(mapToPersonalArchive(missionArchive1))); + + return done; + } + + // memberId, missionId로 archive 꺼내기 + public List getArchive(String userSocialId, Long missionId) { + Member member = memberGetService.getMemberBySocialId(userSocialId); + Mission mission = missionQueryService.findMissionById(missionId); + + return missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId); + } + + +} From 4d027dff9d5dc52d985edb328a1d0167f75d7cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 16:00:33 +0900 Subject: [PATCH 078/619] =?UTF-8?q?entity=20:=20=EC=86=8C=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=20=ED=8C=80=20=EC=A0=90=EC=88=98=20entity=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveScoreService.java | 24 +++++++++++++++++++ .../application/service/ScoreSaveUseCase.java | 10 ++++++++ .../service/ScoreUpdateUseCase.java | 17 +++++++++++++ .../domain/score/domain/entity/Score.java | 22 +++++++++++++++++ .../domain/repository/ScoreRepository.java | 15 ++++++++++++ .../domain/service/ScoreQueryService.java | 18 ++++++++++++++ .../domain/service/ScoreSaveService.java | 20 ++++++++++++++++ 7 files changed, 126 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java create mode 100644 src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/score/domain/entity/Score.java create mode 100644 src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java create mode 100644 src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java create mode 100644 src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java new file mode 100644 index 00000000..89d12f78 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.missionArchive.application.service; + +import com.moing.backend.domain.score.domain.entity.Score; +import com.moing.backend.domain.score.domain.service.ScoreQueryService; +import com.moing.backend.domain.score.domain.service.ScoreSaveService; +import com.moing.backend.domain.team.domain.entity.Team; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class MissionArchiveScoreService { + + private final ScoreQueryService scoreQueryService; + + public void addScore(Team team) { + // steps + // 단계별 + Score score = scoreQueryService.findByTeamId(team.getTeamId()); + score.updateScore(20); + + } + +} diff --git a/src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java b/src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java new file mode 100644 index 00000000..b9403968 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java @@ -0,0 +1,10 @@ +package com.moing.backend.domain.score.application.service; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; + +public class ScoreSaveUseCase { + + + +} diff --git a/src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java new file mode 100644 index 00000000..9e5a60e5 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.score.application.service; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; + +public class ScoreUpdateUseCase { + + public int singleMissionDone(Mission mission) { + + if (mission.getStatus() == MissionStatus.END) { + + + } + + return 3; + } +} diff --git a/src/main/java/com/moing/backend/domain/score/domain/entity/Score.java b/src/main/java/com/moing/backend/domain/score/domain/entity/Score.java new file mode 100644 index 00000000..257e500f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/score/domain/entity/Score.java @@ -0,0 +1,22 @@ +package com.moing.backend.domain.score.domain.entity; + +import lombok.Getter; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +@Getter +public class Score { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private Long teamId; + private int score; + + public int updateScore(int score) { + return this.score += score; + } +} diff --git a/src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java b/src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java new file mode 100644 index 00000000..67d1b303 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java @@ -0,0 +1,15 @@ +package com.moing.backend.domain.score.domain.repository; + +import com.moing.backend.domain.score.domain.entity.Score; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.Optional; + + +public interface ScoreRepository extends JpaRepository { + + @Query("select s from Score s where s.teamId = :teamId ") + Score findByTeamId(Long teamId); + +} diff --git a/src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java b/src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java new file mode 100644 index 00000000..983f3604 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.score.domain.service; + +import com.moing.backend.domain.score.domain.entity.Score; +import com.moing.backend.domain.score.domain.repository.ScoreRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ScoreQueryService { + + private final ScoreRepository scoreRepository; + + public Score findByTeamId(Long teamId) { + return scoreRepository.findByTeamId(teamId); + } + +} diff --git a/src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java b/src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java new file mode 100644 index 00000000..c2ae310e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.score.domain.service; + +import com.moing.backend.domain.score.domain.entity.Score; +import com.moing.backend.domain.score.domain.repository.ScoreRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class ScoreSaveService { + + private final ScoreRepository scoreRepository; + + public Score save(Score score) { + return scoreRepository.save(score); + } + +} From c067865c92b49eeef51f9c126485307880bc5eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 16:07:00 +0900 Subject: [PATCH 079/619] =?UTF-8?q?fix=20:=20SingleMissionArchiveReadUseCa?= =?UTF-8?q?se=EC=A3=BC=EC=84=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/SingleMissionArchiveReadUseCase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java index c5df70bc..c0f9b751 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java @@ -29,7 +29,7 @@ public class SingleMissionArchiveReadUseCase { private final MissionArchiveQueryService missionArchiveQueryService; - // 나의 인증 목록 + // 미션 인증 조회 public List getMyArchive(String userSocialId, Long missionId) { List myArchives = getArchive(userSocialId, missionId); @@ -39,7 +39,7 @@ public List getMyArchive(String userSocialId, Long missionId) return archiveRes; } - // 팀원들 인증 목록 + // 모임원 미션 인증 목록 조회 public List getPersonalArchive(String userSocialId, Long missionId) { Mission mission = missionQueryService.findMissionById(missionId); From cfe91394b61f47bb42f944e2f335a13b3380ebd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 20:19:43 +0900 Subject: [PATCH 080/619] =?UTF-8?q?feat=20:=20=EC=99=84=EB=A3=8C/=EB=AF=B8?= =?UTF-8?q?=EC=99=84=EB=A3=8C=20=EB=AF=B8=EC=85=98=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EC=A0=95=EB=A0=AC=20=EA=B8=B0=EC=A4=80=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=EC=9C=84=ED=95=9C=20querydsl=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/entity/MissionArchive.java | 1 + .../MissionArchiveCustomRepository.java | 12 ++++ .../MissionArchiveCustomRepositoryImpl.java | 59 +++++++++++++++++++ .../repository/MissionArchiveRepository.java | 2 +- .../service/MissionArchiveQueryService.java | 28 ++++----- .../domain/repository/OrderCondition.java | 6 ++ 6 files changed, 90 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/teamMember/domain/repository/OrderCondition.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index c72f62dc..981d54a2 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -33,6 +33,7 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 @Enumerated(value = EnumType.STRING) private MissionArchiveStatus status; + @Column(nullable = false) private String archive; //링크, 글, 사진 뭐든 가능 diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java new file mode 100644 index 00000000..1a4b433a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.missionArchive.domain.repository; + +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.teamMember.domain.repository.OrderCondition; + +import java.util.List; +import java.util.Optional; + +public interface MissionArchiveCustomRepository { + public Optional> findSingleMissionArchivesByMemberId(Long memberId, List missionIds, String status, String archiveStatus, OrderCondition orderCondition); + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java new file mode 100644 index 00000000..72852954 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -0,0 +1,59 @@ +package com.moing.backend.domain.missionArchive.domain.repository; + +import com.moing.backend.domain.mission.domain.entity.QMission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; +import com.moing.backend.domain.teamMember.domain.repository.OrderCondition; +import com.querydsl.core.types.Order; +import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.jpa.impl.JPAQueryFactory; +import feign.Param; +import org.springframework.data.jpa.repository.Query; + +import javax.persistence.EntityManager; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; + +public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { + private final JPAQueryFactory queryFactory; + + public MissionArchiveCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + @Override + public Optional> findSingleMissionArchivesByMemberId(Long memberId, List missionIds, String status, String archiveStatus,OrderCondition orderCondition) { + OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); + return Optional.ofNullable(queryFactory + .select(missionArchive) + .from(missionArchive) + .where( + missionArchive.mission.id.in(missionIds), + missionArchive.mission.status.eq(MissionStatus.valueOf(status)), + missionArchive.status.eq(MissionArchiveStatus.valueOf(archiveStatus)) + ) + .orderBy(orderSpecifiers) + .fetch()); + + } + + private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { + + List orderSpecifiers = new ArrayList<>(); + + if(orderCondition.equals(OrderCondition.DUETO)){ + orderSpecifiers.add(new OrderSpecifier(Order.DESC, missionArchive.mission.dueTo)); + }else if(orderCondition.equals(OrderCondition.CREATED)){ + orderSpecifiers.add(new OrderSpecifier(Order.DESC, missionArchive.createdDate)); + } + return orderSpecifiers.toArray(new OrderSpecifier[orderSpecifiers.size()]); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java index 727e51c6..3a453fe6 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -24,7 +24,7 @@ public interface MissionArchiveRepository extends JpaRepository> findSingleMissionArchivesByMemberId (@Param("memberId") Long memberId, @Param("missionIds") List missionIds, @Param("status")String status, diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 318604ea..d9799c76 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -4,8 +4,10 @@ import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveCustomRepository; import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; import com.moing.backend.domain.missionArchive.exception.NotFoundMissionArchiveException; +import com.moing.backend.domain.teamMember.domain.repository.OrderCondition; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -25,6 +27,7 @@ public class MissionArchiveQueryService { private final MissionRepository missionRepository; private final MissionArchiveRepository missionArchiveRepository; + private final MissionArchiveCustomRepository missionArchiveCustomRepository public List findMyArchive(Long memberId, Long missionId) { return missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId).orElseThrow(); @@ -45,27 +48,18 @@ public Boolean isDone(Long memberId, Long missionId) { } // team의 mission id 들 가져와서 나의 mission archive 리턴 + + /** + * mission.getTeam() 팀의 단일미션 미션 인증 보드 + */ public List findMySingleMissionArchives(Long memberId, List missionIds, MissionStatus missionStatus) { // INCOMPLETE - List incompleteList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), INCOMPLETE.name()) + List incompleteList = missionArchiveCustomRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), INCOMPLETE.name(), OrderCondition.DUETO) .orElseThrow(NotFoundMissionArchiveException::new); - Collections.sort(incompleteList, new Comparator() { - @Override - public int compare(MissionArchive missionArchive1, MissionArchive missionArchive2) { - // missionArchive1의 dueTo와 missionArchive2의 dueTo를 비교하여 오름차순으로 정렬 - return missionArchive1.getMission().getDueTo().compareTo(missionArchive2.getMission().getDueTo()); - } - }); - - List completeList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), COMPLETE.name()) + + List completeList = missionArchiveCustomRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), COMPLETE.name(),OrderCondition.CREATED) .orElseThrow(NotFoundMissionArchiveException::new); - Collections.sort(completeList, new Comparator() { - @Override - public int compare(MissionArchive missionArchive1, MissionArchive missionArchive2) { - // missionArchive1의 dueTo와 missionArchive2의 dueTo를 비교하여 오름차순으로 정렬 - return missionArchive2.getMission().getDueTo().compareTo(missionArchive1.getMission().getDueTo()); - } - }); + incompleteList.addAll(completeList); return incompleteList; } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/OrderCondition.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/OrderCondition.java new file mode 100644 index 00000000..706b8e5a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/OrderCondition.java @@ -0,0 +1,6 @@ +package com.moing.backend.domain.teamMember.domain.repository; + +public enum OrderCondition { + DUETO,CREATED + +} From 020ea1a0ec792391591abd9692bd53c04635f204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 19 Sep 2023 20:26:38 +0900 Subject: [PATCH 081/619] =?UTF-8?q?feat=20:=20mapToSingleMissionBoardResLi?= =?UTF-8?q?st=20mapper=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveBoardUseCase.java | 11 +++++------ .../application/mapper/MissionArchiveMapper.java | 9 +++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java index d20bfb9d..47c1b990 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java @@ -32,6 +32,9 @@ public class MissionArchiveBoardUseCase { private final MemberGetService memberGetService; private final TeamRepository teamRepository; + /* + * 팀별 미션 보드 중 진행중인 단일 미션(한 번 인증) + */ public List getActiveSingleMissions(Long teamId, String memberId,Long missionId) { Team team = teamRepository.findById(teamId).orElseThrow(); @@ -41,12 +44,8 @@ public List getActiveSingleMissions(Long teamId, String m List missionIds = new ArrayList<>(); team.getMissions().forEach(mission -> missionIds.add(mission.getId())); - List singleMissionBoardResList = new ArrayList<>(); - missionArchiveQueryService.findMySingleMissionArchives(member.getMemberId(), missionIds, MissionStatus.ONGOING).forEach( - missionArchive -> singleMissionBoardResList.add(MissionArchiveMapper.mapToSingleMissionBoardRes(missionArchive)) - ); - - return singleMissionBoardResList; + List mySingleMissionArchives = missionArchiveQueryService.findMySingleMissionArchives(member.getMemberId(), missionIds, MissionStatus.ONGOING); + return MissionArchiveMapper.mapToSingleMissionBoardResList(mySingleMissionArchives); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 1c54a7e9..7e85e863 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -59,6 +59,15 @@ public static SingleMissionBoardRes mapToSingleMissionBoardRes(MissionArchive mi } + public static List mapToSingleMissionBoardResList( List missionArchives) { + List singleMissionBoardResList = new ArrayList<>(); + missionArchives.forEach( + missionArchive -> singleMissionBoardResList.add(MissionArchiveMapper.mapToSingleMissionBoardRes(missionArchive)) + ); + + return singleMissionBoardResList; + } + } From 06cac8679bc1c677b8bb50703b3417b52e802e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Sep 2023 02:18:33 +0900 Subject: [PATCH 082/619] =?UTF-8?q?fix=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=A0=95=EB=A6=AC(=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94=20=EB=A6=AC=ED=84=B4=EA=B0=92=20=EC=B6=94=EA=B0=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 나의 인증 / 모두의 인증 분리 --- .../service/MissionArchiveBoardUseCase.java | 2 +- .../dto/res/MissionArchiveRes.java | 5 +--- .../application/dto/res/PersonalArchive.java | 2 +- .../mapper/MissionArchiveMapper.java | 2 ++ .../SingleMissionArchiveReadUseCase.java | 28 ++++++++----------- .../domain/entity/MissionArchive.java | 5 ++++ .../MissionArchiveCustomRepositoryImpl.java | 3 +- .../service/MissionArchiveQueryService.java | 2 +- .../MissionArchiveController.java | 2 +- 9 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java index 47c1b990..3e463af4 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java @@ -40,7 +40,7 @@ public List getActiveSingleMissions(Long teamId, String m Team team = teamRepository.findById(teamId).orElseThrow(); Member member = memberGetService.getMemberBySocialId(memberId); - // 인증상태 가져올 미션 배열 + // 인증 상태 가져올 미션들 List missionIds = new ArrayList<>(); team.getMissions().forEach(mission -> missionIds.add(mission.getId())); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index 6cf5dab5..2d25f016 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -15,9 +15,6 @@ public class MissionArchiveRes { private String createdDate; - private List donePersonalArchives; + private int hearts; - public void setPersonalArchives(List done) { - this.donePersonalArchives = done; - } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java index 05adaaaa..2ddaf9bd 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java @@ -15,6 +15,6 @@ public class PersonalArchive { private String archive; private String createdDate; - private int likes; + private int hearts; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 7e85e863..4ba38ac0 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -31,6 +31,7 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc return MissionArchiveRes.builder() .archive(missionArchive.getArchive()) .createdDate(missionArchive.getCreatedDate().toString()) + .hearts(missionArchive.getHearts()) .build(); } @@ -42,6 +43,7 @@ public static PersonalArchive mapToPersonalArchive(MissionArchive missionArchive .profileImg(member.getProfileImage()) .archive(missionArchive.getArchive()) .createdDate(missionArchive.getCreatedDate().toString()) + .hearts(missionArchive.getHearts()) .build(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java index c0f9b751..d7954993 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java @@ -31,32 +31,28 @@ public class SingleMissionArchiveReadUseCase { // 미션 인증 조회 public List getMyArchive(String userSocialId, Long missionId) { - List myArchives = getArchive(userSocialId, missionId); List archiveRes = new ArrayList<>(); - myArchives.forEach(myArchive -> archiveRes.add(MissionArchiveMapper.mapToMissionArchiveRes(myArchive))); - return archiveRes; - } - - // 모임원 미션 인증 목록 조회 - public List getPersonalArchive(String userSocialId, Long missionId) { + Member member = memberGetService.getMemberBySocialId(userSocialId); Mission mission = missionQueryService.findMissionById(missionId); - List done = new ArrayList<>(); - - mission.getMissionArchiveList() - .forEach(missionArchive1 -> done.add(mapToPersonalArchive(missionArchive1))); + missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId) + .forEach(myArchive -> archiveRes.add(MissionArchiveMapper.mapToMissionArchiveRes(myArchive))); - return done; + return archiveRes; } - // memberId, missionId로 archive 꺼내기 - public List getArchive(String userSocialId, Long missionId) { - Member member = memberGetService.getMemberBySocialId(userSocialId); + // 모두의 미션 인증 목록 조회 + public List getPersonalArchive(Long missionId) { + + List personalArchives = new ArrayList<>(); + Mission mission = missionQueryService.findMissionById(missionId); + mission.getMissionArchiveList() + .forEach(missionArchive1 -> personalArchives.add(mapToPersonalArchive(missionArchive1))); - return missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId); + return personalArchives; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index 981d54a2..da073d61 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -36,6 +36,11 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 @Column(nullable = false) private String archive; //링크, 글, 사진 뭐든 가능 + private int hearts; + public int addHearts() { + return this.hearts++; + } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 72852954..88ded843 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -34,6 +34,7 @@ public Optional> findSingleMissionArchivesByMemberId(Long m .select(missionArchive) .from(missionArchive) .where( + missionArchive.mission.status.eq(MissionStatus.ONGOING), missionArchive.mission.id.in(missionIds), missionArchive.mission.status.eq(MissionStatus.valueOf(status)), missionArchive.status.eq(MissionArchiveStatus.valueOf(archiveStatus)) @@ -50,7 +51,7 @@ private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { if(orderCondition.equals(OrderCondition.DUETO)){ orderSpecifiers.add(new OrderSpecifier(Order.DESC, missionArchive.mission.dueTo)); }else if(orderCondition.equals(OrderCondition.CREATED)){ - orderSpecifiers.add(new OrderSpecifier(Order.DESC, missionArchive.createdDate)); + orderSpecifiers.add(new OrderSpecifier(Order.ASC, missionArchive.createdDate)); } return orderSpecifiers.toArray(new OrderSpecifier[orderSpecifiers.size()]); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index d9799c76..7c3c846a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -27,7 +27,7 @@ public class MissionArchiveQueryService { private final MissionRepository missionRepository; private final MissionArchiveRepository missionArchiveRepository; - private final MissionArchiveCustomRepository missionArchiveCustomRepository + private final MissionArchiveCustomRepository missionArchiveCustomRepository; public List findMyArchive(Long memberId, Long missionId) { return missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId).orElseThrow(); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 0d8b824c..ad3f0ae3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -79,7 +79,7 @@ public ResponseEntity>> getOtherPeopleArch @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId, @RequestBody MissionArchiveReq missionArchiveReq) { - return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(user.getSocialId(), missionId))); + return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(missionId))); } } \ No newline at end of file From 8dd14a158b18bcaf5a889587ca61051f4325b620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Sep 2023 02:56:30 +0900 Subject: [PATCH 083/619] =?UTF-8?q?entity=20:=20MissionArchive=EC=97=90=20?= =?UTF-8?q?hearts=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 나의 인증 / 모두의 인증 좋아요 기능 추가 --- .../dto/req/MissionArchiveHeartReq.java | 13 ++++++ .../dto/res/MissionArchiveHeartRes.java | 16 +++++++ .../dto/res/MissionArchiveRes.java | 1 + .../dto/res/MissionArchiveResImg.java | 5 --- .../application/dto/res/PersonalArchive.java | 1 + .../mapper/MissionArchiveMapper.java | 11 +++++ .../service/MissionArchiveHeartUseCase.java | 44 +++++++++++++++++++ .../MissionArchiveResponseMessage.java | 7 +-- .../domain/entity/MissionArchive.java | 8 +++- .../service/MissionArchiveQueryService.java | 6 ++- .../MissionArchiveController.java | 14 ++++++ 11 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveHeartReq.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveHeartRes.java delete mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveResImg.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveHeartUseCase.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveHeartReq.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveHeartReq.java new file mode 100644 index 00000000..48ec9458 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveHeartReq.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.missionArchive.application.dto.req; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MissionArchiveHeartReq { + private Long archiveId; + private String heartStatus; +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveHeartRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveHeartRes.java new file mode 100644 index 00000000..97314466 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveHeartRes.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.missionArchive.application.dto.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class MissionArchiveHeartRes { + private Long archiveId; + private String heartStatus; + private int hearts; +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index 2d25f016..4d55a194 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -11,6 +11,7 @@ @Setter public class MissionArchiveRes { + private Long archiveId; private String archive; private String createdDate; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveResImg.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveResImg.java deleted file mode 100644 index fa1de2b2..00000000 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveResImg.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.moing.backend.domain.missionArchive.application.dto.res; - -public class MissionArchiveResImg { - private String s3URL; -} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java index 2ddaf9bd..a71f239d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java @@ -9,6 +9,7 @@ @Builder public class PersonalArchive { + private Long archiveId; private String nickname; private String profileImg; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 4ba38ac0..85a37b96 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; @@ -29,6 +30,7 @@ public static MissionArchive mapToMissionArchive(MissionArchiveReq missionArchiv public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArchive) { return MissionArchiveRes.builder() + .archiveId(missionArchive.getId()) .archive(missionArchive.getArchive()) .createdDate(missionArchive.getCreatedDate().toString()) .hearts(missionArchive.getHearts()) @@ -39,6 +41,7 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc public static PersonalArchive mapToPersonalArchive(MissionArchive missionArchive) { Member member = missionArchive.getMember(); return PersonalArchive.builder() + .archiveId(missionArchive.getId()) .nickname(member.getNickName()) .profileImg(member.getProfileImage()) .archive(missionArchive.getArchive()) @@ -70,6 +73,14 @@ public static List mapToSingleMissionBoardResList( List findMyArchive(Long memberId, Long missionId) { - return missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId).orElseThrow(); + return missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId).orElseThrow(NotFoundMissionArchiveException::new); } public MissionArchive findByMemberId(Long memberId) { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index ad3f0ae3..ec43556f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -1,9 +1,12 @@ package com.moing.backend.domain.missionArchive.presentation; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveHeartReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateUseCase; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveHeartUseCase; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveUpdateUseCase; import com.moing.backend.domain.missionArchive.application.service.SingleMissionArchiveReadUseCase; import com.moing.backend.global.config.security.dto.User; @@ -26,6 +29,7 @@ public class MissionArchiveController { private final MissionArchiveCreateUseCase missionArchiveCreateUseCase; private final MissionArchiveUpdateUseCase missionArchiveUpdateUseCase; private final SingleMissionArchiveReadUseCase singleMissionArchiveReadUseCase; + private final MissionArchiveHeartUseCase missionArchiveHeartUseCase; /** * 미션 인증 하기 @@ -82,4 +86,14 @@ public ResponseEntity>> getOtherPeopleArch return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(missionId))); } + @PostMapping("/hearts") + public ResponseEntity> pushHeart(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId, + @RequestBody MissionArchiveHeartReq missionArchiveHeartReq) { + return ResponseEntity.ok(SuccessResponse.create(HEART_UPDATE_SUCCESS.getMessage(), this.missionArchiveHeartUseCase.pushHeart(missionArchiveHeartReq))); + } + + + } \ No newline at end of file From 7a0423afdda3267ff51e451db152f478849f3e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 21 Sep 2023 00:27:13 +0900 Subject: [PATCH 084/619] =?UTF-8?q?fix=20:=20missionArchiveController=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=98=A4=EB=A5=98=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/service/MissionQueryService.java | 3 ++- .../exception/NotFoundMissionException.java | 4 ++-- .../presentation/MissionController.java | 9 ------- .../mapper/MissionArchiveMapper.java | 8 +++++++ .../service/MissionArchiveCreateUseCase.java | 2 ++ .../service/MissionArchiveUpdateUseCase.java | 9 +++++-- .../SingleMissionArchiveReadUseCase.java | 15 ++++++------ .../domain/entity/MissionArchive.java | 5 ++++ .../MissionArchiveCustomRepository.java | 3 ++- .../MissionArchiveCustomRepositoryImpl.java | 20 ++++++++++++++++ .../repository/MissionArchiveRepository.java | 22 +++++++---------- .../service/MissionArchiveQueryService.java | 24 ++++++++++++++----- .../NotFoundMissionArchiveException.java | 4 ++-- .../MissionArchiveController.java | 4 ++-- .../backend/global/response/ErrorCode.java | 6 +++-- 15 files changed, 89 insertions(+), 49 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index e8529a4f..1a591022 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.mission.domain.service; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.exception.NotFoundMissionException; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; @@ -14,6 +15,6 @@ public class MissionQueryService { private final MissionRepository missionRepository; public Mission findMissionById(Long missionId) { - return missionRepository.findById(missionId).orElseThrow(); + return missionRepository.findById(missionId).orElseThrow(NotFoundMissionException::new); } } diff --git a/src/main/java/com/moing/backend/domain/mission/exception/NotFoundMissionException.java b/src/main/java/com/moing/backend/domain/mission/exception/NotFoundMissionException.java index 188dc560..7e67495f 100644 --- a/src/main/java/com/moing/backend/domain/mission/exception/NotFoundMissionException.java +++ b/src/main/java/com/moing/backend/domain/mission/exception/NotFoundMissionException.java @@ -7,7 +7,7 @@ public class NotFoundMissionException extends MissionException { public NotFoundMissionException() { - super(ErrorCode.TOKEN_INVALID_ERROR, - HttpStatus.BAD_REQUEST); + super(ErrorCode.NOT_FOUND_MISSION, + HttpStatus.NOT_FOUND); } } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 4c235f14..f458207b 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -40,16 +40,7 @@ public ResponseEntity> getMission(@Authenticatio return ResponseEntity.ok(SuccessResponse.create(READ_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getMission(user.getSocialId(),missionId))); } - /** - * 미션 리스트 조회 - * [GET] {teamId}/mission/{missionId} - * 작성자 : 정승연 - */ -// @GetMapping() -// public ResponseEntity> getMissionList(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId) { -// return ResponseEntity.ok(SuccessResponse.create(READ_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getMission(user.getSocialId(),teamId))); -// } /** * 미션 생성 diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 85a37b96..89b5d56e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -50,6 +50,14 @@ public static PersonalArchive mapToPersonalArchive(MissionArchive missionArchive .build(); } + public static List mapToPersonalArchiveList(List missionArchiveList) { + List personalArchiveList = new ArrayList<>(); + missionArchiveList.forEach( + missionArchive -> personalArchiveList.add(MissionArchiveMapper.mapToPersonalArchive(missionArchive)) + ); + return personalArchiveList; + } + public static SingleMissionBoardRes mapToSingleMissionBoardRes(MissionArchive missionArchive) { Member member = missionArchive.getMember(); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index b768198a..e13eb48b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -48,6 +48,8 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss Member member = memberGetService.getMemberBySocialId(userSocialId); Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); + + // missionArchive 2개 이상일 때 예외처리 필요 MissionArchive missionArchive = missionArchiveSaveService.save(MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission)); if (isDoneSingleMission(mission)) { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index adb6dca4..de8fa6ae 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -19,6 +19,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Service @Transactional @RequiredArgsConstructor @@ -35,7 +37,7 @@ public class MissionArchiveUpdateUseCase { private final IssuePresignedUrlUseCase getPresignedUrlUseCase; - // 미션 인증 및 재인증 (수정하기도 포함됨) + // 미션 재인증 (수정하기도 포함됨) public MissionArchiveRes updateArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); @@ -48,7 +50,10 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss } - MissionArchive missionArchive = missionArchiveSaveService.save(MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission)); + MissionArchive missionArchive = missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId).get(0); + + missionArchive.updateArchive(missionReq); + return MissionArchiveMapper.mapToMissionArchiveRes(missionArchive); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java index d7954993..695226c4 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java @@ -9,6 +9,7 @@ import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -30,27 +31,25 @@ public class SingleMissionArchiveReadUseCase { // 미션 인증 조회 - public List getMyArchive(String userSocialId, Long missionId) { + public MissionArchiveRes getMyArchive(String userSocialId, Long missionId) { List archiveRes = new ArrayList<>(); Member member = memberGetService.getMemberBySocialId(userSocialId); Mission mission = missionQueryService.findMissionById(missionId); - missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId) - .forEach(myArchive -> archiveRes.add(MissionArchiveMapper.mapToMissionArchiveRes(myArchive))); - - return archiveRes; + return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId).get(0)); } // 모두의 미션 인증 목록 조회 - public List getPersonalArchive(Long missionId) { + public List getPersonalArchive(String userSocialId,Long missionId) { List personalArchives = new ArrayList<>(); + Member member = memberGetService.getMemberBySocialId(userSocialId); Mission mission = missionQueryService.findMissionById(missionId); - mission.getMissionArchiveList() - .forEach(missionArchive1 -> personalArchives.add(mapToPersonalArchive(missionArchive1))); + + MissionArchiveMapper.mapToPersonalArchiveList(missionArchiveQueryService.findOthersArchive(member.getMemberId(), missionId)); return personalArchives; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index 1ff741b7..f54f4d5c 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; import lombok.Builder; @@ -39,6 +40,10 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 private int hearts; + public void updateArchive(MissionArchiveReq missionArchiveReq) { + this.archive = missionArchiveReq.getArchive(); + this.status = MissionArchiveStatus.valueOf(missionArchiveReq.getStatus()); + } public int updateHearts(Boolean status) { if(status) return this.hearts += 1; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 1a4b433a..0260ccda 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -2,11 +2,12 @@ import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.teamMember.domain.repository.OrderCondition; +import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; - public interface MissionArchiveCustomRepository { public Optional> findSingleMissionArchivesByMemberId(Long memberId, List missionIds, String status, String archiveStatus, OrderCondition orderCondition); + public Optional> findOthersArchives(Long memberId, Long missionId) ; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 88ded843..8c726617 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -11,6 +11,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import feign.Param; import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; import javax.persistence.EntityManager; import java.util.ArrayList; @@ -21,6 +22,7 @@ import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { + private final JPAQueryFactory queryFactory; public MissionArchiveCustomRepositoryImpl(EntityManager em) { @@ -57,4 +59,22 @@ private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { } +// @Query("select m from MissionArchive as m where m.mission.id = :missionId and m.member.memberId =:memberId") +// Optional> findArchivesByMissionIdAndMemberId(@Param("memberId") Long memberId, @Param("missionId")Long missionId); + + @Override + public Optional> findOthersArchives(Long memberId, Long missionId) { + + return Optional.ofNullable(queryFactory + .select(missionArchive) + .from(missionArchive) + .where( + missionArchive.mission.id.eq(missionId), + missionArchive.member.memberId.ne(memberId) + ) + .fetch() + ); + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java index 3a453fe6..10a90ee7 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -11,24 +11,18 @@ import java.util.List; import java.util.Optional; -public interface MissionArchiveRepository extends JpaRepository { +public interface MissionArchiveRepository extends JpaRepository,MissionArchiveCustomRepository { @Query("select m from MissionArchive as m where m.member =:memberId" ) - Optional findByMemberId(@Param("memberId") Long memberId); + Optional> findByMemberId(@Param("memberId") Long memberId); @Query("select m from MissionArchive as m where m.mission.id = :missionId and m.member.memberId =:memberId") - Optional> findByMissionIdAndMemberId(@Param("memberId") Long memberId, @Param("missionId")Long missionId); - - - @Query("select m from MissionArchive as m " + - "where m.mission.id IN :missionIds " + - "and m.member.memberId =:memberId " + - "and m.mission.status =:status " + - "and m.status =:archiveStatus" ) - Optional> findSingleMissionArchivesByMemberId (@Param("memberId") Long memberId, - @Param("missionIds") List missionIds, - @Param("status")String status, - @Param("archiveStatus")String archiveStatus); + Optional> findArchivesByMissionIdAndMemberId(@Param("memberId") Long memberId, @Param("missionId")Long missionId); + + @Query("select m from MissionArchive as m where m.mission.id = :missionId and m.member.memberId =:memberId") + Optional findByMissionIdAndMemberId(@Param("memberId") Long memberId, @Param("missionId")Long missionId); + + @Query("select m from MissionArchive as m where m.mission.id IN :missionIds and m.member.memberId =:memberId") Optional> findRepeatMissionArchivesByMission (@Param("memberId") Long memberId, @Param("missionIds") List missionIds); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 0d6c0f40..69b449cb 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveCustomRepository; import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; import com.moing.backend.domain.missionArchive.exception.NotFoundMissionArchiveException; +import com.moing.backend.domain.missionArchive.exception.NotFoundMissionArchiveException; import com.moing.backend.domain.teamMember.domain.repository.OrderCondition; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; @@ -27,22 +28,33 @@ public class MissionArchiveQueryService { private final MissionRepository missionRepository; private final MissionArchiveRepository missionArchiveRepository; - private final MissionArchiveCustomRepository missionArchiveCustomRepository; public MissionArchive findByMissionArchiveId(Long missionArchiveId) { return missionArchiveRepository.findById(missionArchiveId).orElseThrow(NotFoundMissionArchiveException::new); } - public List findMyArchive(Long memberId, Long missionId) { + public MissionArchive findArchive(Long memberId, Long missionId) { return missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId).orElseThrow(NotFoundMissionArchiveException::new); } + public List findMyArchive(Long memberId, Long missionId) { + + Optional> optional = missionArchiveRepository.findArchivesByMissionIdAndMemberId(memberId, missionId); + if (optional.isPresent() && optional.get().size() == 0) { + throw new NotFoundMissionArchiveException(); + } else { + return optional.get(); + } + } + public List findOthersArchive(Long memberId, Long missionId) { + return missionArchiveRepository.findOthersArchives(memberId, missionId).orElseThrow(NotFoundMissionArchiveException::new); + } - public MissionArchive findByMemberId(Long memberId) { + public List findArchivesByMemberId(Long memberId) { return missionArchiveRepository.findByMemberId(memberId).orElseThrow(NotFoundMissionArchiveException::new); } public Boolean isDone(Long memberId, Long missionId) { - Optional> byMemberId = missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId); + Optional> byMemberId = missionArchiveRepository.findArchivesByMissionIdAndMemberId(memberId, missionId); if (byMemberId.isPresent()) { return Boolean.TRUE; } @@ -58,10 +70,10 @@ public Boolean isDone(Long memberId, Long missionId) { */ public List findMySingleMissionArchives(Long memberId, List missionIds, MissionStatus missionStatus) { // INCOMPLETE - List incompleteList = missionArchiveCustomRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), INCOMPLETE.name(), OrderCondition.DUETO) + List incompleteList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), INCOMPLETE.name(), OrderCondition.DUETO) .orElseThrow(NotFoundMissionArchiveException::new); - List completeList = missionArchiveCustomRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), COMPLETE.name(),OrderCondition.CREATED) + List completeList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), COMPLETE.name(),OrderCondition.CREATED) .orElseThrow(NotFoundMissionArchiveException::new); incompleteList.addAll(completeList); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java b/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java index 007aa0d5..db258781 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java @@ -6,7 +6,7 @@ public class NotFoundMissionArchiveException extends MissionArchiveException { public NotFoundMissionArchiveException() { - super(ErrorCode.TOKEN_INVALID_ERROR, - HttpStatus.BAD_REQUEST); + super(ErrorCode.NOT_FOUND_MISSION, + HttpStatus.NOT_FOUND); } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index ec43556f..2ada4d2b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -66,7 +66,7 @@ public ResponseEntity> updateArchive(@Authent */ @GetMapping() - public ResponseEntity>> getMyArchives(@AuthenticationPrincipal User user, + public ResponseEntity> getMyArchive(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId, @RequestBody MissionArchiveReq missionArchiveReq) { @@ -83,7 +83,7 @@ public ResponseEntity>> getOtherPeopleArch @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId, @RequestBody MissionArchiveReq missionArchiveReq) { - return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(missionId))); + return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(user.getSocialId(),missionId))); } @PostMapping("/hearts") diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 9f546aef..a5d75331 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -23,8 +23,10 @@ public enum ErrorCode { //팀멤버 에러 코드 TOO_MANY_TEAM_MEMBER_ERROR("TM0001", "팀 최대 개수 3을 초과했습니다"), - //미션 생성 에러코드 - NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."); + //미션 관련 에러코드 + NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), + NOT_FOUND_MISSION("M0002", "미션을 찾을 수 없습니다."), + NOT_FOUND_MISSION_ARCHIVE("MA0001", "아직 미션을 제출하지 않았습니다."); private String errorCode; From fd0ddf51201a61ddabcbe2cbb3b9678c9d8eecc1 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Thu, 21 Sep 2023 01:06:45 +0900 Subject: [PATCH 085/619] =?UTF-8?q?=EC=86=8C=EB=AA=A8=EC=9E=84=20=EA=B0=95?= =?UTF-8?q?=EC=A0=9C=EC=A2=85=EB=A3=8C=20=EB=B0=8F=20=ED=83=88=ED=87=B4=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Team-API.adoc | 8 ++ .../application/dto/request/TestRequest.java | 15 ++++ .../application/service/SignInUserCase.java | 17 +++++ .../auth/presentation/AuthController.java | 11 +++ .../domain/member/domain/entity/Member.java | 16 +++- .../service/CheckLeaderUserCase.java | 21 ++++++ .../service/DisbandTeamUserCase.java | 22 +++++- .../application/service/GetTeamUserCase.java | 2 +- .../service/WithdrawTeamUserCase.java | 31 ++++++++ .../repository/TeamCustomRepository.java | 4 + .../repository/TeamCustomRepositoryImpl.java | 10 +++ .../domain/repository/TeamRepository.java | 2 + .../team/domain/service/TeamGetService.java | 10 ++- .../team/exception/NotAuthException.java | 11 +++ .../exception/NotFoundByTeamIdException.java | 11 +++ .../domain/team/exception/TeamException.java | 11 +++ .../team/presentation/TeamController.java | 17 ++++- .../constant/TeamResponseMessage.java | 3 +- .../teamMember/domain/entity/TeamMember.java | 18 ++--- .../TeamMemberCustomRepository.java | 2 +- .../TeamMemberCustomRepositoryImpl.java | 2 +- .../repository/TeamMemberRepository.java | 7 ++ .../domain/service/TeamMemberGetService.java | 9 ++- .../exception/TooManyTeamMemberException.java | 11 --- .../config/security/SecurityConfig.java | 6 +- .../backend/global/response/ErrorCode.java | 5 +- .../backend/global/util/StartupRunner.java | 33 +++++++++ .../team/presentation/TeamControllerTest.java | 73 +++++++++++++++++++ 28 files changed, 352 insertions(+), 36 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/auth/application/dto/request/TestRequest.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/team/exception/NotAuthException.java create mode 100644 src/main/java/com/moing/backend/domain/team/exception/NotFoundByTeamIdException.java create mode 100644 src/main/java/com/moing/backend/domain/team/exception/TeamException.java delete mode 100644 src/main/java/com/moing/backend/domain/teamMember/exception/TooManyTeamMemberException.java create mode 100644 src/main/java/com/moing/backend/global/util/StartupRunner.java diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc index 83ee6609..d6ff94ba 100644 --- a/src/docs/asciidoc/Team-API.adoc +++ b/src/docs/asciidoc/Team-API.adoc @@ -31,3 +31,11 @@ operation::team-controller-test/create_team[snippets='http-request,request-field [[Team-소모임-조회]] === Team 소모임 조회 operation::team-controller-test/get_team[snippets='http-request,http-response,response-fields'] + +[[Team-소모임-강제종료]] +=== Team 소모임 강제종료 +operation::team-controller-test/disband_team[snippets='http-request,http-response,response-fields'] + +[[Team-소모임-탈퇴]] +=== Team 소모임원 강제종료 +operation::team-controller-test/withdraw_team[snippets='http-request,http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/TestRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/TestRequest.java new file mode 100644 index 00000000..7bb94c4e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/TestRequest.java @@ -0,0 +1,15 @@ +package com.moing.backend.domain.auth.application.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class TestRequest { + private String socialId; + +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java index 5b001b27..290968d0 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.auth.application.dto.response.SignInResponse; import com.moing.backend.domain.member.domain.constant.RegistrationStatus; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.global.config.security.jwt.TokenUtil; import com.moing.backend.global.config.security.util.AuthenticationUtil; import com.moing.backend.global.response.TokenInfoResponse; @@ -20,6 +21,7 @@ public class SignInUserCase { private final MemberAuthUserCase internalAuthService; private final TokenUtil tokenUtil; private final Map signInProviders; + private final MemberGetService memberGetService; public SignInResponse signIn(String token, String providerInfo) { //1. 사용자 정보 가져오기 @@ -43,4 +45,19 @@ private Member getUserDataFromPlatform(String accessToken, String providerInfo) } return signInProvider.getUserData(accessToken); } + + public SignInResponse testSignIn(String socialId, String providerInfo) { + //1. 사용자 정보 가져오기 + Member member = memberGetService.getMemberBySocialId(socialId); + //2. 로그인 + Member authenticatedMember = internalAuthService.auth(member, providerInfo); + //3. security 처리 + AuthenticationUtil.makeAuthentication(authenticatedMember); + //4. token 만들기 + TokenInfoResponse tokenResponse = tokenUtil.createToken(authenticatedMember, authenticatedMember.getRegistrationStatus().equals(RegistrationStatus.COMPLETED)); + //5. refresh token 저장 + tokenUtil.storeRefreshToken(authenticatedMember.getSocialId(), tokenResponse); + + return SignInResponse.from(tokenResponse, authenticatedMember.getRegistrationStatus()); + } } diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java index bd80611c..e82a8d0f 100644 --- a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.auth.application.dto.request.SignInRequest; import com.moing.backend.domain.auth.application.dto.request.SignUpRequest; +import com.moing.backend.domain.auth.application.dto.request.TestRequest; import com.moing.backend.domain.auth.application.dto.response.CheckNicknameResponse; import com.moing.backend.domain.auth.application.dto.response.ReissueTokenResponse; import com.moing.backend.domain.auth.application.dto.response.SignInResponse; @@ -81,4 +82,14 @@ public ResponseEntity> checkNickname(@Pat return ResponseEntity.ok(SuccessResponse.create(CHECK_NICKNAME_SUCCESS.getMessage(), checkNicknameService.checkNickname(nickname))); } + /** + * 테스트 계정 로그인 (토큰 만드는 컨트롤러) + * [POST] api/auth/test + * 작성자: 김민수 + */ + @PostMapping("/test/{provider}") + public ResponseEntity> testLogin(@PathVariable String provider, + @RequestBody TestRequest testRequest){ + return ResponseEntity.ok(SuccessResponse.create(SIGN_IN_SUCCESS.getMessage(), this.authService.testSignIn(testRequest.getSocialId(),provider))); + } } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index 28c1bde2..465f4a4f 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -56,7 +56,7 @@ public class Member extends BaseTimeEntity { // 추가정보 @Convert(converter = AesConverter.class) - @Column(nullable = false, unique = true) + @Column(nullable = false) private String nickName; //없으면 undef @Column(nullable = false) @@ -154,4 +154,18 @@ public void updateAllPush(boolean allPush) { this.isFirePush = allPush; } + public Member(String ageRange, String email, String fcmToken, String gender, String introduction, String nickName, String profileImage, SocialProvider provider, RegistrationStatus registrationStatus, Role role, String socialId) { + this.ageRange = ageRange; + this.email = email; + this.fcmToken = fcmToken; + this.gender = gender; + this.introduction = introduction; + this.nickName = nickName; + this.profileImage = profileImage; + this.provider = provider; + this.registrationStatus = registrationStatus; + this.role = role; + this.socialId = socialId; + } + } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java new file mode 100644 index 00000000..616b0d31 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java @@ -0,0 +1,21 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class CheckLeaderUserCase { + public boolean isTeamLeader(Member member, Team team) { + if (member.getMemberId() == team.getLeaderId()) { + return true; + } else { + return false; + } + } +} diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java index 5045bc93..3efa23fe 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java @@ -1,6 +1,11 @@ package com.moing.backend.domain.team.application.service; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.team.exception.NotAuthException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -11,9 +16,18 @@ @RequiredArgsConstructor public class DisbandTeamUserCase { - public DeleteTeamResponse disbandTeam(String socialId, Long teamId){ - // 1. 소모임장인지 확인 -> 아니면 오류 - // 2. 소모임 강제 종료 - return null; + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final CheckLeaderUserCase checkLeaderUserCase; + + public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + if (checkLeaderUserCase.isTeamLeader(member, team)) { + team.deleteTeam(); + } else { + throw new NotAuthException(); + } + return new DeleteTeamResponse(team.getTeamId()); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java index 383a7f8e..56ba881a 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java @@ -18,6 +18,6 @@ public class GetTeamUserCase { public GetTeamResponse getTeam(String socialId) { Member member = memberGetService.getMemberBySocialId(socialId); - return teamGetService.getTeam(member); + return teamGetService.getTeamByMember(member); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java new file mode 100644 index 00000000..60c15d3c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java @@ -0,0 +1,31 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class WithdrawTeamUserCase { + + private final TeamMemberGetService teamMemberGetService; + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + + public DeleteTeamResponse withdrawTeam(String socialId, Long teamId) { + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + teamMember.withdrawTeam(); + return new DeleteTeamResponse(team.getTeamId()); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index cf1e1985..faabee4c 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -1,7 +1,11 @@ package com.moing.backend.domain.team.domain.repository; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.team.domain.entity.Team; + +import java.util.Optional; public interface TeamCustomRepository { GetTeamResponse findTeamByMemberId(Long memberId); + Optional findTeamByTeamId(Long TeamId); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index b3718742..715dfee4 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -4,10 +4,12 @@ import com.moing.backend.domain.team.application.dto.response.QTeamBlock; import com.moing.backend.domain.team.application.dto.response.TeamBlock; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; +import com.moing.backend.domain.team.domain.entity.Team; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; import java.util.List; +import java.util.Optional; import static com.moing.backend.domain.team.domain.entity.QTeam.team; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; @@ -27,6 +29,14 @@ public GetTeamResponse findTeamByMemberId(Long memberId) { return new GetTeamResponse(numOfTeam, teamBlocks); } + @Override + public Optional findTeamByTeamId(Long teamId) { + return Optional.ofNullable(queryFactory.selectFrom(team) + .where(team.teamId.eq(teamId)) + .where(team.isDeleted.eq(false)) + .fetchOne()); + } + private List getTeamBlock(Long memberId) { return queryFactory .select(new QTeamBlock(team.teamId, diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamRepository.java index 46d64c1b..709ad833 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamRepository.java @@ -3,5 +3,7 @@ import com.moing.backend.domain.team.domain.entity.Team; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface TeamRepository extends JpaRepository, TeamCustomRepository { } diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index d04fbdad..4afea33b 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -2,18 +2,26 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.repository.TeamRepository; +import com.moing.backend.domain.team.exception.NotFoundByTeamIdException; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; +import java.util.Optional; + @DomainService @RequiredArgsConstructor public class TeamGetService { private final TeamRepository teamRepository; - public GetTeamResponse getTeam(Member member) { + public GetTeamResponse getTeamByMember(Member member) { GetTeamResponse getTeamResponse = teamRepository.findTeamByMemberId(member.getMemberId()); getTeamResponse.updateMemberNickName(member.getNickName()); return getTeamResponse; } + + public Team getTeamByTeamId(Long teamId){ + return teamRepository.findTeamByTeamId(teamId).orElseThrow(()->new NotFoundByTeamIdException()); + } } diff --git a/src/main/java/com/moing/backend/domain/team/exception/NotAuthException.java b/src/main/java/com/moing/backend/domain/team/exception/NotAuthException.java new file mode 100644 index 00000000..14e66aef --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/exception/NotAuthException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.team.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotAuthException extends TeamException{ + public NotAuthException(){ + super(ErrorCode.NOT_AUTH_BY_TEAM_ERROR, + HttpStatus.UNAUTHORIZED); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/exception/NotFoundByTeamIdException.java b/src/main/java/com/moing/backend/domain/team/exception/NotFoundByTeamIdException.java new file mode 100644 index 00000000..cdedc03f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/exception/NotFoundByTeamIdException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.team.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundByTeamIdException extends TeamException{ + public NotFoundByTeamIdException(){ + super(ErrorCode.NOT_FOUND_BY_TEAM_ID_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/exception/TeamException.java b/src/main/java/com/moing/backend/domain/team/exception/TeamException.java new file mode 100644 index 00000000..e7b8006e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/exception/TeamException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.team.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class TeamException extends ApplicationException { + protected TeamException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index 72d09626..3ac3452a 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -7,9 +7,11 @@ import com.moing.backend.domain.team.application.service.CreateTeamUserCase; import com.moing.backend.domain.team.application.service.DisbandTeamUserCase; import com.moing.backend.domain.team.application.service.GetTeamUserCase; +import com.moing.backend.domain.team.application.service.WithdrawTeamUserCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; +import org.checkerframework.checker.units.qual.A; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; @@ -25,6 +27,7 @@ public class TeamController { private final CreateTeamUserCase createTeamService; private final GetTeamUserCase getTeamUserCase; private final DisbandTeamUserCase disbandTeamUserCase; + private final WithdrawTeamUserCase withdrawTeamUserCase; /** * 소모임 생성 (only 개설만) @@ -48,7 +51,7 @@ public ResponseEntity> getTeam(@AuthenticationP } /** - * 소모임 강제 종료 (소모임 권한) + * 소모임 강제 종료 (소모임장 권한) * [DELETE] api/team/{teamId}/disband * 작성자:김민수 */ @@ -57,4 +60,16 @@ public ResponseEntity> disbandTeam(@Authenti @PathVariable Long teamId){ return ResponseEntity.ok(SuccessResponse.create(DISBAND_TEAM_SUCCESS.getMessage(), this.disbandTeamUserCase.disbandTeam(user.getSocialId(), teamId))); } + + /** + * 소모임 탈퇴 (소모임원) + * [DELETE] api/team/{teamId}/withdraw + * 작성자: 김민수 + */ + @DeleteMapping("/{teamId}/withdraw") + public ResponseEntity> withdrawTeam(@AuthenticationPrincipal User user, + @PathVariable Long teamId){ + return ResponseEntity.ok(SuccessResponse.create(WITHDRAW_TEAM_SUCCESS.getMessage(), this.withdrawTeamUserCase.withdrawTeam(user.getSocialId(),teamId))); + } + } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 9dfff563..3e1ad7ef 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -8,6 +8,7 @@ public enum TeamResponseMessage { CREATE_TEAM_SUCCESS("소모임을 생성하였습니다"), GET_TEAM_SUCCESS("홈 화면에서 내 소모임을 모두 조회했습니다."), - DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."); + DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."), + WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"); private final String message; } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java index 64bdfb9f..1acc968a 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java @@ -2,7 +2,6 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.teamMember.exception.TooManyTeamMemberException; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; import lombok.Builder; @@ -34,17 +33,16 @@ public class TeamMember extends BaseTimeEntity { private boolean isDeleted; //소모임 삭제여부, 마이페이지에서는 상관 없이 모두 조회 //==연관관계 메서드 ==// - public void updateTeam(Team team){ - this.team=team; + public void updateTeam(Team team) { + this.team = team; } - public void updateMember(Member member){ - if(member.getTeamMembers().size()<3) { - this.member = member; - member.getTeamMembers().add(this); - }else{ - throw new TooManyTeamMemberException(); - } + public void updateMember(Member member) { + this.member = member; + member.getTeamMembers().add(this); } + public void withdrawTeam() { + this.isDeleted = true; + } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index 25422e2b..4c7f0370 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -3,5 +3,5 @@ import java.util.List; public interface TeamMemberCustomRepository { - List getMemberIdsByTeamId(Long teamId); + List findMemberIdsByTeamId(Long teamId); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index 0e2e1854..880d3e73 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -16,7 +16,7 @@ public TeamMemberCustomRepositoryImpl(EntityManager em) { } @Override - public List getMemberIdsByTeamId(Long teamId) { + public List findMemberIdsByTeamId(Long teamId) { return queryFactory .select(teamMember.member.memberId) .from(teamMember) diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java index 77049443..703bb968 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java @@ -1,7 +1,14 @@ package com.moing.backend.domain.teamMember.domain.repository; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import org.springframework.data.jpa.repository.JpaRepository; +import javax.swing.text.html.Option; +import java.util.Optional; + public interface TeamMemberRepository extends JpaRepository, TeamMemberCustomRepository{ + + TeamMember findTeamMemberByTeamAndMember(Team team, Member member); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index b3cb6b31..f91866e0 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -1,5 +1,8 @@ package com.moing.backend.domain.teamMember.domain.service; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; @@ -12,6 +15,10 @@ public class TeamMemberGetService { private final TeamMemberRepository teamMemberRepository; public List getTeamMemberIds(Long teamId){ - return teamMemberRepository.getMemberIdsByTeamId(teamId); + return teamMemberRepository.findMemberIdsByTeamId(teamId); + } + + public TeamMember getTeamMember(Member member, Team team){ + return teamMemberRepository.findTeamMemberByTeamAndMember(team, member); } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/exception/TooManyTeamMemberException.java b/src/main/java/com/moing/backend/domain/teamMember/exception/TooManyTeamMemberException.java deleted file mode 100644 index d8047bc5..00000000 --- a/src/main/java/com/moing/backend/domain/teamMember/exception/TooManyTeamMemberException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.moing.backend.domain.teamMember.exception; - -import com.moing.backend.global.response.ErrorCode; -import org.springframework.http.HttpStatus; - -public class TooManyTeamMemberException extends TeamMemberException{ - public TooManyTeamMemberException(){ - super(ErrorCode.TOO_MANY_TEAM_MEMBER_ERROR, - HttpStatus.FORBIDDEN); - } -} diff --git a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java index 873811ae..93e8f902 100644 --- a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java +++ b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java @@ -29,7 +29,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(WebSecurity web) throws Exception { - web.ignoring().antMatchers("antMatchers/resource/**", "/css/**", "/js/**", "/img/**", "/lib/**"); + web.ignoring().antMatchers("/resource/**", "/css/**", "/js/**", "/img/**", "/lib/**"); } @@ -48,6 +48,10 @@ protected void configure(HttpSecurity http) throws Exception { .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //Spring Security에서 세션을 사용하지 않도록 설정 .and() .authorizeRequests() + .antMatchers("/swagger-resources/**").permitAll() + .antMatchers("/swagger-ui/**").permitAll() + .antMatchers("/webjars/**").permitAll() + .antMatchers("/v3/api-docs").permitAll() .antMatchers("/api/auth/**", "/docs/**", "/api/image/**").permitAll() .antMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 005893ff..f3992204 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -20,8 +20,9 @@ public enum ErrorCode { APPID_INVALID_ERROR("AU0003", "appId가 유효하지 않습니다"), NICKNAME_DUPLICATION_ERROR("AU0003", "닉네임이 중복됩니다."), - //팀멤버 에러 코드 - TOO_MANY_TEAM_MEMBER_ERROR("TM0001", "팀 최대 개수 3을 초과했습니다"); + //팀 관련 에러 코드 + NOT_FOUND_BY_TEAM_ID_ERROR("T0001", "해당 teamId인 팀이 존재하지 않습니다."), + NOT_AUTH_BY_TEAM_ERROR("T0002","권한이 없습니다."); private String errorCode; private String message; diff --git a/src/main/java/com/moing/backend/global/util/StartupRunner.java b/src/main/java/com/moing/backend/global/util/StartupRunner.java new file mode 100644 index 00000000..a04f7fca --- /dev/null +++ b/src/main/java/com/moing/backend/global/util/StartupRunner.java @@ -0,0 +1,33 @@ +package com.moing.backend.global.util; + +import com.moing.backend.domain.member.domain.constant.RegistrationStatus; +import com.moing.backend.domain.member.domain.constant.Role; +import com.moing.backend.domain.member.domain.constant.SocialProvider; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.member.domain.service.MemberSaveService; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class StartupRunner implements CommandLineRunner { + + /** + * 테스트용 insert + */ + + private final MemberSaveService memberSaveService; + @Override + public void run(String... args) throws Exception { + Member test01 = new Member("undef", "tester1@test.com", "undef", "undef", "undef", "modagbul_tester1", "undef", SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester01"); + memberSaveService.saveMember(test01); + + Member test02=new Member("undef", "tester2@test.com", "undef", "undef", "undef", "modagbul_tester2", "undef", SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester02"); + memberSaveService.saveMember(test02); + + Member test03=new Member("undef", "tester3@test.com", "undef", "undef", "undef", "modagbul_tester3", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester03"); + memberSaveService.saveMember(test03); + } +} diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 6d7c00a2..8ac0dfdb 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -3,11 +3,13 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; +import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.application.dto.response.TeamBlock; import com.moing.backend.domain.team.application.service.CreateTeamUserCase; import com.moing.backend.domain.team.application.service.DisbandTeamUserCase; import com.moing.backend.domain.team.application.service.GetTeamUserCase; +import com.moing.backend.domain.team.application.service.WithdrawTeamUserCase; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -35,6 +37,8 @@ public class TeamControllerTest extends CommonControllerTest { @MockBean private DisbandTeamUserCase disbandTeamUserCase; + @MockBean + private WithdrawTeamUserCase withdrawTeamUserCase; @Test public void create_team() throws Exception { @@ -159,4 +163,73 @@ public void get_team() throws Exception { ) ); } + + @Test + public void disband_team() throws Exception { + //given + Long teamId = 1L; // 예시 ID + DeleteTeamResponse output = DeleteTeamResponse.builder() + .teamId(teamId) + .build(); + + given(disbandTeamUserCase.disbandTeam(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + delete("/api/team/" + teamId + "/disband") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("[소모임장 권한] 소모임을 강제 종료했습니다."), + fieldWithPath("data.teamId").description("강제종료한 소모임 id") + ) + ) + ); + } + @Test + public void withdraw_team() throws Exception { + //given + Long teamId = 1L; // 예시 ID + DeleteTeamResponse output = DeleteTeamResponse.builder() + .teamId(teamId) + .build(); + + given(withdrawTeamUserCase.withdrawTeam(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + delete("/api/team/" + teamId + "/withdraw") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("[소모임원 권한] 소모임을 탈퇴하였습니다"), + fieldWithPath("data.teamId").description("탈퇴한 소모임 id") + ) + ) + ); + } + + } From 311d5a632edf4c38378aaba664ec881b19393d10 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Thu, 21 Sep 2023 17:01:13 +0900 Subject: [PATCH 086/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EA=B0=80=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SignInTeamUserCase.java | 29 +++++++++++++++++++ .../team/presentation/TeamController.java | 18 +++++++++--- .../constant/TeamResponseMessage.java | 1 + 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUserCase.java diff --git a/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUserCase.java new file mode 100644 index 00000000..8515ef61 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUserCase.java @@ -0,0 +1,29 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberSaveService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class SignInTeamUserCase { + + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final TeamMemberSaveService teamMemberSaveService; + public CreateTeamResponse signInTeam(String socialId, Long teamId){ + Member member=memberGetService.getMemberBySocialId(socialId); + Team team=teamGetService.getTeamByTeamId(teamId); + teamMemberSaveService.addTeamMember(team, member); + return new CreateTeamResponse(team.getTeamId()); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index 3ac3452a..dad8cfb2 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -4,10 +4,7 @@ import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; -import com.moing.backend.domain.team.application.service.CreateTeamUserCase; -import com.moing.backend.domain.team.application.service.DisbandTeamUserCase; -import com.moing.backend.domain.team.application.service.GetTeamUserCase; -import com.moing.backend.domain.team.application.service.WithdrawTeamUserCase; +import com.moing.backend.domain.team.application.service.*; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -26,6 +23,7 @@ public class TeamController { private final CreateTeamUserCase createTeamService; private final GetTeamUserCase getTeamUserCase; + private final SignInTeamUserCase signInTeamUserCase; private final DisbandTeamUserCase disbandTeamUserCase; private final WithdrawTeamUserCase withdrawTeamUserCase; @@ -50,6 +48,18 @@ public ResponseEntity> getTeam(@AuthenticationP return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_SUCCESS.getMessage(), this.getTeamUserCase.getTeam(user.getSocialId()))); } + /** + * 소모임 가입하기 (소모임원으로 입장) + * [POST] api/team/{teamId} + * 작성자 : 김민수 + */ + + @PostMapping("/{teamId}") + public ResponseEntity> signInTeam(@AuthenticationPrincipal User user, + @PathVariable Long teamId){ + return ResponseEntity.ok(SuccessResponse.create(SIGNIN_TEAM_SUCCESS.getMessage(),this.signInTeamUserCase.signInTeam(user.getSocialId(), teamId))); + } + /** * 소모임 강제 종료 (소모임장 권한) * [DELETE] api/team/{teamId}/disband diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 3e1ad7ef..45ae0eb5 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -8,6 +8,7 @@ public enum TeamResponseMessage { CREATE_TEAM_SUCCESS("소모임을 생성하였습니다"), GET_TEAM_SUCCESS("홈 화면에서 내 소모임을 모두 조회했습니다."), + SIGNIN_TEAM_SUCCESS("소모임에 가입하였습니다"), DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."), WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"); private final String message; From ee65d53c75d084a0812468f1f2955ef5908e7de5 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Thu, 21 Sep 2023 17:08:05 +0900 Subject: [PATCH 087/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EA=B0=80=EC=9E=85=ED=95=98=EA=B8=B0=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Team-API.adoc | 6 +++ .../team/presentation/TeamControllerTest.java | 41 +++++++++++++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc index d6ff94ba..05ff32e3 100644 --- a/src/docs/asciidoc/Team-API.adoc +++ b/src/docs/asciidoc/Team-API.adoc @@ -28,6 +28,12 @@ operation::team-controller-test/create_team[snippets='http-request,request-field | 그외 자기계발 |=== + +[[Team-소모임-가입]] +=== Team 소모임 가입 +operation::team-controller-test/sign-in_team[snippets='http-request,http-response,response-fields'] + + [[Team-소모임-조회]] === Team 소모임 조회 operation::team-controller-test/get_team[snippets='http-request,http-response,response-fields'] diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 8ac0dfdb..737c7af4 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -6,10 +6,7 @@ import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.application.dto.response.TeamBlock; -import com.moing.backend.domain.team.application.service.CreateTeamUserCase; -import com.moing.backend.domain.team.application.service.DisbandTeamUserCase; -import com.moing.backend.domain.team.application.service.GetTeamUserCase; -import com.moing.backend.domain.team.application.service.WithdrawTeamUserCase; +import com.moing.backend.domain.team.application.service.*; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -39,6 +36,8 @@ public class TeamControllerTest extends CommonControllerTest { private DisbandTeamUserCase disbandTeamUserCase; @MockBean private WithdrawTeamUserCase withdrawTeamUserCase; + @MockBean + private SignInTeamUserCase signInTeamUserCase; @Test public void create_team() throws Exception { @@ -231,5 +230,39 @@ public void withdraw_team() throws Exception { ); } + @Test + public void signIn_team() throws Exception { + //given + Long teamId = 1L; // 예시 ID + CreateTeamResponse output = CreateTeamResponse.builder() + .teamId(teamId) + .build(); + + given(signInTeamUserCase.signInTeam(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + post("/api/team/" + teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("소모임에 가입하였습니다."), + fieldWithPath("data.teamId").description("가입한 소모임 id") + ) + ) + ); + } + } From ad1ee586bf9fac16a15681305d23b770454bdaa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 25 Sep 2023 15:12:28 +0900 Subject: [PATCH 088/619] =?UTF-8?q?fix=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=20rest=20docs=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/req/MissionArchiveReq.java | 2 + .../MissionArchiveController.java | 3 +- .../MissionArchiveControllerTest.java | 316 ++++++++++++++++++ 3 files changed, 319 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java index 81cc1e0b..8b5b7223 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java @@ -1,10 +1,12 @@ package com.moing.backend.domain.missionArchive.application.dto.req; +import lombok.Builder; import lombok.Getter; import lombok.Setter; @Getter @Setter +@Builder public class MissionArchiveReq { private String status; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 2ada4d2b..6a763cef 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -81,8 +81,7 @@ public ResponseEntity> getMyArchive(@Authenti @GetMapping("/others") public ResponseEntity>> getOtherPeopleArchives(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId, - @RequestBody MissionArchiveReq missionArchiveReq) { + @PathVariable("missionId") Long missionId) { return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(user.getSocialId(),missionId))); } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java new file mode 100644 index 00000000..6ed54298 --- /dev/null +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -0,0 +1,316 @@ +package com.moing.backend.domain.missionArchive.representation; + +import com.google.common.collect.ImmutableList; +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.mission.application.dto.req.MissionReq; +import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; +import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; +import com.moing.backend.domain.mission.application.service.MissionCreateUseCase; +import com.moing.backend.domain.mission.application.service.MissionDeleteUseCase; +import com.moing.backend.domain.mission.application.service.MissionReadUseCase; +import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; +import com.moing.backend.domain.mission.presentation.MissionController; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateUseCase; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveHeartUseCase; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveUpdateUseCase; +import com.moing.backend.domain.missionArchive.application.service.SingleMissionArchiveReadUseCase; +import com.moing.backend.domain.missionArchive.presentation.MissionArchiveController; +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; + +@WebMvcTest(MissionArchiveController.class) +public class MissionArchiveControllerTest extends CommonControllerTest { + + @MockBean + private MissionArchiveCreateUseCase missionArchiveCreateUseCase; + @MockBean + private MissionArchiveUpdateUseCase missionArchiveUpdateUseCase; + @MockBean + private SingleMissionArchiveReadUseCase singleMissionArchiveReadUseCase; + @MockBean + private MissionArchiveHeartUseCase missionArchiveHeartUseCase; + + + + @Test + public void 미션_인증하기() throws Exception { + //given + MissionArchiveReq input = MissionArchiveReq.builder() + .status("COMPLETE") + .archive("https://iwheifhoaiwj") + .build(); + + String body = objectMapper.writeValueAsString(input); + + MissionArchiveRes output = MissionArchiveRes.builder() + .archiveId(1L) + .archive("https://iwheifhoaiwj") + .createdDate("2023-09-03T21:32:33.888") + .hearts(3) + .build(); + + given(missionArchiveCreateUseCase.createArchive(any(),any(),any())).willReturn(output); + + Long teamId = 2L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + post("/api/{teamId}/missions/{missionId}/archive",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + requestFields( + fieldWithPath("status").description("미션 인증 상태 [COMPLETE/SKIP]"), + fieldWithPath("archive").description("미션 인증물 [s3URL/text/링크] ") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("미션 인증을 완료 했습니다."), + fieldWithPath("data.archiveId").description("미션 인증 아이디"), + fieldWithPath("data.createdDate").description("미션 제출 시각"), + fieldWithPath("data.hearts").description("미션 인증 좋아요 수") +// fieldWithPath("data.heartsStatus").description("미션 인증 좋아요 상태"), + ) + ) + ) + .andReturn(); + + } + + @Test + public void 미션_수정() throws Exception { + //given + MissionArchiveReq input = MissionArchiveReq.builder() + .status("COMPLETE") + .archive("https://iwheifhoaiwj") + .build(); + + String body = objectMapper.writeValueAsString(input); + + MissionArchiveRes output = MissionArchiveRes.builder() + .archiveId(1L) + .archive("https://iwheifhoaiwj") + .createdDate("2023-09-03T21:32:33.888") + .hearts(3) + .build(); + + given(missionArchiveCreateUseCase.createArchive(any(),any(),any())).willReturn(output); + + Long teamId = 2L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + put("/api/{teamId}/missions/{missionId}/archive",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + requestFields( + fieldWithPath("status").description("미션 인증 상태 [COMPLETE/SKIP]"), + fieldWithPath("archive").description("미션 인증물 [s3URL/text/링크] ") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("미션 인증을 완료 했습니다."), + fieldWithPath("data.archiveId").description("미션 인증 아이디"), + fieldWithPath("data.createdDate").description("미션 제출 시각"), + fieldWithPath("data.hearts").description("미션 인증 좋아요 수") +// fieldWithPath("data.heartsStatus").description("미션 인증 좋아요 상태"), + ) + ) + ) + .andReturn(); + + } + + @Test + public void 나의_미션_인증_조회() throws Exception { + //given + + + MissionArchiveRes output = MissionArchiveRes.builder() + .archiveId(1L) + .archive("https://iwheifhoaiwj") + .createdDate("2023-09-03T21:32:33.888") + .hearts(3) + .build(); + + given(singleMissionArchiveReadUseCase.getMyArchive(any(),any())).willReturn(output); + + Long teamId = 2L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/missions/{missionId}/archive",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("나의 미션 인증 현황 조회를 완료 했습니다."), + fieldWithPath("data.archiveId").description("미션 인증 아이디"), + fieldWithPath("data.createdDate").description("미션 제출 시각"), + fieldWithPath("data.hearts").description("미션 인증 좋아요 수") + + ) + ) + ) + .andReturn(); + + } + + @Test + public void 모임원_미션_인증_조회() throws Exception { + //given + + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + + + List output = Lists.newArrayList(PersonalArchive.builder() + .archiveId(1L) + .nickname("nickname") + .profileImg("https://wehofijaowi") + .archive("hihihihi") + .createdDate("2023-09-03T21:32:33.888") + .hearts(3) + .build()); + + given(singleMissionArchiveReadUseCase.getPersonalArchive(any(),any())).willReturn(output); + + Long teamId = 1L; + Long missionId = 5L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/missions/{missionId}/archive/others",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("팀원 미션 인증 현황 조회를 완료 했습니다."), + fieldWithPath("data.archiveId").description("미션 인증 아이디"), + fieldWithPath("data.nickname").description("미션 인증자 닉네임 "), + fieldWithPath("data.profileImg").description("미션 인증자 프로필 이미지 "), + fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크] "), + fieldWithPath("data.createdDate").description("미션 인증 날짜 "), + fieldWithPath("data.hearts").description("미션 인증 좋아요 수 ") + + ) + ) + ) + .andReturn(); + + } + + @Test + public void 미션_삭제() throws Exception { + //given + + + Long teamId = 2L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/{teamId}/missions/{missionId}",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("삭제할 미션 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("미션을 삭제 했습니다"), + fieldWithPath("data").description("삭제된 미션 아이디") + ) + ) + ) + .andReturn(); + } +} From 7530a0d470811dd9c4c43f8afbbb1ba291097343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 25 Sep 2023 17:19:43 +0900 Subject: [PATCH 089/619] =?UTF-8?q?fix=20:=20MissionArchive=20Rest=20Docs?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SingleMissionArchiveReadUseCase.java | 7 +- .../domain/entity/MissionArchive.java | 2 + .../MissionArchiveCustomRepositoryImpl.java | 3 +- .../MissionArchiveControllerTest.java | 76 +++++-------------- 4 files changed, 27 insertions(+), 61 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java index 695226c4..1959984e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java @@ -36,7 +36,6 @@ public MissionArchiveRes getMyArchive(String userSocialId, Long missionId) { List archiveRes = new ArrayList<>(); Member member = memberGetService.getMemberBySocialId(userSocialId); - Mission mission = missionQueryService.findMissionById(missionId); return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId).get(0)); } @@ -47,11 +46,9 @@ public List getPersonalArchive(String userSocialId,Long mission List personalArchives = new ArrayList<>(); Member member = memberGetService.getMemberBySocialId(userSocialId); - Mission mission = missionQueryService.findMissionById(missionId); + return MissionArchiveMapper.mapToPersonalArchiveList(missionArchiveQueryService.findOthersArchive(member.getMemberId(), missionId)); - MissionArchiveMapper.mapToPersonalArchiveList(missionArchiveQueryService.findOthersArchive(member.getMemberId(), missionId)); - - return personalArchives; +// return personalArchives; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index f54f4d5c..add5fd97 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -26,9 +26,11 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 private Long id; @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") private Member member; @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "mission_id") private Mission mission; @Enumerated(value = EnumType.STRING) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 8c726617..45a811da 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -70,7 +70,8 @@ public Optional> findOthersArchives(Long memberId, Long mis .from(missionArchive) .where( missionArchive.mission.id.eq(missionId), - missionArchive.member.memberId.ne(memberId) + missionArchive.member.memberId.ne(memberId), + missionArchive.status.eq(MissionArchiveStatus.COMPLETE).or(missionArchive.status.eq(MissionArchiveStatus.SKIP)) ) .fetch() ); diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 6ed54298..9c31ec79 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -31,6 +31,7 @@ import java.time.LocalDateTime; import java.util.List; +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.READ_MY_ARCHIVE_SUCCESS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; @@ -72,7 +73,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { given(missionArchiveCreateUseCase.createArchive(any(),any(),any())).willReturn(output); - Long teamId = 2L; + Long teamId = 1L; Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. @@ -102,6 +103,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("미션 인증을 완료 했습니다."), fieldWithPath("data.archiveId").description("미션 인증 아이디"), + fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data.createdDate").description("미션 제출 시각"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수") // fieldWithPath("data.heartsStatus").description("미션 인증 좋아요 상태"), @@ -113,25 +115,25 @@ public class MissionArchiveControllerTest extends CommonControllerTest { } @Test - public void 미션_수정() throws Exception { + public void 미션_재인증하기() throws Exception { //given MissionArchiveReq input = MissionArchiveReq.builder() .status("COMPLETE") - .archive("https://iwheifhoaiwj") + .archive("contents") .build(); String body = objectMapper.writeValueAsString(input); MissionArchiveRes output = MissionArchiveRes.builder() .archiveId(1L) - .archive("https://iwheifhoaiwj") + .archive("contents") .createdDate("2023-09-03T21:32:33.888") .hearts(3) .build(); - given(missionArchiveCreateUseCase.createArchive(any(),any(),any())).willReturn(output); + given(missionArchiveUpdateUseCase.updateArchive(any(),any(),any())).willReturn(output); - Long teamId = 2L; + Long teamId = 1L; Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. @@ -161,6 +163,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("미션 인증을 완료 했습니다."), fieldWithPath("data.archiveId").description("미션 인증 아이디"), + fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data.createdDate").description("미션 제출 시각"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수") // fieldWithPath("data.heartsStatus").description("미션 인증 좋아요 상태"), @@ -175,17 +178,16 @@ public class MissionArchiveControllerTest extends CommonControllerTest { public void 나의_미션_인증_조회() throws Exception { //given - MissionArchiveRes output = MissionArchiveRes.builder() .archiveId(1L) .archive("https://iwheifhoaiwj") .createdDate("2023-09-03T21:32:33.888") - .hearts(3) + .hearts(0) .build(); given(singleMissionArchiveReadUseCase.getMyArchive(any(),any())).willReturn(output); - Long teamId = 2L; + Long teamId = 1L; Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. @@ -209,8 +211,9 @@ public class MissionArchiveControllerTest extends CommonControllerTest { ), responseFields( fieldWithPath("isSuccess").description("true"), - fieldWithPath("message").description("나의 미션 인증 현황 조회를 완료 했습니다."), + fieldWithPath("message").description(READ_MY_ARCHIVE_SUCCESS.getMessage()), fieldWithPath("data.archiveId").description("미션 인증 아이디"), + fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data.createdDate").description("미션 제출 시각"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수") @@ -225,12 +228,9 @@ public class MissionArchiveControllerTest extends CommonControllerTest { public void 모임원_미션_인증_조회() throws Exception { //given - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - - List output = Lists.newArrayList(PersonalArchive.builder() .archiveId(1L) - .nickname("nickname") + .nickname("modagbul_tester1") .profileImg("https://wehofijaowi") .archive("hihihihi") .createdDate("2023-09-03T21:32:33.888") @@ -240,7 +240,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { given(singleMissionArchiveReadUseCase.getPersonalArchive(any(),any())).willReturn(output); Long teamId = 1L; - Long missionId = 5L; + Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. get("/api/{teamId}/missions/{missionId}/archive/others",teamId,missionId) @@ -264,12 +264,12 @@ public class MissionArchiveControllerTest extends CommonControllerTest { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("팀원 미션 인증 현황 조회를 완료 했습니다."), - fieldWithPath("data.archiveId").description("미션 인증 아이디"), - fieldWithPath("data.nickname").description("미션 인증자 닉네임 "), - fieldWithPath("data.profileImg").description("미션 인증자 프로필 이미지 "), - fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크] "), - fieldWithPath("data.createdDate").description("미션 인증 날짜 "), - fieldWithPath("data.hearts").description("미션 인증 좋아요 수 ") + fieldWithPath("data[].archiveId").description("미션 인증 아이디"), + fieldWithPath("data[].nickname").description("미션 인증자 닉네임 "), + fieldWithPath("data[].profileImg").description("미션 인증자 프로필 이미지 "), + fieldWithPath("data[].archive").description("미션 인증물 [s3URL/text/링크] "), + fieldWithPath("data[].createdDate").description("미션 인증 날짜 "), + fieldWithPath("data[].hearts").description("미션 인증 좋아요 수 ") ) ) @@ -278,39 +278,5 @@ public class MissionArchiveControllerTest extends CommonControllerTest { } - @Test - public void 미션_삭제() throws Exception { - //given - - - Long teamId = 2L; - Long missionId = 1L; - //when - ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - delete("/api/{teamId}/missions/{missionId}",teamId,missionId) - .header("Authorization", "Bearer ACCESS_TOKEN") - .contentType(MediaType.APPLICATION_JSON) - ); - //then - actions - .andExpect(MockMvcResultMatchers.status().isOk()) - .andDo( - restDocs.document( - requestHeaders( - headerWithName("Authorization").description("접근 토큰") - ), - pathParameters( - parameterWithName("teamId").description("팀 아이디"), - parameterWithName("missionId").description("삭제할 미션 아이디") - ), - responseFields( - fieldWithPath("isSuccess").description("true"), - fieldWithPath("message").description("미션을 삭제 했습니다"), - fieldWithPath("data").description("삭제된 미션 아이디") - ) - ) - ) - .andReturn(); - } } From a953be76d403ba3f54b0559292fc253cf599b8fa Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Mon, 25 Sep 2023 22:36:46 +0900 Subject: [PATCH 090/619] fix: delete data.sql --- .github/workflows/ci-cd.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 3b975a41..76670219 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -46,9 +46,7 @@ jobs: echo "${{env.APPLICATION}}" > ./application.yml touch ./firebase-key.json echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json - touch ./data.sql - echo "${{env.DATA_SQL}}" | base64 --decode > ./data.sql - + # 설정 파일을 작업공간에 저장 - uses: actions/upload-artifact@v2 with: @@ -60,11 +58,6 @@ jobs: name: firebase-key.json path: ./src/main/resources/firebase-key.json - - uses: actions/upload-artifact@v2 - with: - name: data.sql - path: ./src/main/resources/data.sql - # gradlew 권한 설정 - name: Grant execute permission for gradlew run: chmod +x gradlew From 6f2309c8252f011cabe271faf090cc4289685a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 26 Sep 2023 01:32:10 +0900 Subject: [PATCH 091/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20API=20=EB=AC=B8=EC=84=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionArchive-API.adoc | 29 +++++++++++++++++++ .../MissionArchiveController.java | 3 +- .../MissionArchiveControllerTest.java | 18 ++++++------ 3 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 src/docs/asciidoc/MissionArchive-API.adoc diff --git a/src/docs/asciidoc/MissionArchive-API.adoc b/src/docs/asciidoc/MissionArchive-API.adoc new file mode 100644 index 00000000..d082b9c8 --- /dev/null +++ b/src/docs/asciidoc/MissionArchive-API.adoc @@ -0,0 +1,29 @@ + + +[[MissionArchive-API]] += MissionArchive API + +[[MissionArchive-인증하기]] +=== 미션 인증하기 +operation::mission-archive-controller-test/미션_인증하기[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[MissionArchive-재인증하기]] +=== 미션 재인증하기 +operation::mission-archive-controller-test/미션_재인증하기[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[MissionArchive-나의미션인증조회]] +=== 나의 미션 인증 조회 +operation::mission-archive-controller-test/나의_미션_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[MissionArchive-모임원미션인증조회]] +=== 모임원 미션 인증 조회 +operation::mission-archive-controller-test/모임원_미션_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 6a763cef..d89372cb 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -68,8 +68,7 @@ public ResponseEntity> updateArchive(@Authent @GetMapping() public ResponseEntity> getMyArchive(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId, - @RequestBody MissionArchiveReq missionArchiveReq) { + @PathVariable("missionId") Long missionId) { return ResponseEntity.ok(SuccessResponse.create(READ_MY_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getMyArchive(user.getSocialId(), missionId))); } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 9c31ec79..23d2912b 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -58,15 +58,15 @@ public class MissionArchiveControllerTest extends CommonControllerTest { public void 미션_인증하기() throws Exception { //given MissionArchiveReq input = MissionArchiveReq.builder() - .status("COMPLETE") - .archive("https://iwheifhoaiwj") + .status("COMPLETE/SKIP") + .archive("content[s3 Link / text / link]") .build(); String body = objectMapper.writeValueAsString(input); MissionArchiveRes output = MissionArchiveRes.builder() .archiveId(1L) - .archive("https://iwheifhoaiwj") + .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") .hearts(3) .build(); @@ -118,15 +118,15 @@ public class MissionArchiveControllerTest extends CommonControllerTest { public void 미션_재인증하기() throws Exception { //given MissionArchiveReq input = MissionArchiveReq.builder() - .status("COMPLETE") - .archive("contents") + .status("COMPLETE/SKIP") + .archive("content[s3 Link / text / link]") .build(); String body = objectMapper.writeValueAsString(input); MissionArchiveRes output = MissionArchiveRes.builder() .archiveId(1L) - .archive("contents") + .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") .hearts(3) .build(); @@ -180,7 +180,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { MissionArchiveRes output = MissionArchiveRes.builder() .archiveId(1L) - .archive("https://iwheifhoaiwj") + .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") .hearts(0) .build(); @@ -231,8 +231,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { List output = Lists.newArrayList(PersonalArchive.builder() .archiveId(1L) .nickname("modagbul_tester1") - .profileImg("https://wehofijaowi") - .archive("hihihihi") + .profileImg("[s3 Link]") + .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") .hearts(3) .build()); From e41b46c80bdc6214262ad59a706a9040402b22ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 26 Sep 2023 01:42:14 +0900 Subject: [PATCH 092/619] =?UTF-8?q?fix=20:=20MissionArchiveRes=EC=97=90=20?= =?UTF-8?q?status=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/MissionArchiveRes.java | 2 ++ .../application/mapper/MissionArchiveMapper.java | 1 + .../representation/MissionArchiveControllerTest.java | 12 +++++++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index 4d55a194..a9e8d5b1 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -18,4 +18,6 @@ public class MissionArchiveRes { private int hearts; + private String status; + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 89b5d56e..38831dae 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -34,6 +34,7 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc .archive(missionArchive.getArchive()) .createdDate(missionArchive.getCreatedDate().toString()) .hearts(missionArchive.getHearts()) + .status(missionArchive.getStatus().name()) .build(); } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 23d2912b..6b7e23f6 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -69,6 +69,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") .hearts(3) + .status("COMPLETE/SKIP") .build(); given(missionArchiveCreateUseCase.createArchive(any(),any(),any())).willReturn(output); @@ -105,7 +106,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.archiveId").description("미션 인증 아이디"), fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data.createdDate").description("미션 제출 시각"), - fieldWithPath("data.hearts").description("미션 인증 좋아요 수") + fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), + fieldWithPath("data.status").description("미션 인증 상태") // fieldWithPath("data.heartsStatus").description("미션 인증 좋아요 상태"), ) ) @@ -129,6 +131,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") .hearts(3) + .status("COMPLETE/SKIP") .build(); given(missionArchiveUpdateUseCase.updateArchive(any(),any(),any())).willReturn(output); @@ -165,7 +168,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.archiveId").description("미션 인증 아이디"), fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data.createdDate").description("미션 제출 시각"), - fieldWithPath("data.hearts").description("미션 인증 좋아요 수") + fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), + fieldWithPath("data.status").description("미션 인증 상태") // fieldWithPath("data.heartsStatus").description("미션 인증 좋아요 상태"), ) ) @@ -183,6 +187,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") .hearts(0) + .status("COMPLETE/SKIP") .build(); given(singleMissionArchiveReadUseCase.getMyArchive(any(),any())).willReturn(output); @@ -215,7 +220,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.archiveId").description("미션 인증 아이디"), fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data.createdDate").description("미션 제출 시각"), - fieldWithPath("data.hearts").description("미션 인증 좋아요 수") + fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), + fieldWithPath("data.status").description("미션 인증 상태") ) ) From 93a3b6c83b4104e490248f825644386438c852a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 26 Sep 2023 01:44:30 +0900 Subject: [PATCH 093/619] =?UTF-8?q?fix=20:=20PersonalArchiveRes=20?= =?UTF-8?q?=EC=97=90=20status=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionArchive/application/dto/res/PersonalArchive.java | 2 ++ .../application/mapper/MissionArchiveMapper.java | 1 + .../representation/MissionArchiveControllerTest.java | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java index a71f239d..a534a19e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java @@ -18,4 +18,6 @@ public class PersonalArchive { private int hearts; + private String status; + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 38831dae..765599f5 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -48,6 +48,7 @@ public static PersonalArchive mapToPersonalArchive(MissionArchive missionArchive .archive(missionArchive.getArchive()) .createdDate(missionArchive.getCreatedDate().toString()) .hearts(missionArchive.getHearts()) + .status(missionArchive.getStatus().name()) .build(); } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 6b7e23f6..c998c86b 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -241,6 +241,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") .hearts(3) + .status("COMPLETE/SKIP") .build()); given(singleMissionArchiveReadUseCase.getPersonalArchive(any(),any())).willReturn(output); @@ -275,7 +276,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data[].profileImg").description("미션 인증자 프로필 이미지 "), fieldWithPath("data[].archive").description("미션 인증물 [s3URL/text/링크] "), fieldWithPath("data[].createdDate").description("미션 인증 날짜 "), - fieldWithPath("data[].hearts").description("미션 인증 좋아요 수 ") + fieldWithPath("data[].hearts").description("미션 인증 좋아요 수 "), + fieldWithPath("data[].status").description("미션 인증 상태") ) ) From b27b77046f92d559e4ad1dc7c1d4f9164f1beadb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 26 Sep 2023 01:45:40 +0900 Subject: [PATCH 094/619] =?UTF-8?q?feat=20:=20api.adoc=EC=97=90=20Mission,?= =?UTF-8?q?MissionArchive=20-=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/api.adoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index f4089838..2e4a5a6c 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -16,4 +16,8 @@ include::Mypage-API.adoc[] include::Team-API.adoc[] +include::Mission-API.adoc[] + +include::MissionArchive-API.adoc[] + From 4cba7fd384ba64d89fbc4b1d587a2e3505eca173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 26 Sep 2023 01:56:00 +0900 Subject: [PATCH 095/619] =?UTF-8?q?fix=20:=20Mission-API.adoc=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Mission-API.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/docs/asciidoc/Mission-API.adoc b/src/docs/asciidoc/Mission-API.adoc index cedcde65..2485c8fb 100644 --- a/src/docs/asciidoc/Mission-API.adoc +++ b/src/docs/asciidoc/Mission-API.adoc @@ -10,7 +10,7 @@ operation::mission-controller-test/미션_생성[snippets='http-request,path-par --- [[Mission-조회]] -=== Mission 생성 +=== Mission 조회 operation::mission-controller-test/미션_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- @@ -21,8 +21,8 @@ operation::mission-controller-test/미션_수정[snippets='http-request,path-par --- -[[Mission-수정]] -=== Mission 수정 +[[Mission-삭제]] +=== Mission 삭제 operation::mission-controller-test/미션_삭제[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- From 86cc64ad9cc5c4df9df63e6d1180a9b8462562a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 26 Sep 2023 03:09:30 +0900 Subject: [PATCH 096/619] =?UTF-8?q?fix=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=A1=B0=ED=9A=8C=20controller?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/FinishMissionBoardRes.java | 5 +++ .../service/MissionArchiveBoardUseCase.java | 31 ++++++------- .../mapper/MissionArchiveMapper.java | 22 +++++++++ .../MissionArchiveResponseMessage.java | 4 +- .../MissionArchiveCustomRepository.java | 9 +++- .../MissionArchiveCustomRepositoryImpl.java | 25 ++++++++--- .../service/MissionArchiveQueryService.java | 14 +++--- .../presentation/MissionBoardController.java | 45 +++++++++++++++++++ 8 files changed, 127 insertions(+), 28 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java index 30e48acd..fbb5b9c0 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java @@ -1,5 +1,10 @@ package com.moing.backend.domain.mission.application.dto.res; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter public class FinishMissionBoardRes { private Long missionId; private String dueTo; // 날짜 diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java index 3e463af4..be0f867b 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java @@ -35,20 +35,28 @@ public class MissionArchiveBoardUseCase { /* * 팀별 미션 보드 중 진행중인 단일 미션(한 번 인증) */ - public List getActiveSingleMissions(Long teamId, String memberId,Long missionId) { + public List getActiveSingleMissions(Long teamId, String memberId) { - Team team = teamRepository.findById(teamId).orElseThrow(); Member member = memberGetService.getMemberBySocialId(memberId); - // 인증 상태 가져올 미션들 - List missionIds = new ArrayList<>(); - team.getMissions().forEach(mission -> missionIds.add(mission.getId())); - - List mySingleMissionArchives = missionArchiveQueryService.findMySingleMissionArchives(member.getMemberId(), missionIds, MissionStatus.ONGOING); + List mySingleMissionArchives = missionArchiveQueryService.findMySingleMissionArchives(member.getMemberId(), teamId, MissionStatus.ONGOING); return MissionArchiveMapper.mapToSingleMissionBoardResList(mySingleMissionArchives); } + /* + * 팀별 미션 보드 중 종료한 전체 미션 + */ + public List getFinishMissions(Long teamId, String memberId) { + + Team team = teamRepository.findById(teamId).orElseThrow(); + Member member = memberGetService.getMemberBySocialId(memberId); + + List myAllMissionArchives = missionArchiveQueryService.findMyAllMissionArchives(member.getMemberId(), teamId, MissionStatus.END); + return MissionArchiveMapper.mapToFinishMissionBoardResList(myAllMissionArchives); + + } + // public List getActiveRepeatMissions(Long teamId, String memberId) { // // Team team = teamRepository.findById(teamId).orElseThrow(); @@ -57,12 +65,5 @@ public List getActiveSingleMissions(Long teamId, String m // missionArchiveQueryService.findRepeatMissionMyArchive(memberId, ); // } // -// public List getFinishMissions(Long teamId, Long memberId) { -// -// -// -// } -// public List getFinishRepeatMissions(Long teamId, Long memberId) { -// -// } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 765599f5..f191145c 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.missionArchive.application.mapper; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; @@ -92,5 +93,26 @@ public static MissionArchiveHeartRes mapToMissionArchiveHeartRes(MissionArchive } + public static List mapToFinishMissionBoardResList(List missionArchives) { + List finishMissionBoardResList = new ArrayList<>(); + missionArchives.forEach( + missionArchive -> finishMissionBoardResList.add(MissionArchiveMapper.mapToFinishMissionBoardRes(missionArchive)) + ); + + return finishMissionBoardResList; + } + + public static FinishMissionBoardRes mapToFinishMissionBoardRes(MissionArchive missionArchive) { + Mission mission = missionArchive.getMission(); + return FinishMissionBoardRes.builder() + .missionId(mission.getId()) + .missionType(mission.getType().name()) + .title(mission.getTitle()) + .dueTo(mission.getDueTo().toString()) + .status(missionArchive.getStatus().name()) + .build(); + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java index feb66b2e..39750179 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java @@ -10,7 +10,9 @@ public enum MissionArchiveResponseMessage { CREATE_ARCHIVE_SUCCESS("미션 인증을 완료 했습니다."), READ_MY_ARCHIVE_SUCCESS("나의 미션 인증 현황 조회를 완료 했습니다."), READ_TEAM_ARCHIVE_SUCCESS("팀원 미션 인증 현황 조회를 완료 했습니다."), - HEART_UPDATE_SUCCESS("미션 인증 좋아요를 성공적으로 눌렀습니다."); + HEART_UPDATE_SUCCESS("미션 인증 좋아요를 성공적으로 눌렀습니다."), + ACTIVE_SINGLE_MISSION_SUCCESS("진행 중인 한번 인증 미션 조회를 완료하였습니다."), + FINISH_ALL_MISSION_SUCCESS("종료된 미션 조회를 완료하였습니다."); private final String message; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 0260ccda..ee7ca799 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -1,13 +1,18 @@ package com.moing.backend.domain.missionArchive.domain.repository; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.teamMember.domain.repository.OrderCondition; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; public interface MissionArchiveCustomRepository { - public Optional> findSingleMissionArchivesByMemberId(Long memberId, List missionIds, String status, String archiveStatus, OrderCondition orderCondition); - public Optional> findOthersArchives(Long memberId, Long missionId) ; + Optional> findSingleMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status, MissionArchiveStatus archiveStatus, OrderCondition orderCondition); + Optional> findOthersArchives(Long memberId, Long missionId) ; + + Optional> findAllMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus missionStatus); + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 45a811da..a8fba537 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -30,16 +30,17 @@ public MissionArchiveCustomRepositoryImpl(EntityManager em) { } @Override - public Optional> findSingleMissionArchivesByMemberId(Long memberId, List missionIds, String status, String archiveStatus,OrderCondition orderCondition) { + public Optional> findSingleMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status, + MissionArchiveStatus archiveStatus,OrderCondition orderCondition) { OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); return Optional.ofNullable(queryFactory .select(missionArchive) .from(missionArchive) .where( - missionArchive.mission.status.eq(MissionStatus.ONGOING), - missionArchive.mission.id.in(missionIds), - missionArchive.mission.status.eq(MissionStatus.valueOf(status)), - missionArchive.status.eq(MissionArchiveStatus.valueOf(archiveStatus)) + missionArchive.mission.team.teamId.eq(teamId), + missionArchive.member.memberId.eq(memberId), + missionArchive.mission.status.eq(status), + missionArchive.status.eq(archiveStatus) ) .orderBy(orderSpecifiers) .fetch()); @@ -77,5 +78,19 @@ public Optional> findOthersArchives(Long memberId, Long mis ); } + @Override + public Optional> findAllMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus missionStatus){ + + return Optional.ofNullable(queryFactory + .selectFrom(missionArchive) + .where( + missionArchive.mission.status.eq(missionStatus), + missionArchive.mission.team.teamId.eq(teamId) + ) + .orderBy(missionArchive.mission.dueTo.desc()) + .fetch() + ); + } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 69b449cb..77891d9b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -68,19 +68,23 @@ public Boolean isDone(Long memberId, Long missionId) { /** * mission.getTeam() 팀의 단일미션 미션 인증 보드 */ - public List findMySingleMissionArchives(Long memberId, List missionIds, MissionStatus missionStatus) { + public List findMySingleMissionArchives(Long memberId,Long teamId, MissionStatus missionStatus) { // INCOMPLETE - List incompleteList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), INCOMPLETE.name(), OrderCondition.DUETO) + List incompleteList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, teamId, missionStatus, INCOMPLETE, OrderCondition.DUETO) .orElseThrow(NotFoundMissionArchiveException::new); - List completeList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, missionIds, missionStatus.name(), COMPLETE.name(),OrderCondition.CREATED) + List completeList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, teamId, missionStatus, COMPLETE,OrderCondition.CREATED) .orElseThrow(NotFoundMissionArchiveException::new); incompleteList.addAll(completeList); return incompleteList; } - public List findMyRepeatMissionArchives(Long memberId, List missionIds) { - return missionArchiveRepository.findRepeatMissionArchivesByMission(memberId, missionIds).orElseThrow(NotFoundMissionArchiveException::new); +// public List findMyRepeatMissionArchives(Long memberId, List missionIds) { +// return missionArchiveRepository.findRepeatMissionArchivesByMission(memberId, missionIds).orElseThrow(NotFoundMissionArchiveException::new); +// } + + public List findMyAllMissionArchives(Long memberId, Long teamId, MissionStatus missionStatus) { + return missionArchiveRepository.findAllMissionArchivesByMemberId(memberId, teamId, missionStatus).orElseThrow(NotFoundMissionArchiveException::new); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java new file mode 100644 index 00000000..4a4760b4 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java @@ -0,0 +1,45 @@ +package com.moing.backend.domain.missionArchive.presentation; + +import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; +import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/{teamId}/missions/{missionId}/board") +public class MissionBoardController { + + private final MissionArchiveBoardUseCase missionArchiveBoardUseCase; + + /** + * 단일 인증 조회 + * [POST] {teamId}/missions/{missionId}/board + * 작성자 : 정승연 + */ + + @GetMapping("/single") + public ResponseEntity>> getActiveSingleMission(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveSingleMissions(teamId, user.getSocialId()))); + } + + @GetMapping("/finish") + public ResponseEntity>> getFinishAllMission(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(FINISH_ALL_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getFinishMissions(teamId, user.getSocialId()))); + } +} From 4bf0729624d8ea8da4dc69b37d6a4c4e3833f1cf Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Thu, 28 Sep 2023 18:50:41 +0900 Subject: [PATCH 097/619] =?UTF-8?q?feat:=20Board=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=83=9D=EC=84=B1,=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Auth-API.adoc | 18 +-- src/docs/asciidoc/Board-API.adoc | 12 ++ src/docs/asciidoc/api.adoc | 4 + .../dto/request/CreateBoardRequest.java | 27 ++++ .../dto/request/UpdateBoardRequest.java | 23 +++ .../application/dto/response/BoardBlocks.java | 23 +++ .../dto/response/CreateBoardResponse.java | 14 ++ .../dto/response/GetAllBoardResponse.java | 20 +++ .../dto/response/UpdateBoardResponse.java | 12 ++ .../board/application/mapper/BoardMapper.java | 29 ++++ .../service/CreateBoardUserCase.java | 46 ++++++ .../application/service/GetBoardUserCase.java | 10 ++ .../service/UpdateBoardUserCase.java | 37 +++++ .../domain/board/domain/entity/Board.java | 86 ++++++++++++ .../repository/BoardCustomRepository.java | 4 + .../BoardCustomerRepositoryImpl.java | 4 + .../domain/repository/BoardRepository.java | 11 ++ .../board/domain/service/BoardGetService.java | 22 +++ .../domain/service/BoardSaveService.java | 20 +++ .../board/exception/BoardException.java | 11 ++ .../exception/NotFoundByBoardIdException.java | 11 ++ .../board/presentation/BoardController.java | 54 ++++++++ .../constant/BoardResponseMessage.java | 13 ++ .../boardComment/domain/BoardComment.java | 33 +++++ .../boardRead/domain/entity/BoardRead.java | 53 +++++++ .../application/mapper/MemberMapper.java | 3 - .../team/application/mapper/TeamMapper.java | 17 +++ .../service/CreateTeamUserCase.java | 4 +- .../domain/team/domain/entity/Team.java | 16 --- .../oauth/CustomUserDetailsService.java | 4 +- .../exception/GlobalExceptionHandler.java | 8 +- .../backend/global/response/ErrorCode.java | 7 +- .../presentation/BoardControllerTest.java | 131 ++++++++++++++++++ 33 files changed, 747 insertions(+), 40 deletions(-) create mode 100644 src/docs/asciidoc/Board-API.adoc create mode 100644 src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java create mode 100644 src/main/java/com/moing/backend/domain/board/application/dto/request/UpdateBoardRequest.java create mode 100644 src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java create mode 100644 src/main/java/com/moing/backend/domain/board/application/dto/response/CreateBoardResponse.java create mode 100644 src/main/java/com/moing/backend/domain/board/application/dto/response/GetAllBoardResponse.java create mode 100644 src/main/java/com/moing/backend/domain/board/application/dto/response/UpdateBoardResponse.java create mode 100644 src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java create mode 100644 src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/board/domain/entity/Board.java create mode 100644 src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomerRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/board/domain/repository/BoardRepository.java create mode 100644 src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java create mode 100644 src/main/java/com/moing/backend/domain/board/domain/service/BoardSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/board/exception/BoardException.java create mode 100644 src/main/java/com/moing/backend/domain/board/exception/NotFoundByBoardIdException.java create mode 100644 src/main/java/com/moing/backend/domain/board/presentation/BoardController.java create mode 100644 src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/domain/BoardComment.java create mode 100644 src/main/java/com/moing/backend/domain/boardRead/domain/entity/BoardRead.java create mode 100644 src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java diff --git a/src/docs/asciidoc/Auth-API.adoc b/src/docs/asciidoc/Auth-API.adoc index 45380bc1..900e3d54 100644 --- a/src/docs/asciidoc/Auth-API.adoc +++ b/src/docs/asciidoc/Auth-API.adoc @@ -2,36 +2,24 @@ = Auth API [[Auth-Kako-소셜-로그인]] -=== Auth Kakao 소셜 로그인 요청 +=== Auth Kakao 소셜 로그인 operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-request,request-fields'] - -=== Auth Kakao 소셜 로그인 회원가입 전 응답 operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-response,response-fields'] - -=== Auth Kakao 소셜 로그인 회원가입 후 응답 operation::auth-controller-test/kakao_소셜_로그인_회원가입_후[snippets='http-response,response-fields'] --- [[Auth-Apple-소셜-로그인]] -=== Auth Apple 소셜 로그인 요청 +=== Auth Apple 소셜 로그인 operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-request,request-fields'] - -=== Auth Apple 소셜 로그인 회원가입 전 응답 operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-response,response-fields'] - -=== Auth Apple 소셜 로그인 회원가입 후 응답 operation::auth-controller-test/apple_소셜_로그인_회원가입_후[snippets='http-response,response-fields'] [[Auth-Google-소셜-로그인]] -=== Auth Google 소셜 로그인 요청 +=== Auth Google 소셜 로그인 operation::auth-controller-test/google_소셜_로그인_회원가입_전[snippets='http-request,request-fields'] - -=== Auth Google 소셜 로그인 회원가입 전 응답 operation::auth-controller-test/google_소셜_로그인_회원가입_전[snippets='http-response,response-fields'] - -=== Auth Google 소셜 로그인 회원가입 후 응답 operation::auth-controller-test/google_소셜_로그인_회원가입_후[snippets='http-response,response-fields'] diff --git a/src/docs/asciidoc/Board-API.adoc b/src/docs/asciidoc/Board-API.adoc new file mode 100644 index 00000000..451cd602 --- /dev/null +++ b/src/docs/asciidoc/Board-API.adoc @@ -0,0 +1,12 @@ +[[Board-API]] += Board API + +[[Board-게시글-생성]] +=== Board 게시글 생성 +operation::board-controller-test/create_board[snippets='http-request,request-fields,http-response,response-fields'] +--- + +[[Board-게시글-수정]] +=== Board 게시글 수정 +operation::board-controller-test/update_board[snippets='http-request,request-fields,http-response,response-fields'] +--- \ No newline at end of file diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 2e4a5a6c..26bed444 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -20,4 +20,8 @@ include::Mission-API.adoc[] include::MissionArchive-API.adoc[] +include::Mission-API.adoc[] + +include::Board-API.adoc[] + diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java b/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java new file mode 100644 index 00000000..b1d6209b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.board.application.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class CreateBoardRequest { + @NotBlank(message = "title 을 입력해 주세요.") + @Size(min = 1, max = 15, message = "title 은 최소 1개, 최대 15개의 문자만 입력 가능합니다.") + private String title; + + @NotBlank(message = "content 을 입력해 주세요.") + @Size(min = 1, max = 300, message = "content 은 최소 1개, 최대 10개의 문자만 입력 가능합니다.") + private String content; + + @NotNull(message = "notice 사용 여부(isNotice) 를 입력해 주세요.") + private Boolean isNotice; +} diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/request/UpdateBoardRequest.java b/src/main/java/com/moing/backend/domain/board/application/dto/request/UpdateBoardRequest.java new file mode 100644 index 00000000..685ee2ba --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/dto/request/UpdateBoardRequest.java @@ -0,0 +1,23 @@ +package com.moing.backend.domain.board.application.dto.request; + +import lombok.Builder; +import lombok.Getter; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +@Getter +@Builder +public class UpdateBoardRequest { + @NotBlank(message = "title 을 입력해 주세요.") + @Size(min = 1, max = 15, message = "title 은 최소 1개, 최대 15개의 문자만 입력 가능합니다.") + private String title; + + @NotBlank(message = "content 을 입력해 주세요.") + @Size(min = 1, max = 300, message = "content 은 최소 1개, 최대 10개의 문자만 입력 가능합니다.") + private String content; + + @NotNull(message = "notice 사용 여부(isNotice) 를 입력해 주세요.") + private Boolean isNotice; +} diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java new file mode 100644 index 00000000..08d453bd --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java @@ -0,0 +1,23 @@ +package com.moing.backend.domain.board.application.dto.response; + +import lombok.Getter; + +@Getter +public class BoardBlocks { + + private Long boardId; + + private String writerNickName; + + private Boolean isLeader; + + private String writerProfileImage; + + private String title; + + private String content; + + private Integer commentNum; + + private Boolean isRead; +} diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/CreateBoardResponse.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/CreateBoardResponse.java new file mode 100644 index 00000000..75662b71 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/CreateBoardResponse.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.board.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class CreateBoardResponse { + private Long boardId; +} diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/GetAllBoardResponse.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/GetAllBoardResponse.java new file mode 100644 index 00000000..b2d200ab --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/GetAllBoardResponse.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.board.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class GetAllBoardResponse { + private Long noticeNum; + private List notices=new ArrayList<>(); + private Long notNoticeNum; + private List notNotices=new ArrayList<>(); +} diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/UpdateBoardResponse.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/UpdateBoardResponse.java new file mode 100644 index 00000000..48b4b114 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/UpdateBoardResponse.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.board.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@Builder +public class UpdateBoardResponse { + private Long boardId; +} diff --git a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java new file mode 100644 index 00000000..c10a0659 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java @@ -0,0 +1,29 @@ +package com.moing.backend.domain.board.application.mapper; + +import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class BoardMapper { + + public Board toBoard(Member member, TeamMember teamMember, Team team, CreateBoardRequest createBoardRequest, boolean isLeader) { + Board board = Board.builder() + .writerNickName(member.getNickName()) + .writerProfileImage(member.getProfileImage()) + .title(createBoardRequest.getTitle()) + .content(createBoardRequest.getContent()) + .isNotice(createBoardRequest.getIsNotice()) + .commentNum(0) + .isLeader(isLeader) + .build(); + board.updateTeamMember(teamMember); + board.updateTeam(team); + return board; + } +} diff --git a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java new file mode 100644 index 00000000..9c2c615f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java @@ -0,0 +1,46 @@ +package com.moing.backend.domain.board.application.service; + +import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; +import com.moing.backend.domain.board.application.dto.response.CreateBoardResponse; +import com.moing.backend.domain.board.application.mapper.BoardMapper; +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.service.BoardSaveService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.application.service.CheckLeaderUserCase; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.config.security.dto.User; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CreateBoardUserCase { + + private final MemberGetService memberGetService; + private final BoardSaveService boardSaveService; + private final CheckLeaderUserCase checkLeaderUserCase; + private final TeamGetService teamGetService; + private final BoardMapper boardMapper; + private final TeamMemberGetService teamMemberGetService; + + /** + * 게시글 생성 + * @param user + * @param teamId + * @param createBoardRequest + * @return CreateBoardResponse + */ + public CreateBoardResponse createBoard(User user, Long teamId, CreateBoardRequest createBoardRequest) { + Member member = memberGetService.getMemberBySocialId(user.getSocialId()); + Team team = teamGetService.getTeamByTeamId(teamId); + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + boolean isLeader = checkLeaderUserCase.isTeamLeader(member, team); + Board board = boardMapper.toBoard(member, teamMember, team, createBoardRequest, isLeader); + boardSaveService.saveBoard(board); + return new CreateBoardResponse(board.getBoardId()); + } +} diff --git a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java new file mode 100644 index 00000000..20cf5fba --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java @@ -0,0 +1,10 @@ +package com.moing.backend.domain.board.application.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class GetBoardUserCase { + +} diff --git a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java new file mode 100644 index 00000000..71a8574b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java @@ -0,0 +1,37 @@ +package com.moing.backend.domain.board.application.service; + +import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; +import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; +import com.moing.backend.domain.board.application.mapper.BoardMapper; +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.board.domain.service.BoardSaveService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.application.service.CheckLeaderUserCase; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@RequiredArgsConstructor +public class UpdateBoardUserCase { + private final MemberGetService memberGetService; + private final BoardSaveService boardSaveService; + private final CheckLeaderUserCase checkLeaderUserCase; + private final TeamGetService teamGetService; + private final BoardMapper boardMapper; + private final BoardGetService boardGetService; + + @Transactional + public UpdateBoardResponse updateBoard(String socialId, Long teamId, Long boardId, UpdateBoardRequest updateBoardRequest){ + Member member=memberGetService.getMemberBySocialId(socialId); + Board board=boardGetService.getBoard(boardId); + board.updateBoard(updateBoardRequest); + return new UpdateBoardResponse(board.getBoardId()); + } +} diff --git a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java new file mode 100644 index 00000000..d6034391 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java @@ -0,0 +1,86 @@ +package com.moing.backend.domain.board.domain.entity; + +import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; +import com.moing.backend.domain.boardRead.domain.entity.BoardRead; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.global.entity.BaseTimeEntity; +import com.moing.backend.global.util.AesConverter; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class Board extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "board_id") + private Long boardId; + + //반정규화 -> 작성자에 대한 정보 + @Convert(converter = AesConverter.class) + @Column(nullable = false) + private String writerNickName; + + private boolean isLeader; + + private String writerProfileImage; + + @Column(nullable = false, length = 15) + private String title; + + @Column(nullable = false, length = 300) + private String content; + + private boolean isNotice; + + //반정규화 -> 댓글 개수 + private Integer commentNum; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team_member_id") + private TeamMember teamMember; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team_id") + private Team team; + + @OneToMany(mappedBy = "board", cascade = CascadeType.ALL) + private List boardReads = new ArrayList<>(); + + + public void incrComNum() { + this.commentNum++; + } + + public void decrComNum() { + this.commentNum--; + } + + public void updateBoard(UpdateBoardRequest updateBoardRequest){ + this.title= updateBoardRequest.getTitle(); + this.content= updateBoardRequest.getContent(); + this.isNotice= updateBoardRequest.getIsNotice(); + } + + //==연관관계 메서드 ==// + public void updateTeamMember(TeamMember teamMember) { + this.teamMember = teamMember; + } + + public void updateTeam(Team team) { + this.team = team; + } +} diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java new file mode 100644 index 00000000..ef5053e3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java @@ -0,0 +1,4 @@ +package com.moing.backend.domain.board.domain.repository; + +public interface BoardCustomRepository { +} diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomerRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomerRepositoryImpl.java new file mode 100644 index 00000000..668825cf --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomerRepositoryImpl.java @@ -0,0 +1,4 @@ +package com.moing.backend.domain.board.domain.repository; + +public class BoardCustomerRepositoryImpl implements BoardCustomRepository{ +} diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardRepository.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardRepository.java new file mode 100644 index 00000000..4059cec3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardRepository.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.board.domain.repository; + +import com.moing.backend.domain.board.domain.entity.Board; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface BoardRepository extends JpaRepository, BoardCustomRepository { + + Optional findBoardByBoardId(Long boardId); +} diff --git a/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java b/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java new file mode 100644 index 00000000..88cc75e0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java @@ -0,0 +1,22 @@ +package com.moing.backend.domain.board.domain.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.repository.BoardRepository; +import com.moing.backend.domain.board.exception.NotFoundByBoardIdException; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; +import java.util.Optional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class BoardGetService { + + private final BoardRepository boardRepository; + + public Board getBoard(Long boardId){ + return boardRepository.findBoardByBoardId(boardId).orElseThrow(()->new NotFoundByBoardIdException()); + } +} diff --git a/src/main/java/com/moing/backend/domain/board/domain/service/BoardSaveService.java b/src/main/java/com/moing/backend/domain/board/domain/service/BoardSaveService.java new file mode 100644 index 00000000..33c8a180 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/domain/service/BoardSaveService.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.board.domain.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.repository.BoardRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class BoardSaveService { + + private final BoardRepository boardRepository; + + public void saveBoard(Board board) { + this.boardRepository.save(board); + } +} diff --git a/src/main/java/com/moing/backend/domain/board/exception/BoardException.java b/src/main/java/com/moing/backend/domain/board/exception/BoardException.java new file mode 100644 index 00000000..d0502d4e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/exception/BoardException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.board.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class BoardException extends ApplicationException { + protected BoardException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/board/exception/NotFoundByBoardIdException.java b/src/main/java/com/moing/backend/domain/board/exception/NotFoundByBoardIdException.java new file mode 100644 index 00000000..e9fbb6c7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/exception/NotFoundByBoardIdException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.board.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundByBoardIdException extends BoardException { + public NotFoundByBoardIdException() { + super(ErrorCode.NOT_FOUND_BY_BOARD_ID_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java new file mode 100644 index 00000000..a3b86e9c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java @@ -0,0 +1,54 @@ +package com.moing.backend.domain.board.presentation; + +import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; +import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; +import com.moing.backend.domain.board.application.dto.response.CreateBoardResponse; +import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; +import com.moing.backend.domain.board.application.service.CreateBoardUserCase; +import com.moing.backend.domain.board.application.service.UpdateBoardUserCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +import static com.moing.backend.domain.board.presentation.constant.BoardResponseMessage.CREATE_BOARD_SUCCESS; +import static com.moing.backend.domain.board.presentation.constant.BoardResponseMessage.UPDATE_BOARD_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/{teamId}/board") +public class BoardController { + + private final CreateBoardUserCase createBoardUserCase; + private final UpdateBoardUserCase updateBoardUserCase; + + /** + * 게시글 생성 + * [POST] api/{teamId}/board + * 작성자 : 김민수 + */ + @PostMapping + public ResponseEntity> createBoard(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @Valid @RequestBody CreateBoardRequest createBoardRequest) { + return ResponseEntity.ok(SuccessResponse.create(CREATE_BOARD_SUCCESS.getMessage(), this.createBoardUserCase.createBoard(user, teamId, createBoardRequest))); + } + + /** + * 게시글 수정 + * [PUT] api/{teamId}/board/{boardId} + * 작성자 : 김민수 + */ + + @PutMapping("/{boardId}") + public ResponseEntity> updateBoard(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long boardId, + @Valid @RequestBody UpdateBoardRequest updateBoardRequest) { + return ResponseEntity.ok(SuccessResponse.create(UPDATE_BOARD_SUCCESS.getMessage(), this.updateBoardUserCase.updateBoard(user.getSocialId(), teamId, boardId, updateBoardRequest))); + } +} diff --git a/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java b/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java new file mode 100644 index 00000000..65a9fbcd --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.board.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum BoardResponseMessage { + CREATE_BOARD_SUCCESS("게시글을 생성했습니다."), + GET_BOARD_ALL_SUCCESS("게시글 목록을 모두 조회했습니다."), + UPDATE_BOARD_SUCCESS("게시글을 수정했습니다."); + private final String message; +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/BoardComment.java b/src/main/java/com/moing/backend/domain/boardComment/domain/BoardComment.java new file mode 100644 index 00000000..e3b39428 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/BoardComment.java @@ -0,0 +1,33 @@ +package com.moing.backend.domain.boardComment.domain; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class BoardComment extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "board_comment_id") + private Long boardCommentId; + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team_member_id") + private TeamMember teamMember; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "board_id") + private Board board; +} diff --git a/src/main/java/com/moing/backend/domain/boardRead/domain/entity/BoardRead.java b/src/main/java/com/moing/backend/domain/boardRead/domain/entity/BoardRead.java new file mode 100644 index 00000000..4c5d6334 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardRead/domain/entity/BoardRead.java @@ -0,0 +1,53 @@ +package com.moing.backend.domain.boardRead.domain.entity; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class BoardRead { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "board_read_id") + private Long boardReadId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "board_id") + private Board board; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team__id") + private Team team; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "Member_id") + private Member member; + + + /** + * 연관관계 매핑 + */ + public void updateBoard(Board board) { + this.board = board; + board.getBoardReads().add(this); + } + + public void updateTeam(Team team) { + this.team = team; + } + + public void updateMember(Member member) { + this.member = member; + } +} diff --git a/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java b/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java index df55b8a7..e31a33e0 100644 --- a/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java +++ b/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java @@ -7,9 +7,6 @@ import com.moing.backend.domain.member.domain.entity.Member; import org.springframework.stereotype.Component; -import java.time.LocalDate; -import java.time.LocalDateTime; - @Component public class MemberMapper { diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index 2118d7f0..327adba1 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -1,9 +1,26 @@ package com.moing.backend.domain.team.application.mapper; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; +import com.moing.backend.domain.team.domain.constant.ApprovalStatus; +import com.moing.backend.domain.team.domain.constant.Category; import com.moing.backend.domain.team.domain.entity.Team; import org.springframework.stereotype.Component; @Component public class TeamMapper { + + public Team createTeam(CreateTeamRequest createTeamRequest, Member member) { + return Team.builder() + .category(Enum.valueOf(Category.class, createTeamRequest.getCategory())) + .name(createTeamRequest.getName()) + .introduction(createTeamRequest.getIntroduction()) + .promise(createTeamRequest.getPromise()) + .profileImgUrl(createTeamRequest.getProfileImgUrl()) + .approvalStatus(ApprovalStatus.NO_CONFIRMATION) + .leaderId(member.getMemberId()) + .numOfMember(0) + .levelOfFire(1) + .build(); + } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java index b5b3f423..6513c478 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; +import com.moing.backend.domain.team.application.mapper.TeamMapper; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamSaveService; import com.moing.backend.domain.teamMember.domain.service.TeamMemberSaveService; @@ -20,10 +21,11 @@ public class CreateTeamUserCase { private final MemberGetService memberGetService; private final TeamSaveService teamSaveService; private final TeamMemberSaveService teamMemberSaveService; + private final TeamMapper teamMapper; public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String socialId){ Member member = memberGetService.getMemberBySocialId(socialId); - Team team=Team.createTeam(createTeamRequest, member); + Team team=teamMapper.createTeam(createTeamRequest, member); teamSaveService.saveTeam(team); teamMemberSaveService.addTeamMember(team, member); //====지워야 함 (테스트 용)===== diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java index a7fef763..1b4f531e 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -1,8 +1,6 @@ package com.moing.backend.domain.team.domain.entity; -import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.moing.backend.domain.team.domain.constant.Category; import com.moing.backend.global.entity.BaseTimeEntity; @@ -66,20 +64,6 @@ public class Team extends BaseTimeEntity { @OneToMany(mappedBy = "team") List missions = new ArrayList<>(); - public static Team createTeam(CreateTeamRequest createTeamRequest, Member member) { - return Team.builder() - .category(Enum.valueOf(Category.class, createTeamRequest.getCategory())) - .name(createTeamRequest.getName()) - .introduction(createTeamRequest.getIntroduction()) - .promise(createTeamRequest.getPromise()) - .profileImgUrl(createTeamRequest.getProfileImgUrl()) - .approvalStatus(ApprovalStatus.NO_CONFIRMATION) - .leaderId(member.getMemberId()) - .numOfMember(0) - .levelOfFire(1) - .build(); - } - public void approveTeam() { this.approvalStatus = ApprovalStatus.APPROVAL; this.approvalTime = LocalDateTime.now(ZoneId.of("Asia/Seoul")).withNano(0); diff --git a/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetailsService.java b/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetailsService.java index 07a328ad..c48027a9 100644 --- a/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetailsService.java +++ b/src/main/java/com/moing/backend/global/config/security/oauth/CustomUserDetailsService.java @@ -12,12 +12,12 @@ @Service @RequiredArgsConstructor public class CustomUserDetailsService implements UserDetailsService { - private final MemberGetService memberQueryService; + private final MemberGetService memberGetService; @Override @Transactional(readOnly = true) public UserDetails loadUserByUsername(String socialId) throws UsernameNotFoundException { - Member member = this.memberQueryService.getMemberBySocialId(socialId); + Member member = this.memberGetService.getMemberBySocialId(socialId); if (member == null) { throw new UsernameNotFoundException("User not found with socialId: " + socialId); diff --git a/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java b/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java index 492e6528..7a5b3529 100644 --- a/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java @@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -39,6 +40,11 @@ public ResponseEntity inputPatternSyntaxExceptionHandler(PatternS return handleException(ex, ErrorCode.BAD_REQUEST, ErrorCode.BAD_REQUEST.getMessage(), HttpStatus.BAD_REQUEST, log::warn); } + @ExceptionHandler(HttpMessageNotReadableException.class) + public ResponseEntity jsonParseExceptionHandler(HttpMessageNotReadableException ex) { + return handleException(ex, ErrorCode.BAD_REQUEST, ErrorCode.BAD_REQUEST.getMessage(), HttpStatus.BAD_REQUEST, log::warn); + } + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public ResponseEntity httpRequestNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException ex) { return handleException(ex, ErrorCode.METHOD_NOT_ALLOWED, ErrorCode.METHOD_NOT_ALLOWED.getMessage(), HttpStatus.METHOD_NOT_ALLOWED, log::warn); @@ -50,7 +56,7 @@ public ResponseEntity internalServerErrorHandler(Exception ex) { } private ResponseEntity handleException(Exception ex, ErrorCode errorCode, String message, HttpStatus httpStatus, Consumer logger) { - logger.accept(String.format(LOG_FORMAT, ex.getClass().getSimpleName(), errorCode.getErrorCode(), ex.getMessage())); + log.error(LOG_FORMAT, ex.getClass().getSimpleName(), errorCode.getErrorCode(), ex.getMessage()); ErrorResponse errorResponse = new ErrorResponse(errorCode, message); return ResponseEntity.status(httpStatus.value()).body(errorResponse); } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 6574d86f..dda3ec42 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -8,7 +8,7 @@ @AllArgsConstructor public enum ErrorCode { - BAD_REQUEST("400", "올바른 패턴을 입력하세요."), + BAD_REQUEST("400", "입력값이 유효하지 않습니다."), METHOD_NOT_ALLOWED("405", "클라이언트가 사용한 HTTP 메서드가 리소스에서 허용되지 않습니다."), INTERNAL_SERVER_ERROR("500", "서버에서 요청을 처리하는 동안 오류가 발생했습니다."), NOT_FOUND_REFRESH_TOKEN_ERROR( "J0008", "유효하지 않는 RefreshToken 입니다."), @@ -30,7 +30,10 @@ public enum ErrorCode { //팀 관련 에러 코드 NOT_FOUND_BY_TEAM_ID_ERROR("T0001", "해당 teamId인 팀이 존재하지 않습니다."), - NOT_AUTH_BY_TEAM_ERROR("T0002","권한이 없습니다."); + NOT_AUTH_BY_TEAM_ERROR("T0002","권한이 없습니다."), + + //게시글 관련 에러 코드 + NOT_FOUND_BY_BOARD_ID_ERROR("B0001","해당 boardId인 팀이 존재하지 않습니다."); private String errorCode; private String message; diff --git a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java new file mode 100644 index 00000000..bb368b7a --- /dev/null +++ b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java @@ -0,0 +1,131 @@ +package com.moing.backend.domain.board.presentation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; +import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; +import com.moing.backend.domain.board.application.dto.response.CreateBoardResponse; +import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; +import com.moing.backend.domain.board.application.service.CreateBoardUserCase; +import com.moing.backend.domain.board.application.service.UpdateBoardUserCase; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(BoardController.class) +public class BoardControllerTest extends CommonControllerTest { + @MockBean + private CreateBoardUserCase createBoardUserCase; + @MockBean + private UpdateBoardUserCase updateBoardUserCase; + + @Test + public void create_board() throws Exception { + + //given + Long teamId = 1L; + CreateBoardRequest input = CreateBoardRequest.builder() + .title("게시글 제목") + .content("게시글 내용") + .isNotice(false) + .build(); + + String body = objectMapper.writeValueAsString(input); + + CreateBoardResponse output = CreateBoardResponse.builder() + .boardId(1L) + .build(); + + given(createBoardUserCase.createBoard(any(), any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + post("/api/{teamId}/board", teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + requestFields( + fieldWithPath("title").description("게시글 제목"), + fieldWithPath("content").description("게시글 내용"), + fieldWithPath("isNotice").description("공지 여부") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("게시글을 생성했습니다"), + fieldWithPath("data.boardId").description("생성한 boardId") + ) + ) + ); + } + + @Test + public void update_board() throws Exception { + + //given + Long teamId = 1L; + Long boardId = 1L; + UpdateBoardRequest input = UpdateBoardRequest.builder() + .title("게시글 제목") + .content("게시글 내용") + .isNotice(false) + .build(); + + String body = objectMapper.writeValueAsString(input); + + UpdateBoardResponse output = UpdateBoardResponse.builder() + .boardId(1L) + .build(); + + given(updateBoardUserCase.updateBoard(any(), any(), any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + put("/api/{teamId}/board/{boardId}", teamId, boardId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + requestFields( + fieldWithPath("title").description("게시글 제목"), + fieldWithPath("content").description("게시글 내용"), + fieldWithPath("isNotice").description("공지 여부") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("게시글을 수정했습니다"), + fieldWithPath("data.boardId").description("수정한 boardId") + ) + ) + ); + } +} From ecaf7d0326c53db23296c677347caa5d8fc34111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 30 Sep 2023 03:17:51 +0900 Subject: [PATCH 098/619] =?UTF-8?q?feat=20:=20@/@=EB=AA=85=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=84=B1=EA=B3=B5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/MissionArchiveStatusRes.java | 11 +++++++++++ .../service/SingleMissionArchiveReadUseCase.java | 14 ++++++++++++++ .../constant/MissionArchiveResponseMessage.java | 3 ++- .../repository/MissionArchiveCustomRepository.java | 3 +++ .../MissionArchiveCustomRepositoryImpl.java | 13 +++++++++++++ .../domain/service/MissionArchiveQueryService.java | 4 ++++ .../presentation/MissionArchiveController.java | 11 +++++++++++ 7 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveStatusRes.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveStatusRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveStatusRes.java new file mode 100644 index 00000000..67216a52 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveStatusRes.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.missionArchive.application.dto.res; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class MissionArchiveStatusRes { + private String total; + private String done; +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java index 1959984e..87204ea6 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java @@ -5,11 +5,13 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.repository.TeamRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -28,6 +30,7 @@ public class SingleMissionArchiveReadUseCase { private final MemberGetService memberGetService; private final MissionQueryService missionQueryService; private final MissionArchiveQueryService missionArchiveQueryService; + private final TeamRepository teamRepository; // 미션 인증 조회 @@ -51,5 +54,16 @@ public List getPersonalArchive(String userSocialId,Long mission // return personalArchives; } + public MissionArchiveStatusRes getMissionDoneStatus(Long missionId) { + Mission mission = missionQueryService.findMissionById(missionId); + Team team = mission.getTeam(); + + return MissionArchiveStatusRes.builder() + .total(team.getNumOfMember().toString()) + .done(missionArchiveQueryService.findDoneArchives(missionId).toString()) + .build(); + + } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java index 39750179..5cda14a5 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java @@ -11,7 +11,8 @@ public enum MissionArchiveResponseMessage { READ_MY_ARCHIVE_SUCCESS("나의 미션 인증 현황 조회를 완료 했습니다."), READ_TEAM_ARCHIVE_SUCCESS("팀원 미션 인증 현황 조회를 완료 했습니다."), HEART_UPDATE_SUCCESS("미션 인증 좋아요를 성공적으로 눌렀습니다."), - ACTIVE_SINGLE_MISSION_SUCCESS("진행 중인 한번 인증 미션 조회를 완료하였습니다."), + MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS("미션 인증 성공한 인원 상태 조회를 완료 했습니다."), + ACTIVE_SINGLE_MISSION_SUCCESS("진행 중인 한번 인증 미션 조회를 완료 했습니다."), FINISH_ALL_MISSION_SUCCESS("종료된 미션 조회를 완료하였습니다."); private final String message; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index ee7ca799..19273667 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -14,5 +14,8 @@ public interface MissionArchiveCustomRepository { Optional> findAllMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus missionStatus); + Optional findDonePeopleByMissionId(Long missionId); + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index a8fba537..1c4bff6e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -92,5 +92,18 @@ public Optional> findAllMissionArchivesByMemberId(Long memb ); } + @Override + public Optional findDonePeopleByMissionId(Long missionId) { + return Optional.ofNullable(queryFactory + .select(missionArchive.count()) + .from(missionArchive) + .where( + missionArchive.mission.id.eq(missionId) + ) + .fetchFirst() + + ); + } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 77891d9b..9b3c968c 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -87,6 +87,10 @@ public List findMyAllMissionArchives(Long memberId, Long teamId, return missionArchiveRepository.findAllMissionArchivesByMemberId(memberId, teamId, missionStatus).orElseThrow(NotFoundMissionArchiveException::new); } + public Long findDoneArchives(Long missionId) { + return missionArchiveRepository.findDonePeopleByMissionId(missionId).orElseThrow(NotFoundMissionArchiveException::new); + } + diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index d89372cb..6ced5bf5 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveHeartReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateUseCase; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveHeartUseCase; @@ -84,6 +85,16 @@ public ResponseEntity>> getOtherPeopleArch return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(user.getSocialId(),missionId))); } + + + @GetMapping("/status") + public ResponseEntity> getMissionDoneStatus(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getMissionDoneStatus(missionId))); + } + + @PostMapping("/hearts") public ResponseEntity> pushHeart(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, From 10a71429e9690821212f0b9ad3bc373d21d78404 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 30 Sep 2023 12:56:40 +0900 Subject: [PATCH 099/619] =?UTF-8?q?feat:=20Board=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EB=8B=A8=EA=B1=B4=20=EC=A1=B0=ED=9A=8C,=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Board-API.adoc | 9 +- src/docs/asciidoc/Team-API.adoc | 6 +- src/docs/asciidoc/api.adoc | 2 - .../application/dto/response/BoardBlocks.java | 23 ++- .../dto/response/GetAllBoardResponse.java | 8 +- .../dto/response/GetBoardDetailResponse.java | 31 ++++ .../board/application/mapper/BoardMapper.java | 26 +++ .../service/CreateBoardUserCase.java | 24 ++- .../application/service/GetBoardUserCase.java | 41 +++++ .../service/UpdateBoardUserCase.java | 24 +-- .../domain/board/domain/entity/Board.java | 6 +- .../repository/BoardCustomRepository.java | 3 + .../repository/BoardCustomRepositoryImpl.java | 67 ++++++++ .../BoardCustomerRepositoryImpl.java | 4 - .../board/domain/service/BoardGetService.java | 6 + .../domain/service/BoardSaveService.java | 4 +- .../board/presentation/BoardController.java | 34 +++- .../constant/BoardResponseMessage.java | 3 +- .../application/mapper/BoardReadMapper.java | 17 ++ .../repository/BoardReadRepository.java | 13 ++ .../domain/service/BoardReadSaveService.java | 24 +++ .../repository/TeamMemberRepository.java | 3 +- .../domain/service/TeamMemberGetService.java | 3 +- .../presentation/BoardControllerTest.java | 162 +++++++++++++++++- .../team/presentation/TeamControllerTest.java | 25 ++- 25 files changed, 511 insertions(+), 57 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/board/application/dto/response/GetBoardDetailResponse.java create mode 100644 src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java delete mode 100644 src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomerRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/boardRead/application/mapper/BoardReadMapper.java create mode 100644 src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java create mode 100644 src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java diff --git a/src/docs/asciidoc/Board-API.adoc b/src/docs/asciidoc/Board-API.adoc index 451cd602..91c9cca7 100644 --- a/src/docs/asciidoc/Board-API.adoc +++ b/src/docs/asciidoc/Board-API.adoc @@ -3,10 +3,15 @@ [[Board-게시글-생성]] === Board 게시글 생성 -operation::board-controller-test/create_board[snippets='http-request,request-fields,http-response,response-fields'] +operation::board-controller-test/create_board[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- [[Board-게시글-수정]] === Board 게시글 수정 -operation::board-controller-test/update_board[snippets='http-request,request-fields,http-response,response-fields'] +operation::board-controller-test/update_board[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +--- + +[[Board-게시글-전체-조회]] +=== Board 게시글 전체 조회 +operation::board-controller-test/get_board_all[snippets='http-request,path-parameters,http-response,response-fields'] --- \ No newline at end of file diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc index 05ff32e3..c4269911 100644 --- a/src/docs/asciidoc/Team-API.adoc +++ b/src/docs/asciidoc/Team-API.adoc @@ -31,7 +31,7 @@ operation::team-controller-test/create_team[snippets='http-request,request-field [[Team-소모임-가입]] === Team 소모임 가입 -operation::team-controller-test/sign-in_team[snippets='http-request,http-response,response-fields'] +operation::team-controller-test/sign-in_team[snippets='http-request,path-parameters,http-response,response-fields'] [[Team-소모임-조회]] @@ -40,8 +40,8 @@ operation::team-controller-test/get_team[snippets='http-request,http-response,re [[Team-소모임-강제종료]] === Team 소모임 강제종료 -operation::team-controller-test/disband_team[snippets='http-request,http-response,response-fields'] +operation::team-controller-test/disband_team[snippets='http-request,path-parameters,http-response,response-fields'] [[Team-소모임-탈퇴]] === Team 소모임원 강제종료 -operation::team-controller-test/withdraw_team[snippets='http-request,http-response,response-fields'] +operation::team-controller-test/withdraw_team[snippets='http-request,path-parameters,http-response,response-fields'] diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 26bed444..31ab6d71 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -20,8 +20,6 @@ include::Mission-API.adoc[] include::MissionArchive-API.adoc[] -include::Mission-API.adoc[] - include::Board-API.adoc[] diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java index 08d453bd..eb878fb8 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java @@ -1,15 +1,20 @@ package com.moing.backend.domain.board.application.dto.response; +import com.querydsl.core.annotations.QueryProjection; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; @Getter +@Builder +@AllArgsConstructor public class BoardBlocks { private Long boardId; private String writerNickName; - private Boolean isLeader; + private Boolean writerIsLeader; private String writerProfileImage; @@ -20,4 +25,20 @@ public class BoardBlocks { private Integer commentNum; private Boolean isRead; + + @QueryProjection + public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, String writerProfileImage, String title, String content, Integer commentNum) { + this.boardId = boardId; + this.writerNickName = writerNickName; + this.writerIsLeader = writerIsLeader; + this.writerProfileImage = writerProfileImage; + this.title = title; + this.content = content; + this.commentNum = commentNum; + this.isRead = false; + } + + public void readBoard() { + this.isRead = true; + } } diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/GetAllBoardResponse.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/GetAllBoardResponse.java index b2d200ab..f020d9e7 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/response/GetAllBoardResponse.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/GetAllBoardResponse.java @@ -13,8 +13,8 @@ @NoArgsConstructor @Getter public class GetAllBoardResponse { - private Long noticeNum; - private List notices=new ArrayList<>(); - private Long notNoticeNum; - private List notNotices=new ArrayList<>(); + private int noticeNum; + private List noticeBlocks=new ArrayList<>(); + private int notNoticeNum; + private List notNoticeBlocks=new ArrayList<>(); } diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/GetBoardDetailResponse.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/GetBoardDetailResponse.java new file mode 100644 index 00000000..9d9b4197 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/GetBoardDetailResponse.java @@ -0,0 +1,31 @@ +package com.moing.backend.domain.board.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class GetBoardDetailResponse { + + private Long boardId; + + private String writerNickName; + + private Boolean writerIsLeader; + + private String writerProfileImage; + + private String title; + + private String content; + + private String createdDate; + + private Boolean isWriter; + + private Boolean isNotice; +} diff --git a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java index c10a0659..a32c8452 100644 --- a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java +++ b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.board.application.mapper; import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; +import com.moing.backend.domain.board.application.dto.response.GetBoardDetailResponse; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; @@ -8,6 +9,10 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; + @Component @RequiredArgsConstructor public class BoardMapper { @@ -21,9 +26,30 @@ public Board toBoard(Member member, TeamMember teamMember, Team team, CreateBoar .isNotice(createBoardRequest.getIsNotice()) .commentNum(0) .isLeader(isLeader) + .boardReads(new ArrayList<>()) .build(); board.updateTeamMember(teamMember); board.updateTeam(team); return board; } + + public GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter) { + return GetBoardDetailResponse.builder() + .boardId(board.getBoardId()) + .title(board.getTitle()) + .content(board.getContent()) + .writerNickName(board.getWriterNickName()) + .writerIsLeader(board.isLeader()) + .writerProfileImage(board.getWriterProfileImage()) + .createdDate(getFormattedDate(board.getCreatedDate())) + .isWriter(isWriter) + .isNotice(board.isNotice()) + .build(); + } + + public String getFormattedDate(LocalDateTime localDateTime) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"); + return localDateTime.format(formatter); + } + } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java index 9c2c615f..25576f2d 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java @@ -5,6 +5,9 @@ import com.moing.backend.domain.board.application.mapper.BoardMapper; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardSaveService; +import com.moing.backend.domain.boardRead.application.mapper.BoardReadMapper; +import com.moing.backend.domain.boardRead.domain.entity.BoardRead; +import com.moing.backend.domain.boardRead.domain.service.BoardReadSaveService; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.team.application.service.CheckLeaderUserCase; @@ -16,31 +19,34 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import javax.transaction.Transactional; + @Service +@Transactional @RequiredArgsConstructor public class CreateBoardUserCase { - private final MemberGetService memberGetService; private final BoardSaveService boardSaveService; private final CheckLeaderUserCase checkLeaderUserCase; private final TeamGetService teamGetService; private final BoardMapper boardMapper; private final TeamMemberGetService teamMemberGetService; + private final BoardReadMapper boardReadMapper; + private final BoardReadSaveService boardReadSaveService; /** * 게시글 생성 - * @param user - * @param teamId - * @param createBoardRequest - * @return CreateBoardResponse */ - public CreateBoardResponse createBoard(User user, Long teamId, CreateBoardRequest createBoardRequest) { - Member member = memberGetService.getMemberBySocialId(user.getSocialId()); + public CreateBoardResponse createBoard(String socialId, Long teamId, CreateBoardRequest createBoardRequest) { + Member member=memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); boolean isLeader = checkLeaderUserCase.isTeamLeader(member, team); - Board board = boardMapper.toBoard(member, teamMember, team, createBoardRequest, isLeader); - boardSaveService.saveBoard(board); + Board board=boardSaveService.saveBoard(boardMapper.toBoard(member, teamMember, team, createBoardRequest, isLeader)); + + //읽음 처리 + BoardRead boardRead = boardReadMapper.toBoardRead(team, member); + boardReadSaveService.saveBoardRead(board, boardRead); return new CreateBoardResponse(board.getBoardId()); } } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java index 20cf5fba..6be225ae 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java @@ -1,10 +1,51 @@ package com.moing.backend.domain.board.application.service; +import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; +import com.moing.backend.domain.board.application.dto.response.GetBoardDetailResponse; +import com.moing.backend.domain.board.application.mapper.BoardMapper; +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.boardRead.application.mapper.BoardReadMapper; +import com.moing.backend.domain.boardRead.domain.entity.BoardRead; +import com.moing.backend.domain.boardRead.domain.service.BoardReadSaveService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import javax.transaction.Transactional; + @Service +@Transactional @RequiredArgsConstructor public class GetBoardUserCase { + private final MemberGetService memberGetService; + private final BoardGetService boardGetService; + private final BoardMapper boardMapper; + private final TeamGetService teamGetService; + private final BoardReadMapper boardReadMapper; + private final BoardReadSaveService boardReadSaveService; + private final TeamMemberGetService teamMemberGetService; + + public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long boardId) { + Member member=memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + Board board = boardGetService.getBoard(boardId); + TeamMember teamMember=teamMemberGetService.getTeamMember(member, team); + //읽음 처리 + BoardRead boardRead = boardReadMapper.toBoardRead(team, member); + boardReadSaveService.saveBoardRead(board, boardRead); + + return boardMapper.toBoardDetail(board, teamMember==board.getTeamMember()); + } + + public GetAllBoardResponse getAllBoard(String socialId, Long teamId){ + Member member=memberGetService.getMemberBySocialId(socialId); + return boardGetService.getBoardAll(teamId, member.getMemberId()); + } } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java index 71a8574b..f11512cf 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java @@ -2,15 +2,14 @@ import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; -import com.moing.backend.domain.board.application.mapper.BoardMapper; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardGetService; -import com.moing.backend.domain.board.domain.service.BoardSaveService; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.application.service.CheckLeaderUserCase; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.team.exception.NotAuthException; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -18,20 +17,25 @@ import javax.transaction.Transactional; @Service +@Transactional @RequiredArgsConstructor public class UpdateBoardUserCase { private final MemberGetService memberGetService; - private final BoardSaveService boardSaveService; - private final CheckLeaderUserCase checkLeaderUserCase; private final TeamGetService teamGetService; - private final BoardMapper boardMapper; private final BoardGetService boardGetService; + private final TeamMemberGetService teamMemberGetService; - @Transactional + /** + * 게시글 수정 + */ public UpdateBoardResponse updateBoard(String socialId, Long teamId, Long boardId, UpdateBoardRequest updateBoardRequest){ Member member=memberGetService.getMemberBySocialId(socialId); - Board board=boardGetService.getBoard(boardId); - board.updateBoard(updateBoardRequest); - return new UpdateBoardResponse(board.getBoardId()); + Team team = teamGetService.getTeamByTeamId(teamId); + Board board = boardGetService.getBoard(boardId); + TeamMember teamMember=teamMemberGetService.getTeamMember(member, team); + if(teamMember==board.getTeamMember()) { + board.updateBoard(updateBoardRequest); + return new UpdateBoardResponse(board.getBoardId()); + }else throw new NotAuthException(); } } diff --git a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java index d6034391..cb73c2a7 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java +++ b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java @@ -32,11 +32,11 @@ public class Board extends BaseTimeEntity { //반정규화 -> 작성자에 대한 정보 @Convert(converter = AesConverter.class) @Column(nullable = false) - private String writerNickName; + private String writerNickName; /*작성자 닉네임*/ - private boolean isLeader; + private boolean isLeader; /*작성자 소모임장유무*/ - private String writerProfileImage; + private String writerProfileImage; /*작성자 프로필 사진*/ @Column(nullable = false, length = 15) private String title; diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java index ef5053e3..10d5ffbd 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java @@ -1,4 +1,7 @@ package com.moing.backend.domain.board.domain.repository; +import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; + public interface BoardCustomRepository { + GetAllBoardResponse findBoardAll(Long teamId, Long boardId); } diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java new file mode 100644 index 00000000..b1b0e863 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -0,0 +1,67 @@ +package com.moing.backend.domain.board.domain.repository; + +import com.moing.backend.domain.board.application.dto.response.BoardBlocks; +import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; +import com.moing.backend.domain.board.domain.entity.Board; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static com.moing.backend.domain.board.domain.entity.QBoard.board; +import static com.moing.backend.domain.boardRead.domain.entity.QBoardRead.boardRead; + +public class BoardCustomRepositoryImpl implements BoardCustomRepository { + private final JPAQueryFactory queryFactory; + + public BoardCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + @Override + public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { + // 전체 게시글 보기 + List allBoards = queryFactory.selectFrom(board) + .where(board.team.teamId.eq(teamId)) + .orderBy(board.createdDate.desc()) + .fetch(); + + // 읽은 게시글 보기 + List readBoards = queryFactory.selectFrom(board) + .join(boardRead).on(boardRead.board.eq(board)) + .where(board.team.teamId.eq(teamId)) + .where(boardRead.member.memberId.eq(memberId)) + .groupBy(board.boardId) + .orderBy(board.createdDate.desc()) + .fetch(); + + // 공지와 일반 게시글로 나누기 + List notices = allBoards.stream().filter(Board::isNotice).collect(Collectors.toList()); + List regularPosts = allBoards.stream().filter(b -> !b.isNotice()).collect(Collectors.toList()); + + // Board -> BoardBlocks 변환 + Function toBoardBlocks = b -> { + boolean isRead = readBoards.contains(b); + BoardBlocks boardBlocks = new BoardBlocks( + b.getBoardId(), + b.getWriterNickName(), + b.isLeader(), + b.getWriterProfileImage(), + b.getTitle(), + b.getContent(), + b.getCommentNum() + ); + if (isRead) { + boardBlocks.readBoard(); + } + return boardBlocks; + }; + + List noticeBlocks = notices.stream().map(toBoardBlocks).collect(Collectors.toList()); + List regularBlocks = regularPosts.stream().map(toBoardBlocks).collect(Collectors.toList()); + + return new GetAllBoardResponse(noticeBlocks.size(), noticeBlocks, regularBlocks.size(), regularBlocks); + } +} diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomerRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomerRepositoryImpl.java deleted file mode 100644 index 668825cf..00000000 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomerRepositoryImpl.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.moing.backend.domain.board.domain.repository; - -public class BoardCustomerRepositoryImpl implements BoardCustomRepository{ -} diff --git a/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java b/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java index 88cc75e0..f1c62e2e 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java +++ b/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java @@ -1,5 +1,7 @@ package com.moing.backend.domain.board.domain.service; +import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; +import com.moing.backend.domain.board.application.dto.response.GetBoardDetailResponse; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.repository.BoardRepository; import com.moing.backend.domain.board.exception.NotFoundByBoardIdException; @@ -19,4 +21,8 @@ public class BoardGetService { public Board getBoard(Long boardId){ return boardRepository.findBoardByBoardId(boardId).orElseThrow(()->new NotFoundByBoardIdException()); } + + public GetAllBoardResponse getBoardAll(Long teamId, Long memberId){ + return boardRepository.findBoardAll(teamId, memberId); + } } diff --git a/src/main/java/com/moing/backend/domain/board/domain/service/BoardSaveService.java b/src/main/java/com/moing/backend/domain/board/domain/service/BoardSaveService.java index 33c8a180..e2e800ff 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/service/BoardSaveService.java +++ b/src/main/java/com/moing/backend/domain/board/domain/service/BoardSaveService.java @@ -14,7 +14,7 @@ public class BoardSaveService { private final BoardRepository boardRepository; - public void saveBoard(Board board) { - this.boardRepository.save(board); + public Board saveBoard(Board board) { + return this.boardRepository.save(board); } } diff --git a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java index a3b86e9c..629eebeb 100644 --- a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java +++ b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java @@ -3,9 +3,13 @@ import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; import com.moing.backend.domain.board.application.dto.response.CreateBoardResponse; +import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; +import com.moing.backend.domain.board.application.dto.response.GetBoardDetailResponse; import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; import com.moing.backend.domain.board.application.service.CreateBoardUserCase; +import com.moing.backend.domain.board.application.service.GetBoardUserCase; import com.moing.backend.domain.board.application.service.UpdateBoardUserCase; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -15,8 +19,7 @@ import javax.validation.Valid; -import static com.moing.backend.domain.board.presentation.constant.BoardResponseMessage.CREATE_BOARD_SUCCESS; -import static com.moing.backend.domain.board.presentation.constant.BoardResponseMessage.UPDATE_BOARD_SUCCESS; +import static com.moing.backend.domain.board.presentation.constant.BoardResponseMessage.*; @RestController @AllArgsConstructor @@ -25,6 +28,7 @@ public class BoardController { private final CreateBoardUserCase createBoardUserCase; private final UpdateBoardUserCase updateBoardUserCase; + private final GetBoardUserCase getBoardUserCase; /** * 게시글 생성 @@ -35,7 +39,7 @@ public class BoardController { public ResponseEntity> createBoard(@AuthenticationPrincipal User user, @PathVariable Long teamId, @Valid @RequestBody CreateBoardRequest createBoardRequest) { - return ResponseEntity.ok(SuccessResponse.create(CREATE_BOARD_SUCCESS.getMessage(), this.createBoardUserCase.createBoard(user, teamId, createBoardRequest))); + return ResponseEntity.ok(SuccessResponse.create(CREATE_BOARD_SUCCESS.getMessage(), this.createBoardUserCase.createBoard(user.getSocialId(), teamId, createBoardRequest))); } /** @@ -43,7 +47,6 @@ public ResponseEntity> createBoard(@Authent * [PUT] api/{teamId}/board/{boardId} * 작성자 : 김민수 */ - @PutMapping("/{boardId}") public ResponseEntity> updateBoard(@AuthenticationPrincipal User user, @PathVariable Long teamId, @@ -51,4 +54,27 @@ public ResponseEntity> updateBoard(@Authent @Valid @RequestBody UpdateBoardRequest updateBoardRequest) { return ResponseEntity.ok(SuccessResponse.create(UPDATE_BOARD_SUCCESS.getMessage(), this.updateBoardUserCase.updateBoard(user.getSocialId(), teamId, boardId, updateBoardRequest))); } + + /** + * 게시글 상세 조회 + * [GET] api/{teamId}/board/{boardId} + * 작성자 : 김민수 + */ + @GetMapping("/{boardId}") + public ResponseEntity> getBoardDetail(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long boardId) { + return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_DETAIL_SUCCESS.getMessage(), this.getBoardUserCase.getBoardDetail(user.getSocialId(), teamId, boardId))); + } + + /** + * 게시글 전체 조회 + * [GET] api/{teamId}/board + * 작성자 : 김민수 + */ + @GetMapping + public ResponseEntity> getBoardAll(@AuthenticationPrincipal User user, + @PathVariable Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_ALL_SUCCESS.getMessage(), this.getBoardUserCase.getAllBoard(user.getSocialId(), teamId))); + } } diff --git a/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java b/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java index 65a9fbcd..37eba647 100644 --- a/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java @@ -8,6 +8,7 @@ public enum BoardResponseMessage { CREATE_BOARD_SUCCESS("게시글을 생성했습니다."), GET_BOARD_ALL_SUCCESS("게시글 목록을 모두 조회했습니다."), - UPDATE_BOARD_SUCCESS("게시글을 수정했습니다."); + UPDATE_BOARD_SUCCESS("게시글을 수정했습니다."), + GET_BOARD_DETAIL_SUCCESS("게시글 상세 조회했습니다."); private final String message; } diff --git a/src/main/java/com/moing/backend/domain/boardRead/application/mapper/BoardReadMapper.java b/src/main/java/com/moing/backend/domain/boardRead/application/mapper/BoardReadMapper.java new file mode 100644 index 00000000..740e6b1a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardRead/application/mapper/BoardReadMapper.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.boardRead.application.mapper; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardRead.domain.entity.BoardRead; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import org.springframework.stereotype.Component; + +@Component +public class BoardReadMapper { + public BoardRead toBoardRead(Team team, Member member){ + BoardRead boardRead=new BoardRead(); + boardRead.updateTeam(team); + boardRead.updateMember(member); + return boardRead; + } +} diff --git a/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java b/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java new file mode 100644 index 00000000..b17cca58 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.boardRead.domain.repository; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardRead.domain.entity.BoardRead; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface BoardReadRepository extends JpaRepository { + Optional findBoardReadByBoardAndMemberAndTeam(Board board, Member member, Team team); +} diff --git a/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java b/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java new file mode 100644 index 00000000..1e81792d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.boardRead.domain.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardRead.domain.entity.BoardRead; +import com.moing.backend.domain.boardRead.domain.repository.BoardReadRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@RequiredArgsConstructor +@Transactional +public class BoardReadSaveService { + + private final BoardReadRepository boardReadRepository; + + public void saveBoardRead(Board board, BoardRead boardRead) { + if ((boardReadRepository.findBoardReadByBoardAndMemberAndTeam(board, boardRead.getMember(), boardRead.getTeam())).isEmpty()) { + boardRead.updateBoard(board); + boardReadRepository.save(boardRead); + } + } +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java index 703bb968..6bcc3808 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java @@ -9,6 +9,5 @@ import java.util.Optional; public interface TeamMemberRepository extends JpaRepository, TeamMemberCustomRepository{ - - TeamMember findTeamMemberByTeamAndMember(Team team, Member member); + Optional findTeamMemberByTeamAndMember(Team team, Member member); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index f91866e0..e224a89a 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.exception.NotFoundByTeamIdException; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; import com.moing.backend.global.annotation.DomainService; @@ -19,6 +20,6 @@ public List getTeamMemberIds(Long teamId){ } public TeamMember getTeamMember(Member member, Team team){ - return teamMemberRepository.findTeamMemberByTeamAndMember(team, member); + return teamMemberRepository.findTeamMemberByTeamAndMember(team, member).orElseThrow(()-> new NotFoundByTeamIdException()); } } diff --git a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java index bb368b7a..ed64387e 100644 --- a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java @@ -3,9 +3,9 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; -import com.moing.backend.domain.board.application.dto.response.CreateBoardResponse; -import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; +import com.moing.backend.domain.board.application.dto.response.*; import com.moing.backend.domain.board.application.service.CreateBoardUserCase; +import com.moing.backend.domain.board.application.service.GetBoardUserCase; import com.moing.backend.domain.board.application.service.UpdateBoardUserCase; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -14,11 +14,16 @@ import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; import org.springframework.test.web.servlet.ResultActions; +import java.util.ArrayList; +import java.util.List; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(BoardController.class) @@ -28,6 +33,9 @@ public class BoardControllerTest extends CommonControllerTest { @MockBean private UpdateBoardUserCase updateBoardUserCase; + @MockBean + private GetBoardUserCase getBoardUserCase; + @Test public void create_board() throws Exception { @@ -64,6 +72,9 @@ public void create_board() throws Exception { requestHeaders( headerWithName("Authorization").description("접근 토큰") ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), requestFields( fieldWithPath("title").description("게시글 제목"), fieldWithPath("content").description("게시글 내용"), @@ -115,6 +126,10 @@ public void update_board() throws Exception { requestHeaders( headerWithName("Authorization").description("접근 토큰") ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("boardId").description("게시글 아이디") + ), requestFields( fieldWithPath("title").description("게시글 제목"), fieldWithPath("content").description("게시글 내용"), @@ -128,4 +143,147 @@ public void update_board() throws Exception { ) ); } + + @Test + public void get_board_all() throws Exception { + //given + List noticeBlocks = new ArrayList<>(); + List notNoticeBlocks = new ArrayList<>(); + Long teamId = 1L; + + BoardBlocks noticeBlock = BoardBlocks.builder() + .boardId(1L) + .writerIsLeader(true) + .writerNickName("작성자 닉네임") + .writerProfileImage("작성자 프로필 이미지") + .title("공지 제목") + .content("공지 내용") + .commentNum(2) + .isRead(false) + .build(); + + BoardBlocks notNoticeBlock = BoardBlocks.builder() + .boardId(1L) + .writerIsLeader(true) + .writerNickName("작성자 닉네임") + .writerProfileImage("작성자 프로필 이미지") + .title("게시글 제목") + .content("게시글 내용") + .commentNum(2) + .isRead(false) + .build(); + + noticeBlocks.add(noticeBlock); + notNoticeBlocks.add(notNoticeBlock); + + GetAllBoardResponse output = new GetAllBoardResponse(noticeBlocks.size(), noticeBlocks, notNoticeBlocks.size(), notNoticeBlocks); + + given(getBoardUserCase.getAllBoard(any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/board", teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("게시글 목록을 모두 조회했습니다."), + fieldWithPath("data.noticeNum").description("공지 개수"), + fieldWithPath("data.noticeBlocks[0].boardId").description("공지 아이디"), + fieldWithPath("data.noticeBlocks[0].writerNickName").description("작성자 닉네임"), + fieldWithPath("data.noticeBlocks[0].writerIsLeader").description("작성자 소모임장 여부"), + fieldWithPath("data.noticeBlocks[0].writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.noticeBlocks[0].title").description("공지 제목"), + fieldWithPath("data.noticeBlocks[0].content").description("공지 내용"), + fieldWithPath("data.noticeBlocks[0].commentNum").description("공지 댓글 개수"), + fieldWithPath("data.noticeBlocks[0].isRead").description("공지 읽음 처리 여부"), + fieldWithPath("data.notNoticeNum").description("일반 게시글 개수"), + fieldWithPath("data.notNoticeBlocks[0].boardId").description("일반 게시글 아이디"), + fieldWithPath("data.notNoticeBlocks[0].writerNickName").description("작성자 닉네임"), + fieldWithPath("data.notNoticeBlocks[0].writerIsLeader").description("작성자 소모임장 여부"), + fieldWithPath("data.notNoticeBlocks[0].writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.notNoticeBlocks[0].title").description("일반 게시글 제목"), + fieldWithPath("data.notNoticeBlocks[0].content").description("일반 게시글 내용"), + fieldWithPath("data.notNoticeBlocks[0].commentNum").description("일반 게시글 댓글 개수"), + fieldWithPath("data.notNoticeBlocks[0].isRead").description("일반 게시글 읽음 처리 여부") + ) + + ) + ); + } + + @Test + public void get_board_detail() throws Exception { + //given + Long teamId = 1L; + Long boardId=1L; + + GetBoardDetailResponse output = GetBoardDetailResponse.builder() + .boardId(1L) + .writerIsLeader(true) + .writerNickName("작성자 닉네임") + .writerProfileImage("작성자 프로필 이미지") + .title("게시글 제목") + .content("게시글 내용") + .createdDate("2023/09/29 23:42") + .isWriter(false) + .isNotice(false) + .build(); + + given(getBoardUserCase.getBoardDetail(any(), any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/board/{boardId}", teamId, boardId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("boardId").description("게시글 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("게시글 목록을 모두 조회했습니다."), + fieldWithPath("data.boardId").description("게시글 아이디"), + fieldWithPath("data.writerNickName").description("작성자 닉네임"), + fieldWithPath("data.writerIsLeader").description("작성자 소모임장 여부"), + fieldWithPath("data.writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.title").description("게시글 제목"), + fieldWithPath("data.content").description("게시글 내용"), + fieldWithPath("data.createdDate").description("게시글 생성 날짜, 시간"), + fieldWithPath("data.isWriter").description("게시글 작성자 여부"), + fieldWithPath("data.isNotice").description("게시글 공지 여부") + ) + + ) + ); + } + } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 737c7af4..734d871f 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -8,10 +8,10 @@ import com.moing.backend.domain.team.application.dto.response.TeamBlock; import com.moing.backend.domain.team.application.service.*; import org.junit.jupiter.api.Test; -import org.mockito.Mock; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; import org.springframework.test.web.servlet.ResultActions; import java.util.ArrayList; @@ -22,6 +22,8 @@ import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -174,8 +176,8 @@ public void disband_team() throws Exception { given(disbandTeamUserCase.disbandTeam(any(), any())).willReturn(output); //when - ResultActions actions = mockMvc.perform( - delete("/api/team/" + teamId + "/disband") + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/team/{teamId}/disband", teamId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) ); @@ -188,6 +190,9 @@ public void disband_team() throws Exception { requestHeaders( headerWithName("Authorization").description("접근 토큰") ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("[소모임장 권한] 소모임을 강제 종료했습니다."), @@ -207,8 +212,8 @@ public void withdraw_team() throws Exception { given(withdrawTeamUserCase.withdrawTeam(any(), any())).willReturn(output); //when - ResultActions actions = mockMvc.perform( - delete("/api/team/" + teamId + "/withdraw") + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/team/{teamId}/withdraw", teamId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) ); @@ -221,6 +226,9 @@ public void withdraw_team() throws Exception { requestHeaders( headerWithName("Authorization").description("접근 토큰") ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("[소모임원 권한] 소모임을 탈퇴하였습니다"), @@ -241,8 +249,8 @@ public void signIn_team() throws Exception { given(signInTeamUserCase.signInTeam(any(), any())).willReturn(output); //when - ResultActions actions = mockMvc.perform( - post("/api/team/" + teamId) + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + post("/api/team/{teamId}", teamId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) ); @@ -255,6 +263,9 @@ public void signIn_team() throws Exception { requestHeaders( headerWithName("Authorization").description("접근 토큰") ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("소모임에 가입하였습니다."), From ddecb7955eb8cf4531113fa60cbefe86a1d8f604 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 30 Sep 2023 13:17:00 +0900 Subject: [PATCH 100/619] =?UTF-8?q?errorCode=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Overview.adoc | 38 +++++++++++++++++-- .../service/UpdateBoardUserCase.java | 6 +-- .../exception/NotAuthByBoardException.java | 11 ++++++ .../service/DisbandTeamUserCase.java | 4 +- ...ption.java => NotAuthByTeamException.java} | 4 +- .../backend/global/response/ErrorCode.java | 8 ++-- 6 files changed, 55 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/board/exception/NotAuthByBoardException.java rename src/main/java/com/moing/backend/domain/team/exception/{NotAuthException.java => NotAuthByTeamException.java} (71%) diff --git a/src/docs/asciidoc/Overview.adoc b/src/docs/asciidoc/Overview.adoc index 4461b8a4..2b9e0a24 100644 --- a/src/docs/asciidoc/Overview.adoc +++ b/src/docs/asciidoc/Overview.adoc @@ -78,15 +78,45 @@ | `AU0003` | 로그인할 때 | appId가 일치하지 않음 (유효하지 않음) + +| `AU0004` +| 회원가입할 때 +| 닉네임이 중복됨 +|=== + +=== Team ErrorCode +|=== +| ErrorCode | Scope | Description +| `T0001` +| API PATH에 teamId가 있을 때 +| teamId가 유효하지 않음 (존재하지 않거나, 해당 유저가 그 팀에 속해있지 않거나) + +| `T0002` +| 소모임을 수정, 삭제하려고 할 때 +| 소모임장이 아님 (권한 없음) |=== -=== Team / Team_member ErrorCode +=== Board ErrorCode |=== | ErrorCode | Scope | Description -| `TM0001` -| 팀 개설할 때 -| 팀 최대 개수 3을 초과 +| `B0001` +| API PATH에 boardId가 있을 때 +| boardId가 유효하지 않음 (존재하지 않음) + +| `B0002` +| 게시글을 수정, 삭제하려고 할 때 +| 작성자가 아님 (권한 없음) |=== +=== Mission ErrorCode +|=== +| ErrorCode | Scope | Description +| `M0001` +| 미션 생성할 때 +| 소모임장이 아님 +| `M0002` +| API PATH에 missionId가 있으 때 +| missionId가 유요하지 않음 +|=== diff --git a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java index f11512cf..2643da09 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java @@ -4,11 +4,11 @@ import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.board.exception.NotAuthByBoardException; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.team.exception.NotAuthException; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import lombok.RequiredArgsConstructor; @@ -33,9 +33,9 @@ public UpdateBoardResponse updateBoard(String socialId, Long teamId, Long boardI Team team = teamGetService.getTeamByTeamId(teamId); Board board = boardGetService.getBoard(boardId); TeamMember teamMember=teamMemberGetService.getTeamMember(member, team); - if(teamMember==board.getTeamMember()) { + if (teamMember == board.getTeamMember()) { board.updateBoard(updateBoardRequest); return new UpdateBoardResponse(board.getBoardId()); - }else throw new NotAuthException(); + } else throw new NotAuthByBoardException(); } } diff --git a/src/main/java/com/moing/backend/domain/board/exception/NotAuthByBoardException.java b/src/main/java/com/moing/backend/domain/board/exception/NotAuthByBoardException.java new file mode 100644 index 00000000..704c0873 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/exception/NotAuthByBoardException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.board.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotAuthByBoardException extends BoardException { + public NotAuthByBoardException() { + super(ErrorCode.NOT_AUTH_BY_BOARD_ID_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java index 3efa23fe..19e133ad 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java @@ -5,7 +5,7 @@ import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.team.exception.NotAuthException; +import com.moing.backend.domain.team.exception.NotAuthByTeamException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -26,7 +26,7 @@ public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { if (checkLeaderUserCase.isTeamLeader(member, team)) { team.deleteTeam(); } else { - throw new NotAuthException(); + throw new NotAuthByTeamException(); } return new DeleteTeamResponse(team.getTeamId()); } diff --git a/src/main/java/com/moing/backend/domain/team/exception/NotAuthException.java b/src/main/java/com/moing/backend/domain/team/exception/NotAuthByTeamException.java similarity index 71% rename from src/main/java/com/moing/backend/domain/team/exception/NotAuthException.java rename to src/main/java/com/moing/backend/domain/team/exception/NotAuthByTeamException.java index 14e66aef..7d99e8cb 100644 --- a/src/main/java/com/moing/backend/domain/team/exception/NotAuthException.java +++ b/src/main/java/com/moing/backend/domain/team/exception/NotAuthByTeamException.java @@ -3,8 +3,8 @@ import com.moing.backend.global.response.ErrorCode; import org.springframework.http.HttpStatus; -public class NotAuthException extends TeamException{ - public NotAuthException(){ +public class NotAuthByTeamException extends TeamException{ + public NotAuthByTeamException(){ super(ErrorCode.NOT_AUTH_BY_TEAM_ERROR, HttpStatus.UNAUTHORIZED); } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index dda3ec42..d81c948d 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -18,10 +18,7 @@ public enum ErrorCode { ACCOUNT_ALREADY_EXIST("AU0001", "해당 email로 다른 소셜 플랫폼으로 가입하였습니다."), TOKEN_INVALID_ERROR("AU0002", "입력 토큰이 유효하지 않습니다."), APPID_INVALID_ERROR("AU0003", "appId가 유효하지 않습니다"), - NICKNAME_DUPLICATION_ERROR("AU0003", "닉네임이 중복됩니다."), - - //팀멤버 에러 코드 - TOO_MANY_TEAM_MEMBER_ERROR("TM0001", "팀 최대 개수 3을 초과했습니다"), + NICKNAME_DUPLICATION_ERROR("AU0004", "닉네임이 중복됩니다."), //미션 관련 에러코드 NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), @@ -33,7 +30,8 @@ public enum ErrorCode { NOT_AUTH_BY_TEAM_ERROR("T0002","권한이 없습니다."), //게시글 관련 에러 코드 - NOT_FOUND_BY_BOARD_ID_ERROR("B0001","해당 boardId인 팀이 존재하지 않습니다."); + NOT_FOUND_BY_BOARD_ID_ERROR("B0001","해당 boardId인 팀이 존재하지 않습니다."), + NOT_AUTH_BY_BOARD_ID_ERROR("B0002","권한이 없습니다."); private String errorCode; private String message; From 50f3dc93e0d9f0b39cb86dfc378ae3df37ef02ba Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 30 Sep 2023 14:16:42 +0900 Subject: [PATCH 101/619] =?UTF-8?q?feat:=20Board=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Board-API.adoc | 10 +++++ .../service/DeleteBoardUserCase.java | 42 +++++++++++++++++++ .../application/service/GetBoardUserCase.java | 6 +++ .../domain/service/BoardDeleteService.java | 20 +++++++++ .../board/presentation/BoardController.java | 15 +++++++ .../constant/BoardResponseMessage.java | 3 +- .../presentation/BoardControllerTest.java | 40 +++++++++++++++++- 7 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/board/domain/service/BoardDeleteService.java diff --git a/src/docs/asciidoc/Board-API.adoc b/src/docs/asciidoc/Board-API.adoc index 91c9cca7..8e0de4ca 100644 --- a/src/docs/asciidoc/Board-API.adoc +++ b/src/docs/asciidoc/Board-API.adoc @@ -11,7 +11,17 @@ operation::board-controller-test/create_board[snippets='http-request,path-parame operation::board-controller-test/update_board[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- +[[Board-게시글-삭제]] +=== Board 게시글 삭제 +operation::board-controller-test/delete_board[snippets='http-request,path-parameters,request-fields,response-fields'] +--- + [[Board-게시글-전체-조회]] === Board 게시글 전체 조회 operation::board-controller-test/get_board_all[snippets='http-request,path-parameters,http-response,response-fields'] +--- + +[[Board-게시글-상제-조회]] +=== Board 게시글 상세 조회 +operation::board-controller-test/get_board_detail[snippets='http-request,path-parameters,http-response,response-fields'] --- \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java new file mode 100644 index 00000000..6a6cee91 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java @@ -0,0 +1,42 @@ +package com.moing.backend.domain.board.application.service; + +import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; +import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.service.BoardDeleteService; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.board.exception.NotAuthByBoardException; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class DeleteBoardUserCase { + + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final BoardGetService boardGetService; + private final TeamMemberGetService teamMemberGetService; + private final BoardDeleteService boardDeleteService; + /** + * 게시글 삭제 + */ + public void deleteBoard(String socialId, Long teamId, Long boardId){ + Member member=memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + Board board = boardGetService.getBoard(boardId); + TeamMember teamMember=teamMemberGetService.getTeamMember(member, team); + if (teamMember == board.getTeamMember()) { + boardDeleteService.deleteBoard(board); + } else throw new NotAuthByBoardException(); + } +} diff --git a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java index 6be225ae..c9116f63 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java @@ -32,6 +32,9 @@ public class GetBoardUserCase { private final BoardReadSaveService boardReadSaveService; private final TeamMemberGetService teamMemberGetService; + /** + * 게시글 상세 조회 + */ public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long boardId) { Member member=memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); @@ -44,6 +47,9 @@ public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long return boardMapper.toBoardDetail(board, teamMember==board.getTeamMember()); } + /** + * 게시글 전체 조회 + */ public GetAllBoardResponse getAllBoard(String socialId, Long teamId){ Member member=memberGetService.getMemberBySocialId(socialId); return boardGetService.getBoardAll(teamId, member.getMemberId()); diff --git a/src/main/java/com/moing/backend/domain/board/domain/service/BoardDeleteService.java b/src/main/java/com/moing/backend/domain/board/domain/service/BoardDeleteService.java new file mode 100644 index 00000000..cb016b83 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/domain/service/BoardDeleteService.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.board.domain.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.repository.BoardRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class BoardDeleteService { + + private final BoardRepository boardRepository; + + public void deleteBoard(Board board){ + boardRepository.delete(board); + } +} diff --git a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java index 629eebeb..a25fdf9d 100644 --- a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java +++ b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.board.application.dto.response.GetBoardDetailResponse; import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; import com.moing.backend.domain.board.application.service.CreateBoardUserCase; +import com.moing.backend.domain.board.application.service.DeleteBoardUserCase; import com.moing.backend.domain.board.application.service.GetBoardUserCase; import com.moing.backend.domain.board.application.service.UpdateBoardUserCase; import com.moing.backend.domain.member.domain.entity.Member; @@ -29,6 +30,7 @@ public class BoardController { private final CreateBoardUserCase createBoardUserCase; private final UpdateBoardUserCase updateBoardUserCase; private final GetBoardUserCase getBoardUserCase; + private final DeleteBoardUserCase deleteBoardUserCase; /** * 게시글 생성 @@ -55,6 +57,19 @@ public ResponseEntity> updateBoard(@Authent return ResponseEntity.ok(SuccessResponse.create(UPDATE_BOARD_SUCCESS.getMessage(), this.updateBoardUserCase.updateBoard(user.getSocialId(), teamId, boardId, updateBoardRequest))); } + /** + * 게시글 삭제 + * [DELETE] api/{teamId}/board/{boardId} + * 작성자 : 김민수 + */ + @DeleteMapping("/{boardId}") + public ResponseEntity> deleteBoard(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long boardId) { + this.deleteBoardUserCase.deleteBoard(user.getSocialId(), teamId, boardId); + return ResponseEntity.ok(SuccessResponse.create(DELETE_BOARD_SUCCESS.getMessage())); + } + /** * 게시글 상세 조회 * [GET] api/{teamId}/board/{boardId} diff --git a/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java b/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java index 37eba647..da90a821 100644 --- a/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/board/presentation/constant/BoardResponseMessage.java @@ -9,6 +9,7 @@ public enum BoardResponseMessage { CREATE_BOARD_SUCCESS("게시글을 생성했습니다."), GET_BOARD_ALL_SUCCESS("게시글 목록을 모두 조회했습니다."), UPDATE_BOARD_SUCCESS("게시글을 수정했습니다."), - GET_BOARD_DETAIL_SUCCESS("게시글 상세 조회했습니다."); + GET_BOARD_DETAIL_SUCCESS("게시글 상세 조회했습니다."), + DELETE_BOARD_SUCCESS("게시글을 삭제했습니다"); private final String message; } diff --git a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java index ed64387e..229f067c 100644 --- a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; import com.moing.backend.domain.board.application.dto.response.*; import com.moing.backend.domain.board.application.service.CreateBoardUserCase; +import com.moing.backend.domain.board.application.service.DeleteBoardUserCase; import com.moing.backend.domain.board.application.service.GetBoardUserCase; import com.moing.backend.domain.board.application.service.UpdateBoardUserCase; import org.junit.jupiter.api.Test; @@ -32,9 +33,10 @@ public class BoardControllerTest extends CommonControllerTest { private CreateBoardUserCase createBoardUserCase; @MockBean private UpdateBoardUserCase updateBoardUserCase; - @MockBean private GetBoardUserCase getBoardUserCase; + @MockBean + private DeleteBoardUserCase deleteBoardUserCase; @Test public void create_board() throws Exception { @@ -144,6 +146,42 @@ public void update_board() throws Exception { ); } + @Test + public void delete_board() throws Exception { + + //given + Long teamId = 1L; + Long boardId = 1L; + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/{teamId}/board/{boardId}", teamId, boardId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("boardId").description("게시글 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("게시글을 삭제했습니다") + ) + ) + ); + } + + @Test public void get_board_all() throws Exception { //given From 4fc7343b45fe637d1f915aa3c5858af40ca29b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 30 Sep 2023 18:51:38 +0900 Subject: [PATCH 102/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EA=B2=8C=EC=8B=9C=EB=AC=BC=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94,=20=EC=9D=B8=EC=A6=9D=20=EC=84=B1=EA=B3=B5?= =?UTF-8?q?=20=EC=9D=B8=EC=9B=90=20=EC=A1=B0=ED=9A=8C=20test=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/req/MissionArchiveHeartReq.java | 2 + .../MissionArchiveController.java | 19 ++- .../MissionArchiveControllerTest.java | 109 +++++++++++++++++- 3 files changed, 124 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveHeartReq.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveHeartReq.java index 48ec9458..db569206 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveHeartReq.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveHeartReq.java @@ -1,12 +1,14 @@ package com.moing.backend.domain.missionArchive.application.dto.req; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor @AllArgsConstructor +@Builder public class MissionArchiveHeartReq { private Long archiveId; private String heartStatus; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 6ced5bf5..0d5e628a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -36,7 +36,7 @@ public class MissionArchiveController { * 미션 인증 하기 * [POST] {teamId}/missions/{missionId}/archive * 작성자 : 정승연 - */ + **/ @PostMapping() public ResponseEntity> createArchive(@AuthenticationPrincipal User user, @@ -50,7 +50,7 @@ public ResponseEntity> createArchive(@Authent * 미션 재인증 하기 * [POST] {teamId}/missions/{missionId}/archive * 작성자 : 정승연 - */ + **/ @PutMapping() public ResponseEntity> updateArchive(@AuthenticationPrincipal User user, @@ -64,7 +64,7 @@ public ResponseEntity> updateArchive(@Authent * 미션 인증 조회 * [GET] {teamId}/missions/{missionId}/archive * 작성자 : 정승연 - */ + **/ @GetMapping() public ResponseEntity> getMyArchive(@AuthenticationPrincipal User user, @@ -77,7 +77,7 @@ public ResponseEntity> getMyArchive(@Authenti * 모임원 미션 인증 목록 조회 * [GET] {teamId}/missions/{missionId}/archive/others * 작성자 : 정승연 - */ + **/ @GetMapping("/others") public ResponseEntity>> getOtherPeopleArchives(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @@ -85,7 +85,11 @@ public ResponseEntity>> getOtherPeopleArch return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(user.getSocialId(),missionId))); } - + /** + * 인증 성공 인원 조회 + * [GET] {teamId}/m원issions/{missionId}/archive/status + * 작성자 : 정승연 + **/ @GetMapping("/status") public ResponseEntity> getMissionDoneStatus(@AuthenticationPrincipal User user, @@ -94,6 +98,11 @@ public ResponseEntity> getMissionDoneSt return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getMissionDoneStatus(missionId))); } + /** + * 미션 인증 게시물 좋아요 + * [GET] {teamId}/m원issions/{missionId}/archive/hearts + * 작성자 : 정승연 + **/ @PostMapping("/hearts") public ResponseEntity> pushHeart(@AuthenticationPrincipal User user, diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index c998c86b..5e35a46b 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -10,8 +10,11 @@ import com.moing.backend.domain.mission.application.service.MissionReadUseCase; import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; import com.moing.backend.domain.mission.presentation.MissionController; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveHeartReq; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateUseCase; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveHeartUseCase; @@ -31,7 +34,7 @@ import java.time.LocalDateTime; import java.util.List; -import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.READ_MY_ARCHIVE_SUCCESS; +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; @@ -286,5 +289,109 @@ public class MissionArchiveControllerTest extends CommonControllerTest { } + @Test + public void 인증_성공_인원_조회() throws Exception { + //given + + MissionArchiveStatusRes output = MissionArchiveStatusRes.builder() + .total("8") + .done("3") + .build(); + + given(singleMissionArchiveReadUseCase.getMissionDoneStatus(any())).willReturn(output); + + Long teamId = 1L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/missions/{missionId}/archive/status",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage()), + fieldWithPath("data.total").description("전체 미션 참여자"), + fieldWithPath("data.done").description("미션 인증 완료한 미션 참여자 ") + + ) + ) + ) + .andReturn(); + + } + @Test + public void 미션_인증물_좋아요() throws Exception { + //given + MissionArchiveHeartReq input = MissionArchiveHeartReq.builder() + .archiveId(1L) + .heartStatus("content[s3 Link / text / link]") + .build(); + + String body = objectMapper.writeValueAsString(input); + + MissionArchiveHeartRes output = MissionArchiveHeartRes.builder() + .archiveId(1L) + .heartStatus("content[s3 Link / text / link]") + .hearts(3) + .build(); + + given(missionArchiveHeartUseCase.pushHeart(any())).willReturn(output); + + Long teamId = 1L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + post("/api/{teamId}/missions/{missionId}/archive/hearts", teamId, missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + requestFields( + fieldWithPath("archiveId").description("미션 인증 아이디"), + fieldWithPath("heartStatus").description("미션 인증물 좋아요 상태 [True]") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(HEART_UPDATE_SUCCESS.getMessage()), + fieldWithPath("data.archiveId").description("미션 인증 아이디"), + fieldWithPath("data.heartStatus").description("미션 인증물 좋아요 상태 [True]"), + fieldWithPath("data.hearts").description("미션 인증물 좋아요 수") + + ) + ) + ) + .andReturn(); + } + + + } From e0968a337dfa0cc693ffd81d89318b8ece349879 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 30 Sep 2023 21:59:52 +0900 Subject: [PATCH 103/619] =?UTF-8?q?feat:=20Board=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1,=20=EC=82=AD=EC=A0=9C=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/application/mapper/BoardMapper.java | 1 + .../domain/board/domain/entity/Board.java | 6 +- .../board/presentation/BoardController.java | 3 +- .../request/CreateBoardCommentRequest.java | 18 +++++ .../dto/response/CommentBlocks.java | 24 +++++++ .../response/CreateBoardCommentResponse.java | 14 ++++ .../dto/response/GetBoardCommentResponse.java | 16 +++++ .../mapper/BoardCommentMapper.java | 21 ++++++ .../service/CreateBoardCommentUserCase.java | 42 +++++++++++ .../service/DeleteBoardCommentUserCase.java | 41 +++++++++++ .../service/GetBoardCommentUserCase.java | 33 +++++++++ .../domain/{ => entity}/BoardComment.java | 15 +++- .../BoardCommentCustomRepository.java | 8 +++ .../BoardCommentCustomRepositoryImpl.java | 52 ++++++++++++++ .../repository/BoardCommentRepository.java | 11 +++ .../service/BoardCommentDeleteService.java | 16 +++++ .../service/BoardCommentGetService.java | 27 +++++++ .../service/BoardCommentSaveService.java | 17 +++++ .../exception/BoardCommentException.java | 11 +++ .../NotAuthByBoardCommentException.java | 11 +++ .../NotFoundByBoardCommentIdException.java | 11 +++ .../presentattion/BoardCommentController.java | 70 +++++++++++++++++++ .../constant/BoardCommentResponseMessage.java | 13 ++++ .../backend/global/response/ErrorCode.java | 8 ++- 24 files changed, 481 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CreateBoardCommentResponse.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/application/dto/response/GetBoardCommentResponse.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java rename src/main/java/com/moing/backend/domain/boardComment/domain/{ => entity}/BoardComment.java (71%) create mode 100644 src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentRepository.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentDeleteService.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/exception/BoardCommentException.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/exception/NotAuthByBoardCommentException.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/exception/NotFoundByBoardCommentIdException.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java create mode 100644 src/main/java/com/moing/backend/domain/boardComment/presentattion/constant/BoardCommentResponseMessage.java diff --git a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java index a32c8452..4dc06d79 100644 --- a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java +++ b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java @@ -27,6 +27,7 @@ public Board toBoard(Member member, TeamMember teamMember, Team team, CreateBoar .commentNum(0) .isLeader(isLeader) .boardReads(new ArrayList<>()) + .boardComments(new ArrayList<>()) .build(); board.updateTeamMember(teamMember); board.updateTeam(team); diff --git a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java index cb73c2a7..829bfe53 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java +++ b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.board.domain.entity; import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardRead.domain.entity.BoardRead; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; @@ -12,9 +13,6 @@ import lombok.NoArgsConstructor; import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; import java.util.ArrayList; import java.util.List; @@ -60,6 +58,8 @@ public class Board extends BaseTimeEntity { @OneToMany(mappedBy = "board", cascade = CascadeType.ALL) private List boardReads = new ArrayList<>(); + @OneToMany(mappedBy = "board", cascade = CascadeType.ALL) + private List boardComments = new ArrayList<>(); public void incrComNum() { this.commentNum++; diff --git a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java index a25fdf9d..26443cca 100644 --- a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java +++ b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java @@ -10,7 +10,6 @@ import com.moing.backend.domain.board.application.service.DeleteBoardUserCase; import com.moing.backend.domain.board.application.service.GetBoardUserCase; import com.moing.backend.domain.board.application.service.UpdateBoardUserCase; -import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -63,7 +62,7 @@ public ResponseEntity> updateBoard(@Authent * 작성자 : 김민수 */ @DeleteMapping("/{boardId}") - public ResponseEntity> deleteBoard(@AuthenticationPrincipal User user, + public ResponseEntity deleteBoard(@AuthenticationPrincipal User user, @PathVariable Long teamId, @PathVariable Long boardId) { this.deleteBoardUserCase.deleteBoard(user.getSocialId(), teamId, boardId); diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java new file mode 100644 index 00000000..06bd1a8b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.boardComment.application.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class CreateBoardCommentRequest { + @NotBlank(message = "content 을 입력해 주세요.") + private String content; +} + diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java new file mode 100644 index 00000000..37e40ed0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.boardComment.application.dto.response; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class CommentBlocks { + + private Long boardCommentId; + + private String content; + + private String writerNickName; + + private Boolean writerIsLeader; + + private String writerProfileImage; + + private Boolean isWriter; +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CreateBoardCommentResponse.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CreateBoardCommentResponse.java new file mode 100644 index 00000000..8967920c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CreateBoardCommentResponse.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.boardComment.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class CreateBoardCommentResponse { + private Long boardCommentId; +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/GetBoardCommentResponse.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/GetBoardCommentResponse.java new file mode 100644 index 00000000..94bbbe1d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/GetBoardCommentResponse.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.boardComment.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class GetBoardCommentResponse { + private List commentBlocks; +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java b/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java new file mode 100644 index 00000000..03169f2d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java @@ -0,0 +1,21 @@ +package com.moing.backend.domain.boardComment.application.mapper; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class BoardCommentMapper { + public BoardComment toBoardComment(TeamMember teamMember, Board board, CreateBoardCommentRequest createBoardCommentRequest){ + BoardComment boardComment= BoardComment.builder() + .content(createBoardCommentRequest.getContent()) + .build(); + boardComment.updateBoard(board); + boardComment.updateTeamMember(teamMember); + return boardComment; + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java new file mode 100644 index 00000000..6a2cb5ed --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java @@ -0,0 +1,42 @@ +package com.moing.backend.domain.boardComment.application.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; +import com.moing.backend.domain.boardComment.application.dto.response.CreateBoardCommentResponse; +import com.moing.backend.domain.boardComment.application.mapper.BoardCommentMapper; +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.boardComment.domain.service.BoardCommentSaveService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +public class CreateBoardCommentUserCase { + + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final BoardGetService boardGetService; + private final TeamMemberGetService teamMemberGetService; + private final BoardCommentSaveService boardCommentSaveService; + private final BoardCommentMapper boardCommentMapper; + + public CreateBoardCommentResponse createBoardComment(String socialId, Long teamId, Long boardId, CreateBoardCommentRequest createBoardCommentRequest) { + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + Board board = boardGetService.getBoard(boardId); + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(teamMember, board, createBoardCommentRequest)); + board.incrComNum(); + return new CreateBoardCommentResponse(boardComment.getBoardCommentId()); + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java new file mode 100644 index 00000000..b9aa1be9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java @@ -0,0 +1,41 @@ +package com.moing.backend.domain.boardComment.application.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.board.exception.NotAuthByBoardException; +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.boardComment.domain.service.BoardCommentDeleteService; +import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; +import com.moing.backend.domain.boardComment.domain.service.BoardCommentSaveService; +import com.moing.backend.domain.boardComment.exception.NotAuthByBoardCommentException; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class DeleteBoardCommentUserCase { + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final TeamMemberGetService teamMemberGetService; + private final BoardCommentGetService boardCommentGetService; + private final BoardCommentDeleteService boardCommentDeleteService; + + public void deleteBoardComment(String socialId, Long teamId, Long boardId, Long boardCommentId){ + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + BoardComment boardComment=boardCommentGetService.getBoardComment(boardCommentId); + if (teamMember == boardComment.getTeamMember()) { + boardCommentDeleteService.deleteBoardComment(boardComment); + } else throw new NotAuthByBoardCommentException(); + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java new file mode 100644 index 00000000..8763a033 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java @@ -0,0 +1,33 @@ +package com.moing.backend.domain.boardComment.application.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; +import com.moing.backend.domain.boardComment.domain.service.BoardCommentDeleteService; +import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class GetBoardCommentUserCase { + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final TeamMemberGetService teamMemberGetService; + private final BoardCommentGetService boardCommentGetService; + + public GetBoardCommentResponse getBoardCommentAll(String socialId, Long teamId, Long boardId){ + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + return boardCommentGetService.getBoardCommentAll(boardId, teamMember); + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/BoardComment.java b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java similarity index 71% rename from src/main/java/com/moing/backend/domain/boardComment/domain/BoardComment.java rename to src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java index e3b39428..35381e68 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/BoardComment.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java @@ -1,4 +1,4 @@ -package com.moing.backend.domain.boardComment.domain; +package com.moing.backend.domain.boardComment.domain.entity; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; @@ -30,4 +30,17 @@ public class BoardComment extends BaseTimeEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "board_id") private Board board; + + /** + * 연관관계 매핑 + */ + public void updateBoard(Board board) { + this.board = board; + board.getBoardComments().add(this); + } + + public void updateTeamMember(TeamMember teamMember) { + this.teamMember = teamMember; + } + } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java new file mode 100644 index 00000000..f5e48759 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java @@ -0,0 +1,8 @@ +package com.moing.backend.domain.boardComment.domain.repository; + +import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; + +public interface BoardCommentCustomRepository { + GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember teamMember); +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java new file mode 100644 index 00000000..178a26ea --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -0,0 +1,52 @@ +package com.moing.backend.domain.boardComment.domain.repository; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardComment.application.dto.response.CommentBlocks; +import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; +import com.moing.backend.domain.boardComment.application.service.GetBoardCommentUserCase; +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.boardComment.domain.entity.QBoardComment; +import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.querydsl.core.types.ExpressionUtils; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.util.List; + +import static com.moing.backend.domain.boardComment.domain.entity.QBoardComment.boardComment; +import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; + +public class BoardCommentCustomRepositoryImpl implements BoardCommentCustomRepository{ + + private final JPAQueryFactory queryFactory; + + public BoardCommentCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + + @Override + public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember teamMember) { + List commentBlocks = queryFactory + .select(Projections.constructor(CommentBlocks.class, + boardComment.boardCommentId, + boardComment.content, + boardComment.board.writerNickName, + boardComment.board.isLeader, + boardComment.board.writerProfileImage, + ExpressionUtils.as(JPAExpressions + .selectOne() + .from(QTeamMember.teamMember) + .where(QTeamMember.teamMember.eq(teamMember) + .and(QTeamMember.teamMember.eq(boardComment.teamMember))) + .exists(), "isWriter"))) + .from(boardComment) + .where(boardComment.board.boardId.eq(boardId)) + .orderBy(boardComment.createdDate.asc()) + .fetch(); + return new GetBoardCommentResponse(commentBlocks); + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentRepository.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentRepository.java new file mode 100644 index 00000000..8ccec194 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentRepository.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.boardComment.domain.repository; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface BoardCommentRepository extends JpaRepository, BoardCommentCustomRepository { + Optional findBoardCommentByBoardCommentId(Long boardCommentId); +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentDeleteService.java b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentDeleteService.java new file mode 100644 index 00000000..c3bd102f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentDeleteService.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.boardComment.domain.service; + +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class BoardCommentDeleteService { + private final BoardCommentRepository boardCommentRepository; + + public void deleteBoardComment(BoardComment boardComment){ + this.boardCommentRepository.delete(boardComment); + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java new file mode 100644 index 00000000..005c10a4 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.boardComment.domain.service; + +import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; +import com.moing.backend.domain.boardComment.exception.NotFoundByBoardCommentIdException; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class BoardCommentGetService { + + private final BoardCommentRepository boardCommentRepository; + + public BoardComment getBoardComment(Long boardCommentId){ + return boardCommentRepository.findBoardCommentByBoardCommentId(boardCommentId).orElseThrow(()->new NotFoundByBoardCommentIdException()); + } + + public GetBoardCommentResponse getBoardCommentAll(Long boardId, TeamMember teamMember){ + return boardCommentRepository.findBoardCommentAll(boardId, teamMember); + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentSaveService.java b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentSaveService.java new file mode 100644 index 00000000..48b634aa --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentSaveService.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.boardComment.domain.service; + +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class BoardCommentSaveService { + + private final BoardCommentRepository boardCommentRepository; + + public BoardComment saveBoardComment(BoardComment boardComment){ + return this.boardCommentRepository.save(boardComment); + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/exception/BoardCommentException.java b/src/main/java/com/moing/backend/domain/boardComment/exception/BoardCommentException.java new file mode 100644 index 00000000..6a7778f6 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/exception/BoardCommentException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.boardComment.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class BoardCommentException extends ApplicationException { + protected BoardCommentException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/boardComment/exception/NotAuthByBoardCommentException.java b/src/main/java/com/moing/backend/domain/boardComment/exception/NotAuthByBoardCommentException.java new file mode 100644 index 00000000..4743776a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/exception/NotAuthByBoardCommentException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.boardComment.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotAuthByBoardCommentException extends BoardCommentException { + public NotAuthByBoardCommentException() { + super(ErrorCode.NOT_AUTH_BY_BOARD_COMMENT_ID_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/exception/NotFoundByBoardCommentIdException.java b/src/main/java/com/moing/backend/domain/boardComment/exception/NotFoundByBoardCommentIdException.java new file mode 100644 index 00000000..256aa3e1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/exception/NotFoundByBoardCommentIdException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.boardComment.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundByBoardCommentIdException extends BoardCommentException { + public NotFoundByBoardCommentIdException() { + super(ErrorCode.NOT_FOUND_BY_BOARD_COMMENT_ID_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java b/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java new file mode 100644 index 00000000..1ba471ca --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java @@ -0,0 +1,70 @@ +package com.moing.backend.domain.boardComment.presentattion; + +import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; +import com.moing.backend.domain.boardComment.application.dto.response.CreateBoardCommentResponse; +import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; +import com.moing.backend.domain.boardComment.application.service.CreateBoardCommentUserCase; +import com.moing.backend.domain.boardComment.application.service.DeleteBoardCommentUserCase; +import com.moing.backend.domain.boardComment.application.service.GetBoardCommentUserCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +import static com.moing.backend.domain.board.presentation.constant.BoardResponseMessage.GET_BOARD_ALL_SUCCESS; +import static com.moing.backend.domain.boardComment.presentattion.constant.BoardCommentResponseMessage.CREATE_BOARD_COMMENT_SUCCESS; +import static com.moing.backend.domain.boardComment.presentattion.constant.BoardCommentResponseMessage.DELETE_BOARD_COMMENT_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/{teamId}/{boardId}/comment") +public class BoardCommentController { + + private final CreateBoardCommentUserCase createBoardCommentUserCase; + private final DeleteBoardCommentUserCase deleteBoardCommentUserCase; + private final GetBoardCommentUserCase getBoardCommentUserCase; + + /** + * 댓글 생성 + * [POST] api/{teamId}/{boardId}/comment + * 작성자 : 김민수 + */ + @PostMapping + public ResponseEntity> createBoardComment(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long boardId, + @Valid @RequestBody CreateBoardCommentRequest createBoardCommentRequest) { + return ResponseEntity.ok(SuccessResponse.create(CREATE_BOARD_COMMENT_SUCCESS.getMessage(), this.createBoardCommentUserCase.createBoardComment(user.getSocialId(), teamId, boardId, createBoardCommentRequest))); + } + + /** + * 댓글 삭제 + * [DELETE] api/{teamId}/{boardId}/comment/{commentId} + * 작성자 : 김민수 + */ + @DeleteMapping("/{commentId}") + public ResponseEntity deleteBoardComment(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long boardId, + @PathVariable Long commentId) { + this.deleteBoardCommentUserCase.deleteBoardComment(user.getSocialId(), teamId, boardId, commentId); + return ResponseEntity.ok(SuccessResponse.create(DELETE_BOARD_COMMENT_SUCCESS.getMessage())); + } + + + /** + * 댓글 전체 조회 + * [GET] api/{teamId}/{boardId}/comment + * 작성자 : 김민수 + */ + @GetMapping + public ResponseEntity> getBoardCommentAll(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long boardId) { + return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_ALL_SUCCESS.getMessage(), this.getBoardCommentUserCase.getBoardCommentAll(user.getSocialId(), teamId, boardId))); + } +} diff --git a/src/main/java/com/moing/backend/domain/boardComment/presentattion/constant/BoardCommentResponseMessage.java b/src/main/java/com/moing/backend/domain/boardComment/presentattion/constant/BoardCommentResponseMessage.java new file mode 100644 index 00000000..0cf29554 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/presentattion/constant/BoardCommentResponseMessage.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.boardComment.presentattion.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum BoardCommentResponseMessage { + CREATE_BOARD_COMMENT_SUCCESS("댓글을 생성했습니다."), + GET_BOARD_COMMENT_ALL_SUCCESS("댓글 목록을 모두 조회했습니다."), + DELETE_BOARD_COMMENT_SUCCESS("댓글을 삭제했습니다"); + private final String message; +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index d81c948d..31aa29b6 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -30,8 +30,12 @@ public enum ErrorCode { NOT_AUTH_BY_TEAM_ERROR("T0002","권한이 없습니다."), //게시글 관련 에러 코드 - NOT_FOUND_BY_BOARD_ID_ERROR("B0001","해당 boardId인 팀이 존재하지 않습니다."), - NOT_AUTH_BY_BOARD_ID_ERROR("B0002","권한이 없습니다."); + NOT_FOUND_BY_BOARD_ID_ERROR("B0001","해당 boardId인 게시글이 존재하지 않습니다."), + NOT_AUTH_BY_BOARD_ID_ERROR("B0002","권한이 없습니다."), + + //게시글 댓글 관련 에러 코드 + NOT_FOUND_BY_BOARD_COMMENT_ID_ERROR("B0001","해당 boardCommentId인 댓글이 존재하지 않습니다."), + NOT_AUTH_BY_BOARD_COMMENT_ID_ERROR("B0002","권한이 없습니다."); private String errorCode; private String message; From 28c40ac14b7a40b233b2911185d4047693468bfd Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 30 Sep 2023 23:01:31 +0900 Subject: [PATCH 104/619] feat: Board Comment adoc --- src/docs/asciidoc/BoardComment_API.adoc | 17 ++ .../presentation/BoardControllerTest.java | 2 +- .../BoardCommentControllerTest.java | 186 ++++++++++++++++++ 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 src/docs/asciidoc/BoardComment_API.adoc create mode 100644 src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java diff --git a/src/docs/asciidoc/BoardComment_API.adoc b/src/docs/asciidoc/BoardComment_API.adoc new file mode 100644 index 00000000..e3cb904e --- /dev/null +++ b/src/docs/asciidoc/BoardComment_API.adoc @@ -0,0 +1,17 @@ +[[Board-Comment-API]] += Board Comment API + +[[Board-Comment-댓글-생성]] +=== Board Comment 댓글 생성 +operation::board-comment-controller-test/create_board_comment[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +--- + +[[Board-Comment-게시글-삭제]] +=== Board Comment 게시글 삭제 +operation::board-comment-controller-test/delete_board_comment[snippets='http-request,path-parameters,request-fields,response-fields'] +--- + +[[Board-Comment-댓글-전체-조회]] +=== Board Comment 댓글 전체 조회 +operation::board-comment-controller-test/get_board_comment_all[snippets='http-request,path-parameters,http-response,response-fields'] +--- diff --git a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java index 229f067c..1c76633c 100644 --- a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java @@ -308,7 +308,7 @@ public void get_board_detail() throws Exception { ), responseFields( fieldWithPath("isSuccess").description("true"), - fieldWithPath("message").description("게시글 목록을 모두 조회했습니다."), + fieldWithPath("message").description("게시글 상세 조회했습니다."), fieldWithPath("data.boardId").description("게시글 아이디"), fieldWithPath("data.writerNickName").description("작성자 닉네임"), fieldWithPath("data.writerIsLeader").description("작성자 소모임장 여부"), diff --git a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java new file mode 100644 index 00000000..c3592fdb --- /dev/null +++ b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java @@ -0,0 +1,186 @@ +package com.moing.backend.domain.boardComment.presentation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; +import com.moing.backend.domain.boardComment.application.dto.response.CommentBlocks; +import com.moing.backend.domain.boardComment.application.dto.response.CreateBoardCommentResponse; +import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; +import com.moing.backend.domain.boardComment.application.service.CreateBoardCommentUserCase; +import com.moing.backend.domain.boardComment.application.service.DeleteBoardCommentUserCase; +import com.moing.backend.domain.boardComment.application.service.GetBoardCommentUserCase; +import com.moing.backend.domain.boardComment.presentattion.BoardCommentController; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(BoardCommentController.class) +public class BoardCommentControllerTest extends CommonControllerTest { + @MockBean + private CreateBoardCommentUserCase createBoardCommentUserCase; + @MockBean + private DeleteBoardCommentUserCase deleteBoardCommentUserCase; + @MockBean + private GetBoardCommentUserCase getBoardCommentUserCase; + + @Test + public void create_board_comment() throws Exception { + + //given + Long teamId = 1L; + Long boardId = 1L; + CreateBoardCommentRequest input = CreateBoardCommentRequest.builder() + .content("게시글 내용") + .build(); + + String body = objectMapper.writeValueAsString(input); + + CreateBoardCommentResponse output = CreateBoardCommentResponse.builder() + .boardCommentId(1L) + .build(); + + given(createBoardCommentUserCase.createBoardComment(any(), any(), any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + post("/api/{teamId}/{boardId}/comment", teamId, boardId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("boardId").description("게시글 아이디") + ), + requestFields( + fieldWithPath("content").description("댓글 내용") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("댓글을 생성했습니다"), + fieldWithPath("data.boardCommentId").description("생성한 boardCommentId") + ) + ) + ); + } + + @Test + public void delete_board_comment() throws Exception { + + //given + Long teamId = 1L; + Long boardId = 1L; + Long boardCommentId = 1L; + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/{teamId}/{boardId}/comment/{boardCommentId}", teamId, boardId, boardCommentId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("boardId").description("게시글 아이디"), + parameterWithName("boardCommentId").description("댓글 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("댓글을 삭제했습니다") + ) + ) + ); + } + + + @Test + public void get_board_comment_all() throws Exception { + //given + List commentBlocks = new ArrayList<>(); + Long teamId = 1L; + Long boardId = 1L; + + CommentBlocks commentBlock = CommentBlocks.builder() + .boardCommentId(1L) + .content("댓글 내용") + .writerIsLeader(true) + .writerNickName("작성자 닉네임") + .writerProfileImage("작성자 프로필 이미지") + .isWriter(true) + .build(); + + commentBlocks.add(commentBlock); + + GetBoardCommentResponse output = new GetBoardCommentResponse(commentBlocks); + + given(getBoardCommentUserCase.getBoardCommentAll(any(), any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/{boardId}/comment", teamId, boardId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("boardId").description("게시글 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("댓글 목록을 모두 조회했습니다."), + fieldWithPath("data.commentBlocks[0].boardCommentId").description("댓글 아이디"), + fieldWithPath("data.commentBlocks[0].content").description("댓글 내용"), + fieldWithPath("data.commentBlocks[0].writerIsLeader").description("작성자 소모임장 여부"), + fieldWithPath("data.commentBlocks[0].writerNickName").description("작성자 닉네임"), + fieldWithPath("data.commentBlocks[0].writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.commentBlocks[0].isWriter").description("댓글 작성자 여부") + ) + + ) + ); + } +} From 026b2e4edb9b3e25409e156d36f4588f3df8c391 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 30 Sep 2023 23:04:46 +0900 Subject: [PATCH 105/619] feat: Board Comment adoc --- src/docs/asciidoc/BoardComment_API.adoc | 4 ++-- src/docs/asciidoc/api.adoc | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/docs/asciidoc/BoardComment_API.adoc b/src/docs/asciidoc/BoardComment_API.adoc index e3cb904e..7704d36b 100644 --- a/src/docs/asciidoc/BoardComment_API.adoc +++ b/src/docs/asciidoc/BoardComment_API.adoc @@ -6,8 +6,8 @@ operation::board-comment-controller-test/create_board_comment[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- -[[Board-Comment-게시글-삭제]] -=== Board Comment 게시글 삭제 +[[Board-Comment-댓글-삭제]] +=== Board Comment 댓글 삭제 operation::board-comment-controller-test/delete_board_comment[snippets='http-request,path-parameters,request-fields,response-fields'] --- diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 31ab6d71..d8753290 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -22,4 +22,5 @@ include::MissionArchive-API.adoc[] include::Board-API.adoc[] +include::BoardComment_API.adoc[] From 6faadc4b3b8423565d7f52c8f59b78e1b7fbe6e8 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sat, 30 Sep 2023 23:18:24 +0900 Subject: [PATCH 106/619] =?UTF-8?q?fix:=20=EB=8C=93=EA=B8=80=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=88=AB=EC=9E=90=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/board/domain/service/BoardGetService.java | 2 +- .../application/service/DeleteBoardCommentUserCase.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java b/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java index f1c62e2e..e5db6029 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java +++ b/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java @@ -19,7 +19,7 @@ public class BoardGetService { private final BoardRepository boardRepository; public Board getBoard(Long boardId){ - return boardRepository.findBoardByBoardId(boardId).orElseThrow(()->new NotFoundByBoardIdException()); + return boardRepository.findBoardByBoardId(boardId).orElseThrow(NotFoundByBoardIdException::new); } public GetAllBoardResponse getBoardAll(Long teamId, Long memberId){ diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java index b9aa1be9..0730f2b9 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java @@ -28,14 +28,17 @@ public class DeleteBoardCommentUserCase { private final TeamMemberGetService teamMemberGetService; private final BoardCommentGetService boardCommentGetService; private final BoardCommentDeleteService boardCommentDeleteService; + private final BoardGetService boardGetService; public void deleteBoardComment(String socialId, Long teamId, Long boardId, Long boardCommentId){ Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + Board board=boardGetService.getBoard(boardId); BoardComment boardComment=boardCommentGetService.getBoardComment(boardCommentId); if (teamMember == boardComment.getTeamMember()) { boardCommentDeleteService.deleteBoardComment(boardComment); + board.decrComNum(); } else throw new NotAuthByBoardCommentException(); } } From 7977769876ee24bc50ee2a3f6bdff642f22c9564 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sun, 1 Oct 2023 00:52:47 +0900 Subject: [PATCH 107/619] =?UTF-8?q?feat:=20=EA=B3=B5=ED=86=B5=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CreateBoardUserCase.java | 23 +++++++------ .../service/DeleteBoardUserCase.java | 27 ++++------------ .../application/service/GetBoardUserCase.java | 32 +++++++------------ .../service/UpdateBoardUserCase.java | 27 +++++----------- .../service/CreateBoardCommentUserCase.java | 24 ++++---------- .../service/DeleteBoardCommentUserCase.java | 27 ++++------------ .../service/GetBoardCommentUserCase.java | 21 ++++-------- .../service/CreateBoardReadUserCase.java | 26 +++++++++++++++ .../response/BaseBoardServiceResponse.java | 19 +++++++++++ .../global/response/BaseServiceResponse.java | 17 ++++++++++ .../global/response/SuccessResponse.java | 1 - .../backend/global/util/BaseBoardService.java | 32 +++++++++++++++++++ .../backend/global/util/BaseService.java | 28 ++++++++++++++++ 13 files changed, 178 insertions(+), 126 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java create mode 100644 src/main/java/com/moing/backend/global/response/BaseBoardServiceResponse.java create mode 100644 src/main/java/com/moing/backend/global/response/BaseServiceResponse.java create mode 100644 src/main/java/com/moing/backend/global/util/BaseBoardService.java create mode 100644 src/main/java/com/moing/backend/global/util/BaseService.java diff --git a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java index 25576f2d..84139ae8 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java @@ -6,6 +6,7 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardSaveService; import com.moing.backend.domain.boardRead.application.mapper.BoardReadMapper; +import com.moing.backend.domain.boardRead.application.service.CreateBoardReadUserCase; import com.moing.backend.domain.boardRead.domain.entity.BoardRead; import com.moing.backend.domain.boardRead.domain.service.BoardReadSaveService; import com.moing.backend.domain.member.domain.entity.Member; @@ -16,6 +17,8 @@ import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.BaseServiceResponse; +import com.moing.backend.global.util.BaseService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -25,28 +28,24 @@ @Transactional @RequiredArgsConstructor public class CreateBoardUserCase { - private final MemberGetService memberGetService; + + private final BoardSaveService boardSaveService; private final CheckLeaderUserCase checkLeaderUserCase; - private final TeamGetService teamGetService; private final BoardMapper boardMapper; - private final TeamMemberGetService teamMemberGetService; - private final BoardReadMapper boardReadMapper; - private final BoardReadSaveService boardReadSaveService; + private final CreateBoardReadUserCase createBoardReadUserCase; + private final BaseService baseService; /** * 게시글 생성 */ public CreateBoardResponse createBoard(String socialId, Long teamId, CreateBoardRequest createBoardRequest) { - Member member=memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); - boolean isLeader = checkLeaderUserCase.isTeamLeader(member, team); - Board board=boardSaveService.saveBoard(boardMapper.toBoard(member, teamMember, team, createBoardRequest, isLeader)); + BaseServiceResponse data=baseService.getCommonData(socialId, teamId); + boolean isLeader = checkLeaderUserCase.isTeamLeader(data.getMember(), data.getTeam()); + Board board=boardSaveService.saveBoard(boardMapper.toBoard(data.getMember(), data.getTeamMember(), data.getTeam(), createBoardRequest, isLeader)); //읽음 처리 - BoardRead boardRead = boardReadMapper.toBoardRead(team, member); - boardReadSaveService.saveBoardRead(board, boardRead); + createBoardReadUserCase.createBoardRead(data.getTeam(), data.getMember(), board); return new CreateBoardResponse(board.getBoardId()); } } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java index 6a6cee91..387e17da 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java @@ -1,17 +1,9 @@ package com.moing.backend.domain.board.application.service; -import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; -import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; -import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardDeleteService; -import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.board.exception.NotAuthByBoardException; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -22,21 +14,16 @@ @RequiredArgsConstructor public class DeleteBoardUserCase { - private final MemberGetService memberGetService; - private final TeamGetService teamGetService; - private final BoardGetService boardGetService; - private final TeamMemberGetService teamMemberGetService; + private final BaseBoardService baseBoardService; private final BoardDeleteService boardDeleteService; + /** * 게시글 삭제 */ public void deleteBoard(String socialId, Long teamId, Long boardId){ - Member member=memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - Board board = boardGetService.getBoard(boardId); - TeamMember teamMember=teamMemberGetService.getTeamMember(member, team); - if (teamMember == board.getTeamMember()) { - boardDeleteService.deleteBoard(board); + BaseBoardServiceResponse data= baseBoardService.getCommonData(socialId,teamId,boardId); + if (data.getTeamMember() == data.getBoard().getTeamMember()) { + boardDeleteService.deleteBoard(data.getBoard()); } else throw new NotAuthByBoardException(); } } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java index c9116f63..56430dcc 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java @@ -3,17 +3,12 @@ import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; import com.moing.backend.domain.board.application.dto.response.GetBoardDetailResponse; import com.moing.backend.domain.board.application.mapper.BoardMapper; -import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardGetService; -import com.moing.backend.domain.boardRead.application.mapper.BoardReadMapper; -import com.moing.backend.domain.boardRead.domain.entity.BoardRead; -import com.moing.backend.domain.boardRead.domain.service.BoardReadSaveService; +import com.moing.backend.domain.boardRead.application.service.CreateBoardReadUserCase; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -24,27 +19,22 @@ @RequiredArgsConstructor public class GetBoardUserCase { + + private final BaseBoardService baseBoardService; + private final BoardMapper boardMapper; private final MemberGetService memberGetService; + private final CreateBoardReadUserCase createBoardReadUserCase; private final BoardGetService boardGetService; - private final BoardMapper boardMapper; - private final TeamGetService teamGetService; - private final BoardReadMapper boardReadMapper; - private final BoardReadSaveService boardReadSaveService; - private final TeamMemberGetService teamMemberGetService; + /** * 게시글 상세 조회 */ public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long boardId) { - Member member=memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - Board board = boardGetService.getBoard(boardId); - TeamMember teamMember=teamMemberGetService.getTeamMember(member, team); + BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); //읽음 처리 - BoardRead boardRead = boardReadMapper.toBoardRead(team, member); - boardReadSaveService.saveBoardRead(board, boardRead); - - return boardMapper.toBoardDetail(board, teamMember==board.getTeamMember()); + createBoardReadUserCase.createBoardRead(data.getTeam(), data.getMember(), data.getBoard()); + return boardMapper.toBoardDetail(data.getBoard(), data.getTeamMember() == data.getBoard().getTeamMember()); } /** diff --git a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java index 2643da09..394b34e3 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java @@ -2,15 +2,9 @@ import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; -import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.board.exception.NotAuthByBoardException; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,22 +14,17 @@ @Transactional @RequiredArgsConstructor public class UpdateBoardUserCase { - private final MemberGetService memberGetService; - private final TeamGetService teamGetService; - private final BoardGetService boardGetService; - private final TeamMemberGetService teamMemberGetService; + + private final BaseBoardService baseBoardService; /** * 게시글 수정 */ public UpdateBoardResponse updateBoard(String socialId, Long teamId, Long boardId, UpdateBoardRequest updateBoardRequest){ - Member member=memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - Board board = boardGetService.getBoard(boardId); - TeamMember teamMember=teamMemberGetService.getTeamMember(member, team); - if (teamMember == board.getTeamMember()) { - board.updateBoard(updateBoardRequest); - return new UpdateBoardResponse(board.getBoardId()); + BaseBoardServiceResponse data= baseBoardService.getCommonData(socialId, teamId, boardId); + if (data.getTeamMember() == data.getBoard().getTeamMember()) { + data.getBoard().updateBoard(updateBoardRequest); + return new UpdateBoardResponse(data.getBoard().getBoardId()); } else throw new NotAuthByBoardException(); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java index 6a2cb5ed..759fc5c4 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java @@ -1,18 +1,12 @@ package com.moing.backend.domain.boardComment.application.service; -import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; import com.moing.backend.domain.boardComment.application.dto.response.CreateBoardCommentResponse; import com.moing.backend.domain.boardComment.application.mapper.BoardCommentMapper; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.service.BoardCommentSaveService; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -23,20 +17,14 @@ @Transactional public class CreateBoardCommentUserCase { - private final MemberGetService memberGetService; - private final TeamGetService teamGetService; - private final BoardGetService boardGetService; - private final TeamMemberGetService teamMemberGetService; private final BoardCommentSaveService boardCommentSaveService; private final BoardCommentMapper boardCommentMapper; + private final BaseBoardService baseBoardService; public CreateBoardCommentResponse createBoardComment(String socialId, Long teamId, Long boardId, CreateBoardCommentRequest createBoardCommentRequest) { - Member member = memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - Board board = boardGetService.getBoard(boardId); - TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); - BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(teamMember, board, createBoardCommentRequest)); - board.incrComNum(); + BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); + BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(data.getTeamMember(), data.getBoard(), createBoardCommentRequest)); + data.getBoard().incrComNum(); return new CreateBoardCommentResponse(boardComment.getBoardCommentId()); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java index 0730f2b9..6201717f 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java @@ -1,19 +1,11 @@ package com.moing.backend.domain.boardComment.application.service; -import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.board.domain.service.BoardGetService; -import com.moing.backend.domain.board.exception.NotAuthByBoardException; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.service.BoardCommentDeleteService; import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; -import com.moing.backend.domain.boardComment.domain.service.BoardCommentSaveService; import com.moing.backend.domain.boardComment.exception.NotAuthByBoardCommentException; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -23,22 +15,17 @@ @Transactional @RequiredArgsConstructor public class DeleteBoardCommentUserCase { - private final MemberGetService memberGetService; - private final TeamGetService teamGetService; - private final TeamMemberGetService teamMemberGetService; + private final BoardCommentGetService boardCommentGetService; private final BoardCommentDeleteService boardCommentDeleteService; - private final BoardGetService boardGetService; + private final BaseBoardService baseBoardService; public void deleteBoardComment(String socialId, Long teamId, Long boardId, Long boardCommentId){ - Member member = memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); - Board board=boardGetService.getBoard(boardId); + BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); BoardComment boardComment=boardCommentGetService.getBoardComment(boardCommentId); - if (teamMember == boardComment.getTeamMember()) { + if (data.getTeamMember() == boardComment.getTeamMember()) { boardCommentDeleteService.deleteBoardComment(boardComment); - board.decrComNum(); + data.getBoard().decrComNum(); } else throw new NotAuthByBoardCommentException(); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java index 8763a033..df53c6e1 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java @@ -1,15 +1,9 @@ package com.moing.backend.domain.boardComment.application.service; -import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; -import com.moing.backend.domain.boardComment.domain.service.BoardCommentDeleteService; import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -19,15 +13,12 @@ @Transactional @RequiredArgsConstructor public class GetBoardCommentUserCase { - private final MemberGetService memberGetService; - private final TeamGetService teamGetService; - private final TeamMemberGetService teamMemberGetService; + private final BoardCommentGetService boardCommentGetService; + private final BaseBoardService baseBoardService; public GetBoardCommentResponse getBoardCommentAll(String socialId, Long teamId, Long boardId){ - Member member = memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); - return boardCommentGetService.getBoardCommentAll(boardId, teamMember); + BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); + return boardCommentGetService.getBoardCommentAll(boardId, data.getTeamMember()); } } diff --git a/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java b/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java new file mode 100644 index 00000000..9c55a2fc --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java @@ -0,0 +1,26 @@ +package com.moing.backend.domain.boardRead.application.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardRead.application.mapper.BoardReadMapper; +import com.moing.backend.domain.boardRead.domain.entity.BoardRead; +import com.moing.backend.domain.boardRead.domain.service.BoardReadSaveService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class CreateBoardReadUserCase { + + private final BoardReadMapper boardReadMapper; + private final BoardReadSaveService boardReadSaveService; + + public void createBoardRead(Team team, Member member, Board board){ + BoardRead boardRead = boardReadMapper.toBoardRead(team, member); + boardReadSaveService.saveBoardRead(board, boardRead); + } +} diff --git a/src/main/java/com/moing/backend/global/response/BaseBoardServiceResponse.java b/src/main/java/com/moing/backend/global/response/BaseBoardServiceResponse.java new file mode 100644 index 00000000..c65abe5b --- /dev/null +++ b/src/main/java/com/moing/backend/global/response/BaseBoardServiceResponse.java @@ -0,0 +1,19 @@ +package com.moing.backend.global.response; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class BaseBoardServiceResponse { + private Member member; + private Team team; + private Board board; + private TeamMember teamMember; +} diff --git a/src/main/java/com/moing/backend/global/response/BaseServiceResponse.java b/src/main/java/com/moing/backend/global/response/BaseServiceResponse.java new file mode 100644 index 00000000..1258c29b --- /dev/null +++ b/src/main/java/com/moing/backend/global/response/BaseServiceResponse.java @@ -0,0 +1,17 @@ +package com.moing.backend.global.response; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class BaseServiceResponse { + private Member member; + private Team team; + private TeamMember teamMember; +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/response/SuccessResponse.java b/src/main/java/com/moing/backend/global/response/SuccessResponse.java index 2b787b9d..20353aa0 100644 --- a/src/main/java/com/moing/backend/global/response/SuccessResponse.java +++ b/src/main/java/com/moing/backend/global/response/SuccessResponse.java @@ -8,7 +8,6 @@ @Getter @AllArgsConstructor @NoArgsConstructor - public class SuccessResponse { private Boolean isSuccess; private String message; diff --git a/src/main/java/com/moing/backend/global/util/BaseBoardService.java b/src/main/java/com/moing/backend/global/util/BaseBoardService.java new file mode 100644 index 00000000..c502c37c --- /dev/null +++ b/src/main/java/com/moing/backend/global/util/BaseBoardService.java @@ -0,0 +1,32 @@ +package com.moing.backend.global.util; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BaseBoardService { + + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final BoardGetService boardGetService; + private final TeamMemberGetService teamMemberGetService; + + public BaseBoardServiceResponse getCommonData(String socialId, Long teamId, Long boardId) { + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + Board board = boardGetService.getBoard(boardId); + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + + return new BaseBoardServiceResponse(member, team, board, teamMember); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/util/BaseService.java b/src/main/java/com/moing/backend/global/util/BaseService.java new file mode 100644 index 00000000..0926e321 --- /dev/null +++ b/src/main/java/com/moing/backend/global/util/BaseService.java @@ -0,0 +1,28 @@ +package com.moing.backend.global.util; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseServiceResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BaseService { + + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final TeamMemberGetService teamMemberGetService; + + public BaseServiceResponse getCommonData(String socialId, Long teamId) { + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + + return new BaseServiceResponse(member, team, teamMember); + } +} From 78f9e42997f39c5972760ab702614cb9825fc1b0 Mon Sep 17 00:00:00 2001 From: Minsu Kim Date: Sun, 1 Oct 2023 00:52:47 +0900 Subject: [PATCH 108/619] =?UTF-8?q?feat:=20=EA=B3=B5=ED=86=B5=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CreateBoardUserCase.java | 23 +++++++------ .../service/DeleteBoardUserCase.java | 27 ++++------------ .../application/service/GetBoardUserCase.java | 32 +++++++------------ .../service/UpdateBoardUserCase.java | 27 +++++----------- .../service/CreateBoardCommentUserCase.java | 24 ++++---------- .../service/DeleteBoardCommentUserCase.java | 27 ++++------------ .../service/GetBoardCommentUserCase.java | 21 ++++-------- .../service/CreateBoardReadUserCase.java | 26 +++++++++++++++ .../response/BaseBoardServiceResponse.java | 19 +++++++++++ .../global/response/BaseServiceResponse.java | 17 ++++++++++ .../global/response/SuccessResponse.java | 1 - .../backend/global/util/BaseBoardService.java | 32 +++++++++++++++++++ .../backend/global/util/BaseService.java | 28 ++++++++++++++++ 13 files changed, 178 insertions(+), 126 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java create mode 100644 src/main/java/com/moing/backend/global/response/BaseBoardServiceResponse.java create mode 100644 src/main/java/com/moing/backend/global/response/BaseServiceResponse.java create mode 100644 src/main/java/com/moing/backend/global/util/BaseBoardService.java create mode 100644 src/main/java/com/moing/backend/global/util/BaseService.java diff --git a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java index 25576f2d..84139ae8 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java @@ -6,6 +6,7 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardSaveService; import com.moing.backend.domain.boardRead.application.mapper.BoardReadMapper; +import com.moing.backend.domain.boardRead.application.service.CreateBoardReadUserCase; import com.moing.backend.domain.boardRead.domain.entity.BoardRead; import com.moing.backend.domain.boardRead.domain.service.BoardReadSaveService; import com.moing.backend.domain.member.domain.entity.Member; @@ -16,6 +17,8 @@ import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.BaseServiceResponse; +import com.moing.backend.global.util.BaseService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -25,28 +28,24 @@ @Transactional @RequiredArgsConstructor public class CreateBoardUserCase { - private final MemberGetService memberGetService; + + private final BoardSaveService boardSaveService; private final CheckLeaderUserCase checkLeaderUserCase; - private final TeamGetService teamGetService; private final BoardMapper boardMapper; - private final TeamMemberGetService teamMemberGetService; - private final BoardReadMapper boardReadMapper; - private final BoardReadSaveService boardReadSaveService; + private final CreateBoardReadUserCase createBoardReadUserCase; + private final BaseService baseService; /** * 게시글 생성 */ public CreateBoardResponse createBoard(String socialId, Long teamId, CreateBoardRequest createBoardRequest) { - Member member=memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); - boolean isLeader = checkLeaderUserCase.isTeamLeader(member, team); - Board board=boardSaveService.saveBoard(boardMapper.toBoard(member, teamMember, team, createBoardRequest, isLeader)); + BaseServiceResponse data=baseService.getCommonData(socialId, teamId); + boolean isLeader = checkLeaderUserCase.isTeamLeader(data.getMember(), data.getTeam()); + Board board=boardSaveService.saveBoard(boardMapper.toBoard(data.getMember(), data.getTeamMember(), data.getTeam(), createBoardRequest, isLeader)); //읽음 처리 - BoardRead boardRead = boardReadMapper.toBoardRead(team, member); - boardReadSaveService.saveBoardRead(board, boardRead); + createBoardReadUserCase.createBoardRead(data.getTeam(), data.getMember(), board); return new CreateBoardResponse(board.getBoardId()); } } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java index 6a6cee91..387e17da 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java @@ -1,17 +1,9 @@ package com.moing.backend.domain.board.application.service; -import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; -import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; -import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardDeleteService; -import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.board.exception.NotAuthByBoardException; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -22,21 +14,16 @@ @RequiredArgsConstructor public class DeleteBoardUserCase { - private final MemberGetService memberGetService; - private final TeamGetService teamGetService; - private final BoardGetService boardGetService; - private final TeamMemberGetService teamMemberGetService; + private final BaseBoardService baseBoardService; private final BoardDeleteService boardDeleteService; + /** * 게시글 삭제 */ public void deleteBoard(String socialId, Long teamId, Long boardId){ - Member member=memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - Board board = boardGetService.getBoard(boardId); - TeamMember teamMember=teamMemberGetService.getTeamMember(member, team); - if (teamMember == board.getTeamMember()) { - boardDeleteService.deleteBoard(board); + BaseBoardServiceResponse data= baseBoardService.getCommonData(socialId,teamId,boardId); + if (data.getTeamMember() == data.getBoard().getTeamMember()) { + boardDeleteService.deleteBoard(data.getBoard()); } else throw new NotAuthByBoardException(); } } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java index c9116f63..56430dcc 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java @@ -3,17 +3,12 @@ import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; import com.moing.backend.domain.board.application.dto.response.GetBoardDetailResponse; import com.moing.backend.domain.board.application.mapper.BoardMapper; -import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardGetService; -import com.moing.backend.domain.boardRead.application.mapper.BoardReadMapper; -import com.moing.backend.domain.boardRead.domain.entity.BoardRead; -import com.moing.backend.domain.boardRead.domain.service.BoardReadSaveService; +import com.moing.backend.domain.boardRead.application.service.CreateBoardReadUserCase; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -24,27 +19,22 @@ @RequiredArgsConstructor public class GetBoardUserCase { + + private final BaseBoardService baseBoardService; + private final BoardMapper boardMapper; private final MemberGetService memberGetService; + private final CreateBoardReadUserCase createBoardReadUserCase; private final BoardGetService boardGetService; - private final BoardMapper boardMapper; - private final TeamGetService teamGetService; - private final BoardReadMapper boardReadMapper; - private final BoardReadSaveService boardReadSaveService; - private final TeamMemberGetService teamMemberGetService; + /** * 게시글 상세 조회 */ public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long boardId) { - Member member=memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - Board board = boardGetService.getBoard(boardId); - TeamMember teamMember=teamMemberGetService.getTeamMember(member, team); + BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); //읽음 처리 - BoardRead boardRead = boardReadMapper.toBoardRead(team, member); - boardReadSaveService.saveBoardRead(board, boardRead); - - return boardMapper.toBoardDetail(board, teamMember==board.getTeamMember()); + createBoardReadUserCase.createBoardRead(data.getTeam(), data.getMember(), data.getBoard()); + return boardMapper.toBoardDetail(data.getBoard(), data.getTeamMember() == data.getBoard().getTeamMember()); } /** diff --git a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java index 2643da09..394b34e3 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java @@ -2,15 +2,9 @@ import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; -import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.board.exception.NotAuthByBoardException; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,22 +14,17 @@ @Transactional @RequiredArgsConstructor public class UpdateBoardUserCase { - private final MemberGetService memberGetService; - private final TeamGetService teamGetService; - private final BoardGetService boardGetService; - private final TeamMemberGetService teamMemberGetService; + + private final BaseBoardService baseBoardService; /** * 게시글 수정 */ public UpdateBoardResponse updateBoard(String socialId, Long teamId, Long boardId, UpdateBoardRequest updateBoardRequest){ - Member member=memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - Board board = boardGetService.getBoard(boardId); - TeamMember teamMember=teamMemberGetService.getTeamMember(member, team); - if (teamMember == board.getTeamMember()) { - board.updateBoard(updateBoardRequest); - return new UpdateBoardResponse(board.getBoardId()); + BaseBoardServiceResponse data= baseBoardService.getCommonData(socialId, teamId, boardId); + if (data.getTeamMember() == data.getBoard().getTeamMember()) { + data.getBoard().updateBoard(updateBoardRequest); + return new UpdateBoardResponse(data.getBoard().getBoardId()); } else throw new NotAuthByBoardException(); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java index 6a2cb5ed..759fc5c4 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java @@ -1,18 +1,12 @@ package com.moing.backend.domain.boardComment.application.service; -import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; import com.moing.backend.domain.boardComment.application.dto.response.CreateBoardCommentResponse; import com.moing.backend.domain.boardComment.application.mapper.BoardCommentMapper; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.service.BoardCommentSaveService; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -23,20 +17,14 @@ @Transactional public class CreateBoardCommentUserCase { - private final MemberGetService memberGetService; - private final TeamGetService teamGetService; - private final BoardGetService boardGetService; - private final TeamMemberGetService teamMemberGetService; private final BoardCommentSaveService boardCommentSaveService; private final BoardCommentMapper boardCommentMapper; + private final BaseBoardService baseBoardService; public CreateBoardCommentResponse createBoardComment(String socialId, Long teamId, Long boardId, CreateBoardCommentRequest createBoardCommentRequest) { - Member member = memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - Board board = boardGetService.getBoard(boardId); - TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); - BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(teamMember, board, createBoardCommentRequest)); - board.incrComNum(); + BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); + BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(data.getTeamMember(), data.getBoard(), createBoardCommentRequest)); + data.getBoard().incrComNum(); return new CreateBoardCommentResponse(boardComment.getBoardCommentId()); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java index 0730f2b9..6201717f 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java @@ -1,19 +1,11 @@ package com.moing.backend.domain.boardComment.application.service; -import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.board.domain.service.BoardGetService; -import com.moing.backend.domain.board.exception.NotAuthByBoardException; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.service.BoardCommentDeleteService; import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; -import com.moing.backend.domain.boardComment.domain.service.BoardCommentSaveService; import com.moing.backend.domain.boardComment.exception.NotAuthByBoardCommentException; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -23,22 +15,17 @@ @Transactional @RequiredArgsConstructor public class DeleteBoardCommentUserCase { - private final MemberGetService memberGetService; - private final TeamGetService teamGetService; - private final TeamMemberGetService teamMemberGetService; + private final BoardCommentGetService boardCommentGetService; private final BoardCommentDeleteService boardCommentDeleteService; - private final BoardGetService boardGetService; + private final BaseBoardService baseBoardService; public void deleteBoardComment(String socialId, Long teamId, Long boardId, Long boardCommentId){ - Member member = memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); - Board board=boardGetService.getBoard(boardId); + BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); BoardComment boardComment=boardCommentGetService.getBoardComment(boardCommentId); - if (teamMember == boardComment.getTeamMember()) { + if (data.getTeamMember() == boardComment.getTeamMember()) { boardCommentDeleteService.deleteBoardComment(boardComment); - board.decrComNum(); + data.getBoard().decrComNum(); } else throw new NotAuthByBoardCommentException(); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java index 8763a033..df53c6e1 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java @@ -1,15 +1,9 @@ package com.moing.backend.domain.boardComment.application.service; -import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; -import com.moing.backend.domain.boardComment.domain.service.BoardCommentDeleteService; import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -19,15 +13,12 @@ @Transactional @RequiredArgsConstructor public class GetBoardCommentUserCase { - private final MemberGetService memberGetService; - private final TeamGetService teamGetService; - private final TeamMemberGetService teamMemberGetService; + private final BoardCommentGetService boardCommentGetService; + private final BaseBoardService baseBoardService; public GetBoardCommentResponse getBoardCommentAll(String socialId, Long teamId, Long boardId){ - Member member = memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); - TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); - return boardCommentGetService.getBoardCommentAll(boardId, teamMember); + BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); + return boardCommentGetService.getBoardCommentAll(boardId, data.getTeamMember()); } } diff --git a/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java b/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java new file mode 100644 index 00000000..9c55a2fc --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java @@ -0,0 +1,26 @@ +package com.moing.backend.domain.boardRead.application.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardRead.application.mapper.BoardReadMapper; +import com.moing.backend.domain.boardRead.domain.entity.BoardRead; +import com.moing.backend.domain.boardRead.domain.service.BoardReadSaveService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class CreateBoardReadUserCase { + + private final BoardReadMapper boardReadMapper; + private final BoardReadSaveService boardReadSaveService; + + public void createBoardRead(Team team, Member member, Board board){ + BoardRead boardRead = boardReadMapper.toBoardRead(team, member); + boardReadSaveService.saveBoardRead(board, boardRead); + } +} diff --git a/src/main/java/com/moing/backend/global/response/BaseBoardServiceResponse.java b/src/main/java/com/moing/backend/global/response/BaseBoardServiceResponse.java new file mode 100644 index 00000000..c65abe5b --- /dev/null +++ b/src/main/java/com/moing/backend/global/response/BaseBoardServiceResponse.java @@ -0,0 +1,19 @@ +package com.moing.backend.global.response; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class BaseBoardServiceResponse { + private Member member; + private Team team; + private Board board; + private TeamMember teamMember; +} diff --git a/src/main/java/com/moing/backend/global/response/BaseServiceResponse.java b/src/main/java/com/moing/backend/global/response/BaseServiceResponse.java new file mode 100644 index 00000000..1258c29b --- /dev/null +++ b/src/main/java/com/moing/backend/global/response/BaseServiceResponse.java @@ -0,0 +1,17 @@ +package com.moing.backend.global.response; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class BaseServiceResponse { + private Member member; + private Team team; + private TeamMember teamMember; +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/response/SuccessResponse.java b/src/main/java/com/moing/backend/global/response/SuccessResponse.java index 2b787b9d..20353aa0 100644 --- a/src/main/java/com/moing/backend/global/response/SuccessResponse.java +++ b/src/main/java/com/moing/backend/global/response/SuccessResponse.java @@ -8,7 +8,6 @@ @Getter @AllArgsConstructor @NoArgsConstructor - public class SuccessResponse { private Boolean isSuccess; private String message; diff --git a/src/main/java/com/moing/backend/global/util/BaseBoardService.java b/src/main/java/com/moing/backend/global/util/BaseBoardService.java new file mode 100644 index 00000000..c502c37c --- /dev/null +++ b/src/main/java/com/moing/backend/global/util/BaseBoardService.java @@ -0,0 +1,32 @@ +package com.moing.backend.global.util; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BaseBoardService { + + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final BoardGetService boardGetService; + private final TeamMemberGetService teamMemberGetService; + + public BaseBoardServiceResponse getCommonData(String socialId, Long teamId, Long boardId) { + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + Board board = boardGetService.getBoard(boardId); + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + + return new BaseBoardServiceResponse(member, team, board, teamMember); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/util/BaseService.java b/src/main/java/com/moing/backend/global/util/BaseService.java new file mode 100644 index 00000000..0926e321 --- /dev/null +++ b/src/main/java/com/moing/backend/global/util/BaseService.java @@ -0,0 +1,28 @@ +package com.moing.backend.global.util; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseServiceResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BaseService { + + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final TeamMemberGetService teamMemberGetService; + + public BaseServiceResponse getCommonData(String socialId, Long teamId) { + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + + return new BaseServiceResponse(member, team, teamMember); + } +} From fc753dc9a00e01ab47f781683f1ee6263a09bba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:20:40 +0900 Subject: [PATCH 109/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=A2=8B=EC=95=84=EC=9A=94,=20=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=EC=9D=B8=EC=9B=90=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20API=20=EB=AC=B8=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionArchive-API.adoc | 12 ++++++++++++ src/docs/asciidoc/Overview.adoc | 12 ++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/docs/asciidoc/MissionArchive-API.adoc b/src/docs/asciidoc/MissionArchive-API.adoc index d082b9c8..dc148e22 100644 --- a/src/docs/asciidoc/MissionArchive-API.adoc +++ b/src/docs/asciidoc/MissionArchive-API.adoc @@ -27,3 +27,15 @@ operation::mission-archive-controller-test/모임원_미션_인증_조회[snippe --- +[[MissionArchive-인증성공인원조회]] +=== 인증 성공 인원 조회 ( n/n명 ) +operation::mission-archive-controller-test/인증_성공_인원_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[MissionArchive-미션인증물좋아요]] +=== 미션 인증물 좋아요 +operation::mission-archive-controller-test/미션_인증물_좋아요[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + diff --git a/src/docs/asciidoc/Overview.adoc b/src/docs/asciidoc/Overview.adoc index 2b9e0a24..5f488cc2 100644 --- a/src/docs/asciidoc/Overview.adoc +++ b/src/docs/asciidoc/Overview.adoc @@ -116,7 +116,15 @@ | 소모임장이 아님 | `M0002` -| API PATH에 missionId가 있으 때 -| missionId가 유요하지 않음 +| API PATH에 missionId가 있을 때 +| missionId가 유효하지 않음 +|=== + +=== MissionArchive ErrorCode +|=== +| ErrorCode | Scope | Description +| `MA0001` +| 미션 인증물 조회할 때 +| 미션 missionId 또는 teamId가 유효하지 않음 |=== From e4c4d61806f5ad042e99f0c869bc226d15332cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:56:53 +0900 Subject: [PATCH 110/619] =?UTF-8?q?=20feat=20:=20=ED=8C=80=EB=B3=84=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EA=B0=9C=EC=88=98=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionCustomRepository.java | 5 ++++ .../MissionCustomRepositoryImpl.java | 28 +++++++++++++++++++ .../domain/repository/MissionRepository.java | 2 +- .../domain/service/MissionQueryService.java | 4 +++ .../presentation/MissionController.java | 2 ++ 5 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java new file mode 100644 index 00000000..9ab4a501 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.mission.domain.repository; + +public interface MissionCustomRepository { + Long findMissionsCountByTeam(Long teamId); +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java new file mode 100644 index 00000000..53a7cd60 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.mission.domain.repository; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; + +import static com.moing.backend.domain.mission.domain.entity.QMission.mission; + +public class MissionCustomRepositoryImpl implements MissionCustomRepository{ + + private final JPAQueryFactory queryFactory; + public MissionCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + + @Override + public Long findMissionsCountByTeam(Long teamId) { + return queryFactory + .select(mission.count()) + .from(mission) + .where( + mission.team.teamId.eq(teamId) + ) + .fetchFirst(); + } +} diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java index ec8b779d..5244df48 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java @@ -3,5 +3,5 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import org.springframework.data.jpa.repository.JpaRepository; -public interface MissionRepository extends JpaRepository { +public interface MissionRepository extends JpaRepository,MissionCustomRepository { } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 1a591022..961be80e 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -17,4 +17,8 @@ public class MissionQueryService { public Mission findMissionById(Long missionId) { return missionRepository.findById(missionId).orElseThrow(NotFoundMissionException::new); } + + public Long findMissionsCountByTeam(Long teamId) { + return missionRepository.findMissionsCountByTeam(teamId); + } } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index f458207b..d66ccf85 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -8,6 +8,7 @@ import com.moing.backend.domain.mission.application.service.MissionReadUseCase; import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; import com.moing.backend.domain.mission.domain.service.MissionDeleteService; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -28,6 +29,7 @@ public class MissionController { private final MissionReadUseCase missionReadUseCase; private final MissionUpdateUseCase missionUpdateUseCase; private final MissionDeleteUseCase missionDeleteUseCase; + private final MissionQueryService missionQueryService; /** * 미션 조회 From e8d977fe4a2a1919d9d133cd49ccb6e945709c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 2 Oct 2023 15:35:49 +0900 Subject: [PATCH 111/619] =?UTF-8?q?fix=20:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=EC=9E=A5=20=ED=99=95=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20equals?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionCreateUseCase.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index d5343370..dd4756e7 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -32,13 +32,12 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR Member member = memberGetService.getMemberBySocialId(userSocialId); Team team = teamRepository.findById(teamId).orElseThrow(); - // 소모임장 확인 로직 추가 - if (member.getMemberId() == team.getLeaderId()) { + // 소모임 장 확인 + if (member.getMemberId().equals(team.getLeaderId())) { Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.ONGOING); // teamRepository 변경 예정 mission.setTeam(team); missionSaveService.save(mission); - return MissionMapper.mapToMissionCreateRes(mission); } else{ From 236c4fcd663361f3be807cdb03e9e2628a66476c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:23:13 +0900 Subject: [PATCH 112/619] =?UTF-8?q?feat=20:=20=ED=95=9C=EB=B2=88=EB=AF=B8?= =?UTF-8?q?=EC=85=98,=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EA=B3=B5=EC=9C=A0=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EB=A6=AC=ED=84=B4=20=EA=B0=9D=EC=B2=B4=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/mapper/MissionArchiveMapper.java | 8 ++++++++ .../service/MissionArchiveCreateUseCase.java | 6 +++--- .../service/SingleMissionArchiveReadUseCase.java | 6 ++---- .../repository/MissionArchiveRepository.java | 2 +- .../presentation/MissionArchiveController.java | 2 +- .../MissionArchiveControllerTest.java | 14 +++++++------- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index f191145c..0815ceca 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -39,6 +39,14 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc .build(); } + public static List mapToMissionArchiveResList(List missionArchiveList) { + List missionArchiveResList = new ArrayList<>(); + missionArchiveList.forEach( + missionArchive -> missionArchiveResList.add(MissionArchiveMapper.mapToMissionArchiveRes(missionArchive)) + ); + return missionArchiveResList; + } + public static PersonalArchive mapToPersonalArchive(MissionArchive missionArchive) { Member member = missionArchive.getMember(); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index e13eb48b..19115175 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -52,9 +52,9 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss // missionArchive 2개 이상일 때 예외처리 필요 MissionArchive missionArchive = missionArchiveSaveService.save(MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission)); - if (isDoneSingleMission(mission)) { - missionArchiveScoreService.addScore(team); - } +// if (isDoneSingleMission(mission)) { +// missionArchiveScoreService.addScore(team); +// } return MissionArchiveMapper.mapToMissionArchiveRes(missionArchive); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java index 87204ea6..38c8b683 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java @@ -34,13 +34,11 @@ public class SingleMissionArchiveReadUseCase { // 미션 인증 조회 - public MissionArchiveRes getMyArchive(String userSocialId, Long missionId) { - - List archiveRes = new ArrayList<>(); + public List getMyArchive(String userSocialId, Long missionId) { Member member = memberGetService.getMemberBySocialId(userSocialId); - return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId).get(0)); + return MissionArchiveMapper.mapToMissionArchiveResList(missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId)); } // 모두의 미션 인증 목록 조회 diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java index 10a90ee7..804a5b01 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -16,7 +16,7 @@ public interface MissionArchiveRepository extends JpaRepository> findByMemberId(@Param("memberId") Long memberId); - @Query("select m from MissionArchive as m where m.mission.id = :missionId and m.member.memberId =:memberId") + @Query("select m from MissionArchive as m where m.mission.id = :missionId and m.member.memberId =:memberId order by m.createdDate") Optional> findArchivesByMissionIdAndMemberId(@Param("memberId") Long memberId, @Param("missionId")Long missionId); @Query("select m from MissionArchive as m where m.mission.id = :missionId and m.member.memberId =:memberId") diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 0d5e628a..bb446ce8 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -67,7 +67,7 @@ public ResponseEntity> updateArchive(@Authent **/ @GetMapping() - public ResponseEntity> getMyArchive(@AuthenticationPrincipal User user, + public ResponseEntity>> getMyArchive(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId) { return ResponseEntity.ok(SuccessResponse.create(READ_MY_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getMyArchive(user.getSocialId(), missionId))); diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 5e35a46b..10625b91 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -185,13 +185,13 @@ public class MissionArchiveControllerTest extends CommonControllerTest { public void 나의_미션_인증_조회() throws Exception { //given - MissionArchiveRes output = MissionArchiveRes.builder() + List output = Lists.newArrayList(MissionArchiveRes.builder() .archiveId(1L) .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") .hearts(0) .status("COMPLETE/SKIP") - .build(); + .build()); given(singleMissionArchiveReadUseCase.getMyArchive(any(),any())).willReturn(output); @@ -220,11 +220,11 @@ public class MissionArchiveControllerTest extends CommonControllerTest { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description(READ_MY_ARCHIVE_SUCCESS.getMessage()), - fieldWithPath("data.archiveId").description("미션 인증 아이디"), - fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), - fieldWithPath("data.createdDate").description("미션 제출 시각"), - fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data.status").description("미션 인증 상태") + fieldWithPath("data[].archiveId").description("미션 인증 아이디"), + fieldWithPath("data[].archive").description("미션 인증물 [s3URL/text/링크]"), + fieldWithPath("data[].createdDate").description("미션 제출 시각"), + fieldWithPath("data[].hearts").description("미션 인증 좋아요 수"), + fieldWithPath("data[].status").description("미션 인증 상태") ) ) From 7abe1034d17e0754c46e1321e65a56c9dd1135f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:50:34 +0900 Subject: [PATCH 113/619] =?UTF-8?q?feat=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20-=20=EB=82=98=EC=9D=98=20=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=ED=98=84=ED=99=A9=20=EC=A1=B0=ED=9A=8C=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RepeatMissionArchiveReadUseCase.java | 14 +++++++ .../MissionArchiveCustomRepository.java | 1 + .../MissionArchiveCustomRepositoryImpl.java | 14 +++++++ .../service/MissionArchiveQueryService.java | 3 ++ .../MissionArchiveController.java | 38 +++++++++++++------ 5 files changed, 58 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java index 7690445a..6a58da93 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java @@ -5,10 +5,12 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -59,5 +61,17 @@ public List getArchive(String userSocialId, Long missionId) { return missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId); } + public MissionArchiveStatusRes getMyMissionDoneStatus(String userSocialId,Long missionId) { + Member member = memberGetService.getMemberBySocialId(userSocialId); + Mission mission = missionQueryService.findMissionById(missionId); + Team team = mission.getTeam(); + + return MissionArchiveStatusRes.builder() + .total(String.valueOf(mission.getNumber())) + .done(missionArchiveQueryService.findMyDoneArchives(member.getMemberId(),missionId).toString()) + .build(); + + } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 19273667..365fe7f9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -15,6 +15,7 @@ public interface MissionArchiveCustomRepository { Optional> findAllMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus missionStatus); Optional findDonePeopleByMissionId(Long missionId); + Optional findMyDoneCountByMissionId(Long missionId,Long memberId); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 1c4bff6e..2c934479 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -105,5 +105,19 @@ public Optional findDonePeopleByMissionId(Long missionId) { ); } + @Override + public Optional findMyDoneCountByMissionId(Long missionId,Long memberId){ + return Optional.ofNullable(queryFactory + .select(missionArchive.count()) + .from(missionArchive) + .where( + missionArchive.mission.id.eq(missionId), + missionArchive.member.memberId.eq(memberId) + ) + .fetchFirst() + ); + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 9b3c968c..cded00d4 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -90,6 +90,9 @@ public List findMyAllMissionArchives(Long memberId, Long teamId, public Long findDoneArchives(Long missionId) { return missionArchiveRepository.findDonePeopleByMissionId(missionId).orElseThrow(NotFoundMissionArchiveException::new); } + public Long findMyDoneArchives(Long memberId,Long missionId) { + return missionArchiveRepository.findMyDoneCountByMissionId(missionId,memberId).orElseThrow(NotFoundMissionArchiveException::new); + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index bb446ce8..23b7829b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -6,10 +6,7 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; -import com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateUseCase; -import com.moing.backend.domain.missionArchive.application.service.MissionArchiveHeartUseCase; -import com.moing.backend.domain.missionArchive.application.service.MissionArchiveUpdateUseCase; -import com.moing.backend.domain.missionArchive.application.service.SingleMissionArchiveReadUseCase; +import com.moing.backend.domain.missionArchive.application.service.*; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -30,6 +27,7 @@ public class MissionArchiveController { private final MissionArchiveCreateUseCase missionArchiveCreateUseCase; private final MissionArchiveUpdateUseCase missionArchiveUpdateUseCase; private final SingleMissionArchiveReadUseCase singleMissionArchiveReadUseCase; + private final RepeatMissionArchiveReadUseCase repeatMissionArchiveReadUseCase; private final MissionArchiveHeartUseCase missionArchiveHeartUseCase; /** @@ -85,6 +83,20 @@ public ResponseEntity>> getOtherPeopleArch return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(user.getSocialId(),missionId))); } + /** + * 미션 인증 게시물 좋아요 + * [GET] {teamId}/m원issions/{missionId}/archive/hearts + * 작성자 : 정승연 + **/ + + @PostMapping("/hearts") + public ResponseEntity> pushHeart(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId, + @RequestBody MissionArchiveHeartReq missionArchiveHeartReq) { + return ResponseEntity.ok(SuccessResponse.create(HEART_UPDATE_SUCCESS.getMessage(), this.missionArchiveHeartUseCase.pushHeart(missionArchiveHeartReq))); + } + /** * 인증 성공 인원 조회 * [GET] {teamId}/m원issions/{missionId}/archive/status @@ -98,20 +110,22 @@ public ResponseEntity> getMissionDoneSt return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getMissionDoneStatus(missionId))); } + + /** - * 미션 인증 게시물 좋아요 - * [GET] {teamId}/m원issions/{missionId}/archive/hearts + * 반복미션 - 나의 성공 횟수 조회 + * [GET] {teamId}/missions/{missionId}/archive/my-status * 작성자 : 정승연 **/ - @PostMapping("/hearts") - public ResponseEntity> pushHeart(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId, - @RequestBody MissionArchiveHeartReq missionArchiveHeartReq) { - return ResponseEntity.ok(SuccessResponse.create(HEART_UPDATE_SUCCESS.getMessage(), this.missionArchiveHeartUseCase.pushHeart(missionArchiveHeartReq))); + @GetMapping("/my-status") + public ResponseEntity> getMyMissionDoneStatus(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage(), this.repeatMissionArchiveReadUseCase.getMyMissionDoneStatus(user.getSocialId(),missionId))); } + } \ No newline at end of file From 6d029c8cc1f6d1d87e4d5d9616d30253e6ff4dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:36:46 +0900 Subject: [PATCH 114/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=ED=9A=8C=EC=B0=A8=20=EB=A6=AC=ED=84=B4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/MissionArchiveRes.java | 5 +- .../mapper/MissionArchiveMapper.java | 1 + .../service/MissionArchiveCreateUseCase.java | 35 ++++++++--- .../service/MissionArchiveUpdateUseCase.java | 18 +++++- .../RepeatMissionArchiveReadUseCase.java | 58 +++++++++---------- .../domain/entity/MissionArchive.java | 6 ++ .../service/MissionArchiveQueryService.java | 8 +-- .../NoMoreMissionArchiveException.java | 12 ++++ .../NotFoundMissionArchiveException.java | 2 +- .../backend/global/response/ErrorCode.java | 1 + 10 files changed, 96 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/exception/NoMoreMissionArchiveException.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index a9e8d5b1..d025cb70 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -13,11 +13,10 @@ public class MissionArchiveRes { private Long archiveId; private String archive; - private String createdDate; - private int hearts; - private String status; + private Long count; + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 0815ceca..87f411f1 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -36,6 +36,7 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc .createdDate(missionArchive.getCreatedDate().toString()) .hearts(missionArchive.getHearts()) .status(missionArchive.getStatus().name()) + .count(missionArchive.getCount()) .build(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 19115175..6f09380b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -6,6 +6,7 @@ import com.moing.backend.domain.mission.application.dto.req.MissionReq; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.mission.domain.service.MissionDeleteService; import com.moing.backend.domain.mission.domain.service.MissionQueryService; @@ -17,6 +18,7 @@ import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; +import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -46,24 +48,39 @@ public class MissionArchiveCreateUseCase { public MissionArchiveRes createArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); + Long memberId = member.getMemberId(); + Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); - // missionArchive 2개 이상일 때 예외처리 필요 - MissionArchive missionArchive = missionArchiveSaveService.save(MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission)); + MissionArchive newArchive = MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission); -// if (isDoneSingleMission(mission)) { -// missionArchiveScoreService.addScore(team); -// } + if (isDoneMission(memberId,mission)) { + throw new NoMoreMissionArchiveException(); + } - return MissionArchiveMapper.mapToMissionArchiveRes(missionArchive); + if (mission.getType().equals(MissionType.ONCE)) { + // missionArchive 2개 이상일 때 예외처리 +// missionArchiveScoreService.addScore(team); + newArchive.updateCount(1L); + } + else { + newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); + } + return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive)); } - // 모든 모임원이 단일 미션을 완료하였는지 - public Boolean isDoneSingleMission(Mission mission) { + // 이 미션을 완료 했는지 + public Boolean isDoneMission(Long memberId,Mission mission) { + return missionArchiveQueryService.findMyDoneArchives(memberId, mission.getId()) >= mission.getNumber(); + } + + // 이 미션을 완료 했는지 + public Boolean isEndMission(Member member,Mission mission) { Team team = mission.getTeam(); - if (mission.getMissionArchiveList().size() == team.getLeaderId()-1) { + + if (mission.getMissionArchiveList().size() == team.getNumOfMember()-1) { mission.setStatus(MissionStatus.END); return true; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index de8fa6ae..8c670092 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; @@ -50,11 +51,22 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss } - MissionArchive missionArchive = missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId).get(0); + MissionArchive updateArchive = missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId).get(0); - missionArchive.updateArchive(missionReq); + if (mission.getType().equals(MissionType.ONCE)) { + // missionArchive 2개 이상일 때 예외처리 필요 +// if (isDoneSingleMission(mission)) { +// missionArchiveScoreService.addScore(team); +// } + updateArchive.updateCount(1L); + } + else{ + updateArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(member.getMemberId(), missionId)+1); + } + + updateArchive.updateArchive(missionReq); + return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(updateArchive)); - return MissionArchiveMapper.mapToMissionArchiveRes(missionArchive); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java index 6a58da93..e0f53ca0 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java @@ -31,35 +31,35 @@ public class RepeatMissionArchiveReadUseCase { private final MissionArchiveQueryService missionArchiveQueryService; - // 나의 인증 목록 - public List getMyArchive(String userSocialId, Long missionId) { - List myArchives = getArchive(userSocialId, missionId); - - List archiveRes = new ArrayList<>(); - myArchives.forEach(myArchive -> archiveRes.add(MissionArchiveMapper.mapToMissionArchiveRes(myArchive))); - - return archiveRes; - } - - // 팀원들 인증 목록 - public List getPersonalArchive(String userSocialId, Long missionId) { - Mission mission = missionQueryService.findMissionById(missionId); - - List done = new ArrayList<>(); - - mission.getMissionArchiveList() - .forEach(missionArchive1 -> done.add(mapToPersonalArchive(missionArchive1))); - - return done; - } - - // memberId, missionId로 archive 꺼내기 - public List getArchive(String userSocialId, Long missionId) { - Member member = memberGetService.getMemberBySocialId(userSocialId); - Mission mission = missionQueryService.findMissionById(missionId); - - return missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId); - } +// // 나의 인증 목록 +// public List getMyArchive(String userSocialId, Long missionId) { +// List myArchives = getArchive(userSocialId, missionId); +// +// List archiveRes = new ArrayList<>(); +// myArchives.forEach(myArchive -> archiveRes.add(MissionArchiveMapper.mapToMissionArchiveRes(myArchive))); +// +// return archiveRes; +// } +// +// // 팀원들 인증 목록 +// public List getPersonalArchive(String userSocialId, Long missionId) { +// Mission mission = missionQueryService.findMissionById(missionId); +// +// List done = new ArrayList<>(); +// +// mission.getMissionArchiveList() +// .forEach(missionArchive1 -> done.add(mapToPersonalArchive(missionArchive1))); +// +// return done; +// } +// +// // memberId, missionId로 archive 꺼내기 +// public List getArchive(String userSocialId, Long missionId) { +// Member member = memberGetService.getMemberBySocialId(userSocialId); +// Mission mission = missionQueryService.findMissionById(missionId); +// +// return missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId); +// } public MissionArchiveStatusRes getMyMissionDoneStatus(String userSocialId,Long missionId) { Member member = memberGetService.getMemberBySocialId(userSocialId); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index add5fd97..eae88c76 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -41,6 +41,8 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 private int hearts; + private Long count; + public void updateArchive(MissionArchiveReq missionArchiveReq) { this.archive = missionArchiveReq.getArchive(); @@ -53,5 +55,9 @@ public int updateHearts(Boolean status) { return this.hearts -= 1; } + public void updateCount(Long count) { + this.count = count; + } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index cded00d4..2bcb61fa 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -13,10 +13,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Optional; +import java.util.*; import static com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus.*; import static com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus.INCOMPLETE; @@ -40,7 +37,8 @@ public List findMyArchive(Long memberId, Long missionId) { Optional> optional = missionArchiveRepository.findArchivesByMissionIdAndMemberId(memberId, missionId); if (optional.isPresent() && optional.get().size() == 0) { - throw new NotFoundMissionArchiveException(); + return new ArrayList<>(); +// throw new NotFoundMissionArchiveException(); } else { return optional.get(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/exception/NoMoreMissionArchiveException.java b/src/main/java/com/moing/backend/domain/missionArchive/exception/NoMoreMissionArchiveException.java new file mode 100644 index 00000000..cd35fc03 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/exception/NoMoreMissionArchiveException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.missionArchive.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NoMoreMissionArchiveException extends MissionArchiveException { + + public NoMoreMissionArchiveException() { + super(ErrorCode.NO_MORE_ARCHIVE_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java b/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java index db258781..521bb472 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/exception/NotFoundMissionArchiveException.java @@ -6,7 +6,7 @@ public class NotFoundMissionArchiveException extends MissionArchiveException { public NotFoundMissionArchiveException() { - super(ErrorCode.NOT_FOUND_MISSION, + super(ErrorCode.NOT_FOUND_MISSION_ARCHIVE, HttpStatus.NOT_FOUND); } } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 31aa29b6..90feb2f4 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -24,6 +24,7 @@ public enum ErrorCode { NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), NOT_FOUND_MISSION("M0002", "미션을 찾을 수 없습니다."), NOT_FOUND_MISSION_ARCHIVE("MA0001", "아직 미션을 제출하지 않았습니다."), + NO_MORE_ARCHIVE_ERROR("MA0001", "지정한 횟수 이상 미션을 인증할 수 없습니다."), //팀 관련 에러 코드 NOT_FOUND_BY_TEAM_ID_ERROR("T0001", "해당 teamId인 팀이 존재하지 않습니다."), From 2ec6854d1a98e390b4df695efe22b6808e9eb2ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:47:29 +0900 Subject: [PATCH 115/619] =?UTF-8?q?fix=20:=20PersonalArchive=20->=20Person?= =?UTF-8?q?alArchiveRes=20,=20=EB=AA=A8=EC=9E=84=EC=9B=90=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=ED=98=84=ED=99=A9=EC=97=90=20=ED=9A=8C=EC=B0=A8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...rsonalArchive.java => PersonalArchiveRes.java} | 3 ++- .../application/mapper/MissionArchiveMapper.java | 13 ++++++------- .../service/MissionArchiveCreateUseCase.java | 10 ---------- .../service/RepeatMissionArchiveReadUseCase.java | 8 -------- .../service/SingleMissionArchiveReadUseCase.java | 9 +++------ .../presentation/MissionArchiveController.java | 8 ++++---- .../MissionArchiveControllerTest.java | 15 ++------------- 7 files changed, 17 insertions(+), 49 deletions(-) rename src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/{PersonalArchive.java => PersonalArchiveRes.java} (86%) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java similarity index 86% rename from src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java rename to src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java index a534a19e..82d8146d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java @@ -7,7 +7,7 @@ @Getter @Setter @Builder -public class PersonalArchive { +public class PersonalArchiveRes { private Long archiveId; private String nickname; @@ -19,5 +19,6 @@ public class PersonalArchive { private int hearts; private String status; + private Long count; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 87f411f1..0eeec9df 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -4,14 +4,12 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; -import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; +import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.annotation.Mapper; import java.util.ArrayList; @@ -49,9 +47,9 @@ public static List mapToMissionArchiveResList(List mapToPersonalArchiveList(List missionArchiveList) { - List personalArchiveList = new ArrayList<>(); + public static List mapToPersonalArchiveList(List missionArchiveList) { + List personalArchiveList = new ArrayList<>(); missionArchiveList.forEach( missionArchive -> personalArchiveList.add(MissionArchiveMapper.mapToPersonalArchive(missionArchive)) ); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 6f09380b..5835d28e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -1,18 +1,13 @@ package com.moing.backend.domain.missionArchive.application.service; -import com.moing.backend.domain.infra.image.application.service.IssuePresignedUrlUseCase; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.mission.application.dto.req.MissionReq; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; -import com.moing.backend.domain.mission.domain.service.MissionDeleteService; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; -import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; @@ -24,11 +19,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; - -import static com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper.mapToPersonalArchive; - @Service @Transactional @RequiredArgsConstructor diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java index e0f53ca0..ff971211 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java @@ -4,21 +4,13 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; -import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; -import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import javax.transaction.Transactional; -import java.util.ArrayList; -import java.util.List; - -import static com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper.mapToPersonalArchive; @Service @Transactional diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java index 38c8b683..95e15e1b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java @@ -6,9 +6,8 @@ import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; -import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; +import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.repository.TeamRepository; @@ -19,8 +18,6 @@ import java.util.ArrayList; import java.util.List; -import static com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper.mapToPersonalArchive; - @Service @Transactional @RequiredArgsConstructor @@ -42,9 +39,9 @@ public List getMyArchive(String userSocialId, Long missionId) } // 모두의 미션 인증 목록 조회 - public List getPersonalArchive(String userSocialId,Long missionId) { + public List getPersonalArchive(String userSocialId, Long missionId) { - List personalArchives = new ArrayList<>(); + List personalArchives = new ArrayList<>(); Member member = memberGetService.getMemberBySocialId(userSocialId); return MissionArchiveMapper.mapToPersonalArchiveList(missionArchiveQueryService.findOthersArchive(member.getMemberId(), missionId)); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 23b7829b..f331662d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -5,7 +5,7 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; -import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; +import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.service.*; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; @@ -77,9 +77,9 @@ public ResponseEntity>> getMyArchive(@Au * 작성자 : 정승연 **/ @GetMapping("/others") - public ResponseEntity>> getOtherPeopleArchives(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId) { + public ResponseEntity>> getOtherPeopleArchives(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(user.getSocialId(),missionId))); } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 10625b91..bd651f2c 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -1,21 +1,12 @@ package com.moing.backend.domain.missionArchive.representation; -import com.google.common.collect.ImmutableList; import com.moing.backend.config.CommonControllerTest; -import com.moing.backend.domain.mission.application.dto.req.MissionReq; -import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; -import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; -import com.moing.backend.domain.mission.application.service.MissionCreateUseCase; -import com.moing.backend.domain.mission.application.service.MissionDeleteUseCase; -import com.moing.backend.domain.mission.application.service.MissionReadUseCase; -import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; -import com.moing.backend.domain.mission.presentation.MissionController; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveHeartReq; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; -import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchive; +import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateUseCase; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveHeartUseCase; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveUpdateUseCase; @@ -30,8 +21,6 @@ import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import java.text.SimpleDateFormat; -import java.time.LocalDateTime; import java.util.List; import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; @@ -237,7 +226,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { public void 모임원_미션_인증_조회() throws Exception { //given - List output = Lists.newArrayList(PersonalArchive.builder() + List output = Lists.newArrayList(PersonalArchiveRes.builder() .archiveId(1L) .nickname("modagbul_tester1") .profileImg("[s3 Link]") From 3f1ba15ceb34cc14898da8d9e6762a31669efd96 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 2 Oct 2023 22:37:10 +0900 Subject: [PATCH 116/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=ED=83=88=ED=87=B4=20=ED=9B=84=20=ED=9A=8C=EC=9B=90=20=EB=8B=89?= =?UTF-8?q?=EB=84=A4=EC=9E=84=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/application/dto/response/BoardBlocks.java | 13 ++++++++++++- .../repository/BoardCustomRepositoryImpl.java | 5 +++-- .../application/dto/response/CommentBlocks.java | 7 +++++++ .../BoardCommentCustomRepositoryImpl.java | 11 +++++------ .../backend/domain/member/domain/entity/Member.java | 9 ++++++++- .../mypage/application/service/SignOutUserCase.java | 3 +++ .../application/service/DisbandTeamUserCase.java | 5 +++++ .../application/service/WithdrawTeamUserCase.java | 2 +- .../domain/teamMember/domain/entity/TeamMember.java | 2 +- .../board/presentation/BoardControllerTest.java | 4 ++++ .../presentation/BoardCommentControllerTest.java | 3 +++ .../representation/MissionControllerTest.java | 5 +++++ 12 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java index eb878fb8..4c06d3c0 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java @@ -26,8 +26,10 @@ public class BoardBlocks { private Boolean isRead; + private Boolean writerIsDeleted; + @QueryProjection - public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, String writerProfileImage, String title, String content, Integer commentNum) { + public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, String writerProfileImage, String title, String content, Integer commentNum, Boolean writerIsDeleted) { this.boardId = boardId; this.writerNickName = writerNickName; this.writerIsLeader = writerIsLeader; @@ -36,9 +38,18 @@ public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, this.content = content; this.commentNum = commentNum; this.isRead = false; + this.writerIsDeleted=writerIsDeleted; + deleteMember(); } public void readBoard() { this.isRead = true; } + + public void deleteMember() { + if(Boolean.TRUE.equals(writerIsDeleted)) { + this.writerNickName = "(알 수 없음)"; + this.writerProfileImage = "undef"; + } + } } diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index b1b0e863..2532ea09 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -13,7 +13,7 @@ import static com.moing.backend.domain.board.domain.entity.QBoard.board; import static com.moing.backend.domain.boardRead.domain.entity.QBoardRead.boardRead; -public class BoardCustomRepositoryImpl implements BoardCustomRepository { +public class BoardCustomRepositoryImpl implements BoardCustomRepository { private final JPAQueryFactory queryFactory; public BoardCustomRepositoryImpl(EntityManager em) { @@ -51,7 +51,8 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { b.getWriterProfileImage(), b.getTitle(), b.getContent(), - b.getCommentNum() + b.getCommentNum(), + b.getTeamMember().isDeleted() ); if (isRead) { boardBlocks.readBoard(); diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java index 37e40ed0..8a24f5f9 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java @@ -21,4 +21,11 @@ public class CommentBlocks { private String writerProfileImage; private Boolean isWriter; + + private Boolean writerIsDeleted; + + public void deleteMember(){ + this.writerNickName="(알 수 없음)"; + this.writerProfileImage="undef"; + } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index 178a26ea..f31d6e11 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -1,11 +1,7 @@ package com.moing.backend.domain.boardComment.domain.repository; -import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.boardComment.application.dto.response.CommentBlocks; import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; -import com.moing.backend.domain.boardComment.application.service.GetBoardCommentUserCase; -import com.moing.backend.domain.boardComment.domain.entity.BoardComment; -import com.moing.backend.domain.boardComment.domain.entity.QBoardComment; import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.querydsl.core.types.ExpressionUtils; @@ -17,7 +13,6 @@ import java.util.List; import static com.moing.backend.domain.boardComment.domain.entity.QBoardComment.boardComment; -import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; public class BoardCommentCustomRepositoryImpl implements BoardCommentCustomRepository{ @@ -42,11 +37,15 @@ public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember team .from(QTeamMember.teamMember) .where(QTeamMember.teamMember.eq(teamMember) .and(QTeamMember.teamMember.eq(boardComment.teamMember))) - .exists(), "isWriter"))) + .exists(), "isWriter"), + boardComment.teamMember.isDeleted)) .from(boardComment) .where(boardComment.board.boardId.eq(boardId)) .orderBy(boardComment.createdDate.asc()) .fetch(); + + commentBlocks.forEach(CommentBlocks::deleteMember); + return new GetBoardCommentResponse(commentBlocks); } } diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index 465f4a4f..b8990e7c 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -79,7 +79,7 @@ public class Member extends BaseTimeEntity { @ColumnDefault("true") private boolean isFirePush; - @OneToMany(mappedBy = "member", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "member") private List teamMembers = new ArrayList<>(); //최대 3개이므로 양방향 //==생성 메서드==// @@ -168,4 +168,11 @@ public Member(String ageRange, String email, String fcmToken, String gender, Str this.socialId = socialId; } + public void deleteTeamMember(){ + List teamMemberList=this.getTeamMembers(); + for(TeamMember teamMember:teamMemberList){ + teamMember.deleteMember(); + } + } + } diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java index abce0334..cbb14594 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.config.security.jwt.TokenUtil; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -11,8 +12,10 @@ public class SignOutUserCase { private final TokenUtil tokenUtil; + private final MemberGetService memberGetService; public void signOut(String socialId){ + //TODO: teamMember가 isDeleted가 아닌게 한개라도 있으면 error 반환 tokenUtil.expireRefreshToken(socialId); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java index 19e133ad..77ef8c86 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java @@ -6,6 +6,8 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.team.exception.NotAuthByTeamException; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -19,11 +21,14 @@ public class DisbandTeamUserCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; private final CheckLeaderUserCase checkLeaderUserCase; + private final TeamMemberGetService teamMemberGetService; public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); + if (checkLeaderUserCase.isTeamLeader(member, team)) { + //TODO: 팀의 모든 멤버 isDeleted true 해주환 team.deleteTeam(); } else { throw new NotAuthByTeamException(); diff --git a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java index 60c15d3c..46c42dfa 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java @@ -25,7 +25,7 @@ public DeleteTeamResponse withdrawTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); - teamMember.withdrawTeam(); + teamMember.deleteMember(); return new DeleteTeamResponse(team.getTeamId()); } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java index 1acc968a..c30cf2ed 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java @@ -42,7 +42,7 @@ public void updateMember(Member member) { member.getTeamMembers().add(this); } - public void withdrawTeam() { + public void deleteMember() { this.isDeleted = true; } } diff --git a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java index 1c76633c..000a3f04 100644 --- a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java @@ -193,6 +193,7 @@ public void get_board_all() throws Exception { .boardId(1L) .writerIsLeader(true) .writerNickName("작성자 닉네임") + .writerIsDeleted(false) .writerProfileImage("작성자 프로필 이미지") .title("공지 제목") .content("공지 내용") @@ -204,6 +205,7 @@ public void get_board_all() throws Exception { .boardId(1L) .writerIsLeader(true) .writerNickName("작성자 닉네임") + .writerIsDeleted(false) .writerProfileImage("작성자 프로필 이미지") .title("게시글 제목") .content("게시글 내용") @@ -246,6 +248,7 @@ public void get_board_all() throws Exception { fieldWithPath("data.noticeBlocks[0].writerNickName").description("작성자 닉네임"), fieldWithPath("data.noticeBlocks[0].writerIsLeader").description("작성자 소모임장 여부"), fieldWithPath("data.noticeBlocks[0].writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.noticeBlocks[0].writerIsDeleted").description("작성자 삭제 여부"), fieldWithPath("data.noticeBlocks[0].title").description("공지 제목"), fieldWithPath("data.noticeBlocks[0].content").description("공지 내용"), fieldWithPath("data.noticeBlocks[0].commentNum").description("공지 댓글 개수"), @@ -255,6 +258,7 @@ public void get_board_all() throws Exception { fieldWithPath("data.notNoticeBlocks[0].writerNickName").description("작성자 닉네임"), fieldWithPath("data.notNoticeBlocks[0].writerIsLeader").description("작성자 소모임장 여부"), fieldWithPath("data.notNoticeBlocks[0].writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.notNoticeBlocks[0].writerIsDeleted").description("작성자 삭제 여부"), fieldWithPath("data.notNoticeBlocks[0].title").description("일반 게시글 제목"), fieldWithPath("data.notNoticeBlocks[0].content").description("일반 게시글 내용"), fieldWithPath("data.notNoticeBlocks[0].commentNum").description("일반 게시글 댓글 개수"), diff --git a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java index c3592fdb..846fd443 100644 --- a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java +++ b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java @@ -30,6 +30,7 @@ @WebMvcTest(BoardCommentController.class) public class BoardCommentControllerTest extends CommonControllerTest { + @MockBean private CreateBoardCommentUserCase createBoardCommentUserCase; @MockBean @@ -139,6 +140,7 @@ public void get_board_comment_all() throws Exception { .writerIsLeader(true) .writerNickName("작성자 닉네임") .writerProfileImage("작성자 프로필 이미지") + .writerIsDeleted(false) .isWriter(true) .build(); @@ -177,6 +179,7 @@ public void get_board_comment_all() throws Exception { fieldWithPath("data.commentBlocks[0].writerIsLeader").description("작성자 소모임장 여부"), fieldWithPath("data.commentBlocks[0].writerNickName").description("작성자 닉네임"), fieldWithPath("data.commentBlocks[0].writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.commentBlocks[0].writerIsDeleted").description("작성자 삭제 여부"), fieldWithPath("data.commentBlocks[0].isWriter").description("댓글 작성자 여부") ) diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index 8ac524c7..6b7424de 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -9,8 +9,10 @@ import com.moing.backend.domain.mission.application.service.MissionReadUseCase; import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; import com.moing.backend.domain.mission.domain.repository.MissionRepository; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.mission.presentation.MissionController; import org.junit.jupiter.api.Test; +import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -47,6 +49,9 @@ public class MissionControllerTest extends CommonControllerTest { @MockBean private MissionDeleteUseCase missionDeleteUseCase; + @MockBean + private MissionQueryService missionQueryService; + @Test From ba5c6ce0564e13e6daddc00b5ca63806c093d0b6 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 4 Oct 2023 22:29:56 +0900 Subject: [PATCH 117/619] =?UTF-8?q?feat:=20fcm=20=ED=99=98=EA=B2=BD=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/global/config/fcm/FcmConfig.java | 59 +++++++ .../config/fcm/dto/request/MultiRequest.java | 23 +++ .../config/fcm/dto/request/SingleRequest.java | 21 +++ .../fcm/dto/response/MultiResponse.java | 14 ++ .../fcm/dto/response/SingleResponse.java | 11 ++ .../fcm/exception/FirebaseException.java | 11 ++ .../fcm/exception/InitializeException.java | 12 ++ .../fcm/exception/MessagingException.java | 11 ++ .../fcm/exception/NotificationException.java | 11 ++ .../global/config/fcm/service/FcmService.java | 151 ++++++++++++++++++ .../backend/global/response/ErrorCode.java | 5 + 11 files changed, 329 insertions(+) create mode 100644 src/main/java/com/moing/backend/global/config/fcm/FcmConfig.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/dto/request/MultiRequest.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/dto/request/SingleRequest.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/dto/response/MultiResponse.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/dto/response/SingleResponse.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/exception/FirebaseException.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/exception/InitializeException.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/exception/MessagingException.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/exception/NotificationException.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java diff --git a/src/main/java/com/moing/backend/global/config/fcm/FcmConfig.java b/src/main/java/com/moing/backend/global/config/fcm/FcmConfig.java new file mode 100644 index 00000000..711c4290 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/FcmConfig.java @@ -0,0 +1,59 @@ +package com.moing.backend.global.config.fcm; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.firebase.FirebaseApp; +import com.google.firebase.FirebaseOptions; +import com.google.firebase.messaging.FirebaseMessaging; +import com.moing.backend.global.config.fcm.exception.InitializeException; +import com.moing.backend.global.config.fcm.exception.MessagingException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +@Configuration +@Slf4j +public class FcmConfig { + + + @Value("${firebase.config.path}") + private String firebaseConfigPath; + + @Value("${firebase.config.projectId}") + private String projectId; + + @Bean + public FirebaseApp firebaseApp() { + try { + FileInputStream serviceAccount = new FileInputStream(firebaseConfigPath); + + FirebaseOptions options = FirebaseOptions.builder() + .setCredentials(GoogleCredentials.fromStream(serviceAccount)) + .setProjectId(projectId) + .build(); + + return FirebaseApp.initializeApp(options); + } catch (FileNotFoundException e) { + throw new IllegalStateException("파일을 찾을 수 없습니다." + e.getMessage()); + } catch (IOException e) { + throw new InitializeException(); + } + } + + @Bean + public FirebaseMessaging firebaseMessaging() { + try { + return FirebaseMessaging.getInstance(firebaseApp()); + } catch (IllegalStateException e) { + throw new MessagingException("FirebaseApp 초기화에 실패하였습니다." + e.getMessage()); + } catch (NullPointerException e) { + throw new IllegalStateException("FirebaseApp을 불러오는데 실패하였습니다." + e.getMessage()); + } catch (Exception e) { + throw new IllegalArgumentException("firebaseConfigPath를 읽어오는데 실패하였습니다." + e.getMessage()); + } + } +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/request/MultiRequest.java b/src/main/java/com/moing/backend/global/config/fcm/dto/request/MultiRequest.java new file mode 100644 index 00000000..222e1258 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/request/MultiRequest.java @@ -0,0 +1,23 @@ +package com.moing.backend.global.config.fcm.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; +import java.util.List; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MultiRequest { + @NotNull(message = "기기 등록 토큰들을 입력해 주세요.") + private List registrationToken; + + @NotNull(message = "알림 제목을 입력해 주세요.") + private String title; + + @NotNull(message = "알림 내용을 입력해 주세요.") + private String body; + +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/request/SingleRequest.java b/src/main/java/com/moing/backend/global/config/fcm/dto/request/SingleRequest.java new file mode 100644 index 00000000..01f2a37a --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/request/SingleRequest.java @@ -0,0 +1,21 @@ +package com.moing.backend.global.config.fcm.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class SingleRequest { + @NotNull(message = "기기 등록 토큰을 입력해 주세요.") + private String registrationToken; + + @NotNull(message = "알림 제목을 입력해 주세요.") + private String title; + + @NotNull(message = "알림 내용을 입력해 주세요.") + private String body; +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/response/MultiResponse.java b/src/main/java/com/moing/backend/global/config/fcm/dto/response/MultiResponse.java new file mode 100644 index 00000000..39f67767 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/response/MultiResponse.java @@ -0,0 +1,14 @@ +package com.moing.backend.global.config.fcm.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class MultiResponse { + private final String response; + private final List failedTokens; + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/response/SingleResponse.java b/src/main/java/com/moing/backend/global/config/fcm/dto/response/SingleResponse.java new file mode 100644 index 00000000..b4f0cbf9 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/response/SingleResponse.java @@ -0,0 +1,11 @@ +package com.moing.backend.global.config.fcm.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class SingleResponse { + private final String response; + +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/exception/FirebaseException.java b/src/main/java/com/moing/backend/global/config/fcm/exception/FirebaseException.java new file mode 100644 index 00000000..11c67de3 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/exception/FirebaseException.java @@ -0,0 +1,11 @@ +package com.moing.backend.global.config.fcm.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class FirebaseException extends ApplicationException { + protected FirebaseException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/exception/InitializeException.java b/src/main/java/com/moing/backend/global/config/fcm/exception/InitializeException.java new file mode 100644 index 00000000..34b560ca --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/exception/InitializeException.java @@ -0,0 +1,12 @@ +package com.moing.backend.global.config.fcm.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class InitializeException extends FirebaseException { + public InitializeException() { + super(ErrorCode.INITIALIZE_ERROR, + HttpStatus.INTERNAL_SERVER_ERROR + ); + } +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/exception/MessagingException.java b/src/main/java/com/moing/backend/global/config/fcm/exception/MessagingException.java new file mode 100644 index 00000000..0acc476b --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/exception/MessagingException.java @@ -0,0 +1,11 @@ +package com.moing.backend.global.config.fcm.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class MessagingException extends FirebaseException { + public MessagingException(String message) { + super(ErrorCode.MESSAGING_ERROR, + HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/exception/NotificationException.java b/src/main/java/com/moing/backend/global/config/fcm/exception/NotificationException.java new file mode 100644 index 00000000..b7dd8a90 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/exception/NotificationException.java @@ -0,0 +1,11 @@ +package com.moing.backend.global.config.fcm.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotificationException extends FirebaseException { + public NotificationException(String message) { + super(ErrorCode.NOTIFICATION_ERROR, + HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java new file mode 100644 index 00000000..74cdb54d --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java @@ -0,0 +1,151 @@ +package com.moing.backend.global.config.fcm.service; + +import com.google.firebase.messaging.*; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +import com.moing.backend.global.config.fcm.dto.response.MultiResponse; +import com.moing.backend.global.config.fcm.dto.response.SingleResponse; +import com.moing.backend.global.config.fcm.exception.NotificationException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +@Slf4j +public class FcmService { + + private final FirebaseMessaging firebaseMessaging; + + + public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { + + Notification notification = Notification.builder() + .setTitle(toSingleRequest.getTitle()) + .setBody(toSingleRequest.getBody()) + .build(); + + // Android Configuration + AndroidConfig androidConfig = AndroidConfig.builder() + .setPriority(AndroidConfig.Priority.HIGH) + .setNotification(AndroidNotification.builder() + .setChannelId("FCM_Channel") + .setTitle(toSingleRequest.getTitle()) + .setBody(toSingleRequest.getBody()) + .build()) + .build(); + + // APNs Configuration + ApnsConfig apnsConfig = ApnsConfig.builder() + .setAps(Aps.builder() + .setCategory("YOUR_CATEGORY") // Replace with your category + .setAlert(ApsAlert.builder() + .setTitle(toSingleRequest.getTitle()) + .setBody(toSingleRequest.getBody()) + .build()) + .build()) + .build(); + + Message message = Message.builder() + .setToken(toSingleRequest.getRegistrationToken()) + .setNotification(notification) + .setAndroidConfig(androidConfig) // Applying Android configuration + .setApnsConfig(apnsConfig) // Applying APNs configuration + .build(); + + try { + String response = firebaseMessaging.send(message); + return new SingleResponse(response); + } catch (FirebaseMessagingException e) { + throw handleException(e); + } + } + + + public MultiResponse sendMultipleDevices(MultiRequest toMultiRequest) { + + Notification notification = Notification.builder() + .setTitle(toMultiRequest.getTitle()) + .setBody(toMultiRequest.getBody()) + .build(); + + // Android Configuration + AndroidConfig androidConfig = AndroidConfig.builder() + .setPriority(AndroidConfig.Priority.HIGH) + .setNotification(AndroidNotification.builder() + .setChannelId("FCM_Channel") + .setTitle(toMultiRequest.getTitle()) + .setBody(toMultiRequest.getBody()) + .build()) + .build(); + + // APNs Configuration + ApnsConfig apnsConfig = ApnsConfig.builder() + .setAps(Aps.builder() + .setCategory("YOUR_CATEGORY") // Replace with your category + .setAlert(ApsAlert.builder() + .setTitle(toMultiRequest.getTitle()) + .setBody(toMultiRequest.getBody()) + .build()) + .build()) + .build(); + + MulticastMessage message = MulticastMessage.builder() + .addAllTokens(toMultiRequest.getRegistrationToken()) + .setNotification(notification) + .setAndroidConfig(androidConfig) // Applying Android configuration + .setApnsConfig(apnsConfig) // Applying APNs configuration + .build(); + + try { + BatchResponse response = firebaseMessaging.sendMulticast(message); + List failedTokens = new ArrayList<>(); + + if (response.getFailureCount() > 0) { + List responses = response.getResponses(); + + for (int i = 0; i < responses.size(); i++) { + if (!responses.get(i).isSuccessful()) { + // Add the failed tokens to the list + failedTokens.add(toMultiRequest.getRegistrationToken().get(i)); + } + } + } + + String messageString = String.format("%d messages were sent successfully.", response.getSuccessCount()); + + return new MultiResponse(messageString, failedTokens); + + } catch (FirebaseMessagingException e) { + throw handleException(e); + } + } + + + + private NotificationException handleException(FirebaseMessagingException e) { + String errorCode = e.getErrorCode().name(); + String errorMessage = e.getMessage(); + + switch (errorCode) { + case "INVALID_ARGUMENT": + return new NotificationException("올바르지 않은 인자 값입니다: " + errorMessage); + case "NOT_FOUND": + return new NotificationException("등록 토큰이 유효하지 않거나, 주제(Topic)가 존재하지 않습니다: " + errorMessage); + case "UNREGISTERED": + return new NotificationException("해당 주제(Topic)의 구독이 해지되었습니다: " + errorMessage); + case "UNAVAILABLE": + return new NotificationException("서비스를 사용할 수 없습니다: " + errorMessage); + default: + return new NotificationException("메시지 전송에 실패했습니다: " + errorMessage); + } + } + +} + + diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 31aa29b6..e31bf8ed 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -13,6 +13,11 @@ public enum ErrorCode { INTERNAL_SERVER_ERROR("500", "서버에서 요청을 처리하는 동안 오류가 발생했습니다."), NOT_FOUND_REFRESH_TOKEN_ERROR( "J0008", "유효하지 않는 RefreshToken 입니다."), + //FCM 토큰 관련 + INITIALIZE_ERROR("F0001", "Firebase Admin SDK 초기화에 실패했습니다."), + NOTIFICATION_ERROR("F0002", "메시지 전송에 실패했습니다."), + MESSAGING_ERROR("F0003", "firebaseConfigPath를 읽어오는데 실패하였습니다"), + //유저 관련 에러 코드 NOT_FOUND_BY_SOCIAL_ID_ERROR( "U0001", "해당 socialId인 유저가 존재하지 않습니다."), ACCOUNT_ALREADY_EXIST("AU0001", "해당 email로 다른 소셜 플랫폼으로 가입하였습니다."), From 6b47ff8f3318776708eea5de55b330fa276f0039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 5 Oct 2023 18:24:54 +0900 Subject: [PATCH 118/619] =?UTF-8?q?feat=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=EC=9D=B8=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=ED=98=84?= =?UTF-8?q?=ED=99=A9=20=EB=B3=B4=EB=93=9C=20=EC=99=84=EB=A3=8C=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/RepeatMissionBoardRes.java | 22 +++++-- .../service/MissionArchiveBoardUseCase.java | 17 +++--- .../repository/MissionCustomRepository.java | 10 ++- .../MissionCustomRepositoryImpl.java | 19 ++++++ .../domain/service/MissionQueryService.java | 7 +++ .../mapper/MissionArchiveMapper.java | 1 + .../service/MissionArchiveCreateUseCase.java | 4 +- .../MissionArchiveCustomRepository.java | 2 + .../MissionArchiveCustomRepositoryImpl.java | 61 +++++++++++++++++-- .../service/MissionArchiveQueryService.java | 7 ++- .../presentation/MissionBoardController.java | 29 +++++++-- 11 files changed, 151 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java index ddef3b56..1e3b46cf 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java @@ -1,12 +1,26 @@ package com.moing.backend.domain.mission.application.dto.res; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +//@Builder public class RepeatMissionBoardRes { private Long missionId; - private String dueTo; //요일 private String title; - private String status; - private int num; - private int done; + + private String dueTo; // 요일 상태 넘겨주기 +// private String status; + private Long done; + private int number; + public RepeatMissionBoardRes(Long missionId, String title, Long done,int number) { + this.missionId = missionId; + this.title = title; + this.number = number; + this.done = done; + } } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java index be0f867b..358c907e 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; @@ -28,6 +29,7 @@ public class MissionArchiveBoardUseCase { private final MissionArchiveQueryService missionArchiveQueryService; + private final MissionQueryService missionQueryService; private final MemberGetService memberGetService; private final TeamRepository teamRepository; @@ -57,13 +59,12 @@ public List getFinishMissions(Long teamId, String memberI } -// public List getActiveRepeatMissions(Long teamId, String memberId) { -// -// Team team = teamRepository.findById(teamId).orElseThrow(); -// Member member = memberGetService.getMemberBySocialId(memberId); -// -// missionArchiveQueryService.findRepeatMissionMyArchive(memberId, ); -// } -// + public List getActiveRepeatMissions(Long teamId, String memberId) { + + Member member = memberGetService.getMemberBySocialId(memberId); + + return missionArchiveQueryService.findMyRepeatMissionArchives(member.getMemberId(),teamId,MissionStatus.ONGOING); + + } } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index 9ab4a501..b09cd218 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -1,5 +1,13 @@ package com.moing.backend.domain.mission.domain.repository; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; + +import java.util.List; +import java.util.Optional; + public interface MissionCustomRepository { Long findMissionsCountByTeam(Long teamId); -} \ No newline at end of file + Optional> findRepeatMissionByMemberId(Long teamId, MissionStatus status); + + } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 53a7cd60..7ab14a9f 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -1,10 +1,15 @@ package com.moing.backend.domain.mission.domain.repository; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; +import java.util.List; +import java.util.Optional; + import static com.moing.backend.domain.mission.domain.entity.QMission.mission; public class MissionCustomRepositoryImpl implements MissionCustomRepository{ @@ -25,4 +30,18 @@ public Long findMissionsCountByTeam(Long teamId) { ) .fetchFirst(); } + + @Override + public Optional> findRepeatMissionByMemberId(Long teamId, MissionStatus status) { + + return Optional.ofNullable(queryFactory + .select(mission) + .from(mission) + .where( + mission.team.teamId.eq(teamId), + mission.status.eq(status), + mission.type.eq(MissionType.REPEAT) + ) + .fetch()); + } } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 961be80e..821c5022 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -1,12 +1,15 @@ package com.moing.backend.domain.mission.domain.service; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.exception.NotFoundMissionException; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @DomainService @Transactional @RequiredArgsConstructor @@ -21,4 +24,8 @@ public Mission findMissionById(Long missionId) { public Long findMissionsCountByTeam(Long teamId) { return missionRepository.findMissionsCountByTeam(teamId); } + + public List findRepeatMissionByTeamId(Long teamId) { + return missionRepository.findRepeatMissionByMemberId(teamId, MissionStatus.ONGOING).orElseThrow(NotFoundMissionException::new); + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 0eeec9df..eafa243c 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 5835d28e..22ee82de 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -70,7 +70,9 @@ public Boolean isDoneMission(Long memberId,Mission mission) { public Boolean isEndMission(Member member,Mission mission) { Team team = mission.getTeam(); - if (mission.getMissionArchiveList().size() == team.getNumOfMember()-1) { + Long missionsCountByTeam = missionQueryService.findMissionsCountByTeam(team.getTeamId()); + + if (missionsCountByTeam == team.getNumOfMember()-1) { mission.setStatus(MissionStatus.END); return true; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 365fe7f9..1acd16d5 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.domain.repository; +import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; @@ -17,6 +18,7 @@ public interface MissionArchiveCustomRepository { Optional findDonePeopleByMissionId(Long missionId); Optional findMyDoneCountByMissionId(Long missionId,Long memberId); + Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 2c934479..eb476116 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -1,13 +1,17 @@ package com.moing.backend.domain.missionArchive.domain.repository; +import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.QMission; +import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; import com.moing.backend.domain.teamMember.domain.repository.OrderCondition; import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; import feign.Param; import org.springframework.data.jpa.repository.Query; @@ -19,7 +23,10 @@ import java.util.Objects; import java.util.Optional; +import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; +import static javax.swing.Spring.constant; +import static org.hibernate.internal.util.NullnessHelper.coalesce; public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { @@ -31,7 +38,7 @@ public MissionArchiveCustomRepositoryImpl(EntityManager em) { @Override public Optional> findSingleMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status, - MissionArchiveStatus archiveStatus,OrderCondition orderCondition) { + MissionArchiveStatus archiveStatus, OrderCondition orderCondition) { OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); return Optional.ofNullable(queryFactory .select(missionArchive) @@ -51,9 +58,9 @@ private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { List orderSpecifiers = new ArrayList<>(); - if(orderCondition.equals(OrderCondition.DUETO)){ + if (orderCondition.equals(OrderCondition.DUETO)) { orderSpecifiers.add(new OrderSpecifier(Order.DESC, missionArchive.mission.dueTo)); - }else if(orderCondition.equals(OrderCondition.CREATED)){ + } else if (orderCondition.equals(OrderCondition.CREATED)) { orderSpecifiers.add(new OrderSpecifier(Order.ASC, missionArchive.createdDate)); } return orderSpecifiers.toArray(new OrderSpecifier[orderSpecifiers.size()]); @@ -79,7 +86,7 @@ public Optional> findOthersArchives(Long memberId, Long mis } @Override - public Optional> findAllMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus missionStatus){ + public Optional> findAllMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus missionStatus) { return Optional.ofNullable(queryFactory .selectFrom(missionArchive) @@ -106,7 +113,7 @@ public Optional findDonePeopleByMissionId(Long missionId) { } @Override - public Optional findMyDoneCountByMissionId(Long missionId,Long memberId){ + public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) { return Optional.ofNullable(queryFactory .select(missionArchive.count()) .from(missionArchive) @@ -119,5 +126,49 @@ public Optional findMyDoneCountByMissionId(Long missionId,Long memberId){ } +// @Override +// public Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status) { +// return Optional.ofNullable(queryFactory +// .select(Projections.constructor(RepeatMissionBoardRes.class, +// missionArchive.mission.id, +// missionArchive.mission.title, +// missionArchive.count, +// missionArchive.mission.number +// )) +// .from(missionArchive) +// .where( +// missionArchive.mission.team.teamId.eq(teamId), +// missionArchive.mission.type.eq(MissionType.REPEAT), +// missionArchive.member.memberId.eq(memberId), +// missionArchive.mission.status.eq(status) +// ) +// .groupBy(missionArchive.mission.id) +// .fetch()); +// +// +// } + @Override + public Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status) { + return Optional.ofNullable(queryFactory + .select(Projections.constructor(RepeatMissionBoardRes.class, + mission.id, + mission.title, + missionArchive.count.coalesce(0L).as("num"), + mission.number + )) + .from(mission) + .leftJoin(mission.missionArchiveList,missionArchive) + .on( missionArchive.member.memberId.eq(memberId), + missionArchive.mission.status.eq(status)) + .where( + mission.team.teamId.eq(teamId), + mission.type.eq(MissionType.REPEAT) +// missionArchive.member.memberId.eq(memberId), +// missionArchive.mission.status.eq(status) + ) + .groupBy(mission.id) + .fetch()); + + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 2bcb61fa..89a4e5d9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.domain.service; +import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; @@ -77,9 +78,9 @@ public List findMySingleMissionArchives(Long memberId,Long teamI incompleteList.addAll(completeList); return incompleteList; } -// public List findMyRepeatMissionArchives(Long memberId, List missionIds) { -// return missionArchiveRepository.findRepeatMissionArchivesByMission(memberId, missionIds).orElseThrow(NotFoundMissionArchiveException::new); -// } + public List findMyRepeatMissionArchives(Long memberId, Long teamId, MissionStatus missionStatus) { + return missionArchiveRepository.findRepeatMissionArchivesByMemberId(memberId, teamId, missionStatus).orElseThrow(NotFoundMissionArchiveException::new); + } public List findMyAllMissionArchives(Long memberId, Long teamId, MissionStatus missionStatus) { return missionArchiveRepository.findAllMissionArchivesByMemberId(memberId, teamId, missionStatus).orElseThrow(NotFoundMissionArchiveException::new); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java index 4a4760b4..066bf683 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.missionArchive.presentation; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; @@ -18,28 +19,44 @@ @RestController @AllArgsConstructor -@RequestMapping("/api/{teamId}/missions/{missionId}/board") +@RequestMapping("/api/{teamId}/missions/board") public class MissionBoardController { private final MissionArchiveBoardUseCase missionArchiveBoardUseCase; /** * 단일 인증 조회 - * [POST] {teamId}/missions/{missionId}/board + * [POST] {teamId}/missions/board/single * 작성자 : 정승연 */ @GetMapping("/single") public ResponseEntity>> getActiveSingleMission(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId) { + @PathVariable("teamId") Long teamId) { return ResponseEntity.ok(SuccessResponse.create(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveSingleMissions(teamId, user.getSocialId()))); } + /** + * 종료된 인증 조회 + * [POST] {teamId}/missions/board/finish + * 작성자 : 정승연 + */ + @GetMapping("/finish") public ResponseEntity>> getFinishAllMission(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId) { + @PathVariable("teamId") Long teamId) { return ResponseEntity.ok(SuccessResponse.create(FINISH_ALL_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getFinishMissions(teamId, user.getSocialId()))); } + + /** + * 반복 미션 인증 조회 + * [GET] {teamId}/missions/board/repeat + * 작성자 : 정승연 + */ + @GetMapping("/repeat") + public ResponseEntity>> getActiveRepeatMission(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(FINISH_ALL_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); + } + } From 8776afc826ecc8cc7ff22340ded12c533e389e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 5 Oct 2023 18:35:12 +0900 Subject: [PATCH 119/619] =?UTF-8?q?feat=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EB=B3=B4=EB=93=9C=20'=EB=82=B4=EC=9D=BC=EB=A6=AC?= =?UTF-8?q?=EC=85=8B'=20=EB=A6=AC=ED=84=B4=20(dueTo:True/False)=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/RepeatMissionBoardRes.java | 1 + .../service/MissionArchiveBoardUseCase.java | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java index 1e3b46cf..9868972b 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java @@ -20,6 +20,7 @@ public class RepeatMissionBoardRes { public RepeatMissionBoardRes(Long missionId, String title, Long done,int number) { this.missionId = missionId; this.title = title; + this.dueTo="False"; this.number = number; this.done = done; } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java index 358c907e..1f512d08 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java @@ -19,6 +19,9 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -63,7 +66,18 @@ public List getActiveRepeatMissions(Long teamId, String m Member member = memberGetService.getMemberBySocialId(memberId); - return missionArchiveQueryService.findMyRepeatMissionArchives(member.getMemberId(),teamId,MissionStatus.ONGOING); + List myRepeatMissionArchives = missionArchiveQueryService.findMyRepeatMissionArchives(member.getMemberId(), teamId, MissionStatus.ONGOING); + + + LocalDate currentDate = LocalDate.now(); + DayOfWeek currentDayOfWeek = currentDate.getDayOfWeek(); + if (currentDayOfWeek == DayOfWeek.SUNDAY) { + myRepeatMissionArchives.stream().forEach( + repeatMissionBoardRes -> repeatMissionBoardRes.setDueTo("True") + ); + } + + return myRepeatMissionArchives; } From 472ad2e1204083997684148fa2ae544c01a49e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 5 Oct 2023 18:39:04 +0900 Subject: [PATCH 120/619] =?UTF-8?q?fix=20:=20=ED=95=9C=EB=B2=88=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EB=AF=B8=EC=85=98=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20once=20=EC=88=98=EC=A0=95=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index eb476116..bfac1e32 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -47,6 +47,7 @@ public Optional> findSingleMissionArchivesByMemberId(Long m missionArchive.mission.team.teamId.eq(teamId), missionArchive.member.memberId.eq(memberId), missionArchive.mission.status.eq(status), + missionArchive.mission.type.eq(MissionType.ONCE), missionArchive.status.eq(archiveStatus) ) .orderBy(orderSpecifiers) From 0f8e244cf25bf9a805b633bcdde6d240c291d83f Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 5 Oct 2023 21:34:58 +0900 Subject: [PATCH 121/619] =?UTF-8?q?feat:=20=EC=8B=A0=EA=B7=9C=EA=B3=B5?= =?UTF-8?q?=EC=A7=80=20=EC=95=8C=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/AlarmBoardUserCase.java | 42 +++++++++++++++++++ .../service/CreateBoardUserCase.java | 7 +++- .../TeamMemberCustomRepository.java | 2 + .../TeamMemberCustomRepositoryImpl.java | 11 +++++ .../domain/service/TeamMemberGetService.java | 6 +++ .../config/fcm/constant/NewUploadTitle.java | 13 ++++++ 6 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/board/application/service/AlarmBoardUserCase.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/constant/NewUploadTitle.java diff --git a/src/main/java/com/moing/backend/domain/board/application/service/AlarmBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/AlarmBoardUserCase.java new file mode 100644 index 00000000..fab65fc7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/board/application/service/AlarmBoardUserCase.java @@ -0,0 +1,42 @@ +package com.moing.backend.domain.board.application.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.service.FcmService; +import com.moing.backend.global.response.BaseServiceResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; + +import static com.moing.backend.global.config.fcm.constant.NewUploadTitle.UPLOAD_NOTICE_NEW_TITLE; + +@Service +@RequiredArgsConstructor +@Transactional +public class AlarmBoardUserCase { + + private final TeamMemberGetService teamMemberGetService; + private final FcmService fcmService; + + public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board board) { + Member member = baseServiceResponse.getMember(); + Team team = baseServiceResponse.getTeam(); + + if (board.isNotice() && member.isNewUploadPush()) { + String title = team.getName() + " " + UPLOAD_NOTICE_NEW_TITLE.getTitle(); + String message = board.getTitle(); + Optional> fcmTokens = teamMemberGetService.getFcmTokens(team.getTeamId(), member.getMemberId()); + if (fcmTokens.isPresent() && !fcmTokens.get().isEmpty()) { + MultiRequest toMultiRequest = new MultiRequest(fcmTokens.get(), title, message); + fcmService.sendMultipleDevices(toMultiRequest); + } + } + } +} + diff --git a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java index 84139ae8..e5d11c0e 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java @@ -40,12 +40,15 @@ public class CreateBoardUserCase { * 게시글 생성 */ public CreateBoardResponse createBoard(String socialId, Long teamId, CreateBoardRequest createBoardRequest) { + //1, 게시글 생성, 저장 BaseServiceResponse data=baseService.getCommonData(socialId, teamId); - boolean isLeader = checkLeaderUserCase.isTeamLeader(data.getMember(), data.getTeam()); + boolean isLeader = checkLeaderUserCase.isTeamLeader(data.getMember(), data.getTeam()); //작성자 리더 여부 Board board=boardSaveService.saveBoard(boardMapper.toBoard(data.getMember(), data.getTeamMember(), data.getTeam(), createBoardRequest, isLeader)); - //읽음 처리 + //2. 읽음 처리 - 생성한 사람은 무조건 읽음 createBoardReadUserCase.createBoardRead(data.getTeam(), data.getMember(), board); + + //3. 알림 보내기 - 공지인 경우 return new CreateBoardResponse(board.getBoardId()); } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index 4c7f0370..cc81ff9f 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -1,7 +1,9 @@ package com.moing.backend.domain.teamMember.domain.repository; import java.util.List; +import java.util.Optional; public interface TeamMemberCustomRepository { List findMemberIdsByTeamId(Long teamId); + Optional> findFcmTokensByTeamId(Long teamId, Long userId); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index 880d3e73..615603e7 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -5,6 +5,7 @@ import javax.persistence.EntityManager; import java.util.List; +import java.util.Optional; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; @@ -24,4 +25,14 @@ public List findMemberIdsByTeamId(Long teamId) { .where(teamMember.team.isDeleted.eq(false)) .fetch(); } + + @Override + public Optional> findFcmTokensByTeamId(Long teamId, Long memberId) { + return Optional.ofNullable(queryFactory.select(teamMember.member.fcmToken) + .from(teamMember) + .where(teamMember.team.teamId.eq(teamId)) //해당 소모임에 참여하고 있고 + .where(teamMember.member.isNewUploadPush.eq(true)) //알림 설정 on해 있고 + .where(teamMember.member.memberId.ne(memberId)) //지금 유저가 아닌 경우 + .fetch()); + } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index e224a89a..a8ba11bc 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -9,6 +9,7 @@ import lombok.RequiredArgsConstructor; import java.util.List; +import java.util.Optional; @DomainService @RequiredArgsConstructor @@ -22,4 +23,9 @@ public List getTeamMemberIds(Long teamId){ public TeamMember getTeamMember(Member member, Team team){ return teamMemberRepository.findTeamMemberByTeamAndMember(team, member).orElseThrow(()-> new NotFoundByTeamIdException()); } + + public Optional> getFcmTokens(Long teamId, Long memberId) { + return teamMemberRepository.findFcmTokensByTeamId(teamId, memberId); + } + } diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/NewUploadTitle.java b/src/main/java/com/moing/backend/global/config/fcm/constant/NewUploadTitle.java new file mode 100644 index 00000000..98690142 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/NewUploadTitle.java @@ -0,0 +1,13 @@ +package com.moing.backend.global.config.fcm.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum NewUploadTitle{ + UPLOAD_NOTICE_NEW_TITLE("새로운 공지 알려드려요!"), + UPLOAD_VOTE_NEW_TITLE("새로운 투표 알려드려요!"), + UPLOAD_MISSION_NEW_TITLE("새로운 미션 알려드려요!"); + private final String title; +} From 96c7ec5c372dc375c6bd8570c63b28aea6dc2491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 6 Oct 2023 11:32:57 +0900 Subject: [PATCH 122/619] =?UTF-8?q?refactor=20:=20singleMissionArchive=20r?= =?UTF-8?q?eturn=20=EC=97=90=20=EC=93=B0=EC=9D=B4=EB=8A=94=20OrderConditio?= =?UTF-8?q?n=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionArchiveCustomRepository.java | 2 -- .../repository/MissionArchiveCustomRepositoryImpl.java | 9 --------- .../missionArchive/domain/repository/OrderCondition.java | 6 ++++++ .../domain/service/MissionArchiveQueryService.java | 5 +---- .../teamMember/domain/repository/OrderCondition.java | 6 ------ 5 files changed, 7 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/repository/OrderCondition.java delete mode 100644 src/main/java/com/moing/backend/domain/teamMember/domain/repository/OrderCondition.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 1acd16d5..11a5de7e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -4,8 +4,6 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.domain.teamMember.domain.repository.OrderCondition; -import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index bfac1e32..f862658b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -1,32 +1,23 @@ package com.moing.backend.domain.missionArchive.domain.repository; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; -import com.moing.backend.domain.mission.domain.entity.QMission; -import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; -import com.moing.backend.domain.teamMember.domain.repository.OrderCondition; import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; -import feign.Param; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Repository; import javax.persistence.EntityManager; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.Optional; import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; import static javax.swing.Spring.constant; -import static org.hibernate.internal.util.NullnessHelper.coalesce; public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/OrderCondition.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/OrderCondition.java new file mode 100644 index 00000000..ab250eca --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/OrderCondition.java @@ -0,0 +1,6 @@ +package com.moing.backend.domain.missionArchive.domain.repository; + +public enum OrderCondition { + DUETO,CREATED + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 89a4e5d9..c0d1b0b4 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -4,12 +4,9 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveCustomRepository; import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; import com.moing.backend.domain.missionArchive.exception.NotFoundMissionArchiveException; -import com.moing.backend.domain.missionArchive.exception.NotFoundMissionArchiveException; -import com.moing.backend.domain.teamMember.domain.repository.OrderCondition; +import com.moing.backend.domain.missionArchive.domain.repository.OrderCondition; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/OrderCondition.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/OrderCondition.java deleted file mode 100644 index 706b8e5a..00000000 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/OrderCondition.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.moing.backend.domain.teamMember.domain.repository; - -public enum OrderCondition { - DUETO,CREATED - -} From c830a0440a873b49728b9365e396ea8ee9b36051 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 6 Oct 2023 22:10:55 +0900 Subject: [PATCH 123/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1,=20=EB=B0=98=EB=A0=A4=20=EC=95=8C=EB=A6=BC?= =?UTF-8?q?=20=EB=B3=B4=EB=82=B4=EA=B8=B0=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CreateBoardUserCase.java | 12 +----- .../service/DeleteBoardUserCase.java | 3 ++ .../application/service/GetBoardUserCase.java | 3 +- ...rCase.java => SendBoardAlarmUserCase.java} | 4 +- .../service/UpdateBoardUserCase.java | 3 ++ .../service/CreateBoardCommentUserCase.java | 5 +++ .../service/DeleteBoardCommentUserCase.java | 8 ++++ .../service/GetBoardCommentUserCase.java | 3 ++ .../service/SendTeamAlarmUserCase.java | 43 +++++++++++++++++++ .../presentation/AdminTeamController.java | 33 ++++++++++++-- .../constant/TeamResponseMessage.java | 4 +- .../TeamMemberCustomRepository.java | 3 +- .../TeamMemberCustomRepositoryImpl.java | 11 ++++- .../domain/service/TeamMemberGetService.java | 8 +++- 14 files changed, 122 insertions(+), 21 deletions(-) rename src/main/java/com/moing/backend/domain/board/application/service/{AlarmBoardUserCase.java => SendBoardAlarmUserCase.java} (94%) create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/SendTeamAlarmUserCase.java diff --git a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java index e5d11c0e..c6e401c0 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java @@ -5,18 +5,8 @@ import com.moing.backend.domain.board.application.mapper.BoardMapper; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardSaveService; -import com.moing.backend.domain.boardRead.application.mapper.BoardReadMapper; import com.moing.backend.domain.boardRead.application.service.CreateBoardReadUserCase; -import com.moing.backend.domain.boardRead.domain.entity.BoardRead; -import com.moing.backend.domain.boardRead.domain.service.BoardReadSaveService; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.team.application.service.CheckLeaderUserCase; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; -import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.BaseServiceResponse; import com.moing.backend.global.util.BaseService; import lombok.RequiredArgsConstructor; @@ -35,6 +25,7 @@ public class CreateBoardUserCase { private final BoardMapper boardMapper; private final CreateBoardReadUserCase createBoardReadUserCase; private final BaseService baseService; + private final SendBoardAlarmUserCase sendBoardAlarmUserCase; /** * 게시글 생성 @@ -49,6 +40,7 @@ public CreateBoardResponse createBoard(String socialId, Long teamId, CreateBoard createBoardReadUserCase.createBoardRead(data.getTeam(), data.getMember(), board); //3. 알림 보내기 - 공지인 경우 + sendBoardAlarmUserCase.sendNewUploadAlarm(data, board); return new CreateBoardResponse(board.getBoardId()); } } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java index 387e17da..0274a771 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java @@ -21,8 +21,11 @@ public class DeleteBoardUserCase { * 게시글 삭제 */ public void deleteBoard(String socialId, Long teamId, Long boardId){ + //1. 게시글 조회 BaseBoardServiceResponse data= baseBoardService.getCommonData(socialId,teamId,boardId); + //2. 작성자인 경우 if (data.getTeamMember() == data.getBoard().getTeamMember()) { + //3. 삭제 boardDeleteService.deleteBoard(data.getBoard()); } else throw new NotAuthByBoardException(); } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java index 56430dcc..e72be8e8 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java @@ -31,8 +31,9 @@ public class GetBoardUserCase { * 게시글 상세 조회 */ public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long boardId) { + // 1. 게시글 조회 BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); - //읽음 처리 + // 2. 읽음 처리 createBoardReadUserCase.createBoardRead(data.getTeam(), data.getMember(), data.getBoard()); return boardMapper.toBoardDetail(data.getBoard(), data.getTeamMember() == data.getBoard().getTeamMember()); } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/AlarmBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUserCase.java similarity index 94% rename from src/main/java/com/moing/backend/domain/board/application/service/AlarmBoardUserCase.java rename to src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUserCase.java index fab65fc7..94efba16 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/AlarmBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUserCase.java @@ -19,7 +19,7 @@ @Service @RequiredArgsConstructor @Transactional -public class AlarmBoardUserCase { +public class SendBoardAlarmUserCase { private final TeamMemberGetService teamMemberGetService; private final FcmService fcmService; @@ -31,7 +31,7 @@ public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board bo if (board.isNotice() && member.isNewUploadPush()) { String title = team.getName() + " " + UPLOAD_NOTICE_NEW_TITLE.getTitle(); String message = board.getTitle(); - Optional> fcmTokens = teamMemberGetService.getFcmTokens(team.getTeamId(), member.getMemberId()); + Optional> fcmTokens = teamMemberGetService.getFcmTokensExceptMe(team.getTeamId(), member.getMemberId()); if (fcmTokens.isPresent() && !fcmTokens.get().isEmpty()) { MultiRequest toMultiRequest = new MultiRequest(fcmTokens.get(), title, message); fcmService.sendMultipleDevices(toMultiRequest); diff --git a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java index 394b34e3..21e20b91 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java @@ -21,8 +21,11 @@ public class UpdateBoardUserCase { * 게시글 수정 */ public UpdateBoardResponse updateBoard(String socialId, Long teamId, Long boardId, UpdateBoardRequest updateBoardRequest){ + // 1. 게시글 조회 BaseBoardServiceResponse data= baseBoardService.getCommonData(socialId, teamId, boardId); + // 2. 게시글 작성자만 if (data.getTeamMember() == data.getBoard().getTeamMember()) { + // 3. 수정 data.getBoard().updateBoard(updateBoardRequest); return new UpdateBoardResponse(data.getBoard().getBoardId()); } else throw new NotAuthByBoardException(); diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java index 759fc5c4..23e1d12b 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java @@ -21,9 +21,14 @@ public class CreateBoardCommentUserCase { private final BoardCommentMapper boardCommentMapper; private final BaseBoardService baseBoardService; + /** + * 게시글 댓글 생성 + */ public CreateBoardCommentResponse createBoardComment(String socialId, Long teamId, Long boardId, CreateBoardCommentRequest createBoardCommentRequest) { + // 1. 게시글 댓글 생성 BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(data.getTeamMember(), data.getBoard(), createBoardCommentRequest)); + // 2. 게시글 댓글 개수 증가 data.getBoard().incrComNum(); return new CreateBoardCommentResponse(boardComment.getBoardCommentId()); } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java index 6201717f..2f0285c3 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java @@ -20,11 +20,19 @@ public class DeleteBoardCommentUserCase { private final BoardCommentDeleteService boardCommentDeleteService; private final BaseBoardService baseBoardService; + /** + * 게시글 댓글 삭제 + */ + public void deleteBoardComment(String socialId, Long teamId, Long boardId, Long boardCommentId){ + // 1. 게시글 댓글 조회 BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); BoardComment boardComment=boardCommentGetService.getBoardComment(boardCommentId); + // 2. 게시글 댓글 작성자만 if (data.getTeamMember() == boardComment.getTeamMember()) { + // 3. 삭제 boardCommentDeleteService.deleteBoardComment(boardComment); + // 4. 댓글 개수 줄이기 data.getBoard().decrComNum(); } else throw new NotAuthByBoardCommentException(); } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java index df53c6e1..544c5174 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java @@ -17,6 +17,9 @@ public class GetBoardCommentUserCase { private final BoardCommentGetService boardCommentGetService; private final BaseBoardService baseBoardService; + /** + * 게시글 댓글 전체 조회 + */ public GetBoardCommentResponse getBoardCommentAll(String socialId, Long teamId, Long boardId){ BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); return boardCommentGetService.getBoardCommentAll(boardId, data.getTeamMember()); diff --git a/src/main/java/com/moing/backend/domain/team/application/service/SendTeamAlarmUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/SendTeamAlarmUserCase.java new file mode 100644 index 00000000..e5ef6690 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/SendTeamAlarmUserCase.java @@ -0,0 +1,43 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.service.FcmService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; + +import static com.moing.backend.global.config.fcm.constant.NewUploadTitle.UPLOAD_NOTICE_NEW_TITLE; + +@Service +@Transactional +@RequiredArgsConstructor +public class SendTeamAlarmUserCase { + private final TeamMemberGetService teamMemberGetService; + private final FcmService fcmService; + + public void sendApprovalAlarm(Long teamId) { + //TODO: 승인, 반려 문구 constant로 + String title = "소모임 승인 안내"; + String message = "소모임이 승인되었습니다."; + sendAlarm(teamId, title, message); + } + + public void sendRejectionAlarm(Long teamId) { + String title = "소모임 반려 안내"; + String message = "소모임이 반려되었습니다."; + sendAlarm(teamId, title, message); + } + + private void sendAlarm(Long teamId, String title, String message) { + Optional> fcmTokens = teamMemberGetService.getFcmTokens(teamId); + if(fcmTokens.isPresent() && !fcmTokens.get().isEmpty()) { + MultiRequest toMultiRequest = new MultiRequest(fcmTokens.get(), title, message); + fcmService.sendMultipleDevices(toMultiRequest); + } + } +} + diff --git a/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java index 3241479e..5ffa70f9 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java @@ -1,18 +1,45 @@ package com.moing.backend.domain.team.presentation; -import com.moing.backend.domain.team.application.service.CreateTeamUserCase; +import com.moing.backend.domain.team.application.service.SendTeamAlarmUserCase; +import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import static com.moing.backend.domain.team.presentation.constant.TeamResponseMessage.*; + @RestController @AllArgsConstructor @RequestMapping("/api/admin/team") public class AdminTeamController { - //TODO 소모임 승인, 반려하기 - private final CreateTeamUserCase createTeamService; + private final SendTeamAlarmUserCase sendTeamAlarmUserCase; + + /** + * 소모임 승인 알림 보내기 + * [POST] api/admin/team/approval/{teamId} + * 작성자 : 김민수 + */ + + @PostMapping("/approval/{teamId}") + public ResponseEntity sendApproveAlarm(@PathVariable Long teamId) { + this.sendTeamAlarmUserCase.sendApprovalAlarm(teamId); + return ResponseEntity.ok(SuccessResponse.create(SEND_APPROVAL_ALARM_SUCCESS.getMessage())); + } + /** + * 소모임 반려 알림 보내기 + * [POST] api/admin/team/rejection/{teamId} + * 작성자: 김민수 + */ + @PostMapping("/rejection/{teamId}") + public ResponseEntity sendRejectionAlarm(@PathVariable Long teamId){ + this.sendTeamAlarmUserCase.sendRejectionAlarm(teamId); + return ResponseEntity.ok(SuccessResponse.create(SEND_REJECTION_ALARM_SUCCESS.getMessage())); + } } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 45ae0eb5..2b1ccdcb 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -10,6 +10,8 @@ public enum TeamResponseMessage { GET_TEAM_SUCCESS("홈 화면에서 내 소모임을 모두 조회했습니다."), SIGNIN_TEAM_SUCCESS("소모임에 가입하였습니다"), DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."), - WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"); + WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"), + SEND_APPROVAL_ALARM_SUCCESS("소모임 승인 알림을 보냈습니다."), + SEND_REJECTION_ALARM_SUCCESS("소모임 반려 알림을 보냈습니다."); private final String message; } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index cc81ff9f..725b70e1 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -5,5 +5,6 @@ public interface TeamMemberCustomRepository { List findMemberIdsByTeamId(Long teamId); - Optional> findFcmTokensByTeamId(Long teamId, Long userId); + Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId); + Optional> findFcmTokensByTeamId(Long teamId); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index 615603e7..40f64eaa 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -27,7 +27,7 @@ public List findMemberIdsByTeamId(Long teamId) { } @Override - public Optional> findFcmTokensByTeamId(Long teamId, Long memberId) { + public Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId) { return Optional.ofNullable(queryFactory.select(teamMember.member.fcmToken) .from(teamMember) .where(teamMember.team.teamId.eq(teamId)) //해당 소모임에 참여하고 있고 @@ -35,4 +35,13 @@ public Optional> findFcmTokensByTeamId(Long teamId, Long memberId) .where(teamMember.member.memberId.ne(memberId)) //지금 유저가 아닌 경우 .fetch()); } + + @Override + public Optional> findFcmTokensByTeamId(Long teamId) { + return Optional.ofNullable(queryFactory.select(teamMember.member.fcmToken) + .from(teamMember) + .where(teamMember.team.teamId.eq(teamId)) //해당 소모임에 참여하고 있고 + .where(teamMember.member.isNewUploadPush.eq(true)) //알림 설정 on해 있고 + .fetch()); + } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index a8ba11bc..6ba8f3db 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -24,8 +24,12 @@ public TeamMember getTeamMember(Member member, Team team){ return teamMemberRepository.findTeamMemberByTeamAndMember(team, member).orElseThrow(()-> new NotFoundByTeamIdException()); } - public Optional> getFcmTokens(Long teamId, Long memberId) { - return teamMemberRepository.findFcmTokensByTeamId(teamId, memberId); + public Optional> getFcmTokensExceptMe(Long teamId, Long memberId) { + return teamMemberRepository.findFcmTokensByTeamIdAndMemberId(teamId, memberId); + } + + public Optional> getFcmTokens(Long teamId) { + return teamMemberRepository.findFcmTokensByTeamId(teamId); } } From e5ce422617d528020d6a06fd034e7b65cfcc0873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 7 Oct 2023 01:56:09 +0900 Subject: [PATCH 124/619] =?UTF-8?q?feat=20:=20=EB=82=98=EC=9D=98=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=20=EB=AF=B8=EC=85=98=20=EB=B0=98=EB=B3=B5?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=ED=8F=AC=ED=95=A8=ED=95=B4=EC=84=9C=20?= =?UTF-8?q?=EB=A6=AC=ED=84=B4=ED=95=98=EA=B8=B0=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveCustomRepository.java | 2 ++ .../MissionArchiveCustomRepositoryImpl.java | 6 +++++ .../service/MissionArchiveQueryService.java | 20 +++++++++++----- .../presentation/MissionBoardController.java | 24 +++++++++---------- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 11a5de7e..bf7caed9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.domain.repository; +import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; @@ -18,5 +19,6 @@ public interface MissionArchiveCustomRepository { Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status); + Optional> findMyMissionsByStatus(Long memberId, Long teamId, MissionStatus missionStatus); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index f862658b..4a719e65 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.domain.repository; +import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; @@ -162,5 +163,10 @@ public Optional> findRepeatMissionArchivesByMemberId .fetch()); + } + + @Override + public Optional> findMyMissionsByStatus(Long memberId, Long teamId, MissionStatus missionStatus) { + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index c0d1b0b4..52a3a7fb 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -1,6 +1,8 @@ package com.moing.backend.domain.missionArchive.domain.service; +import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; @@ -31,6 +33,7 @@ public MissionArchive findByMissionArchiveId(Long missionArchiveId) { public MissionArchive findArchive(Long memberId, Long missionId) { return missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId).orElseThrow(NotFoundMissionArchiveException::new); } + public List findMyArchive(Long memberId, Long missionId) { Optional> optional = missionArchiveRepository.findArchivesByMissionIdAndMemberId(memberId, missionId); @@ -41,6 +44,7 @@ public List findMyArchive(Long memberId, Long missionId) { return optional.get(); } } + public List findOthersArchive(Long memberId, Long missionId) { return missionArchiveRepository.findOthersArchives(memberId, missionId).orElseThrow(NotFoundMissionArchiveException::new); } @@ -53,8 +57,7 @@ public Boolean isDone(Long memberId, Long missionId) { Optional> byMemberId = missionArchiveRepository.findArchivesByMissionIdAndMemberId(memberId, missionId); if (byMemberId.isPresent()) { return Boolean.TRUE; - } - else{ + } else { return Boolean.FALSE; } } @@ -64,17 +67,18 @@ public Boolean isDone(Long memberId, Long missionId) { /** * mission.getTeam() 팀의 단일미션 미션 인증 보드 */ - public List findMySingleMissionArchives(Long memberId,Long teamId, MissionStatus missionStatus) { + public List findMySingleMissionArchives(Long memberId, Long teamId, MissionStatus missionStatus) { // INCOMPLETE List incompleteList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, teamId, missionStatus, INCOMPLETE, OrderCondition.DUETO) .orElseThrow(NotFoundMissionArchiveException::new); - List completeList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, teamId, missionStatus, COMPLETE,OrderCondition.CREATED) + List completeList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, teamId, missionStatus, COMPLETE, OrderCondition.CREATED) .orElseThrow(NotFoundMissionArchiveException::new); incompleteList.addAll(completeList); return incompleteList; } + public List findMyRepeatMissionArchives(Long memberId, Long teamId, MissionStatus missionStatus) { return missionArchiveRepository.findRepeatMissionArchivesByMemberId(memberId, teamId, missionStatus).orElseThrow(NotFoundMissionArchiveException::new); } @@ -86,11 +90,15 @@ public List findMyAllMissionArchives(Long memberId, Long teamId, public Long findDoneArchives(Long missionId) { return missionArchiveRepository.findDonePeopleByMissionId(missionId).orElseThrow(NotFoundMissionArchiveException::new); } - public Long findMyDoneArchives(Long memberId,Long missionId) { - return missionArchiveRepository.findMyDoneCountByMissionId(missionId,memberId).orElseThrow(NotFoundMissionArchiveException::new); + + public Long findMyDoneArchives(Long memberId, Long missionId) { + return missionArchiveRepository.findMyDoneCountByMissionId(missionId, memberId).orElseThrow(NotFoundMissionArchiveException::new); } + public List findMyFinishMissions(Long memberId, Long teamId, MissionStatus missionStatus) { + return missionArchiveRepository.findMyMissionsByStatus(memberId, teamId, missionStatus).orElseThrow(NotFoundMissionArchiveException::new); + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java index 066bf683..3a37836d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java @@ -36,18 +36,6 @@ public ResponseEntity>> getActiveSin return ResponseEntity.ok(SuccessResponse.create(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveSingleMissions(teamId, user.getSocialId()))); } - /** - * 종료된 인증 조회 - * [POST] {teamId}/missions/board/finish - * 작성자 : 정승연 - */ - - @GetMapping("/finish") - public ResponseEntity>> getFinishAllMission(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(FINISH_ALL_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getFinishMissions(teamId, user.getSocialId()))); - } - /** * 반복 미션 인증 조회 * [GET] {teamId}/missions/board/repeat @@ -59,4 +47,16 @@ public ResponseEntity>> getActiveRep return ResponseEntity.ok(SuccessResponse.create(FINISH_ALL_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); } + /** + * 종료된 인증 조회 + * [POST] {teamId}/missions/board/finish + * 작성자 : 정승연 + */ + + @GetMapping("/finish") + public ResponseEntity>> getFinishAllMission(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(FINISH_ALL_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getFinishMissions(teamId, user.getSocialId()))); + } + } From 2658f10bbfb1370f458abed866ff4d5ba11c70fc Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sat, 7 Oct 2023 18:36:41 +0900 Subject: [PATCH 125/619] =?UTF-8?q?feat=20:=20=EC=A2=85=EB=A1=9C=EB=90=9C?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98(=ED=95=9C=EB=B2=88,=EB=B0=98=EB=B3=B5)=20?= =?UTF-8?q?=EB=AA=A8=EB=91=90=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/FinishMissionBoardRes.java | 20 +++++++++++++--- .../service/MissionArchiveBoardUseCase.java | 3 +-- .../mapper/MissionArchiveMapper.java | 6 ++--- .../MissionArchiveResponseMessage.java | 1 + .../MissionArchiveCustomRepositoryImpl.java | 24 +++++++++++++++++++ .../presentation/MissionBoardController.java | 2 +- 6 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java index fbb5b9c0..de1d37d0 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java @@ -1,15 +1,29 @@ package com.moing.backend.domain.mission.application.dto.res; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import lombok.Builder; import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; @Builder @Getter +@Setter public class FinishMissionBoardRes { private Long missionId; - private String dueTo; // 날짜 + private LocalDateTime dueTo; // 날짜 private String title; - private String status; - private String missionType; + private MissionArchiveStatus status; + private MissionType missionType; + public FinishMissionBoardRes(Long missionId, LocalDateTime dueTo, String title, MissionArchiveStatus status, MissionType missionType) { + this.missionId = missionId; + this.dueTo = dueTo; + this.title = title; + this.status = status; + this.missionType = missionType; + } } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java index 1f512d08..7a635373 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java @@ -57,8 +57,7 @@ public List getFinishMissions(Long teamId, String memberI Team team = teamRepository.findById(teamId).orElseThrow(); Member member = memberGetService.getMemberBySocialId(memberId); - List myAllMissionArchives = missionArchiveQueryService.findMyAllMissionArchives(member.getMemberId(), teamId, MissionStatus.END); - return MissionArchiveMapper.mapToFinishMissionBoardResList(myAllMissionArchives); + return missionArchiveQueryService.findMyFinishMissions(member.getMemberId(), teamId, MissionStatus.END); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index eafa243c..552c4971 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -115,10 +115,10 @@ public static FinishMissionBoardRes mapToFinishMissionBoardRes(MissionArchive mi Mission mission = missionArchive.getMission(); return FinishMissionBoardRes.builder() .missionId(mission.getId()) - .missionType(mission.getType().name()) + .missionType(mission.getType()) .title(mission.getTitle()) - .dueTo(mission.getDueTo().toString()) - .status(missionArchive.getStatus().name()) + .dueTo(mission.getDueTo()) + .status(missionArchive.getStatus()) .build(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java index 5cda14a5..9dec4edf 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java @@ -13,6 +13,7 @@ public enum MissionArchiveResponseMessage { HEART_UPDATE_SUCCESS("미션 인증 좋아요를 성공적으로 눌렀습니다."), MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS("미션 인증 성공한 인원 상태 조회를 완료 했습니다."), ACTIVE_SINGLE_MISSION_SUCCESS("진행 중인 한번 인증 미션 조회를 완료 했습니다."), + ACTIVE_REPEAT_MISSION_SUCCESS("진행 중인 반복 인증 미션 조회를 완료 했습니다."), FINISH_ALL_MISSION_SUCCESS("종료된 미션 조회를 완료하였습니다."); private final String message; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 4a719e65..8cfa4b01 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -6,9 +6,11 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.querydsl.core.types.Expression; import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -168,5 +170,27 @@ public Optional> findRepeatMissionArchivesByMemberId @Override public Optional> findMyMissionsByStatus(Long memberId, Long teamId, MissionStatus missionStatus) { + Expression dueToString = Expressions.stringTemplate("DATE_FORMAT({0}, '%Y-%m-%d %H:%i.%s')", mission.dueTo); + Expression status = Expressions.stringTemplate(String.valueOf(missionArchive.status)); + Expression type = Expressions.stringTemplate(String.valueOf(mission.type)); + + + return Optional.ofNullable(queryFactory + .select(Projections.constructor(FinishMissionBoardRes.class, + mission.id, + mission.dueTo, + mission.title, + missionArchive.status, + mission.type + )) + .from(mission) + .leftJoin(mission.missionArchiveList,missionArchive) + .on(missionArchive.member.memberId.eq(memberId)) + .where( + mission.team.teamId.eq(teamId), + mission.status.eq(missionStatus) + ) + .fetch() + ); } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java index 3a37836d..64648461 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java @@ -44,7 +44,7 @@ public ResponseEntity>> getActiveSin @GetMapping("/repeat") public ResponseEntity>> getActiveRepeatMission(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(FINISH_ALL_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); } /** From 561fa03367210e86b01a58eb210187bc795e36ee Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sat, 7 Oct 2023 18:45:55 +0900 Subject: [PATCH 126/619] fix : FinishMissionBoardRes field Type --- .../application/dto/res/FinishMissionBoardRes.java | 8 ++++---- .../application/mapper/MissionArchiveMapper.java | 6 +++--- .../repository/MissionArchiveCustomRepositoryImpl.java | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java index de1d37d0..ecd0c0b3 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java @@ -14,12 +14,12 @@ @Setter public class FinishMissionBoardRes { private Long missionId; - private LocalDateTime dueTo; // 날짜 + private String dueTo; // 날짜 private String title; - private MissionArchiveStatus status; - private MissionType missionType; + private String status; + private String missionType; - public FinishMissionBoardRes(Long missionId, LocalDateTime dueTo, String title, MissionArchiveStatus status, MissionType missionType) { + public FinishMissionBoardRes(Long missionId, String dueTo, String title, String status, String missionType) { this.missionId = missionId; this.dueTo = dueTo; this.title = title; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 552c4971..eafa243c 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -115,10 +115,10 @@ public static FinishMissionBoardRes mapToFinishMissionBoardRes(MissionArchive mi Mission mission = missionArchive.getMission(); return FinishMissionBoardRes.builder() .missionId(mission.getId()) - .missionType(mission.getType()) + .missionType(mission.getType().name()) .title(mission.getTitle()) - .dueTo(mission.getDueTo()) - .status(missionArchive.getStatus()) + .dueTo(mission.getDueTo().toString()) + .status(missionArchive.getStatus().name()) .build(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 8cfa4b01..cc562945 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -178,10 +178,10 @@ public Optional> findMyMissionsByStatus(Long memberI return Optional.ofNullable(queryFactory .select(Projections.constructor(FinishMissionBoardRes.class, mission.id, - mission.dueTo, + mission.dueTo.stringValue(), mission.title, - missionArchive.status, - mission.type + missionArchive.status.stringValue(), + mission.type.stringValue() )) .from(mission) .leftJoin(mission.missionArchiveList,missionArchive) From 45d629db4dde8a57c400053a64f08415f5eb73c9 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sat, 7 Oct 2023 23:01:52 +0900 Subject: [PATCH 127/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=B3=B4=EB=93=9C=20=EA=B4=80=EB=A0=A8=20MissionBoardControlle?= =?UTF-8?q?rTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/RepeatMissionBoardRes.java | 9 + .../presentation/MissionBoardController.java | 2 +- .../MissionBoardControllerTest.java | 190 ++++++++++++++++++ 3 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java index 9868972b..099c187c 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java @@ -24,4 +24,13 @@ public RepeatMissionBoardRes(Long missionId, String title, Long done,int number) this.number = number; this.done = done; } + + @Builder + public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long done, int number) { + this.missionId = missionId; + this.title = title; + this.dueTo = "False"; + this.done = done; + this.number = number; + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java index 64648461..b48f595b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java @@ -26,7 +26,7 @@ public class MissionBoardController { /** * 단일 인증 조회 - * [POST] {teamId}/missions/board/single + * [GET] {teamId}/missions/board/single * 작성자 : 정승연 */ diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java new file mode 100644 index 00000000..e2361a30 --- /dev/null +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java @@ -0,0 +1,190 @@ +package com.moing.backend.domain.missionArchive.representation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; +import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.presentation.MissionBoardController; +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.List; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; + +@WebMvcTest(MissionBoardController.class) +public class MissionBoardControllerTest extends CommonControllerTest { + + + @MockBean + private MissionArchiveBoardUseCase missionArchiveBoardUseCase; + + @Test + public void 단일_미션_인증_조회() throws Exception { + //given + + List output = Lists.newArrayList(SingleMissionBoardRes.builder() + .missionId(1L) + .dueTo("2023-09-03T21:32:33.888") + .title("Mission title") + .status("SKIP/COMPLETE") + .missionType("ONCE/REPEAT") + .build()); + + given(missionArchiveBoardUseCase.getActiveSingleMissions(any(),any())).willReturn(output); + + Long teamId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/missions/board/single",teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage()), + fieldWithPath("data[].missionId").description("미션 아이디"), + fieldWithPath("data[].dueTo").description("미션 마감 시각"), + fieldWithPath("data[].title").description("미션 제목"), + fieldWithPath("data[].status").description("미션 인증 상태"), + fieldWithPath("data[].missionType").description("미션 타입") + + ) + ) + ) + .andReturn(); + + } + + @Test + public void 반복_미션_인증_조회() throws Exception { + //given + + List output = Lists.newArrayList(RepeatMissionBoardRes.builder() + .missionId(1L) + .title("Mission title") + .dueTo("True/False") + .done(1L) + .number(3) + .build()); + + given(missionArchiveBoardUseCase.getActiveRepeatMissions(any(),any())).willReturn(output); + + Long teamId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/missions/board/repeat",teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage()), + fieldWithPath("data[].missionId").description("미션 아이디"), + fieldWithPath("data[].title").description("미션 제목"), + fieldWithPath("data[].dueTo").description("내일 리셋 상태 리턴, 일요일이면 true[True/False]"), + fieldWithPath("data[].number").description("전체 횟수"), + fieldWithPath("data[].done").description("인증한 횟수") + + ) + ) + ) + .andReturn(); + + } + + @Test + public void 종료된_인증_조회() throws Exception { + //given + + List output = Lists.newArrayList(FinishMissionBoardRes.builder() + .missionId(1L) + .title("Mission title") + .dueTo("2023-09-03T21:32:33.888") + .status("SUCCESS/FAIL") + .missionType("ONCE/REPEAT") + .build()); + + given(missionArchiveBoardUseCase.getFinishMissions(any(),any())).willReturn(output); + + Long teamId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/missions/board/finish",teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(FINISH_ALL_MISSION_SUCCESS.getMessage()), + fieldWithPath("data[].missionId").description("미션 아이디"), + fieldWithPath("data[].title").description("미션 제목"), + fieldWithPath("data[].dueTo").description("내일 리셋 상태 리턴, 일요일이면 true[True/False]"), + fieldWithPath("data[].status").description("미션 종료된 상태 (성공/실패)"), + fieldWithPath("data[].missionType").description("미션 타입 (한번/반복)") + + ) + ) + ) + .andReturn(); + + } + + +} \ No newline at end of file From 8d7bbecb6a4e459933ecc51720a822365b6e9f9d Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 8 Oct 2023 03:46:24 +0900 Subject: [PATCH 128/619] =?UTF-8?q?fix=20:=20MissionStatus=20=ED=95=AD?= =?UTF-8?q?=EB=AA=A9=20END=20->=20SUCCESS,FAIL=20=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionArchiveBoardUseCase.java | 2 +- .../domain/mission/domain/entity/constant/MissionStatus.java | 2 ++ .../domain/repository/MissionArchiveCustomRepository.java | 2 +- .../repository/MissionArchiveCustomRepositoryImpl.java | 4 ++-- .../domain/service/MissionArchiveQueryService.java | 5 ++--- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java index 7a635373..8518976f 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java @@ -57,7 +57,7 @@ public List getFinishMissions(Long teamId, String memberI Team team = teamRepository.findById(teamId).orElseThrow(); Member member = memberGetService.getMemberBySocialId(memberId); - return missionArchiveQueryService.findMyFinishMissions(member.getMemberId(), teamId, MissionStatus.END); + return missionArchiveQueryService.findMyFinishMissions(member.getMemberId(), teamId); } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java index e561994a..07007a45 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java @@ -8,4 +8,6 @@ public enum MissionStatus { END, ONGOING, + SUCCESS, + FAIL } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index bf7caed9..890c89ea 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -19,6 +19,6 @@ public interface MissionArchiveCustomRepository { Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status); - Optional> findMyMissionsByStatus(Long memberId, Long teamId, MissionStatus missionStatus); + Optional> findFinishMissionsByStatus(Long memberId, Long teamId); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index cc562945..95a8dedd 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -168,7 +168,7 @@ public Optional> findRepeatMissionArchivesByMemberId } @Override - public Optional> findMyMissionsByStatus(Long memberId, Long teamId, MissionStatus missionStatus) { + public Optional> findFinishMissionsByStatus(Long memberId, Long teamId) { Expression dueToString = Expressions.stringTemplate("DATE_FORMAT({0}, '%Y-%m-%d %H:%i.%s')", mission.dueTo); Expression status = Expressions.stringTemplate(String.valueOf(missionArchive.status)); @@ -188,7 +188,7 @@ public Optional> findMyMissionsByStatus(Long memberI .on(missionArchive.member.memberId.eq(memberId)) .where( mission.team.teamId.eq(teamId), - mission.status.eq(missionStatus) + mission.status.eq(MissionStatus.SUCCESS).or(mission.status.eq(MissionStatus.FAIL)) ) .fetch() ); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 52a3a7fb..8b24c4c1 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -2,7 +2,6 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; -import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; @@ -96,8 +95,8 @@ public Long findMyDoneArchives(Long memberId, Long missionId) { } - public List findMyFinishMissions(Long memberId, Long teamId, MissionStatus missionStatus) { - return missionArchiveRepository.findMyMissionsByStatus(memberId, teamId, missionStatus).orElseThrow(NotFoundMissionArchiveException::new); + public List findMyFinishMissions(Long memberId, Long teamId) { + return missionArchiveRepository.findFinishMissionsByStatus(memberId, teamId).orElseThrow(NotFoundMissionArchiveException::new); } From eb8d2f0d6b6489dfedb68cfc523e03de28bf7d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 10 Oct 2023 11:13:40 +0900 Subject: [PATCH 129/619] =?UTF-8?q?feat=20:=20MissionBoard-API.adoc=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionArchive-API.adoc | 2 +- src/docs/asciidoc/MissionBoard-API.adoc | 28 +++++++++++++++++ src/docs/asciidoc/api.adoc | 2 ++ .../repository/MissionCustomRepository.java | 2 ++ .../presentation/MissionController.java | 1 - .../RepeatMissionArchiveReadUseCase.java | 31 ------------------- .../MissionArchiveCustomRepository.java | 2 ++ .../MissionArchiveControllerTest.java | 25 ++++++++++----- 8 files changed, 52 insertions(+), 41 deletions(-) create mode 100644 src/docs/asciidoc/MissionBoard-API.adoc diff --git a/src/docs/asciidoc/MissionArchive-API.adoc b/src/docs/asciidoc/MissionArchive-API.adoc index dc148e22..8d287be0 100644 --- a/src/docs/asciidoc/MissionArchive-API.adoc +++ b/src/docs/asciidoc/MissionArchive-API.adoc @@ -11,7 +11,7 @@ operation::mission-archive-controller-test/미션_인증하기[snippets='http-re [[MissionArchive-재인증하기]] === 미션 재인증하기 -operation::mission-archive-controller-test/미션_재인증하기[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +operation::mission-archive-controller-test/미션_재인증하기[snipipets='http-request,path-parameters,request-fields,http-response,response-fields'] --- diff --git a/src/docs/asciidoc/MissionBoard-API.adoc b/src/docs/asciidoc/MissionBoard-API.adoc new file mode 100644 index 00000000..fb985bf0 --- /dev/null +++ b/src/docs/asciidoc/MissionBoard-API.adoc @@ -0,0 +1,28 @@ + + +[[MissionBoard-API]] += MissionBoard API + +[[MissionBoard-단일미션인증조회]] +=== 단일 미션 인증 조회 +operation::mission-board-controller-test/단일_미션_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[MissionBoard-반복미션인증조회]] +=== 반복 미션 인증 조회 +operation::mission-board-controller-test/반복 미션 인증 조회[snipipets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[MissionBoard-나의미션인증조회]] +=== 나의 미션 인증 조회 +operation::mission-archive-controller-test/나의_미션_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[MissionBoard-종료된인증조회]] +=== 종료된 인증 조회 +operation::mission-board-controller-test/종료된_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index d8753290..d103ef14 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -20,6 +20,8 @@ include::Mission-API.adoc[] include::MissionArchive-API.adoc[] +include::MissionBoard-API.adoc[] + include::Board-API.adoc[] include::BoardComment_API.adoc[] diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index b09cd218..f46913d5 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -2,10 +2,12 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; +@Repository public interface MissionCustomRepository { Long findMissionsCountByTeam(Long teamId); Optional> findRepeatMissionByMemberId(Long teamId, MissionStatus status); diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index d66ccf85..1aa19a20 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -29,7 +29,6 @@ public class MissionController { private final MissionReadUseCase missionReadUseCase; private final MissionUpdateUseCase missionUpdateUseCase; private final MissionDeleteUseCase missionDeleteUseCase; - private final MissionQueryService missionQueryService; /** * 미션 조회 diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java index ff971211..02a17034 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/RepeatMissionArchiveReadUseCase.java @@ -22,37 +22,6 @@ public class RepeatMissionArchiveReadUseCase { private final MissionQueryService missionQueryService; private final MissionArchiveQueryService missionArchiveQueryService; - -// // 나의 인증 목록 -// public List getMyArchive(String userSocialId, Long missionId) { -// List myArchives = getArchive(userSocialId, missionId); -// -// List archiveRes = new ArrayList<>(); -// myArchives.forEach(myArchive -> archiveRes.add(MissionArchiveMapper.mapToMissionArchiveRes(myArchive))); -// -// return archiveRes; -// } -// -// // 팀원들 인증 목록 -// public List getPersonalArchive(String userSocialId, Long missionId) { -// Mission mission = missionQueryService.findMissionById(missionId); -// -// List done = new ArrayList<>(); -// -// mission.getMissionArchiveList() -// .forEach(missionArchive1 -> done.add(mapToPersonalArchive(missionArchive1))); -// -// return done; -// } -// -// // memberId, missionId로 archive 꺼내기 -// public List getArchive(String userSocialId, Long missionId) { -// Member member = memberGetService.getMemberBySocialId(userSocialId); -// Mission mission = missionQueryService.findMissionById(missionId); -// -// return missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId); -// } - public MissionArchiveStatusRes getMyMissionDoneStatus(String userSocialId,Long missionId) { Member member = memberGetService.getMemberBySocialId(userSocialId); Mission mission = missionQueryService.findMissionById(missionId); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 890c89ea..9ddb0af8 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -5,9 +5,11 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; +@Repository public interface MissionArchiveCustomRepository { Optional> findSingleMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status, MissionArchiveStatus archiveStatus, OrderCondition orderCondition); Optional> findOthersArchives(Long memberId, Long missionId) ; diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index bd651f2c..7cb3d752 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -7,10 +7,7 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; -import com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateUseCase; -import com.moing.backend.domain.missionArchive.application.service.MissionArchiveHeartUseCase; -import com.moing.backend.domain.missionArchive.application.service.MissionArchiveUpdateUseCase; -import com.moing.backend.domain.missionArchive.application.service.SingleMissionArchiveReadUseCase; +import com.moing.backend.domain.missionArchive.application.service.*; import com.moing.backend.domain.missionArchive.presentation.MissionArchiveController; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; @@ -42,6 +39,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { @MockBean private SingleMissionArchiveReadUseCase singleMissionArchiveReadUseCase; @MockBean + private RepeatMissionArchiveReadUseCase repeatMissionArchiveReadUseCase; + @MockBean private MissionArchiveHeartUseCase missionArchiveHeartUseCase; @@ -62,6 +61,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .createdDate("2023-09-03T21:32:33.888") .hearts(3) .status("COMPLETE/SKIP") + .count(1L) .build(); given(missionArchiveCreateUseCase.createArchive(any(),any(),any())).willReturn(output); @@ -99,7 +99,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data.createdDate").description("미션 제출 시각"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data.status").description("미션 인증 상태") + fieldWithPath("data.status").description("미션 인증 상태"), + fieldWithPath("data.count").description("미션 인증 횟수") // fieldWithPath("data.heartsStatus").description("미션 인증 좋아요 상태"), ) ) @@ -124,6 +125,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .createdDate("2023-09-03T21:32:33.888") .hearts(3) .status("COMPLETE/SKIP") + .count(1L) .build(); given(missionArchiveUpdateUseCase.updateArchive(any(),any(),any())).willReturn(output); @@ -161,7 +163,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data.createdDate").description("미션 제출 시각"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data.status").description("미션 인증 상태") + fieldWithPath("data.status").description("미션 인증 상태"), + fieldWithPath("data.count").description("미션 인증 횟수") // fieldWithPath("data.heartsStatus").description("미션 인증 좋아요 상태"), ) ) @@ -180,6 +183,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .createdDate("2023-09-03T21:32:33.888") .hearts(0) .status("COMPLETE/SKIP") + .count(1L) .build()); given(singleMissionArchiveReadUseCase.getMyArchive(any(),any())).willReturn(output); @@ -213,7 +217,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data[].archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data[].createdDate").description("미션 제출 시각"), fieldWithPath("data[].hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data[].status").description("미션 인증 상태") + fieldWithPath("data[].status").description("미션 인증 상태"), + fieldWithPath("data[].count").description("미션 인증 횟수") ) ) @@ -234,6 +239,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .createdDate("2023-09-03T21:32:33.888") .hearts(3) .status("COMPLETE/SKIP") + .count(1L) .build()); given(singleMissionArchiveReadUseCase.getPersonalArchive(any(),any())).willReturn(output); @@ -269,7 +275,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data[].archive").description("미션 인증물 [s3URL/text/링크] "), fieldWithPath("data[].createdDate").description("미션 인증 날짜 "), fieldWithPath("data[].hearts").description("미션 인증 좋아요 수 "), - fieldWithPath("data[].status").description("미션 인증 상태") + fieldWithPath("data[].status").description("미션 인증 상태"), + fieldWithPath("data[].count").description("미션 인증 횟수") ) ) @@ -383,4 +390,6 @@ public class MissionArchiveControllerTest extends CommonControllerTest { + + } From aa30809ad467cb5137a7281a666d8c8ae6d47c63 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 10 Oct 2023 16:53:32 +0900 Subject: [PATCH 130/619] =?UTF-8?q?feat=20:=20=EB=B6=88=EB=8D=98=EC=A7=80?= =?UTF-8?q?=EA=B8=B0=20Fire=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/FireThrowRes.java | 11 +++++++ .../fire/application/mapper/FireMapper.java | 13 ++++++++ .../application/service/FireThrowUseCase.java | 31 +++++++++++++++++++ .../domain/fire/domain/entity/Fire.java | 28 +++++++++++++++++ .../repository/FireCustomRepository.java | 13 ++++++++ .../repository/FireCustomRepositoryImpl.java | 26 ++++++++++++++++ .../fire/domain/service/FireQueryService.java | 18 +++++++++++ .../fire/domain/service/FireSaveService.java | 19 ++++++++++++ 8 files changed, 159 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/fire/application/dto/res/FireThrowRes.java create mode 100644 src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java create mode 100644 src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java create mode 100644 src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java create mode 100644 src/main/java/com/moing/backend/domain/fire/domain/service/FireSaveService.java diff --git a/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireThrowRes.java b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireThrowRes.java new file mode 100644 index 00000000..12d19db3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireThrowRes.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.fire.application.dto.res; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class FireThrowRes { + + private Long receiveMemberId; +} diff --git a/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java b/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java new file mode 100644 index 00000000..b9fe4b27 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.fire.application.mapper; + +import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; +import com.moing.backend.domain.fire.domain.entity.Fire; + +public class FireMapper { + + public static FireThrowRes mapToFireThrowRes(Fire fire) { + return FireThrowRes.builder() + .receiveMemberId(fire.getReceiveMemberId()) + .build(); + } +} diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java new file mode 100644 index 00000000..6c1eec71 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -0,0 +1,31 @@ +package com.moing.backend.domain.fire.application.service; + +import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; +import com.moing.backend.domain.fire.application.mapper.FireMapper; +import com.moing.backend.domain.fire.domain.entity.Fire; +import com.moing.backend.domain.fire.domain.repository.FireCustomRepository; +import com.moing.backend.domain.fire.domain.service.FireQueryService; +import com.moing.backend.domain.fire.domain.service.FireSaveService; +import com.moing.backend.domain.mission.application.service.MissionCreateUseCase; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class FireThrowUseCase { + + public final FireSaveService fireSaveService; + public final FireQueryService fireQueryService; + + public FireThrowRes createFireThrow(Long throwMemberId, Long receiveMemberId) { + + + + return FireMapper.mapToFireThrowRes(fireSaveService.save(Fire.builder() + .throwMemberId(throwMemberId) + .receiveMemberId(receiveMemberId) + .build())); + } +} diff --git a/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java b/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java new file mode 100644 index 00000000..9b32a630 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.fire.domain.entity; + +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Builder +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class Fire extends BaseTimeEntity { + + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "fire_id") + private Long id; + + private Long throwMemberId; + + private Long receiveMemberId; + +} diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java new file mode 100644 index 00000000..30b97109 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.fire.domain.repository; + + +import com.moing.backend.domain.fire.domain.entity.Fire; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface FireCustomRepository extends JpaRepository { + + Optional findMyRecentFire(Long memberId); + +} diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java new file mode 100644 index 00000000..24c19af5 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -0,0 +1,26 @@ +package com.moing.backend.domain.fire.domain.repository; + +import com.moing.backend.domain.fire.domain.entity.Fire; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.util.Optional; + +public class FireCustomRepositoryImpl implements FireCustomRepository { + private final JPAQueryFactory queryFactory; + + public FireCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + +// +// Optional findMyRecentFire(Long memberId){ +// return Optional.ofNullable(queryFactory +// .select() +// .from() +// .where() +// .fetchFirst() +// ); +// } + +} diff --git a/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java b/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java new file mode 100644 index 00000000..aa9a9090 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.fire.domain.service; + +import com.moing.backend.domain.fire.domain.entity.Fire; +import com.moing.backend.domain.fire.domain.repository.FireCustomRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class FireQueryService { + + private final FireCustomRepository fireCustomRepository; + + public Fire findMyRecentFire(Long memberId) { + return fireCustomRepository.findMyRecentFire(Long, memberId); + } + +} diff --git a/src/main/java/com/moing/backend/domain/fire/domain/service/FireSaveService.java b/src/main/java/com/moing/backend/domain/fire/domain/service/FireSaveService.java new file mode 100644 index 00000000..bf9e1f2c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/domain/service/FireSaveService.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.fire.domain.service; + +import com.moing.backend.domain.fire.domain.entity.Fire; +import com.moing.backend.domain.fire.domain.repository.FireCustomRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class FireSaveService { + + private final FireCustomRepository fireCustomRepository; + + public Fire save(Fire fire) { + return fireCustomRepository.save(fire); + } +} From 4a54be3cb3c179d73d7c136b52a34bf6f4aeaacc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:55:40 +0900 Subject: [PATCH 131/619] =?UTF-8?q?feat=20:=20=EB=B6=88=EB=8D=98=EC=A7=80?= =?UTF-8?q?=EA=B8=B0=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/FireReceiveRes.java | 8 ++++ .../application/service/FireThrowUseCase.java | 16 ++++++- .../repository/FireCustomRepository.java | 4 +- .../repository/FireCustomRepositoryImpl.java | 32 ++++++++++---- .../domain/repository/FireRepository.java | 7 ++++ .../fire/domain/service/FireQueryService.java | 15 +++++-- .../fire/domain/service/FireSaveService.java | 5 ++- .../domain/fire/exception/FireException.java | 13 ++++++ .../exception/NoAuthThrowFireException.java | 12 ++++++ .../fire/exception/NotFoundFireException.java | 12 ++++++ .../fire/presentation/FireController.java | 42 +++++++++++++++++++ .../constant/FireResponseMessage.java | 13 ++++++ .../backend/global/response/ErrorCode.java | 4 ++ 13 files changed, 166 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java create mode 100644 src/main/java/com/moing/backend/domain/fire/domain/repository/FireRepository.java create mode 100644 src/main/java/com/moing/backend/domain/fire/exception/FireException.java create mode 100644 src/main/java/com/moing/backend/domain/fire/exception/NoAuthThrowFireException.java create mode 100644 src/main/java/com/moing/backend/domain/fire/exception/NotFoundFireException.java create mode 100644 src/main/java/com/moing/backend/domain/fire/presentation/FireController.java create mode 100644 src/main/java/com/moing/backend/domain/fire/presentation/constant/FireResponseMessage.java diff --git a/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java new file mode 100644 index 00000000..56eff3eb --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java @@ -0,0 +1,8 @@ +package com.moing.backend.domain.fire.application.dto.res; + +public class FireReceiveRes { + + private Long receiveMemberId; + private String nickName; + private String fireStatus; +} diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java index 6c1eec71..2ffd75cb 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -1,16 +1,21 @@ package com.moing.backend.domain.fire.application.service; +import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; import com.moing.backend.domain.fire.application.mapper.FireMapper; import com.moing.backend.domain.fire.domain.entity.Fire; import com.moing.backend.domain.fire.domain.repository.FireCustomRepository; import com.moing.backend.domain.fire.domain.service.FireQueryService; import com.moing.backend.domain.fire.domain.service.FireSaveService; +import com.moing.backend.domain.fire.exception.NoAuthThrowFireException; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.application.service.MissionCreateUseCase; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Service @Transactional @RequiredArgsConstructor @@ -18,14 +23,23 @@ public class FireThrowUseCase { public final FireSaveService fireSaveService; public final FireQueryService fireQueryService; + private final MemberGetService memberGetService; - public FireThrowRes createFireThrow(Long throwMemberId, Long receiveMemberId) { + public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { + Long throwMemberId = memberGetService.getMemberBySocialId(userId).getMemberId(); + if (fireQueryService.hasFireCreatedWithinOneHour(throwMemberId, receiveMemberId)) { + throw new NoAuthThrowFireException(); + } return FireMapper.mapToFireThrowRes(fireSaveService.save(Fire.builder() .throwMemberId(throwMemberId) .receiveMemberId(receiveMemberId) .build())); } + +// public List getFireReceiveList(Long missionArchiveId) { +// fireQueryService. +// } } diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java index 30b97109..f0fc3d4a 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java @@ -6,8 +6,8 @@ import java.util.Optional; -public interface FireCustomRepository extends JpaRepository { +public interface FireCustomRepository { - Optional findMyRecentFire(Long memberId); + boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMemberId); } diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 24c19af5..437a10ec 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -1,11 +1,16 @@ package com.moing.backend.domain.fire.domain.repository; import com.moing.backend.domain.fire.domain.entity.Fire; +import com.moing.backend.domain.fire.domain.entity.QFire; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; +import java.time.LocalDateTime; +import java.util.List; import java.util.Optional; +import static com.moing.backend.domain.fire.domain.entity.QFire.fire; + public class FireCustomRepositoryImpl implements FireCustomRepository { private final JPAQueryFactory queryFactory; @@ -13,14 +18,23 @@ public FireCustomRepositoryImpl(EntityManager em) { this.queryFactory = new JPAQueryFactory(em); } -// -// Optional findMyRecentFire(Long memberId){ -// return Optional.ofNullable(queryFactory -// .select() -// .from() -// .where() -// .fetchFirst() -// ); -// } + + public boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMemberId) { + LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1); // 현재 시간에서 1시간을 뺀 시간 + long count = queryFactory + .select() + .from(fire) + .where( + fire.throwMemberId.eq(throwMemberId), + fire.receiveMemberId.eq(receiveMemberId), + fire.createdDate.after(oneHourAgo) // createdDate가 oneHourAgo 이후인 데이터 + ) + .fetchCount(); + + return count > 0; // 1시간 이내에 생성된 데이터가 존재하면 true를 반환, 그렇지 않으면 false 반환 + } + + +// public List get } diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireRepository.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireRepository.java new file mode 100644 index 00000000..6a9b01af --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.fire.domain.repository; + +import com.moing.backend.domain.fire.domain.entity.Fire; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FireRepository extends JpaRepository,FireCustomRepository { +} diff --git a/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java b/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java index aa9a9090..d1ce2ea5 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java @@ -2,17 +2,26 @@ import com.moing.backend.domain.fire.domain.entity.Fire; import com.moing.backend.domain.fire.domain.repository.FireCustomRepository; +import com.moing.backend.domain.fire.domain.repository.FireRepository; +import com.moing.backend.domain.fire.exception.NotFoundFireException; +import com.moing.backend.domain.member.domain.entity.Member; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; + @Service @RequiredArgsConstructor public class FireQueryService { - private final FireCustomRepository fireCustomRepository; + private final FireRepository fireRepository; - public Fire findMyRecentFire(Long memberId) { - return fireCustomRepository.findMyRecentFire(Long, memberId); + public boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMemberId) { + return fireRepository.hasFireCreatedWithinOneHour(throwMemberId,receiveMemberId); } +// public List getNotYetMissionMember(Long missionArchiveId) { +// return fireCustomRepository. +// } + } diff --git a/src/main/java/com/moing/backend/domain/fire/domain/service/FireSaveService.java b/src/main/java/com/moing/backend/domain/fire/domain/service/FireSaveService.java index bf9e1f2c..14a94b30 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/service/FireSaveService.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/service/FireSaveService.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.fire.domain.entity.Fire; import com.moing.backend.domain.fire.domain.repository.FireCustomRepository; +import com.moing.backend.domain.fire.domain.repository.FireRepository; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -11,9 +12,9 @@ @RequiredArgsConstructor public class FireSaveService { - private final FireCustomRepository fireCustomRepository; + private final FireRepository fireRepository; public Fire save(Fire fire) { - return fireCustomRepository.save(fire); + return fireRepository.save(fire); } } diff --git a/src/main/java/com/moing/backend/domain/fire/exception/FireException.java b/src/main/java/com/moing/backend/domain/fire/exception/FireException.java new file mode 100644 index 00000000..9540cd09 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/exception/FireException.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.fire.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class FireException extends ApplicationException { + + protected FireException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/fire/exception/NoAuthThrowFireException.java b/src/main/java/com/moing/backend/domain/fire/exception/NoAuthThrowFireException.java new file mode 100644 index 00000000..fda8174d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/exception/NoAuthThrowFireException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.fire.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NoAuthThrowFireException extends FireException { + + public NoAuthThrowFireException() { + super(ErrorCode.NOT_AUTH_FIRE_THROW, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/fire/exception/NotFoundFireException.java b/src/main/java/com/moing/backend/domain/fire/exception/NotFoundFireException.java new file mode 100644 index 00000000..666d85b0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/exception/NotFoundFireException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.fire.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundFireException extends FireException { + + public NotFoundFireException() { + super(ErrorCode.NOT_FOUND_FIRE, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java new file mode 100644 index 00000000..3ca5bf05 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java @@ -0,0 +1,42 @@ +package com.moing.backend.domain.fire.presentation; + +import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; +import com.moing.backend.domain.fire.application.service.FireThrowUseCase; +import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static com.moing.backend.domain.fire.presentation.constant.FireResponseMessage.THROW_FIRE_SUCCESS; +import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.READ_MISSION_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/{teamId}/missions/{missionId}/fire") +public class FireController { + + private final FireThrowUseCase fireThrowUseCase; + + /** + * 불 던지기 + * [POST] {teamId}/mission/{missionId}/archive/{missionArchiveId} + * 작성자 : 정승연 + */ + + @PostMapping("{receiveMemberId}") + public ResponseEntity> throwFire (@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, + @PathVariable("receiveMemberId") Long receiveMemberId) { + return ResponseEntity.ok(SuccessResponse.create(THROW_FIRE_SUCCESS.getMessage(), this.fireThrowUseCase.createFireThrow(user.getSocialId(),receiveMemberId))); + } + + + + + +} diff --git a/src/main/java/com/moing/backend/domain/fire/presentation/constant/FireResponseMessage.java b/src/main/java/com/moing/backend/domain/fire/presentation/constant/FireResponseMessage.java new file mode 100644 index 00000000..81048fd0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/presentation/constant/FireResponseMessage.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.fire.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum FireResponseMessage { + THROW_FIRE_SUCCESS("불던지기를 완료 했습니다"); + + private final String message; + +} diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 31aa29b6..ccf340c9 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -25,6 +25,10 @@ public enum ErrorCode { NOT_FOUND_MISSION("M0002", "미션을 찾을 수 없습니다."), NOT_FOUND_MISSION_ARCHIVE("MA0001", "아직 미션을 제출하지 않았습니다."), + //불던지기 관련 에러 코드 + NOT_FOUND_FIRE("F001","불던지기 현황을 찾을 수 없습니다"), + NOT_AUTH_FIRE_THROW("F002","1시간 이내에 불던지기를 할 수 없습니다"), + //팀 관련 에러 코드 NOT_FOUND_BY_TEAM_ID_ERROR("T0001", "해당 teamId인 팀이 존재하지 않습니다."), NOT_AUTH_BY_TEAM_ERROR("T0002","권한이 없습니다."), From 18a4dead8a03e4380e351de6c591cbfeea326d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:21:53 +0900 Subject: [PATCH 132/619] =?UTF-8?q?feat=20:=20=EB=B6=88=20=EB=B0=9B?= =?UTF-8?q?=EC=9D=84=20=EC=82=AC=EB=9E=8C=20list=20return=20&=20=EB=B6=88?= =?UTF-8?q?=EB=8D=98=EC=A7=80=EA=B8=B0=20=EA=B0=80=EB=8A=A5=EC=97=AC?= =?UTF-8?q?=EB=B6=80=20=ED=99=95=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/FireReceiveRes.java | 11 +++++++ .../fire/application/mapper/FireMapper.java | 21 ++++++++++++++ .../application/service/FireThrowUseCase.java | 15 +++++++--- .../repository/FireCustomRepository.java | 5 +++- .../repository/FireCustomRepositoryImpl.java | 29 +++++++++++++++++-- .../fire/domain/service/FireQueryService.java | 7 +++-- .../NotFoundFireReceiversException.java | 12 ++++++++ .../fire/presentation/FireController.java | 20 ++++++++++--- .../backend/global/response/ErrorCode.java | 1 + 9 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/fire/exception/NotFoundFireReceiversException.java diff --git a/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java index 56eff3eb..d5e228a1 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java +++ b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java @@ -1,8 +1,19 @@ package com.moing.backend.domain.fire.application.dto.res; +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter public class FireReceiveRes { private Long receiveMemberId; private String nickName; private String fireStatus; + + public void updateFireStatus(boolean status) { + if (status) + this.fireStatus = "True"; + else this.fireStatus = "False"; + } } diff --git a/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java b/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java index b9fe4b27..82b0853e 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java +++ b/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java @@ -1,7 +1,12 @@ package com.moing.backend.domain.fire.application.mapper; +import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; import com.moing.backend.domain.fire.domain.entity.Fire; +import com.moing.backend.domain.member.domain.entity.Member; + +import java.util.ArrayList; +import java.util.List; public class FireMapper { @@ -10,4 +15,20 @@ public static FireThrowRes mapToFireThrowRes(Fire fire) { .receiveMemberId(fire.getReceiveMemberId()) .build(); } + + public static List mapToFireReceiversList(List members) { + List fireReceiveResList = new ArrayList<>(); + members.forEach( + member -> fireReceiveResList.add(FireMapper.mapToFireReceiveRes(member)) + ); + return fireReceiveResList; + } + + public static FireReceiveRes mapToFireReceiveRes(Member member) { + return FireReceiveRes.builder() + .receiveMemberId(member.getMemberId()) + .nickName(member.getNickName()) + .fireStatus("TRUE") + .build(); + } } diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java index 2ffd75cb..36d5175f 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -29,7 +29,7 @@ public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { Long throwMemberId = memberGetService.getMemberBySocialId(userId).getMemberId(); - if (fireQueryService.hasFireCreatedWithinOneHour(throwMemberId, receiveMemberId)) { + if (!fireQueryService.hasFireCreatedWithinOneHour(throwMemberId, receiveMemberId)) { throw new NoAuthThrowFireException(); } @@ -39,7 +39,14 @@ public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { .build())); } -// public List getFireReceiveList(Long missionArchiveId) { -// fireQueryService. -// } + public List getFireReceiveList(String userId,Long teamId, Long missionId) { + Long memberId = memberGetService.getMemberBySocialId(userId).getMemberId(); + + List fireReceiveRes = FireMapper.mapToFireReceiversList(fireQueryService.getNotYetMissionMember(teamId, missionId)); + fireReceiveRes.forEach( + res -> res.updateFireStatus(fireQueryService.hasFireCreatedWithinOneHour(memberId,res.getReceiveMemberId()) + )); + + return fireReceiveRes; + } } diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java index f0fc3d4a..4e2d2b10 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java @@ -2,12 +2,15 @@ import com.moing.backend.domain.fire.domain.entity.Fire; +import com.moing.backend.domain.member.domain.entity.Member; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; import java.util.Optional; public interface FireCustomRepository { boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMemberId); + Optional> getFireReceivers(Long teamId, Long missionId); -} + } diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 437a10ec..92b958eb 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -2,6 +2,9 @@ import com.moing.backend.domain.fire.domain.entity.Fire; import com.moing.backend.domain.fire.domain.entity.QFire; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -10,6 +13,12 @@ import java.util.Optional; import static com.moing.backend.domain.fire.domain.entity.QFire.fire; +import static com.moing.backend.domain.member.domain.entity.QMember.member; +import static com.moing.backend.domain.mission.domain.entity.QMission.mission; +import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; +import static com.moing.backend.domain.team.domain.entity.QTeam.team; +import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; +import static com.querydsl.jpa.JPAExpressions.select; public class FireCustomRepositoryImpl implements FireCustomRepository { private final JPAQueryFactory queryFactory; @@ -20,6 +29,8 @@ public FireCustomRepositoryImpl(EntityManager em) { public boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMemberId) { + + LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1); // 현재 시간에서 1시간을 뺀 시간 long count = queryFactory .select() @@ -31,10 +42,24 @@ public boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMembe ) .fetchCount(); - return count > 0; // 1시간 이내에 생성된 데이터가 존재하면 true를 반환, 그렇지 않으면 false 반환 + return count <= 0; // 1시간 이내에 생성된 데이터가 존재하면 true를 반환, 그렇지 않으면 false 반환 } -// public List get + public Optional> getFireReceivers(Long teamId, Long missionId) { + return Optional.ofNullable(queryFactory + .select(teamMember.member) + .from(teamMember) + .where( + teamMember.team.teamId.eq(teamId), + teamMember.member.memberId.notIn( + JPAExpressions + .select(missionArchive.member.memberId) + .from(missionArchive) + .where(missionArchive.mission.id.eq(missionId)) + ) + ) + .fetch()); + } } diff --git a/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java b/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java index d1ce2ea5..abb94e44 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.fire.domain.repository.FireCustomRepository; import com.moing.backend.domain.fire.domain.repository.FireRepository; import com.moing.backend.domain.fire.exception.NotFoundFireException; +import com.moing.backend.domain.fire.exception.NotFoundFireReceiversException; import com.moing.backend.domain.member.domain.entity.Member; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,8 +21,8 @@ public boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMembe return fireRepository.hasFireCreatedWithinOneHour(throwMemberId,receiveMemberId); } -// public List getNotYetMissionMember(Long missionArchiveId) { -// return fireCustomRepository. -// } + public List getNotYetMissionMember(Long teamId, Long missionId) { + return fireRepository.getFireReceivers(teamId, missionId).orElseThrow(NotFoundFireReceiversException::new); + } } diff --git a/src/main/java/com/moing/backend/domain/fire/exception/NotFoundFireReceiversException.java b/src/main/java/com/moing/backend/domain/fire/exception/NotFoundFireReceiversException.java new file mode 100644 index 00000000..b41c2eb7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/exception/NotFoundFireReceiversException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.fire.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundFireReceiversException extends FireException { + + public NotFoundFireReceiversException() { + super(ErrorCode.NOT_FOUND_FIRE_RECEIVERS, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java index 3ca5bf05..dcd03370 100644 --- a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java +++ b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.fire.presentation; +import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; import com.moing.backend.domain.fire.application.service.FireThrowUseCase; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; @@ -8,10 +9,9 @@ import lombok.AllArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; import static com.moing.backend.domain.fire.presentation.constant.FireResponseMessage.THROW_FIRE_SUCCESS; import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.READ_MISSION_SUCCESS; @@ -35,6 +35,18 @@ public ResponseEntity> throwFire (@AuthenticationP return ResponseEntity.ok(SuccessResponse.create(THROW_FIRE_SUCCESS.getMessage(), this.fireThrowUseCase.createFireThrow(user.getSocialId(),receiveMemberId))); } + /** + * 불 던지기 + * [POST] {teamId}/mission/{missionId}/archive/{missionArchiveId} + * 작성자 : 정승연 + */ + + @GetMapping("") + public ResponseEntity>> throwFireList (@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(THROW_FIRE_SUCCESS.getMessage(), this.fireThrowUseCase.getFireReceiveList(user.getSocialId(),teamId,missionId))); + } + diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index ccf340c9..a84ef05e 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -27,6 +27,7 @@ public enum ErrorCode { //불던지기 관련 에러 코드 NOT_FOUND_FIRE("F001","불던지기 현황을 찾을 수 없습니다"), + NOT_FOUND_FIRE_RECEIVERS("F001","불던지기를 받을 사람을 찾을 수 없습니다"), NOT_AUTH_FIRE_THROW("F002","1시간 이내에 불던지기를 할 수 없습니다"), //팀 관련 에러 코드 From 27693effb113aa2c4960736396b1f3b1a2597dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 12 Oct 2023 02:44:28 +0900 Subject: [PATCH 133/619] fix : MissionArchiveController edit --- .../missionArchive/presentation/MissionArchiveController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 0d5e628a..e594d99a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -86,8 +86,8 @@ public ResponseEntity>> getOtherPeopleArch } /** - * 인증 성공 인원 조회 - * [GET] {teamId}/m원issions/{missionId}/archive/status + * 인증 성공 인원 조회 (n/n명) + * [GET] {teamId}/missions/{missionId}/archive/status * 작성자 : 정승연 **/ From ee25e7855cbc5e87e2f7a4c0dd3cbf653cc581e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 12 Oct 2023 17:10:26 +0900 Subject: [PATCH 134/619] =?UTF-8?q?feat=20:=20=ED=95=9C=EB=B2=88=EB=AF=B8?= =?UTF-8?q?=EC=85=98,=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=ED=86=B5?= =?UTF-8?q?=ED=95=A9=EB=90=98=EB=8A=94=20=EB=B6=88=20=EB=8D=98=EC=A7=88=20?= =?UTF-8?q?=EC=82=AC=EB=9E=8C=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/FireCustomRepositoryImpl.java | 13 +++++++++++-- .../domain/fire/presentation/FireController.java | 6 +++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 92b958eb..da51ece9 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -18,6 +18,7 @@ import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; import static com.moing.backend.domain.team.domain.entity.QTeam.team; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; +import static com.querydsl.jpa.JPAExpressions.max; import static com.querydsl.jpa.JPAExpressions.select; public class FireCustomRepositoryImpl implements FireCustomRepository { @@ -55,11 +56,19 @@ public Optional> getFireReceivers(Long teamId, Long missionId) { teamMember.member.memberId.notIn( JPAExpressions .select(missionArchive.member.memberId) - .from(missionArchive) - .where(missionArchive.mission.id.eq(missionId)) + .from(missionArchive,mission) + .where(missionArchive.mission.id.eq(missionId), + mission.id.eq(missionId)) + .groupBy(missionArchive.member.memberId, missionArchive.mission.id, + missionArchive.count, mission.number) + .having( + missionArchive.mission.id.eq(missionId), + missionArchive.count.max().goe(mission.number) + ) ) ) .fetch()); } + } diff --git a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java index dcd03370..5a97a05c 100644 --- a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java +++ b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java @@ -25,7 +25,7 @@ public class FireController { /** * 불 던지기 - * [POST] {teamId}/mission/{missionId}/archive/{missionArchiveId} + * [POST] {teamId}/mission/{missionId}/fire/{receiveMemberId} * 작성자 : 정승연 */ @@ -36,8 +36,8 @@ public ResponseEntity> throwFire (@AuthenticationP } /** - * 불 던지기 - * [POST] {teamId}/mission/{missionId}/archive/{missionArchiveId} + * 불 던질 사람 조회 (receivers) + * [GET] {teamId}/mission/{missionId}/fire * 작성자 : 정승연 */ From 71f6b4dd7492dc7f5f698e617557e8f26e396f58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:56:46 +0900 Subject: [PATCH 135/619] =?UTF-8?q?feat=20:=20=EB=B6=88=EB=8D=98=EC=A7=80?= =?UTF-8?q?=EA=B8=B0=20=EA=B4=80=EB=A0=A8=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/FireReceiveRes.java | 2 +- .../fire/application/mapper/FireMapper.java | 2 +- .../fire/presentation/FireController.java | 3 +- .../constant/FireResponseMessage.java | 3 +- .../representation/FireControllerTest.java | 133 ++++++++++++++++++ 5 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java diff --git a/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java index d5e228a1..7b59d0a9 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java +++ b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java @@ -8,7 +8,7 @@ public class FireReceiveRes { private Long receiveMemberId; - private String nickName; + private String nickname; private String fireStatus; public void updateFireStatus(boolean status) { diff --git a/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java b/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java index 82b0853e..c8a803b7 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java +++ b/src/main/java/com/moing/backend/domain/fire/application/mapper/FireMapper.java @@ -27,7 +27,7 @@ public static List mapToFireReceiversList(List members) public static FireReceiveRes mapToFireReceiveRes(Member member) { return FireReceiveRes.builder() .receiveMemberId(member.getMemberId()) - .nickName(member.getNickName()) + .nickname(member.getNickName()) .fireStatus("TRUE") .build(); } diff --git a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java index 5a97a05c..a9210481 100644 --- a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java +++ b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java @@ -13,6 +13,7 @@ import java.util.List; +import static com.moing.backend.domain.fire.presentation.constant.FireResponseMessage.GET_RECEIVERS_SUCCESS; import static com.moing.backend.domain.fire.presentation.constant.FireResponseMessage.THROW_FIRE_SUCCESS; import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.READ_MISSION_SUCCESS; @@ -44,7 +45,7 @@ public ResponseEntity> throwFire (@AuthenticationP @GetMapping("") public ResponseEntity>> throwFireList (@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(THROW_FIRE_SUCCESS.getMessage(), this.fireThrowUseCase.getFireReceiveList(user.getSocialId(),teamId,missionId))); + return ResponseEntity.ok(SuccessResponse.create(GET_RECEIVERS_SUCCESS.getMessage(), this.fireThrowUseCase.getFireReceiveList(user.getSocialId(),teamId,missionId))); } diff --git a/src/main/java/com/moing/backend/domain/fire/presentation/constant/FireResponseMessage.java b/src/main/java/com/moing/backend/domain/fire/presentation/constant/FireResponseMessage.java index 81048fd0..8bbb91aa 100644 --- a/src/main/java/com/moing/backend/domain/fire/presentation/constant/FireResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/fire/presentation/constant/FireResponseMessage.java @@ -6,7 +6,8 @@ @Getter @RequiredArgsConstructor public enum FireResponseMessage { - THROW_FIRE_SUCCESS("불던지기를 완료 했습니다"); + THROW_FIRE_SUCCESS("불던지기를 완료 했습니다"), + GET_RECEIVERS_SUCCESS("불 던질사람 조회를 완료 했습니다"); private final String message; diff --git a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java new file mode 100644 index 00000000..767f6e4c --- /dev/null +++ b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java @@ -0,0 +1,133 @@ +package com.moing.backend.domain.fire.representation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; +import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; +import com.moing.backend.domain.fire.application.service.FireThrowUseCase; +import com.moing.backend.domain.fire.presentation.FireController; +import com.moing.backend.domain.mission.application.dto.req.MissionReq; +import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.List; + +import static com.moing.backend.domain.fire.presentation.constant.FireResponseMessage.GET_RECEIVERS_SUCCESS; +import static com.moing.backend.domain.fire.presentation.constant.FireResponseMessage.THROW_FIRE_SUCCESS; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; + +@WebMvcTest(FireController.class) +public class FireControllerTest extends CommonControllerTest { + + @MockBean + private FireThrowUseCase fireThrowUseCase; + + + @Test + public void 불_던질_사람_조회() throws Exception { + //given + + List output = Lists.newArrayList(FireReceiveRes.builder() + .receiveMemberId(1L) + .nickname("receiver 닉네임") + .fireStatus("True/False") + .build()); + + given(fireThrowUseCase.getFireReceiveList(any(),any(),any())).willReturn(output); + + Long teamId = 1L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/missions/{missionId}/fire",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(GET_RECEIVERS_SUCCESS.getMessage()), + fieldWithPath("data[].receiveMemberId").description("미션 아이디"), + fieldWithPath("data[].nickname").description("불 받을 사람 "), + fieldWithPath("data[].fireStatus").description("불 던질 수 있는 상태 리턴, 1시간 내 불 던진 내역에 따라 true[True/False]") + + ) + ) + ) + .andReturn(); + + } + + + @Test + public void 불_던지기() throws Exception { + //given + + FireThrowRes output = FireThrowRes.builder() + .receiveMemberId(1L) + .build(); + + given(fireThrowUseCase.createFireThrow(any(),any())).willReturn(output); + + Long teamId = 2L; + Long missionId = 2L; + Long receiveMemberId = 2L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + post("/api/{teamId}/missions/{missionId}/fire/{receiveMemberId}",teamId,missionId,receiveMemberId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디"), + parameterWithName("receiveMemberId").description("불 받을 사람 아이디") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(THROW_FIRE_SUCCESS.getMessage()), + fieldWithPath("data.receiveMemberId").description("미션 아이디") + ) + ) + ) + .andReturn(); + + } + + +} From 25fbfb6deb0390c181c5a203940b5c704797e654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 16 Oct 2023 12:14:21 +0900 Subject: [PATCH 136/619] =?UTF-8?q?feat=20:=20Fire-API.adoc=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Fire-API.adoc | 16 ++++++++++++++++ src/docs/asciidoc/api.adoc | 2 ++ 2 files changed, 18 insertions(+) create mode 100644 src/docs/asciidoc/Fire-API.adoc diff --git a/src/docs/asciidoc/Fire-API.adoc b/src/docs/asciidoc/Fire-API.adoc new file mode 100644 index 00000000..3da56ea5 --- /dev/null +++ b/src/docs/asciidoc/Fire-API.adoc @@ -0,0 +1,16 @@ + + +[[Fire-API]] += Fire API + +[[Fire-불던지기]] +=== 불 던지기 +operation::fire-controller-test/불_던지기[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- +[[Fire-불던질사람조회]] +=== 불 던질 사람 조회 +operation::fire-controller-test/불_던질_사람_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index d103ef14..12774927 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -22,6 +22,8 @@ include::MissionArchive-API.adoc[] include::MissionBoard-API.adoc[] +include::Fire-API.adoc[] + include::Board-API.adoc[] include::BoardComment_API.adoc[] From 87917547f698dced452d08213a9e9bdd2ac4e98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:35:09 +0900 Subject: [PATCH 137/619] =?UTF-8?q?feat=20:=20Mission-MissionArchive=20?= =?UTF-8?q?=EC=A4=91=EA=B0=84=EA=B0=9D=EC=B2=B4=20MissionStatus=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EA=B4=80=EB=A0=A8=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionCheckScheduler.java | 4 ++ .../service/MissionTerminationUseCase.java | 48 +++++++++++++++++++ .../repository/MissionCustomRepository.java | 3 ++ .../MissionCustomRepositoryImpl.java | 15 ++++++ .../domain/repository/MissionRepository.java | 3 +- .../domain/service/MissionQueryService.java | 9 ++++ .../NotFoundEndMissionException.java | 12 +++++ .../service/MissionArchiveBoardUseCase.java | 2 +- .../presentation/MissionBoardController.java | 4 +- .../application/dto/MissionStatusRes.java | 8 ++++ .../domain/entity/MissionStatus.java | 31 ++++++++++++ .../missionStatus/domain/entity/Status.java | 5 ++ .../MissionStatusCustomRepository.java | 4 ++ .../MissionStatusCustomRepositoryImpl.java | 30 ++++++++++++ .../repository/MissionStatusRepository.java | 7 +++ .../service/MissionStatusSaveService.java | 28 +++++++++++ .../backend/global/response/ErrorCode.java | 1 + .../MissionBoardControllerTest.java | 4 +- 18 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/mission/exception/NotFoundEndMissionException.java rename src/main/java/com/moing/backend/domain/{mission => missionArchive}/application/service/MissionArchiveBoardUseCase.java (97%) create mode 100644 src/main/java/com/moing/backend/domain/missionStatus/application/dto/MissionStatusRes.java create mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/entity/MissionStatus.java create mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/entity/Status.java create mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/service/MissionStatusSaveService.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java new file mode 100644 index 00000000..824407a3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java @@ -0,0 +1,4 @@ +package com.moing.backend.domain.mission.application.service; + +public class MissionCheckScheduler { +} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java new file mode 100644 index 00000000..ecd93df0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java @@ -0,0 +1,48 @@ +package com.moing.backend.domain.mission.application.service; + +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionStatus.domain.repository.MissionStatusRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionTerminationUseCase { + + private final MemberGetService memberGetService; + private final MissionQueryService missionQueryService; + + // 스케쥴러에서 호출 + public void terminateMission() { + + List missionByDueTo = missionQueryService.findMissionByDueTo(); + + missionByDueTo.stream().forEach( + // 미션 종료 처리 + mission -> mission.setStatus(MissionStatus.END) + + ); + } + + // 미션 점수 반영 -> MissionStatus + + + // MissionStatus 조회 해서 미션 점수 현황조회 + + public void getMissionScoreStatus() { + + } + + // 팀별 점수 반영 + public void updateMissionScore() { + + } + +} diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index f46913d5..74346877 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -12,4 +12,7 @@ public interface MissionCustomRepository { Long findMissionsCountByTeam(Long teamId); Optional> findRepeatMissionByMemberId(Long teamId, MissionStatus status); + Optional> findMissionByDueTo(); + + } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 7ab14a9f..be760214 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -7,6 +7,7 @@ import javax.persistence.EntityManager; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -44,4 +45,18 @@ public Optional> findRepeatMissionByMemberId(Long teamId, MissionS ) .fetch()); } + + + @Override + public Optional> findMissionByDueTo() { + + LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1); + + return Optional.ofNullable(queryFactory + .selectFrom(mission) + .where( + mission.dueTo.after(oneHourAgo) + ).fetch() + ); + } } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java index 5244df48..bd3244f7 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java @@ -3,5 +3,6 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import org.springframework.data.jpa.repository.JpaRepository; -public interface MissionRepository extends JpaRepository,MissionCustomRepository { +public interface MissionRepository extends JpaRepository, MissionCustomRepository { + } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 821c5022..a6d5325e 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.exception.NotFoundEndMissionException; import com.moing.backend.domain.mission.exception.NotFoundMissionException; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.global.annotation.DomainService; @@ -28,4 +29,12 @@ public Long findMissionsCountByTeam(Long teamId) { public List findRepeatMissionByTeamId(Long teamId) { return missionRepository.findRepeatMissionByMemberId(teamId, MissionStatus.ONGOING).orElseThrow(NotFoundMissionException::new); } + + /** + * 스케쥴러에서 한시간 단위로 실행 + * 현재 시간으로부터 1시간 이내 종료 되는 미션 리턴 + */ + public List findMissionByDueTo() { + return missionRepository.findMissionByDueTo().orElseThrow(NotFoundEndMissionException::new); + } } diff --git a/src/main/java/com/moing/backend/domain/mission/exception/NotFoundEndMissionException.java b/src/main/java/com/moing/backend/domain/mission/exception/NotFoundEndMissionException.java new file mode 100644 index 00000000..942f2861 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/exception/NotFoundEndMissionException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mission.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundEndMissionException extends MissionException { + + public NotFoundEndMissionException() { + super(ErrorCode.NOT_FOUND_MISSION, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveBoardUseCase.java similarity index 97% rename from src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java rename to src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveBoardUseCase.java index 8518976f..cb3360c6 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveBoardUseCase.java @@ -1,4 +1,4 @@ -package com.moing.backend.domain.mission.application.service; +package com.moing.backend.domain.missionArchive.application.service; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java index b48f595b..94a66474 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java @@ -3,9 +3,7 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; -import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; -import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveBoardUseCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/moing/backend/domain/missionStatus/application/dto/MissionStatusRes.java b/src/main/java/com/moing/backend/domain/missionStatus/application/dto/MissionStatusRes.java new file mode 100644 index 00000000..d3f50d40 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionStatus/application/dto/MissionStatusRes.java @@ -0,0 +1,8 @@ +package com.moing.backend.domain.missionStatus.application.dto; + +public class MissionStatusRes { + + private Long done; + private Long total; + +} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/MissionStatus.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/MissionStatus.java new file mode 100644 index 00000000..0ebe1d94 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/MissionStatus.java @@ -0,0 +1,31 @@ +package com.moing.backend.domain.missionStatus.domain.entity; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Builder +public class MissionStatus extends BaseTimeEntity { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "missionStatus_id") + private Long id; + + @OneToOne + private Mission mission; + @OneToOne + private Member member; + + private Status status; + +} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/Status.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/Status.java new file mode 100644 index 00000000..7472cd49 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/Status.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.missionStatus.domain.entity; + +public enum Status { + SUCCESS,FAIL +} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepository.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepository.java new file mode 100644 index 00000000..83d16141 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepository.java @@ -0,0 +1,4 @@ +package com.moing.backend.domain.missionStatus.domain.repository; + +public interface MissionStatusCustomRepository { +} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepositoryImpl.java new file mode 100644 index 00000000..628f53bf --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepositoryImpl.java @@ -0,0 +1,30 @@ +package com.moing.backend.domain.missionStatus.domain.repository; + +import com.moing.backend.domain.missionStatus.application.dto.MissionStatusRes; +import com.moing.backend.domain.missionStatus.domain.entity.MissionStatus; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.util.List; + +public class MissionStatusCustomRepositoryImpl implements MissionStatusCustomRepository { + + private final JPAQueryFactory queryFactory; + + public MissionStatusCustomRepositoryImpl(EntityManager entityManager) { + this.queryFactory = new JPAQueryFactory(entityManager); + } + +// public MissionStatusRes getMissionStatus() { +// +// queryFactory +// .select() +// .from(MissionStatus) +// .where( +// +// ) +// } + + + +} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusRepository.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusRepository.java new file mode 100644 index 00000000..2891e664 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.missionStatus.domain.repository; + +import com.moing.backend.domain.missionStatus.domain.entity.MissionStatus; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MissionStatusRepository extends JpaRepository { +} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/service/MissionStatusSaveService.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/service/MissionStatusSaveService.java new file mode 100644 index 00000000..7a39ce4f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionStatus/domain/service/MissionStatusSaveService.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.missionStatus.domain.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.missionStatus.domain.entity.MissionStatus; +import com.moing.backend.domain.missionStatus.domain.entity.Status; +import com.moing.backend.domain.missionStatus.domain.repository.MissionStatusRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionStatusSaveService { + + private final MissionStatusRepository missionStatusRepository; + + public void saveMissionStatus(Member member, Mission mission, Status status) { + missionStatusRepository.save(MissionStatus.builder() + .mission(mission) + .member(member) + .status(status) + .build()); + } + +} diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index bd2bd522..09ca3a18 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -28,6 +28,7 @@ public enum ErrorCode { //미션 관련 에러코드 NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), NOT_FOUND_MISSION("M0002", "미션을 찾을 수 없습니다."), + NOT_FOUND_END_MISSION("M0002", "기한이 지난 미션을 찾을 수 없습니다."), NOT_FOUND_MISSION_ARCHIVE("MA0001", "아직 미션을 제출하지 않았습니다."), NO_MORE_ARCHIVE_ERROR("MA0001", "지정한 횟수 이상 미션을 인증할 수 없습니다."), diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java index e2361a30..8f10c603 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java @@ -4,8 +4,7 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; -import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveBoardUseCase; import com.moing.backend.domain.missionArchive.presentation.MissionBoardController; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; @@ -19,7 +18,6 @@ import java.util.List; import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; -import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; From a706eb197cf97a3616eb6530ce20d7124049c5f0 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 16 Oct 2023 22:23:13 +0900 Subject: [PATCH 138/619] =?UTF-8?q?fix:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20request=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/SignUpRequest.java | 14 +++++ .../dto/response/GoogleUserResponse.java | 1 - .../response/KakaoAccessTokenResponse.java | 1 - .../dto/response/KakaoUserResponse.java | 11 +--- .../application/service/SignUpUserCase.java | 2 +- .../service/kakao/KakaoTokenUserCase.java | 2 - .../application/mapper/MemberMapper.java | 7 ++- .../domain/member/domain/constant/Gender.java | 10 ++++ .../domain/member/domain/entity/Member.java | 57 ++++++++----------- 9 files changed, 56 insertions(+), 49 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/member/domain/constant/Gender.java diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java index 8d7170a6..bfa735c3 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java @@ -1,8 +1,13 @@ package com.moing.backend.domain.auth.application.dto.request; +import com.moing.backend.domain.member.domain.constant.Gender; +import com.moing.backend.domain.team.domain.constant.Category; +import com.moing.backend.global.annotation.Enum; import lombok.*; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; @Builder @@ -10,10 +15,19 @@ @NoArgsConstructor @Getter public class SignUpRequest { + @NotBlank(message = "nickName 을 입력해주세요.") @Size(min = 1, max = 10, message="nickName 은 최소 1개, 최대 10개의 문자만 입력 가능합니다.") private String nickName; + @NotNull(message = "유효하지 않은 gender가 입력되었습니다.") + private Gender gender; + + @NotNull(message="birthDate 을 입력해주세요.") + @Pattern(regexp = "^\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$", message = "날짜 형식이 잘못되었습니다. YYYY-MM-DD 형식으로 입력해주세요.") + private String birthDate; + @NotBlank(message = "fcmToken 을 입력해주세요.") private String fcmToken; + } diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/GoogleUserResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/GoogleUserResponse.java index 5d5388c0..6856a0a9 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/response/GoogleUserResponse.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/GoogleUserResponse.java @@ -20,6 +20,5 @@ public class GoogleUserResponse { public void adaptResponse() { if(email.length() > 50) email = email.substring(0, 50); - if(name.length() > 7) name = name.substring(0, 7); } } diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java index a04370f0..99e0fb2a 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoAccessTokenResponse.java @@ -10,7 +10,6 @@ @Getter @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) public class KakaoAccessTokenResponse { - private String appId; } diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java index cf8d8be3..b2f2c636 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/response/KakaoUserResponse.java @@ -19,23 +19,18 @@ public class KakaoUserResponse { @AllArgsConstructor @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) public static class Properties { - private String nickname; } + @Getter @NoArgsConstructor @AllArgsConstructor public static class KakaoAccount { - private String email; - private String gender; - private String ageRange; } + public void adaptResponse() { - if(kakaoAccount.gender == null || kakaoAccount.gender.isBlank()) kakaoAccount.gender = "undef"; - if(kakaoAccount.ageRange == null || kakaoAccount.ageRange.isBlank()) kakaoAccount.ageRange = "undef"; - if(properties.nickname==null||properties.nickname.isBlank()) properties.nickname="undef"; if(kakaoAccount.email.length() > 50) kakaoAccount.email = kakaoAccount.email.substring(0, 50); - if(properties.nickname.length() > 7) properties.nickname = properties.nickname.substring(0, 7); } + } diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java index f73b36d9..195ce705 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java @@ -32,7 +32,7 @@ public SignInResponse signUp(String token, SignUpRequest signUpRequest) { //2. signUp 처리 String nickName=signUpRequest.getNickName(); if(memberCheckService.checkNickname(nickName)) throw new NicknameDuplicationException(); //닉네임 중복검사 (이중체크) - member.signUp(nickName, signUpRequest.getFcmToken()); + member.signUp(signUpRequest); //3. security 처리 AuthenticationUtil.makeAuthentication(member); //4. token 만들기 diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java index 3b4ccc95..09a7dbea 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java @@ -22,8 +22,6 @@ public class KakaoTokenUserCase { public void verifyAccessToken(String accessToken) { - - KakaoAccessTokenResponse kakaoAccessTokenResponse = webClient.get() .uri("https://kapi.kakao.com/v1/user/access_token_info") .headers(h -> h.setBearerAuth(accessToken)) diff --git a/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java b/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java index e31a33e0..84ceea6e 100644 --- a/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java +++ b/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.auth.application.dto.response.GoogleUserResponse; import com.moing.backend.domain.auth.application.dto.response.KakaoUserResponse; +import com.moing.backend.domain.member.domain.constant.RegistrationStatus; import com.moing.backend.domain.member.domain.constant.Role; import com.moing.backend.domain.member.domain.constant.SocialProvider; import com.moing.backend.domain.member.domain.entity.Member; @@ -15,10 +16,8 @@ public Member createKakaoMember(KakaoUserResponse kakaoUserResponse) { .socialId(SocialProvider.KAKAO + "@" + kakaoUserResponse.getId()) .provider(SocialProvider.KAKAO) .email(kakaoUserResponse.getKakaoAccount().getEmail()) - .nickName(kakaoUserResponse.getProperties().getNickname()) - .gender(kakaoUserResponse.getKakaoAccount().getGender()) - .ageRange(kakaoUserResponse.getKakaoAccount().getAgeRange()) .role(Role.USER) + .registrationStatus(RegistrationStatus.UNCOMPLETED) .build(); return newMember; @@ -30,6 +29,7 @@ public Member createAppleMember(String socialId, String email) { .provider(SocialProvider.APPLE) .email(email) .role(Role.USER) + .registrationStatus(RegistrationStatus.UNCOMPLETED) .build(); return newMember; @@ -41,6 +41,7 @@ public Member createGoogleMember(GoogleUserResponse googleUserResponse){ .provider(SocialProvider.GOOGLE) .email(googleUserResponse.getEmail()) .role(Role.USER) + .registrationStatus(RegistrationStatus.UNCOMPLETED) .build(); return newMember; diff --git a/src/main/java/com/moing/backend/domain/member/domain/constant/Gender.java b/src/main/java/com/moing/backend/domain/member/domain/constant/Gender.java new file mode 100644 index 00000000..e66c7b8f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/domain/constant/Gender.java @@ -0,0 +1,10 @@ +package com.moing.backend.domain.member.domain.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum Gender { + MAN, WOMAN, NEUTRALITY +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index b8990e7c..f9ea472f 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -1,5 +1,7 @@ package com.moing.backend.domain.member.domain.entity; +import com.moing.backend.domain.auth.application.dto.request.SignUpRequest; +import com.moing.backend.domain.member.domain.constant.Gender; import com.moing.backend.domain.member.domain.constant.RegistrationStatus; import com.moing.backend.domain.member.domain.constant.Role; import com.moing.backend.domain.member.domain.constant.SocialProvider; @@ -14,6 +16,8 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import javax.persistence.*; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; @@ -44,39 +48,38 @@ public class Member extends BaseTimeEntity { private String email; @Convert(converter = AesConverter.class) - @Column(nullable = false) private String profileImage; //없으면 undef - @Column(nullable = false, length = 6) - private String gender; //없으면 undef - - @Column(nullable = false, length = 10) - private String ageRange; //없으면 undef + @Column(length = 10) + @Enumerated(EnumType.STRING) + private Gender gender; + private LocalDate birthDate; - // 추가정보 @Convert(converter = AesConverter.class) - @Column(nullable = false) - private String nickName; //없으면 undef + @Column(unique = true) + private String nickName; @Column(nullable = false) @Enumerated(EnumType.STRING) private Role role; @Convert(converter = AesConverter.class) - @Column(nullable = false) - private String introduction; //없으면 undef + private String introduction; @Column(nullable = false) - private String fcmToken; //없으면 undef + private String fcmToken; @ColumnDefault("true") + @Column(nullable = false) private boolean isNewUploadPush; @ColumnDefault("true") + @Column(nullable = false) private boolean isRemindPush; @ColumnDefault("true") + @Column(nullable = false) private boolean isFirePush; @OneToMany(mappedBy = "member") @@ -90,37 +93,25 @@ public static Member valueOf(OAuth2User oAuth2User) { .provider((SocialProvider) attributes.get("provider")) .nickName((String) attributes.get("nickname")) .email((String) attributes.get("email")) - .gender((String) attributes.get("gender")) - .ageRange((String) attributes.get("age")) .role((Role) attributes.get("role")) .registrationStatus(RegistrationStatus.UNCOMPLETED) .build(); } - //==초기화==// - @PrePersist - public void prePersist() { - if (profileImage == null) profileImage = "undef"; - if (gender == null) gender = "undef"; - if (ageRange == null) ageRange = "undef"; - if (nickName == null) nickName = "undef"; - if (introduction == null) introduction = "undef"; - if (fcmToken == null) fcmToken = "undef"; - if (registrationStatus == null) registrationStatus = RegistrationStatus.UNCOMPLETED; - } - - public void signUp(String nickName, String fcmToken) { - this.nickName = nickName; - this.fcmToken = fcmToken; + public void signUp(SignUpRequest signUpRequest) { + this.nickName = signUpRequest.getNickName(); + this.gender = signUpRequest.getGender(); + this.birthDate = LocalDate.parse(signUpRequest.getBirthDate(), DateTimeFormatter.ISO_DATE);; + this.fcmToken = signUpRequest.getFcmToken(); this.registrationStatus = RegistrationStatus.COMPLETED; } @Builder - public Member(String email, String profileImage, String gender, String ageRange, Role role) { + public Member(String email, String profileImage, Gender gender, LocalDate birthDate, Role role) { this.email = email; this.profileImage = profileImage; this.gender = gender; - this.ageRange = ageRange; + this.birthDate = birthDate; this.role = role; } @@ -154,8 +145,8 @@ public void updateAllPush(boolean allPush) { this.isFirePush = allPush; } - public Member(String ageRange, String email, String fcmToken, String gender, String introduction, String nickName, String profileImage, SocialProvider provider, RegistrationStatus registrationStatus, Role role, String socialId) { - this.ageRange = ageRange; + public Member(LocalDate birthDate, String email, String fcmToken, Gender øgender, String introduction, String nickName, String profileImage, SocialProvider provider, RegistrationStatus registrationStatus, Role role, String socialId) { + this.birthDate = birthDate; this.email = email; this.fcmToken = fcmToken; this.gender = gender; From e848ee12ff076c12ca65d6c2a11ecbe1a3d88715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 17 Oct 2023 02:00:28 +0900 Subject: [PATCH 139/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B3=80=EA=B2=BD=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/MissionHeartRes.java | 10 +++++ .../mapper/MissionHeartMapper.java | 24 +++++++++++ .../service/MissionHeartUseCase.java | 41 ++++++++++++++++++ .../domain/constant/MissionHeartStatus.java | 5 +++ .../domain/entity/MissionHeart.java | 34 +++++++++++++++ .../MissionHeartCustomRepository.java | 15 +++++++ .../MissionHeartCustomRepositoryImpl.java | 42 +++++++++++++++++++ .../repository/MissionHeartRepository.java | 7 ++++ .../service/MissionHeartQueryService.java | 24 +++++++++++ .../service/MissionHeartSaveService.java | 21 ++++++++++ .../service/MissionHeartUpdateService.java | 26 ++++++++++++ .../presentation/MissionHeartController.java | 22 ++++++++++ 12 files changed, 271 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/domain/constant/MissionHeartStatus.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartQueryService.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/presentation/MissionHeartController.java diff --git a/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java b/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java new file mode 100644 index 00000000..a6e2f254 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java @@ -0,0 +1,10 @@ +package com.moing.backend.domain.missionHeart.application.dto; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class MissionHeartRes { + private String missionHeartStatus; +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java b/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java new file mode 100644 index 00000000..24464b1b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.missionHeart.application.mapper; + +import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; +import com.moing.backend.domain.missionHeart.domain.constant.MissionHeartStatus; +import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; +import com.moing.backend.global.annotation.Mapper; + +@Mapper +public class MissionHeartMapper { + + public static MissionHeart mapToMissionHeart(Long memberId, Long archiveId, MissionHeartStatus missionHeartStatus) { + return MissionHeart.builder() + .pushMemberId(memberId) + .missionArchiveId(archiveId) + .heartStatus(missionHeartStatus) + .build(); + } + + public static MissionHeartRes mapToMissionHeartRes(MissionHeart missionHeart) { + return MissionHeartRes.builder() + .missionHeartStatus(missionHeart.getHeartStatus().name()) + .build(); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java b/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java new file mode 100644 index 00000000..269969a7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java @@ -0,0 +1,41 @@ +package com.moing.backend.domain.missionHeart.application.service; + +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; +import com.moing.backend.domain.missionHeart.application.mapper.MissionHeartMapper; +import com.moing.backend.domain.missionHeart.domain.constant.MissionHeartStatus; +import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; +import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; +import com.moing.backend.domain.missionHeart.domain.service.MissionHeartSaveService; +import com.moing.backend.domain.missionHeart.domain.service.MissionHeartUpdateService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionHeartUseCase { + + private final MissionHeartSaveService missionHeartSaveService; + private final MissionHeartUpdateService missionHeartUpdateService; + private final MissionHeartQueryService missionHeartQueryService; + private final MemberGetService memberGetService; + + + public MissionHeartRes pushHeart(String socialId,Long archiveId, String status) { + + Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); + MissionHeart missionHeart = MissionHeartMapper.mapToMissionHeart(memberId, archiveId, MissionHeartStatus.valueOf(status)); + + if(missionHeartQueryService.isAlreadyHeart(memberId, archiveId)) { + return MissionHeartMapper.mapToMissionHeartRes( + missionHeartUpdateService.update(missionHeart)); + } + else{ + return MissionHeartMapper.mapToMissionHeartRes( + missionHeartSaveService.save(missionHeart)); + } + + } +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/constant/MissionHeartStatus.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/constant/MissionHeartStatus.java new file mode 100644 index 00000000..aca08956 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/constant/MissionHeartStatus.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.missionHeart.domain.constant; + +public enum MissionHeartStatus { + TRUE,FALSE +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java new file mode 100644 index 00000000..761856e1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java @@ -0,0 +1,34 @@ +package com.moing.backend.domain.missionHeart.domain.entity; + +import com.moing.backend.domain.missionHeart.domain.constant.MissionHeartStatus; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class MissionHeart extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "missionHeart_id") + private Long id; + + private Long pushMemberId; + private Long missionArchiveId; + + private MissionHeartStatus heartStatus; + + public void updateHeartStatus(MissionHeartStatus heartStatus) { + this.heartStatus = heartStatus; + } + + +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepository.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepository.java new file mode 100644 index 00000000..df82bfb1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepository.java @@ -0,0 +1,15 @@ +package com.moing.backend.domain.missionHeart.domain.repository; + +import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface MissionHeartCustomRepository { + + boolean findAlreadyHeart(Long memberId, Long archiveId); + MissionHeart findByMemberIdAndArchiveId(Long memberId, Long archiveId); + + + } diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java new file mode 100644 index 00000000..df6b07e3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java @@ -0,0 +1,42 @@ +package com.moing.backend.domain.missionHeart.domain.repository; + +import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; +import com.moing.backend.domain.missionHeart.domain.entity.QMissionHeart; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.util.Optional; + +import static com.moing.backend.domain.missionHeart.domain.entity.QMissionHeart.missionHeart; + +public class MissionHeartCustomRepositoryImpl implements MissionHeartCustomRepository { + + private final JPAQueryFactory queryFactory; + + public MissionHeartCustomRepositoryImpl(EntityManager entityManager) { + this.queryFactory = new JPAQueryFactory(entityManager); + } + + public boolean findAlreadyHeart(Long memberId, Long archiveId) { + + return queryFactory + .selectFrom(missionHeart) + .where( + missionHeart.pushMemberId.eq(memberId), + missionHeart.missionArchiveId.eq(archiveId) + ).fetchCount() > 0; + + } + public MissionHeart findByMemberIdAndArchiveId(Long memberId, Long archiveId) { + + return queryFactory + .selectFrom(missionHeart) + .where( + missionHeart.pushMemberId.eq(memberId), + missionHeart.missionArchiveId.eq(archiveId) + ).fetchFirst(); + + } + + +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartRepository.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartRepository.java new file mode 100644 index 00000000..b79e5f97 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.missionHeart.domain.repository; + +import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MissionHeartRepository extends JpaRepository,MissionHeartCustomRepository { +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartQueryService.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartQueryService.java new file mode 100644 index 00000000..8ab7dcac --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartQueryService.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.missionHeart.domain.service; + +import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; +import com.moing.backend.domain.missionHeart.domain.repository.MissionHeartRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionHeartQueryService { + + private final MissionHeartRepository missionHeartRepository; + + public boolean isAlreadyHeart(Long memberId, Long archiveId) { + return missionHeartRepository.findAlreadyHeart(memberId, archiveId); + } + public MissionHeart findMissionHeartById(Long memberId, Long archiveId) { + return missionHeartRepository.findByMemberIdAndArchiveId(memberId, archiveId); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartSaveService.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartSaveService.java new file mode 100644 index 00000000..e8ab13fc --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartSaveService.java @@ -0,0 +1,21 @@ +package com.moing.backend.domain.missionHeart.domain.service; + +import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; +import com.moing.backend.domain.missionHeart.domain.repository.MissionHeartCustomRepository; +import com.moing.backend.domain.missionHeart.domain.repository.MissionHeartRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionHeartSaveService { + + private final MissionHeartRepository missionHeartRepository; + + public MissionHeart save(MissionHeart missionHeart) { + return missionHeartRepository.save(missionHeart); + } + +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java new file mode 100644 index 00000000..cc38f8cb --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java @@ -0,0 +1,26 @@ +package com.moing.backend.domain.missionHeart.domain.service; + +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; +import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; +import com.moing.backend.domain.missionHeart.domain.repository.MissionHeartRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionHeartUpdateService { + + private final MissionHeartRepository missionHeartRepository; + + public MissionHeart update(MissionHeart missionHeart) { + + MissionHeart updateHeart = missionHeartRepository.findByMemberIdAndArchiveId(missionHeart.getPushMemberId(), missionHeart.getMissionArchiveId()); + updateHeart.updateHeartStatus(missionHeart.getHeartStatus()); + return updateHeart; + + } + +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/presentation/MissionHeartController.java b/src/main/java/com/moing/backend/domain/missionHeart/presentation/MissionHeartController.java new file mode 100644 index 00000000..56928376 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/presentation/MissionHeartController.java @@ -0,0 +1,22 @@ +package com.moing.backend.domain.missionHeart.presentation; + +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; +import com.moing.backend.domain.missionHeart.application.service.MissionHeartUseCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.CREATE_ARCHIVE_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/{teamId}/missions/{missionId}/archive/{archiveId}/heart") +public class MissionHeartController { + + +} From 921bef9fdede50ecbec9e3d0e997da63822d5977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 17 Oct 2023 02:00:58 +0900 Subject: [PATCH 140/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=EB=A6=AC=ED=84=B4=20=EA=B0=9D=EC=B2=B4=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD(=EC=A7=84?= =?UTF-8?q?=ED=96=89=EC=A4=91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/MissionArchiveRes.java | 1 + .../dto/res/PersonalArchiveRes.java | 1 + .../mapper/MissionArchiveMapper.java | 3 --- .../service/MissionArchiveCreateUseCase.java | 1 - .../domain/entity/MissionArchive.java | 10 +------- .../MissionArchiveController.java | 23 +++++++++++-------- .../MissionArchiveControllerTest.java | 6 ++--- 7 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index d025cb70..1d5a198e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -17,6 +17,7 @@ public class MissionArchiveRes { private int hearts; private String status; private Long count; + private String heartStatus; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java index 82d8146d..cdd4a2d3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java @@ -16,6 +16,7 @@ public class PersonalArchiveRes { private String archive; private String createdDate; + private String heartStatus; private int hearts; private String status; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index eafa243c..8dd786bb 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -33,7 +33,6 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc .archiveId(missionArchive.getId()) .archive(missionArchive.getArchive()) .createdDate(missionArchive.getCreatedDate().toString()) - .hearts(missionArchive.getHearts()) .status(missionArchive.getStatus().name()) .count(missionArchive.getCount()) .build(); @@ -56,7 +55,6 @@ public static PersonalArchiveRes mapToPersonalArchive(MissionArchive missionArch .profileImg(member.getProfileImage()) .archive(missionArchive.getArchive()) .createdDate(missionArchive.getCreatedDate().toString()) - .hearts(missionArchive.getHearts()) .status(missionArchive.getStatus().name()) .count(missionArchive.getCount()) .build(); @@ -96,7 +94,6 @@ public static List mapToSingleMissionBoardResList( List>> getOtherPeopleA return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(user.getSocialId(),missionId))); } + /** - * 미션 인증 게시물 좋아요 - * [GET] {teamId}/m원issions/{missionId}/archive/hearts + * 미션 인증 좋아요 누르기 + * [POST] {teamId}/missions/{missionId}/archive * 작성자 : 정승연 **/ - @PostMapping("/hearts") - public ResponseEntity> pushHeart(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId, - @RequestBody MissionArchiveHeartReq missionArchiveHeartReq) { - return ResponseEntity.ok(SuccessResponse.create(HEART_UPDATE_SUCCESS.getMessage(), this.missionArchiveHeartUseCase.pushHeart(missionArchiveHeartReq))); + @PutMapping("{archiveId}/heart/{missionHeartStatus}") + public ResponseEntity> pushHeart(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId, + @PathVariable("archiveId") Long archiveId, + @PathVariable("missionHeartStatus") String missionHeartStatus) { + return ResponseEntity.ok(SuccessResponse.create(CREATE_ARCHIVE_SUCCESS.getMessage(), this.missionHeartUseCase.pushHeart(user.getSocialId(),archiveId,missionHeartStatus))); } /** diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 7cb3d752..32848ea3 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -98,10 +98,10 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.archiveId").description("미션 인증 아이디"), fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data.createdDate").description("미션 제출 시각"), - fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), fieldWithPath("data.status").description("미션 인증 상태"), - fieldWithPath("data.count").description("미션 인증 횟수") -// fieldWithPath("data.heartsStatus").description("미션 인증 좋아요 상태"), + fieldWithPath("data.count").description("미션 인증 횟수"), + fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), + fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태") ) ) ) From 8604e9d7cbca8dd6830f1aec9b054fbd8dd7a7f0 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 17 Oct 2023 22:34:05 +0900 Subject: [PATCH 141/619] =?UTF-8?q?fix:=20Convert=20null=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Auth-API.adoc | 7 ++++++- .../backend/domain/member/domain/entity/Member.java | 7 ++----- .../java/com/moing/backend/global/util/AesConverter.java | 6 ++++++ .../com/moing/backend/global/util/StartupRunner.java | 9 ++++++--- .../domain/auth/presentation/AuthControllerTest.java | 5 +++++ 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/docs/asciidoc/Auth-API.adoc b/src/docs/asciidoc/Auth-API.adoc index 900e3d54..2a9412a4 100644 --- a/src/docs/asciidoc/Auth-API.adoc +++ b/src/docs/asciidoc/Auth-API.adoc @@ -26,7 +26,12 @@ operation::auth-controller-test/google_소셜_로그인_회원가입_후[snippet [[Auth-회원가입]] === Auth 회원가입 operation::auth-controller-test/sign_up[snippets='http-request,request-fields,http-response,response-fields'] - +|=== +| 성별 | +| `MAN` +| `WOMAN` +| `NEUTRALITY` +|=== [[Auth-토큰-재발급]] === Auth 토큰 재발급 diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index f9ea472f..ad9370f8 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -47,7 +47,6 @@ public class Member extends BaseTimeEntity { @Column(nullable = false, unique = true) private String email; - @Convert(converter = AesConverter.class) private String profileImage; //없으면 undef @Column(length = 10) @@ -57,17 +56,15 @@ public class Member extends BaseTimeEntity { private LocalDate birthDate; @Convert(converter = AesConverter.class) - @Column(unique = true) + @Column(unique=true) private String nickName; @Column(nullable = false) @Enumerated(EnumType.STRING) private Role role; - @Convert(converter = AesConverter.class) private String introduction; - @Column(nullable = false) private String fcmToken; @ColumnDefault("true") @@ -145,7 +142,7 @@ public void updateAllPush(boolean allPush) { this.isFirePush = allPush; } - public Member(LocalDate birthDate, String email, String fcmToken, Gender øgender, String introduction, String nickName, String profileImage, SocialProvider provider, RegistrationStatus registrationStatus, Role role, String socialId) { + public Member(LocalDate birthDate, String email, String fcmToken, Gender gender, String introduction, String nickName, String profileImage, SocialProvider provider, RegistrationStatus registrationStatus, Role role, String socialId) { this.birthDate = birthDate; this.email = email; this.fcmToken = fcmToken; diff --git a/src/main/java/com/moing/backend/global/util/AesConverter.java b/src/main/java/com/moing/backend/global/util/AesConverter.java index 5da9aa0c..fc7da8b7 100644 --- a/src/main/java/com/moing/backend/global/util/AesConverter.java +++ b/src/main/java/com/moing/backend/global/util/AesConverter.java @@ -13,6 +13,9 @@ public AesConverter(AesUtil aesUtil) { @Override public String convertToDatabaseColumn(String attribute) { + if (attribute == null) { + return null; // attribute가 null인 경우 null 반환 + } try { return aesUtil.encrypt(attribute); } catch (Exception e) { @@ -22,6 +25,9 @@ public String convertToDatabaseColumn(String attribute) { @Override public String convertToEntityAttribute(String dbData) { + if (dbData == null) { + return null; // dbData가 null인 경우 null 반환 + } try { return aesUtil.decrypt(dbData); } catch (Exception e) { diff --git a/src/main/java/com/moing/backend/global/util/StartupRunner.java b/src/main/java/com/moing/backend/global/util/StartupRunner.java index a04f7fca..de40dc56 100644 --- a/src/main/java/com/moing/backend/global/util/StartupRunner.java +++ b/src/main/java/com/moing/backend/global/util/StartupRunner.java @@ -1,5 +1,6 @@ package com.moing.backend.global.util; +import com.moing.backend.domain.member.domain.constant.Gender; import com.moing.backend.domain.member.domain.constant.RegistrationStatus; import com.moing.backend.domain.member.domain.constant.Role; import com.moing.backend.domain.member.domain.constant.SocialProvider; @@ -10,6 +11,8 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; +import java.time.LocalDate; + @Component @RequiredArgsConstructor public class StartupRunner implements CommandLineRunner { @@ -21,13 +24,13 @@ public class StartupRunner implements CommandLineRunner { private final MemberSaveService memberSaveService; @Override public void run(String... args) throws Exception { - Member test01 = new Member("undef", "tester1@test.com", "undef", "undef", "undef", "modagbul_tester1", "undef", SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester01"); + Member test01 = new Member(LocalDate.now(), "tester1@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester1", "undef", SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester01"); memberSaveService.saveMember(test01); - Member test02=new Member("undef", "tester2@test.com", "undef", "undef", "undef", "modagbul_tester2", "undef", SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester02"); + Member test02=new Member(LocalDate.now(), "tester2@test.com", "undef", Gender.MAN, "undef", "modagbul_tester2", "undef", SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester02"); memberSaveService.saveMember(test02); - Member test03=new Member("undef", "tester3@test.com", "undef", "undef", "undef", "modagbul_tester3", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester03"); + Member test03=new Member(LocalDate.now(), "tester3@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester3", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester03"); memberSaveService.saveMember(test03); } } diff --git a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java index 03d1eaa2..38eec2b7 100644 --- a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java +++ b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java @@ -10,6 +10,7 @@ import com.moing.backend.domain.auth.application.service.ReissueTokenUserCase; import com.moing.backend.domain.auth.application.service.SignInUserCase; import com.moing.backend.domain.auth.application.service.SignUpUserCase; +import com.moing.backend.domain.member.domain.constant.Gender; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -307,6 +308,8 @@ public void sign_up() throws Exception { //given SignUpRequest input = SignUpRequest.builder() .nickName("NICKNAME") + .gender(Gender.MAN) + .birthDate("2000-03-28") .fcmToken("FCMTOKEN") .build(); @@ -340,6 +343,8 @@ public void sign_up() throws Exception { ), requestFields( fieldWithPath("nickName").description("유저 닉네임"), + fieldWithPath("gender").description("성별"), + fieldWithPath("birthDate").description("태어난 날짜(YYYY-MM-DD)"), fieldWithPath("fcmToken").description("FCM TOKEN") ), responseFields( From 39c17272eff3429fe13c4ae6f4b21078f1bc24ae Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 17 Oct 2023 22:56:24 +0900 Subject: [PATCH 142/619] =?UTF-8?q?hotfix:=20fcmConfig=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moing/backend/global/config/fcm/FcmConfig.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/global/config/fcm/FcmConfig.java b/src/main/java/com/moing/backend/global/config/fcm/FcmConfig.java index 711c4290..cf375005 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/FcmConfig.java +++ b/src/main/java/com/moing/backend/global/config/fcm/FcmConfig.java @@ -10,16 +10,17 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; @Configuration @Slf4j public class FcmConfig { - @Value("${firebase.config.path}") private String firebaseConfigPath; @@ -29,7 +30,9 @@ public class FcmConfig { @Bean public FirebaseApp firebaseApp() { try { - FileInputStream serviceAccount = new FileInputStream(firebaseConfigPath); + // FileInputStream 대신 ClassPathResource를 사용하여 파일 로드 + ClassPathResource resource = new ClassPathResource(firebaseConfigPath); + InputStream serviceAccount = resource.getInputStream(); FirebaseOptions options = FirebaseOptions.builder() .setCredentials(GoogleCredentials.fromStream(serviceAccount)) From 26e735d29fc38488bebaba06267b27dd5c129ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 19 Oct 2023 03:52:04 +0900 Subject: [PATCH 143/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=EB=AC=BC=20=EC=A2=8B=EC=95=84=EC=9A=94=20#23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/MissionArchiveRes.java | 11 ++++- .../mapper/MissionArchiveMapper.java | 26 ++++++++--- .../service/MissionArchiveCreateUseCase.java | 7 ++- .../service/MissionArchiveHeartUseCase.java | 44 ------------------- ...se.java => MissionArchiveReadUseCase.java} | 12 +++-- .../service/MissionArchiveUpdateUseCase.java | 15 +++++-- .../domain/entity/MissionArchive.java | 7 +++ .../MissionArchiveCustomRepository.java | 2 + .../MissionArchiveCustomRepositoryImpl.java | 42 ++++++++---------- .../MissionArchiveController.java | 10 ++--- .../application/dto/MissionHeartRes.java | 2 + .../mapper/MissionHeartMapper.java | 7 ++- .../service/MissionHeartUseCase.java | 6 ++- .../domain/constant/MissionHeartStatus.java | 2 +- .../domain/entity/MissionHeart.java | 11 ++++- .../MissionHeartCustomRepositoryImpl.java | 4 +- .../service/MissionHeartUpdateService.java | 3 +- .../MissionArchiveControllerTest.java | 21 ++++----- 18 files changed, 121 insertions(+), 111 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveHeartUseCase.java rename src/main/java/com/moing/backend/domain/missionArchive/application/service/{SingleMissionArchiveReadUseCase.java => MissionArchiveReadUseCase.java} (85%) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index 1d5a198e..fb041759 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -4,6 +4,7 @@ import lombok.Getter; import lombok.Setter; +import javax.annotation.Nullable; import java.util.List; @Builder @@ -14,10 +15,18 @@ public class MissionArchiveRes { private Long archiveId; private String archive; private String createdDate; - private int hearts; private String status; private Long count; private String heartStatus; + private Long hearts; + + public void updateHeartStatus(boolean status) { + if (status) { + this.heartStatus = "True"; + }else{ + this.heartStatus = "False"; + } + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 8dd786bb..bf857493 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -11,6 +11,7 @@ import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.moing.backend.domain.missionHeart.domain.constant.MissionHeartStatus; import com.moing.backend.global.annotation.Mapper; import java.util.ArrayList; @@ -25,29 +26,38 @@ public static MissionArchive mapToMissionArchive(MissionArchiveReq missionArchiv .status(MissionArchiveStatus.valueOf(missionArchiveReq.getStatus())) .member(member) .mission(mission) + .heartList(new ArrayList<>()) .build(); } - public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArchive) { + public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArchive,Long memberId) { return MissionArchiveRes.builder() .archiveId(missionArchive.getId()) .archive(missionArchive.getArchive()) .createdDate(missionArchive.getCreatedDate().toString()) .status(missionArchive.getStatus().name()) .count(missionArchive.getCount()) + .heartStatus( + String.valueOf(missionArchive.getHeartList().stream().anyMatch( + missionHeart -> missionHeart.getPushMemberId().equals(memberId) && + missionHeart.getHeartStatus().equals(MissionHeartStatus.True) + ))) + .hearts(missionArchive.getHeartList().stream().filter( + missionHeart -> missionHeart.getHeartStatus().equals(MissionHeartStatus.True) + ).count()) .build(); } - public static List mapToMissionArchiveResList(List missionArchiveList) { + public static List mapToMissionArchiveResList(List missionArchiveList,Long memberId) { List missionArchiveResList = new ArrayList<>(); missionArchiveList.forEach( - missionArchive -> missionArchiveResList.add(MissionArchiveMapper.mapToMissionArchiveRes(missionArchive)) + missionArchive -> missionArchiveResList.add(MissionArchiveMapper.mapToMissionArchiveRes(missionArchive,memberId)) ); return missionArchiveResList; } - public static PersonalArchiveRes mapToPersonalArchive(MissionArchive missionArchive) { + public static PersonalArchiveRes mapToPersonalArchive(MissionArchive missionArchive,Long memberId) { Member member = missionArchive.getMember(); return PersonalArchiveRes.builder() .archiveId(missionArchive.getId()) @@ -57,13 +67,17 @@ public static PersonalArchiveRes mapToPersonalArchive(MissionArchive missionArch .createdDate(missionArchive.getCreatedDate().toString()) .status(missionArchive.getStatus().name()) .count(missionArchive.getCount()) + .heartStatus( + String.valueOf(missionArchive.getHeartList().stream().anyMatch( + missionHeart -> missionHeart.getPushMemberId().equals(memberId)))) + .hearts(missionArchive.getHeartList().size()) .build(); } - public static List mapToPersonalArchiveList(List missionArchiveList) { + public static List mapToPersonalArchiveList(List missionArchiveList,Long memberId) { List personalArchiveList = new ArrayList<>(); missionArchiveList.forEach( - missionArchive -> personalArchiveList.add(MissionArchiveMapper.mapToPersonalArchive(missionArchive)) + missionArchive -> personalArchiveList.add(MissionArchiveMapper.mapToPersonalArchive(missionArchive,memberId)) ); return personalArchiveList; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 3a5575c3..d42a98c2 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -14,6 +14,7 @@ import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; +import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -27,6 +28,7 @@ public class MissionArchiveCreateUseCase { private final MissionArchiveSaveService missionArchiveSaveService; private final MissionArchiveQueryService missionArchiveQueryService; private final MissionArchiveDeleteService missionArchiveDeleteService; + private final MissionHeartQueryService missionHeartQueryService; private final MissionQueryService missionQueryService; @@ -49,14 +51,15 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss throw new NoMoreMissionArchiveException(); } + // archive 회차 if (mission.getType().equals(MissionType.ONCE)) { - // missionArchive 2개 이상일 때 예외처리 newArchive.updateCount(1L); } else { newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); } - return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive)); + + return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive),memberId); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveHeartUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveHeartUseCase.java deleted file mode 100644 index 0cca0fd8..00000000 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveHeartUseCase.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.moing.backend.domain.missionArchive.application.service; - -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveHeartReq; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; -import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; -import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; -import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@Transactional -@RequiredArgsConstructor -public class MissionArchiveHeartUseCase { - - - private final MissionArchiveSaveService missionArchiveSaveService; - private final MissionArchiveQueryService missionArchiveQueryService; - private final MissionArchiveDeleteService missionArchiveDeleteService; - - private final MissionQueryService missionQueryService; - - private final MemberGetService memberGetService; - - private final MissionArchiveScoreService missionArchiveScoreService; - - public MissionArchiveHeartRes pushHeart(MissionArchiveHeartReq missionArchiveHeartReq) { - - MissionArchive missionArchive = missionArchiveQueryService.findByMissionArchiveId(missionArchiveHeartReq.getArchiveId()); - - Boolean heartStatus = Boolean.valueOf(missionArchiveHeartReq.getHeartStatus()); - missionArchive.updateHearts(heartStatus); - return MissionArchiveMapper.mapToMissionArchiveHeartRes(missionArchive, heartStatus); - - } - -} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java similarity index 85% rename from src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java rename to src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java index 95e15e1b..ceac49f3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SingleMissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java @@ -21,7 +21,7 @@ @Service @Transactional @RequiredArgsConstructor -public class SingleMissionArchiveReadUseCase { +public class MissionArchiveReadUseCase { //미션 아치브 읽어오기 private final MemberGetService memberGetService; @@ -33,9 +33,9 @@ public class SingleMissionArchiveReadUseCase { // 미션 인증 조회 public List getMyArchive(String userSocialId, Long missionId) { - Member member = memberGetService.getMemberBySocialId(userSocialId); + Long memberId = memberGetService.getMemberBySocialId(userSocialId).getMemberId(); - return MissionArchiveMapper.mapToMissionArchiveResList(missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId)); + return MissionArchiveMapper.mapToMissionArchiveResList(missionArchiveQueryService.findMyArchive(memberId, missionId),memberId); } // 모두의 미션 인증 목록 조회 @@ -43,10 +43,8 @@ public List getPersonalArchive(String userSocialId, Long mis List personalArchives = new ArrayList<>(); - Member member = memberGetService.getMemberBySocialId(userSocialId); - return MissionArchiveMapper.mapToPersonalArchiveList(missionArchiveQueryService.findOthersArchive(member.getMemberId(), missionId)); - -// return personalArchives; + Long memberId = memberGetService.getMemberBySocialId(userSocialId).getMemberId(); + return MissionArchiveMapper.mapToPersonalArchiveList(missionArchiveQueryService.findOthersArchive(memberId, missionId),memberId); } public MissionArchiveStatusRes getMissionDoneStatus(Long missionId) { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index 8c670092..4e7b956a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -15,6 +15,8 @@ import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; +import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; +import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -30,6 +32,7 @@ public class MissionArchiveUpdateUseCase { private final MissionArchiveSaveService missionArchiveSaveService; private final MissionArchiveQueryService missionArchiveQueryService; private final MissionArchiveDeleteService missionArchiveDeleteService; + private final MissionHeartQueryService missionHeartQueryService; private final MissionQueryService missionQueryService; @@ -42,16 +45,18 @@ public class MissionArchiveUpdateUseCase { public MissionArchiveRes updateArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); + Long memberId = member.getMemberId(); + Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); // 사진 제출 했다면, - if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(member.getMemberId(), missionId)) { + if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(memberId, missionId)) { //s3삭제 } - MissionArchive updateArchive = missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId).get(0); + MissionArchive updateArchive = missionArchiveQueryService.findMyArchive(memberId, missionId).get(0); if (mission.getType().equals(MissionType.ONCE)) { // missionArchive 2개 이상일 때 예외처리 필요 @@ -61,11 +66,13 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss updateArchive.updateCount(1L); } else{ - updateArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(member.getMemberId(), missionId)+1); + updateArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); } updateArchive.updateArchive(missionReq); - return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(updateArchive)); + + return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(updateArchive),memberId); + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index 99c7b563..eece71b9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; import lombok.Builder; @@ -12,6 +13,8 @@ import lombok.NoArgsConstructor; import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; @Entity @Builder @@ -41,6 +44,9 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 private Long count; // 횟수 + @OneToMany(mappedBy = "missionArchive") + private List heartList = new ArrayList<>(); + public void updateArchive(MissionArchiveReq missionArchiveReq) { this.archive = missionArchiveReq.getArchive(); @@ -52,4 +58,5 @@ public void updateCount(Long count) { } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 9ddb0af8..d0108511 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -12,6 +12,8 @@ @Repository public interface MissionArchiveCustomRepository { Optional> findSingleMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status, MissionArchiveStatus archiveStatus, OrderCondition orderCondition); + Optional> findMyArchives(Long memberId,Long missionId); + Optional> findOthersArchives(Long memberId, Long missionId) ; Optional> findAllMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus missionStatus); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 95a8dedd..53f21493 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.querydsl.core.types.Expression; @@ -12,6 +13,8 @@ import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.impl.JPAQueryFactory; +import feign.Param; +import org.springframework.data.jpa.repository.Query; import javax.persistence.EntityManager; import java.util.ArrayList; @@ -20,6 +23,7 @@ import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; +import static com.moing.backend.domain.missionHeart.domain.entity.QMissionHeart.missionHeart; import static javax.swing.Spring.constant; public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { @@ -61,9 +65,21 @@ private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { return orderSpecifiers.toArray(new OrderSpecifier[orderSpecifiers.size()]); } + @Override + public Optional> findMyArchives(Long memberId,Long missionId) { -// @Query("select m from MissionArchive as m where m.mission.id = :missionId and m.member.memberId =:memberId") -// Optional> findArchivesByMissionIdAndMemberId(@Param("memberId") Long memberId, @Param("missionId")Long missionId); + return Optional.ofNullable(queryFactory + .select(missionArchive) + .from(missionArchive) + .where( + missionArchive.mission.id.eq(missionId), + missionArchive.member.memberId.eq(memberId) + ) + .orderBy(missionArchive.createdDate.desc()) + .fetch() + + ); + } @Override public Optional> findOthersArchives(Long memberId, Long missionId) { @@ -76,6 +92,7 @@ public Optional> findOthersArchives(Long memberId, Long mis missionArchive.member.memberId.ne(memberId), missionArchive.status.eq(MissionArchiveStatus.COMPLETE).or(missionArchive.status.eq(MissionArchiveStatus.SKIP)) ) + .orderBy(missionArchive.createdDate.desc()) .fetch() ); } @@ -121,27 +138,6 @@ public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) } -// @Override -// public Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status) { -// return Optional.ofNullable(queryFactory -// .select(Projections.constructor(RepeatMissionBoardRes.class, -// missionArchive.mission.id, -// missionArchive.mission.title, -// missionArchive.count, -// missionArchive.mission.number -// )) -// .from(missionArchive) -// .where( -// missionArchive.mission.team.teamId.eq(teamId), -// missionArchive.mission.type.eq(MissionType.REPEAT), -// missionArchive.member.memberId.eq(memberId), -// missionArchive.mission.status.eq(status) -// ) -// .groupBy(missionArchive.mission.id) -// .fetch()); -// -// -// } @Override public Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status) { return Optional.ofNullable(queryFactory diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 1ae99750..31256897 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -1,9 +1,7 @@ package com.moing.backend.domain.missionArchive.presentation; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; -import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveHeartReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.service.*; @@ -28,7 +26,7 @@ public class MissionArchiveController { private final MissionArchiveCreateUseCase missionArchiveCreateUseCase; private final MissionArchiveUpdateUseCase missionArchiveUpdateUseCase; - private final SingleMissionArchiveReadUseCase singleMissionArchiveReadUseCase; + private final MissionArchiveReadUseCase missionArchiveReadUseCase; private final RepeatMissionArchiveReadUseCase repeatMissionArchiveReadUseCase; private final MissionHeartUseCase missionHeartUseCase; @@ -71,7 +69,7 @@ public ResponseEntity> updateArchive(@Authent public ResponseEntity>> getMyArchive(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(READ_MY_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getMyArchive(user.getSocialId(), missionId))); + return ResponseEntity.ok(SuccessResponse.create(READ_MY_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getMyArchive(user.getSocialId(), missionId))); } /** @@ -83,7 +81,7 @@ public ResponseEntity>> getMyArchive(@Au public ResponseEntity>> getOtherPeopleArchives(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getPersonalArchive(user.getSocialId(),missionId))); + return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getPersonalArchive(user.getSocialId(),missionId))); } @@ -112,7 +110,7 @@ public ResponseEntity> pushHeart(@Authenticatio public ResponseEntity> getMissionDoneStatus(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage(), this.singleMissionArchiveReadUseCase.getMissionDoneStatus(missionId))); + return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getMissionDoneStatus(missionId))); } diff --git a/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java b/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java index a6e2f254..ee0634a9 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java @@ -6,5 +6,7 @@ @Getter @Builder public class MissionHeartRes { + private Long missionArchiveId; private String missionHeartStatus; + private int hearts; } diff --git a/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java b/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java index 24464b1b..7a049638 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionHeart.application.mapper; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; import com.moing.backend.domain.missionHeart.domain.constant.MissionHeartStatus; import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; @@ -8,17 +9,19 @@ @Mapper public class MissionHeartMapper { - public static MissionHeart mapToMissionHeart(Long memberId, Long archiveId, MissionHeartStatus missionHeartStatus) { + public static MissionHeart mapToMissionHeart(Long memberId, MissionArchive archiveId, MissionHeartStatus missionHeartStatus) { return MissionHeart.builder() .pushMemberId(memberId) - .missionArchiveId(archiveId) + .missionArchive(archiveId) .heartStatus(missionHeartStatus) .build(); } public static MissionHeartRes mapToMissionHeartRes(MissionHeart missionHeart) { return MissionHeartRes.builder() + .missionArchiveId(missionHeart.getMissionArchive().getId()) .missionHeartStatus(missionHeart.getHeartStatus().name()) + .hearts(missionHeart.getMissionArchive().getHeartList().size()) .build(); } } diff --git a/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java b/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java index 269969a7..86304259 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java @@ -1,6 +1,8 @@ package com.moing.backend.domain.missionHeart.application.service; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; import com.moing.backend.domain.missionHeart.application.mapper.MissionHeartMapper; import com.moing.backend.domain.missionHeart.domain.constant.MissionHeartStatus; @@ -21,12 +23,14 @@ public class MissionHeartUseCase { private final MissionHeartUpdateService missionHeartUpdateService; private final MissionHeartQueryService missionHeartQueryService; private final MemberGetService memberGetService; + private final MissionArchiveQueryService missionArchiveQueryService; public MissionHeartRes pushHeart(String socialId,Long archiveId, String status) { Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); - MissionHeart missionHeart = MissionHeartMapper.mapToMissionHeart(memberId, archiveId, MissionHeartStatus.valueOf(status)); + MissionArchive archive = missionArchiveQueryService.findByMissionArchiveId(archiveId); + MissionHeart missionHeart = MissionHeartMapper.mapToMissionHeart(memberId, archive, MissionHeartStatus.valueOf(status)); if(missionHeartQueryService.isAlreadyHeart(memberId, archiveId)) { return MissionHeartMapper.mapToMissionHeartRes( diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/constant/MissionHeartStatus.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/constant/MissionHeartStatus.java index aca08956..b9501375 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/domain/constant/MissionHeartStatus.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/constant/MissionHeartStatus.java @@ -1,5 +1,5 @@ package com.moing.backend.domain.missionHeart.domain.constant; public enum MissionHeartStatus { - TRUE,FALSE + True,False } diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java index 761856e1..c0290eec 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionHeart.domain.entity; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionHeart.domain.constant.MissionHeartStatus; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; @@ -22,7 +23,10 @@ public class MissionHeart extends BaseTimeEntity { private Long id; private Long pushMemberId; - private Long missionArchiveId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "missionArchiveId") + private MissionArchive missionArchive; private MissionHeartStatus heartStatus; @@ -30,5 +34,10 @@ public void updateHeartStatus(MissionHeartStatus heartStatus) { this.heartStatus = heartStatus; } + public void changeByHeart(MissionArchive missionArchive) { + this.missionArchive = missionArchive; + missionArchive.getHeartList().add(this); + } + } diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java index df6b07e3..092f6ece 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java @@ -23,7 +23,7 @@ public boolean findAlreadyHeart(Long memberId, Long archiveId) { .selectFrom(missionHeart) .where( missionHeart.pushMemberId.eq(memberId), - missionHeart.missionArchiveId.eq(archiveId) + missionHeart.missionArchive.id.eq(archiveId) ).fetchCount() > 0; } @@ -33,7 +33,7 @@ public MissionHeart findByMemberIdAndArchiveId(Long memberId, Long archiveId) { .selectFrom(missionHeart) .where( missionHeart.pushMemberId.eq(memberId), - missionHeart.missionArchiveId.eq(archiveId) + missionHeart.missionArchive.id.eq(archiveId) ).fetchFirst(); } diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java index cc38f8cb..7acaee62 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java @@ -17,8 +17,9 @@ public class MissionHeartUpdateService { public MissionHeart update(MissionHeart missionHeart) { - MissionHeart updateHeart = missionHeartRepository.findByMemberIdAndArchiveId(missionHeart.getPushMemberId(), missionHeart.getMissionArchiveId()); + MissionHeart updateHeart = missionHeartRepository.findByMemberIdAndArchiveId(missionHeart.getPushMemberId(), missionHeart.getMissionArchive().getId()); updateHeart.updateHeartStatus(missionHeart.getHeartStatus()); + updateHeart.changeByHeart(missionHeart.getMissionArchive()); return updateHeart; } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 32848ea3..ae58b41c 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -3,12 +3,13 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveHeartReq; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveHeartRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.service.*; import com.moing.backend.domain.missionArchive.presentation.MissionArchiveController; +import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; +import com.moing.backend.domain.missionHeart.application.service.MissionHeartUseCase; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -37,11 +38,11 @@ public class MissionArchiveControllerTest extends CommonControllerTest { @MockBean private MissionArchiveUpdateUseCase missionArchiveUpdateUseCase; @MockBean - private SingleMissionArchiveReadUseCase singleMissionArchiveReadUseCase; + private MissionArchiveReadUseCase missionArchiveReadUseCase; @MockBean private RepeatMissionArchiveReadUseCase repeatMissionArchiveReadUseCase; @MockBean - private MissionArchiveHeartUseCase missionArchiveHeartUseCase; + private MissionHeartUseCase missionHeartUseCase; @@ -186,7 +187,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .count(1L) .build()); - given(singleMissionArchiveReadUseCase.getMyArchive(any(),any())).willReturn(output); + given(missionArchiveReadUseCase.getMyArchive(any(),any())).willReturn(output); Long teamId = 1L; Long missionId = 1L; @@ -242,7 +243,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .count(1L) .build()); - given(singleMissionArchiveReadUseCase.getPersonalArchive(any(),any())).willReturn(output); + given(missionArchiveReadUseCase.getPersonalArchive(any(),any())).willReturn(output); Long teamId = 1L; Long missionId = 1L; @@ -294,7 +295,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .done("3") .build(); - given(singleMissionArchiveReadUseCase.getMissionDoneStatus(any())).willReturn(output); + given(missionArchiveReadUseCase.getMissionDoneStatus(any())).willReturn(output); Long teamId = 1L; Long missionId = 1L; @@ -340,13 +341,13 @@ public class MissionArchiveControllerTest extends CommonControllerTest { String body = objectMapper.writeValueAsString(input); - MissionArchiveHeartRes output = MissionArchiveHeartRes.builder() - .archiveId(1L) - .heartStatus("content[s3 Link / text / link]") + MissionHeartRes output = MissionHeartRes.builder() + .missionArchiveId(1L) + .missionHeartStatus("content[s3 Link / text / link]") .hearts(3) .build(); - given(missionArchiveHeartUseCase.pushHeart(any())).willReturn(output); + given(missionHeartUseCase.pushHeart(any(),any(),any())).willReturn(output); Long teamId = 1L; Long missionId = 1L; From e18149eafef8438cf530f3572e2352cb9b1e8477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 19 Oct 2023 15:04:09 +0900 Subject: [PATCH 144/619] =?UTF-8?q?fix=20:=20url=20/api/{teamId}=20->=20/a?= =?UTF-8?q?pi/team/{teamId}=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/MissionController.java | 2 +- .../MissionArchiveController.java | 2 +- .../presentation/MissionBoardController.java | 3 +- .../MissionTotalBoardController.java | 64 +++++++++++++++++++ .../presentation/MissionHeartController.java | 22 ------- 5 files changed, 68 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionTotalBoardController.java delete mode 100644 src/main/java/com/moing/backend/domain/missionHeart/presentation/MissionHeartController.java diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 1aa19a20..f2a33bd5 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -21,7 +21,7 @@ @RestController @AllArgsConstructor -@RequestMapping("/api/{teamId}/missions") +@RequestMapping("/api/team/{teamId}/missions") public class MissionController { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 31256897..1d6892d7 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -21,7 +21,7 @@ @RestController @AllArgsConstructor -@RequestMapping("/api/{teamId}/missions/{missionId}/archive") +@RequestMapping("/api/team/{teamId}/missions/{missionId}/archive") public class MissionArchiveController { private final MissionArchiveCreateUseCase missionArchiveCreateUseCase; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java index b48f595b..21cc7001 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java @@ -19,11 +19,12 @@ @RestController @AllArgsConstructor -@RequestMapping("/api/{teamId}/missions/board") +@RequestMapping("/api/team/{teamId}/missions/board") public class MissionBoardController { private final MissionArchiveBoardUseCase missionArchiveBoardUseCase; + /** * 단일 인증 조회 * [GET] {teamId}/missions/board/single diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionTotalBoardController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionTotalBoardController.java new file mode 100644 index 00000000..84de76b7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionTotalBoardController.java @@ -0,0 +1,64 @@ +package com.moing.backend.domain.missionArchive.presentation; + +import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; +import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +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; + +import java.util.List; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/team/{teamId}/missions/board") +public class MissionTotalBoardController { + + private final MissionArchiveBoardUseCase missionArchiveBoardUseCase; + + + /** + * 단일 인증 조회 + * [GET] {teamId}/missions/board/single + * 작성자 : 정승연 + */ + + @GetMapping("/single") + public ResponseEntity>> getActiveSingleMission(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveSingleMissions(teamId, user.getSocialId()))); + } + + /** + * 반복 미션 인증 조회 + * [GET] {teamId}/missions/board/repeat + * 작성자 : 정승연 + */ + @GetMapping("/repeat") + public ResponseEntity>> getActiveRepeatMission(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); + } + + /** + * 종료된 인증 조회 + * [POST] {teamId}/missions/board/finish + * 작성자 : 정승연 + */ + + @GetMapping("/finish") + public ResponseEntity>> getFinishAllMission(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(FINISH_ALL_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getFinishMissions(teamId, user.getSocialId()))); + } + +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/presentation/MissionHeartController.java b/src/main/java/com/moing/backend/domain/missionHeart/presentation/MissionHeartController.java deleted file mode 100644 index 56928376..00000000 --- a/src/main/java/com/moing/backend/domain/missionHeart/presentation/MissionHeartController.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.moing.backend.domain.missionHeart.presentation; - -import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; -import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; -import com.moing.backend.domain.missionHeart.application.service.MissionHeartUseCase; -import com.moing.backend.global.config.security.dto.User; -import com.moing.backend.global.response.SuccessResponse; -import lombok.AllArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.CREATE_ARCHIVE_SUCCESS; - -@RestController -@AllArgsConstructor -@RequestMapping("/api/{teamId}/missions/{missionId}/archive/{archiveId}/heart") -public class MissionHeartController { - - -} From 748d507e4ecfaf21ba314a0464ca3455e576cefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 19 Oct 2023 16:18:46 +0900 Subject: [PATCH 145/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0=20-=20=EB=8B=A8=EC=9D=BC?= =?UTF-8?q?=EB=AF=B8=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/GatherSingleMissionRes.java | 13 ++++ .../service/MissionArchiveBoardUseCase.java | 4 + .../service/MissionGatherBoardUseCase.java | 28 +++++++ .../repository/MissionCustomRepository.java | 6 +- .../MissionCustomRepositoryImpl.java | 21 ++++++ .../domain/service/MissionQueryService.java | 9 +++ .../MissionArchiveCustomRepository.java | 2 + .../MissionArchiveCustomRepositoryImpl.java | 5 ++ .../service/MissionArchiveQueryService.java | 5 ++ .../presentation/MissionGatherController.java | 74 +++++++++++++++++++ .../MissionTotalBoardController.java | 64 ---------------- 11 files changed, 166 insertions(+), 65 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java delete mode 100644 src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionTotalBoardController.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java new file mode 100644 index 00000000..310292cf --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.mission.application.dto.res; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class GatherSingleMissionRes { + private Long missionId; + private String teamName; + private String missionTitle; + private String dueTo; +} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java index 8518976f..6b0a4c82 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.Mission; @@ -80,4 +81,7 @@ public List getActiveRepeatMissions(Long teamId, String m } + + + } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java new file mode 100644 index 00000000..b1d0aa9e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.mission.application.service; + +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionGatherBoardUseCase { + + private final MissionQueryService missionQueryService; + private final MemberGetService memberGetService; + + public List getAllActiveSingleMissions(String userId) { + Long memberId = memberGetService.getMemberBySocialId(userId).getMemberId(); + return missionQueryService.findAllSingleMission(memberId); + + } + + + +} diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index f46913d5..58a967ee 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.mission.domain.repository; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import org.springframework.stereotype.Repository; @@ -12,4 +13,7 @@ public interface MissionCustomRepository { Long findMissionsCountByTeam(Long teamId); Optional> findRepeatMissionByMemberId(Long teamId, MissionStatus status); - } \ No newline at end of file + Optional> findMissionsByMemberId(Long memberId, List teams); + + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 7ab14a9f..a63a5dd1 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -1,8 +1,10 @@ package com.moing.backend.domain.mission.domain.repository; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -44,4 +46,23 @@ public Optional> findRepeatMissionByMemberId(Long teamId, MissionS ) .fetch()); } + + @Override + public Optional> findMissionsByMemberId(Long memberId, List teams) { + return Optional.ofNullable(queryFactory + .select(Projections.constructor(GatherSingleMissionRes.class, + mission.id, + mission.team.name, + mission.title, + mission.dueTo + )) + .from(mission) + .where( + mission.team.teamId.in(teams), + mission.status.eq(MissionStatus.ONGOING) + ) + .fetch() + + ); + } } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 821c5022..1cf4c8d2 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.mission.domain.service; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.exception.NotFoundMissionException; @@ -8,6 +9,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; @DomainService @@ -28,4 +30,11 @@ public Long findMissionsCountByTeam(Long teamId) { public List findRepeatMissionByTeamId(Long teamId) { return missionRepository.findRepeatMissionByMemberId(teamId, MissionStatus.ONGOING).orElseThrow(NotFoundMissionException::new); } + + public List findAllSingleMission(Long memberId) { + + List teams = new ArrayList<>(); + teams.add(1L); + return missionRepository.findMissionsByMemberId(memberId, teams).orElseThrow(); + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index d0108511..c3de7466 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.missionArchive.domain.repository; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; @@ -25,4 +26,5 @@ public interface MissionArchiveCustomRepository { Optional> findFinishMissionsByStatus(Long memberId, Long teamId); + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 53f21493..145bf74e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -1,12 +1,15 @@ package com.moing.backend.domain.missionArchive.domain.repository; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.moing.backend.domain.team.domain.entity.Team; import com.querydsl.core.types.Expression; import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; @@ -189,4 +192,6 @@ public Optional> findFinishMissionsByStatus(Long mem .fetch() ); } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 8b24c4c1..7d36d492 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.missionArchive.domain.service; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.repository.MissionRepository; @@ -8,6 +9,7 @@ import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; import com.moing.backend.domain.missionArchive.exception.NotFoundMissionArchiveException; import com.moing.backend.domain.missionArchive.domain.repository.OrderCondition; +import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -24,6 +26,7 @@ public class MissionArchiveQueryService { private final MissionRepository missionRepository; private final MissionArchiveRepository missionArchiveRepository; + private final TeamMemberRepository teamMemberRepository; public MissionArchive findByMissionArchiveId(Long missionArchiveId) { return missionArchiveRepository.findById(missionArchiveId).orElseThrow(NotFoundMissionArchiveException::new); @@ -100,4 +103,6 @@ public List findMyFinishMissions(Long memberId, Long team } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java new file mode 100644 index 00000000..82fe9f46 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java @@ -0,0 +1,74 @@ +package com.moing.backend.domain.missionArchive.presentation; + +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; +import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; +import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +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; + +import java.util.List; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/team") +public class MissionGatherController { + + private final MissionGatherBoardUseCase missionGatherBoardUseCase; + + + /** + * 미션 모아보기 - 단일 미션 + * [GET] my-single + * 작성자 : 정승연 + */ + + @GetMapping("/my-single") + public ResponseEntity>> getMyActiveSingleMission(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getAllActiveSingleMissions(user.getSocialId()))); + } + + /** + * 미션 모아보기 - 반복 미션 + * [GET] my-repeat + * 작성자 : 정승연 + */ + + @GetMapping("/my-repeat") + public ResponseEntity>> getMyActiveRepeatMission(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); + } + + /** + * 모임별 미션 - 단일 미션 + * [GET] {teamId}/missions/board/repeat + * 작성자 : 정승연 + */ + @GetMapping("/{teamId}/mission/single") + public ResponseEntity>> geActiveRepeatMissionByTeam(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); + } + /** + * 모임별 미션 - 반복 미션 + * [GET] {teamId}/missions/board/repeat + * 작성자 : 정승연 + */ + @GetMapping("/{teamId}/mission/repeat") + public ResponseEntity>> getActiveRepeatMissionByTeam(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); + } + + + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionTotalBoardController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionTotalBoardController.java deleted file mode 100644 index 84de76b7..00000000 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionTotalBoardController.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.moing.backend.domain.missionArchive.presentation; - -import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; -import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; -import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; -import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; -import com.moing.backend.global.config.security.dto.User; -import com.moing.backend.global.response.SuccessResponse; -import lombok.AllArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -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; - -import java.util.List; - -import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; - -@RestController -@AllArgsConstructor -@RequestMapping("/api/team/{teamId}/missions/board") -public class MissionTotalBoardController { - - private final MissionArchiveBoardUseCase missionArchiveBoardUseCase; - - - /** - * 단일 인증 조회 - * [GET] {teamId}/missions/board/single - * 작성자 : 정승연 - */ - - @GetMapping("/single") - public ResponseEntity>> getActiveSingleMission(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveSingleMissions(teamId, user.getSocialId()))); - } - - /** - * 반복 미션 인증 조회 - * [GET] {teamId}/missions/board/repeat - * 작성자 : 정승연 - */ - @GetMapping("/repeat") - public ResponseEntity>> getActiveRepeatMission(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); - } - - /** - * 종료된 인증 조회 - * [POST] {teamId}/missions/board/finish - * 작성자 : 정승연 - */ - - @GetMapping("/finish") - public ResponseEntity>> getFinishAllMission(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(FINISH_ALL_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getFinishMissions(teamId, user.getSocialId()))); - } - -} From 0e19e9a982e10980867903670cee8fba43d6250f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 19 Oct 2023 17:12:53 +0900 Subject: [PATCH 146/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0=20-=20=EB=B0=98=EB=B3=B5?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20(=EC=A7=84=ED=96=89=EC=A4=91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/GatherRepeatMissionRes.java | 18 ++++++++++++ .../dto/res/GatherSingleMissionRes.java | 4 +++ .../service/MissionGatherBoardUseCase.java | 6 ++++ .../repository/MissionCustomRepository.java | 8 +++-- .../MissionCustomRepositoryImpl.java | 29 ++++++++++++++----- .../domain/service/MissionQueryService.java | 11 +++++-- .../MissionArchiveCustomRepository.java | 2 -- .../MissionArchiveCustomRepositoryImpl.java | 13 --------- .../service/MissionArchiveQueryService.java | 3 -- .../presentation/MissionGatherController.java | 25 ++++++++-------- 10 files changed, 76 insertions(+), 43 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java new file mode 100644 index 00000000..bfedd3d8 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.mission.application.dto.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class GatherRepeatMissionRes { + + private Long missionId; + private String teamName; + private String missionTitle; + private String totalNum; + private String doneNum; + +} diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java index 310292cf..fba77c0a 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java @@ -1,13 +1,17 @@ package com.moing.backend.domain.mission.application.dto.res; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @Getter @Builder +@AllArgsConstructor public class GatherSingleMissionRes { private Long missionId; private String teamName; private String missionTitle; private String dueTo; + + } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java index b1d0aa9e..57c2b51e 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.mission.application.service; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import lombok.RequiredArgsConstructor; @@ -22,6 +23,11 @@ public List getAllActiveSingleMissions(String userId) { return missionQueryService.findAllSingleMission(memberId); } + public List getAllActiveRepeatMissions(String userId) { + Long memberId = memberGetService.getMemberBySocialId(userId).getMemberId(); + return missionQueryService.findAllRepeatMission(memberId); + + } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index 58a967ee..7cf2b174 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.mission.domain.repository; +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; @@ -11,9 +12,10 @@ @Repository public interface MissionCustomRepository { Long findMissionsCountByTeam(Long teamId); - Optional> findRepeatMissionByMemberId(Long teamId, MissionStatus status); - Optional> findMissionsByMemberId(Long memberId, List teams); + Optional> findSingleMissionByMemberId(Long memberId, List teams); + Optional> findRepeatMissionByMemberId(Long memberId, Listteams); -} \ No newline at end of file + + } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index a63a5dd1..dea7900e 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.mission.domain.repository; +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; @@ -13,6 +14,7 @@ import java.util.Optional; import static com.moing.backend.domain.mission.domain.entity.QMission.mission; +import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; public class MissionCustomRepositoryImpl implements MissionCustomRepository{ @@ -34,32 +36,45 @@ public Long findMissionsCountByTeam(Long teamId) { } @Override - public Optional> findRepeatMissionByMemberId(Long teamId, MissionStatus status) { + public Optional> findRepeatMissionByMemberId(Long memberId,Listteams) { return Optional.ofNullable(queryFactory - .select(mission) + .select(Projections.constructor(GatherRepeatMissionRes.class, + mission.id, + mission.team.name, + mission.title, + mission.number.stringValue(), + missionArchive.count().stringValue() + + )) .from(mission) + .leftJoin(missionArchive) + .on(missionArchive.mission.id.eq(mission.id), + missionArchive.member.memberId.eq(memberId)) .where( - mission.team.teamId.eq(teamId), - mission.status.eq(status), + mission.team.teamId.in(teams), + mission.status.eq(MissionStatus.ONGOING), mission.type.eq(MissionType.REPEAT) ) +// .groupBy(mission.id) .fetch()); } @Override - public Optional> findMissionsByMemberId(Long memberId, List teams) { + public Optional> findSingleMissionByMemberId(Long memberId, List teams) { return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherSingleMissionRes.class, mission.id, mission.team.name, mission.title, - mission.dueTo + mission.dueTo.stringValue() )) .from(mission) .where( mission.team.teamId.in(teams), - mission.status.eq(MissionStatus.ONGOING) + mission.status.eq(MissionStatus.ONGOING), + mission.type.eq(MissionType.ONCE) + ) .fetch() diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 1cf4c8d2..7b497908 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.mission.domain.service; +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; @@ -27,14 +28,18 @@ public Long findMissionsCountByTeam(Long teamId) { return missionRepository.findMissionsCountByTeam(teamId); } - public List findRepeatMissionByTeamId(Long teamId) { - return missionRepository.findRepeatMissionByMemberId(teamId, MissionStatus.ONGOING).orElseThrow(NotFoundMissionException::new); + public List findAllRepeatMission(Long memberId) { + List teams = new ArrayList<>(); + teams.add(1L); + teams.add(2L); + return missionRepository.findRepeatMissionByMemberId(memberId,teams).orElseThrow(NotFoundMissionException::new); } public List findAllSingleMission(Long memberId) { List teams = new ArrayList<>(); teams.add(1L); - return missionRepository.findMissionsByMemberId(memberId, teams).orElseThrow(); + teams.add(2L); + return missionRepository.findSingleMissionByMemberId(memberId, teams).orElseThrow(NotFoundMissionException::new); } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index c3de7466..06d642b1 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -17,8 +17,6 @@ public interface MissionArchiveCustomRepository { Optional> findOthersArchives(Long memberId, Long missionId) ; - Optional> findAllMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus missionStatus); - Optional findDonePeopleByMissionId(Long missionId); Optional findMyDoneCountByMissionId(Long missionId,Long memberId); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 145bf74e..6949157a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -100,19 +100,6 @@ public Optional> findOthersArchives(Long memberId, Long mis ); } - @Override - public Optional> findAllMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus missionStatus) { - - return Optional.ofNullable(queryFactory - .selectFrom(missionArchive) - .where( - missionArchive.mission.status.eq(missionStatus), - missionArchive.mission.team.teamId.eq(teamId) - ) - .orderBy(missionArchive.mission.dueTo.desc()) - .fetch() - ); - } @Override public Optional findDonePeopleByMissionId(Long missionId) { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 7d36d492..ff10c3bd 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -85,9 +85,6 @@ public List findMyRepeatMissionArchives(Long memberId, Lo return missionArchiveRepository.findRepeatMissionArchivesByMemberId(memberId, teamId, missionStatus).orElseThrow(NotFoundMissionArchiveException::new); } - public List findMyAllMissionArchives(Long memberId, Long teamId, MissionStatus missionStatus) { - return missionArchiveRepository.findAllMissionArchivesByMemberId(memberId, teamId, missionStatus).orElseThrow(NotFoundMissionArchiveException::new); - } public Long findDoneArchives(Long missionId) { return missionArchiveRepository.findDonePeopleByMissionId(missionId).orElseThrow(NotFoundMissionArchiveException::new); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java index 82fe9f46..0d86fe4a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.presentation; +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; @@ -44,8 +45,8 @@ public ResponseEntity>> getMyActive */ @GetMapping("/my-repeat") - public ResponseEntity>> getMyActiveRepeatMission(@AuthenticationPrincipal User user) { - return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); + public ResponseEntity>> getMyActiveRepeatMission(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getAllActiveRepeatMissions( user.getSocialId()))); } /** @@ -53,21 +54,21 @@ public ResponseEntity>> getMyActiveR * [GET] {teamId}/missions/board/repeat * 작성자 : 정승연 */ - @GetMapping("/{teamId}/mission/single") - public ResponseEntity>> geActiveRepeatMissionByTeam(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); - } +// @GetMapping("/{teamId}/mission/single") +// public ResponseEntity>> geActiveRepeatMissionByTeam(@AuthenticationPrincipal User user, +// @PathVariable("teamId") Long teamId) { +// return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); +// } /** * 모임별 미션 - 반복 미션 * [GET] {teamId}/missions/board/repeat * 작성자 : 정승연 */ - @GetMapping("/{teamId}/mission/repeat") - public ResponseEntity>> getActiveRepeatMissionByTeam(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); - } +// @GetMapping("/{teamId}/mission/repeat") +// public ResponseEntity>> getActiveRepeatMissionByTeam(@AuthenticationPrincipal User user, +// @PathVariable("teamId") Long teamId) { +// return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); +// } From 8e87ca56a5d758b3ba3f844b59746ec487d36615 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 19 Oct 2023 20:22:38 +0900 Subject: [PATCH 147/619] =?UTF-8?q?feat:=20memberId=EB=A1=9C=20teamId?= =?UTF-8?q?=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Auth-API.adoc | 5 +-- .../dto/request/UpdateTeamRequest.java | 26 ++++++++++++++ .../dto/response/UpdateTeamResponse.java | 10 ++++++ .../service/UpdateTeamUserCase.java | 34 +++++++++++++++++++ .../repository/TeamCustomRepository.java | 2 ++ .../repository/TeamCustomRepositoryImpl.java | 13 +++++++ .../team/domain/service/TeamGetService.java | 6 +++- .../team/presentation/TeamController.java | 15 ++++++++ .../constant/TeamResponseMessage.java | 1 + .../global/config/security/jwt/TokenUtil.java | 5 ++- 10 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/request/UpdateTeamRequest.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/UpdateTeamResponse.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java diff --git a/src/docs/asciidoc/Auth-API.adoc b/src/docs/asciidoc/Auth-API.adoc index 2a9412a4..30a21e6c 100644 --- a/src/docs/asciidoc/Auth-API.adoc +++ b/src/docs/asciidoc/Auth-API.adoc @@ -25,13 +25,14 @@ operation::auth-controller-test/google_소셜_로그인_회원가입_후[snippet [[Auth-회원가입]] === Auth 회원가입 -operation::auth-controller-test/sign_up[snippets='http-request,request-fields,http-response,response-fields'] |=== -| 성별 | +| 성별 | `MAN` | `WOMAN` | `NEUTRALITY` |=== +operation::auth-controller-test/sign_up[snippets='http-request,request-fields,http-response,response-fields'] + [[Auth-토큰-재발급]] === Auth 토큰 재발급 diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/request/UpdateTeamRequest.java b/src/main/java/com/moing/backend/domain/team/application/dto/request/UpdateTeamRequest.java new file mode 100644 index 00000000..81f5f3ce --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/request/UpdateTeamRequest.java @@ -0,0 +1,26 @@ +package com.moing.backend.domain.team.application.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class UpdateTeamRequest { + @NotBlank(message = "name 을 입력해 주세요.") + @Size(min = 1, max = 10, message = "name 은 최소 1개, 최대 10개의 문자만 입력 가능합니다.") + private String name; + + @NotBlank(message = "introduction 을 입력해 주세요.") + @Size(min = 1, max = 300, message = "introduction 은 최소 1개, 최대 300개의 문자만 입력 가능합니다.") + private String introduction; + + @NotBlank(message = "profileImgUrl 을 입력해 주세요.") + private String profileImgUrl; +} diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/UpdateTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/UpdateTeamResponse.java new file mode 100644 index 00000000..c08ad4e0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/UpdateTeamResponse.java @@ -0,0 +1,10 @@ +package com.moing.backend.domain.team.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class UpdateTeamResponse { + private Long teamId; +} diff --git a/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java new file mode 100644 index 00000000..2eea1890 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java @@ -0,0 +1,34 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.application.dto.request.UpdateTeamRequest; +import com.moing.backend.domain.team.application.dto.response.UpdateTeamResponse; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.team.exception.NotAuthByTeamException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class UpdateTeamUserCase { + + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final CheckLeaderUserCase checkLeaderUserCase; + + public UpdateTeamResponse updateTeam(UpdateTeamRequest updateTeamRequest, String socialId, Long teamId){ + Member member = memberGetService.getMemberBySocialId(socialId); + Team team=teamGetService.getTeamByTeamId(teamId); + if (checkLeaderUserCase.isTeamLeader(member, team)) { + team.updateTeam(updateTeamRequest.getName(), updateTeamRequest.getIntroduction(), updateTeamRequest.getProfileImgUrl()); + } else { + throw new NotAuthByTeamException(); + } + return new UpdateTeamResponse(team.getTeamId()); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index faabee4c..3a2921d4 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -3,9 +3,11 @@ import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; +import java.util.List; import java.util.Optional; public interface TeamCustomRepository { GetTeamResponse findTeamByMemberId(Long memberId); Optional findTeamByTeamId(Long TeamId); + List findTeamIdByMemberId(Long memberId); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index 715dfee4..21664917 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -37,6 +37,19 @@ public Optional findTeamByTeamId(Long teamId) { .fetchOne()); } + @Override + public List findTeamIdByMemberId(Long memberId){ + return queryFactory + .select(team.teamId) + .from(teamMember) + .innerJoin(teamMember.team, team) + .on(teamMember.member.memberId.eq(memberId)) + .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) //승인 되었고 + .where(team.isDeleted.eq(false)) //강제종료되었는지 + .where(teamMember.isDeleted.eq(false)) //탈퇴했는지 + .orderBy(team.approvalTime.asc()) + .fetch(); + } private List getTeamBlock(Long memberId) { return queryFactory .select(new QTeamBlock(team.teamId, diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index 4afea33b..56e9e372 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -8,7 +8,7 @@ import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; -import java.util.Optional; +import java.util.List; @DomainService @RequiredArgsConstructor @@ -21,6 +21,10 @@ public GetTeamResponse getTeamByMember(Member member) { return getTeamResponse; } + public List getTeamIdByMemberId(Long memberId) { + return teamRepository.findTeamIdByMemberId(memberId); + } + public Team getTeamByTeamId(Long teamId){ return teamRepository.findTeamByTeamId(teamId).orElseThrow(()->new NotFoundByTeamIdException()); } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index dad8cfb2..624e2615 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -1,9 +1,11 @@ package com.moing.backend.domain.team.presentation; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; +import com.moing.backend.domain.team.application.dto.request.UpdateTeamRequest; import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.team.application.dto.response.UpdateTeamResponse; import com.moing.backend.domain.team.application.service.*; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; @@ -26,6 +28,7 @@ public class TeamController { private final SignInTeamUserCase signInTeamUserCase; private final DisbandTeamUserCase disbandTeamUserCase; private final WithdrawTeamUserCase withdrawTeamUserCase; + private final UpdateTeamUserCase updateTeamUserCase; /** * 소모임 생성 (only 개설만) @@ -82,4 +85,16 @@ public ResponseEntity> withdrawTeam(@Authent return ResponseEntity.ok(SuccessResponse.create(WITHDRAW_TEAM_SUCCESS.getMessage(), this.withdrawTeamUserCase.withdrawTeam(user.getSocialId(),teamId))); } + /** + * 소모임 수정 (소모임장) + * [POST] api/team/{teamId} + */ + + @PutMapping("/{teamId}") + public ResponseEntity> updateTeam(@Valid @RequestBody UpdateTeamRequest updateTeamRequest, + @AuthenticationPrincipal User user, + @PathVariable Long teamId){ + return ResponseEntity.ok(SuccessResponse.create(UPDATE_TEAM_SUCCESS.getMessage(), this.updateTeamUserCase.updateTeam(updateTeamRequest, user.getSocialId(), teamId))); + } + } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 2b1ccdcb..2ed8320a 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -10,6 +10,7 @@ public enum TeamResponseMessage { GET_TEAM_SUCCESS("홈 화면에서 내 소모임을 모두 조회했습니다."), SIGNIN_TEAM_SUCCESS("소모임에 가입하였습니다"), DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."), + UPDATE_TEAM_SUCCESS("[소모임장 권한] 소모임을 수정했습니다"), WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"), SEND_APPROVAL_ALARM_SUCCESS("소모임 승인 알림을 보냈습니다."), SEND_REJECTION_ALARM_SUCCESS("소모임 반려 알림을 보냈습니다."); diff --git a/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java b/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java index 6dc56697..bd691806 100644 --- a/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java +++ b/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java @@ -109,7 +109,10 @@ public TokenInfoResponse tokenReissue(String token) { Member member = memberQueryService.getMemberBySocialId(socialId); // socialId 에 해당하는 refreshToken redis 에서 가져오기 - String storedRefreshToken = redisUtil.findById(socialId).orElseThrow(() -> new NotFoundRefreshToken()); + String storedRefreshToken = redisUtil.findById(socialId).orElseThrow(NotFoundRefreshToken::new); + + //가져온 refeshToken이랑 입력한 refeshToken이랑 비교 + if(storedRefreshToken == null || !storedRefreshToken.equals(token)) throw new NotFoundRefreshToken(); // Token 생성 TokenInfoResponse newToken = createToken(member, true); From b5858f7f546b0007c877cc5c8ccc3b8edc29c681 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 19 Oct 2023 21:17:20 +0900 Subject: [PATCH 148/619] =?UTF-8?q?feat:=20docs=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Auth-API.adoc | 2 +- src/docs/asciidoc/Team-API.adoc | 5 +- .../dto/response/UpdateTeamResponse.java | 2 + .../team/presentation/TeamControllerTest.java | 68 +++++++++++++++++-- 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/docs/asciidoc/Auth-API.adoc b/src/docs/asciidoc/Auth-API.adoc index 30a21e6c..2795415a 100644 --- a/src/docs/asciidoc/Auth-API.adoc +++ b/src/docs/asciidoc/Auth-API.adoc @@ -40,7 +40,7 @@ operation::auth-controller-test/reissue_token[snippets='http-request,http-respon [[Auth-닉네임-검사]] === Auth 닉네임 중복검사 요청 -operation::auth-controller-test/check_nickname_중복o[snippets='http-request'] +operation::auth-controller-test/check_nickname_중복o[snippets='http-request,path-parameters'] === Auth 닉네임 중복인 경우 operation::auth-controller-test/check_nickname_중복o[snippets='http-response,response-fields'] diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc index c4269911..0fe3436e 100644 --- a/src/docs/asciidoc/Team-API.adoc +++ b/src/docs/asciidoc/Team-API.adoc @@ -33,11 +33,14 @@ operation::team-controller-test/create_team[snippets='http-request,request-field === Team 소모임 가입 operation::team-controller-test/sign-in_team[snippets='http-request,path-parameters,http-response,response-fields'] - [[Team-소모임-조회]] === Team 소모임 조회 operation::team-controller-test/get_team[snippets='http-request,http-response,response-fields'] +[[Team-소모임-수정]] +=== Team 소모임 수정 +operation::team-controller-test/update_team[snippets='http-request,path-parameters,http-response,request-fields,response-fields'] + [[Team-소모임-강제종료]] === Team 소모임 강제종료 operation::team-controller-test/disband_team[snippets='http-request,path-parameters,http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/UpdateTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/UpdateTeamResponse.java index c08ad4e0..79a15208 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/UpdateTeamResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/UpdateTeamResponse.java @@ -1,10 +1,12 @@ package com.moing.backend.domain.team.application.dto.response; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; @Getter @AllArgsConstructor +@Builder public class UpdateTeamResponse { private Long teamId; } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 734d871f..0b96c84d 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -2,10 +2,8 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; -import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; -import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; -import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; -import com.moing.backend.domain.team.application.dto.response.TeamBlock; +import com.moing.backend.domain.team.application.dto.request.UpdateTeamRequest; +import com.moing.backend.domain.team.application.dto.response.*; import com.moing.backend.domain.team.application.service.*; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -24,7 +22,8 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.*; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(TeamController.class) @@ -33,13 +32,14 @@ public class TeamControllerTest extends CommonControllerTest { private CreateTeamUserCase createTeamService; @MockBean private GetTeamUserCase getTeamUserCase; - @MockBean private DisbandTeamUserCase disbandTeamUserCase; @MockBean private WithdrawTeamUserCase withdrawTeamUserCase; @MockBean private SignInTeamUserCase signInTeamUserCase; + @MockBean + private UpdateTeamUserCase updateTeamUserCase; @Test public void create_team() throws Exception { @@ -276,4 +276,60 @@ public void signIn_team() throws Exception { } + @Test + public void update_team() throws Exception { + + // given + Long teamId = 1L; + UpdateTeamRequest input = UpdateTeamRequest.builder() + .name("수정 후 팀 이름") + .introduction("수정 후 소개") + .profileImgUrl("수정 후 프로필 이미지") + .build(); + + + String body = objectMapper.writeValueAsString(input); + + UpdateTeamResponse output = UpdateTeamResponse.builder() + .teamId(1L) + .build(); + + given(updateTeamUserCase.updateTeam(any(), any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + put("/api/team/{teamId}", teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), + requestFields( + fieldWithPath("name").description("변경 후 소모임 이름"), + fieldWithPath("introduction").description("변경 후 소모임 소개글"), + fieldWithPath("profileImgUrl").description("변경 후 소모임 대표 사진") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("소모임을 수정했습니다."), + fieldWithPath("data.teamId").description("수정한 teamId") + ) + ) + ); + } + + } From ad3b0d2d451765cc721016d3883205a405e9f758 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 20 Oct 2023 00:24:50 +0900 Subject: [PATCH 149/619] =?UTF-8?q?feat:=20=EB=AA=A9=ED=91=9C=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=EB=A1=9C=20=EB=82=B4=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=ED=95=98=EB=82=98=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/BoardCustomRepository.java | 3 +- .../repository/BoardCustomRepositoryImpl.java | 22 ++++++++- .../board/domain/service/BoardGetService.java | 4 ++ .../domain/member/domain/entity/Member.java | 2 +- .../dto/response/GetTeamDetailResponse.java | 18 ++++++++ .../application/dto/response/TeamInfo.java | 20 ++++++++ .../dto/response/TeamMemberInfo.java | 24 ++++++++++ .../team/application/mapper/TeamMapper.java | 13 ++++++ .../service/CheckLeaderUserCase.java | 7 +-- .../application/service/GetTeamUserCase.java | 18 ++++++++ .../repository/TeamCustomRepository.java | 1 + .../repository/TeamCustomRepositoryImpl.java | 6 +-- .../team/presentation/TeamController.java | 19 +++++--- .../constant/TeamResponseMessage.java | 1 + .../TeamMemberCustomRepository.java | 3 ++ .../TeamMemberCustomRepositoryImpl.java | 46 ++++++++++++++----- .../domain/service/TeamMemberGetService.java | 4 ++ 17 files changed, 182 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamDetailResponse.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/TeamMemberInfo.java diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java index 10d5ffbd..ec8f67d9 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepository.java @@ -3,5 +3,6 @@ import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; public interface BoardCustomRepository { - GetAllBoardResponse findBoardAll(Long teamId, Long boardId); + GetAllBoardResponse findBoardAll(Long teamId, Long memberId); + Integer findUnReadBoardNum(Long teamId, Long memberId); } diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index 2532ea09..8a3001a5 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -13,9 +13,9 @@ import static com.moing.backend.domain.board.domain.entity.QBoard.board; import static com.moing.backend.domain.boardRead.domain.entity.QBoardRead.boardRead; -public class BoardCustomRepositoryImpl implements BoardCustomRepository { - private final JPAQueryFactory queryFactory; +public class BoardCustomRepositoryImpl implements BoardCustomRepository { + private final JPAQueryFactory queryFactory; public BoardCustomRepositoryImpl(EntityManager em) { this.queryFactory = new JPAQueryFactory(em); } @@ -65,4 +65,22 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { return new GetAllBoardResponse(noticeBlocks.size(), noticeBlocks, regularBlocks.size(), regularBlocks); } + + @Override + public Integer findUnReadBoardNum(Long teamId, Long memberId) { + // 전체 게시글 수 + Long allBoards = queryFactory + .selectFrom(board) + .where(board.team.teamId.eq(teamId)) + .fetchCount(); + + // 멤버가 읽은 게시글 수 + Long readBoards = queryFactory + .selectFrom(boardRead) + .where(boardRead.member.memberId.eq(memberId)) + .where(boardRead.board.team.teamId.eq(teamId)) + .fetchCount(); + + return Math.toIntExact(allBoards - readBoards); + } } diff --git a/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java b/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java index e5db6029..2a20429d 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java +++ b/src/main/java/com/moing/backend/domain/board/domain/service/BoardGetService.java @@ -25,4 +25,8 @@ public Board getBoard(Long boardId){ public GetAllBoardResponse getBoardAll(Long teamId, Long memberId){ return boardRepository.findBoardAll(teamId, memberId); } + + public Integer getUnReadBoardNum(Long teamId, Long memberId){ + return boardRepository.findUnReadBoardNum(teamId, memberId); + } } diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index ad9370f8..2899fbbd 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -47,7 +47,7 @@ public class Member extends BaseTimeEntity { @Column(nullable = false, unique = true) private String email; - private String profileImage; //없으면 undef + private String profileImage; @Column(length = 10) @Enumerated(EnumType.STRING) diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamDetailResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamDetailResponse.java new file mode 100644 index 00000000..63af6dcb --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamDetailResponse.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.team.application.dto.response; + +import com.moing.backend.domain.team.domain.constant.Category; +import com.querydsl.core.annotations.QueryProjection; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@Builder +@AllArgsConstructor +public class GetTeamDetailResponse { + private Integer boardNum; //안 읽은 게시글 + private TeamInfo teamInfo; +} diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java new file mode 100644 index 00000000..63574fd6 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.team.application.dto.response; + +import com.moing.backend.domain.team.domain.constant.Category; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +@AllArgsConstructor +@Getter +@Builder +public class TeamInfo { + private String teamName; //소모임 이름 + private Integer numOfMember; //소모임원 수 + private Category category; //카테고리 + private String introduction; //소개 + private List teamMemberInfoList = new ArrayList<>(); //소모임원 정보 +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamMemberInfo.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamMemberInfo.java new file mode 100644 index 00000000..f3d647ea --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamMemberInfo.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.team.application.dto.response; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class TeamMemberInfo { + private Long memberId; + private String nickName; + private String profileImage; + private String introduction; + private Boolean isLeader; + + @QueryProjection + public TeamMemberInfo(Long memberId, String nickName, String profileImage, String introduction, Long leaderId){ + this.memberId=memberId; + this.nickName=nickName; + this.profileImage=profileImage; + this.introduction=introduction; + this.isLeader=memberId.equals(leaderId); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index 327adba1..6debf056 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -2,11 +2,16 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; +import com.moing.backend.domain.team.application.dto.response.GetTeamDetailResponse; +import com.moing.backend.domain.team.application.dto.response.TeamInfo; +import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.moing.backend.domain.team.domain.constant.Category; import com.moing.backend.domain.team.domain.entity.Team; import org.springframework.stereotype.Component; +import java.util.List; + @Component public class TeamMapper { @@ -23,4 +28,12 @@ public Team createTeam(CreateTeamRequest createTeamRequest, Member member) { .levelOfFire(1) .build(); } + + public GetTeamDetailResponse toTeamDetailResponse(Team team, Integer boardNum, List teamMemberInfoList) { + TeamInfo teamInfo = new TeamInfo(team.getName(), teamMemberInfoList.size(), team.getCategory(), team.getIntroduction(), teamMemberInfoList); + return GetTeamDetailResponse.builder() + .boardNum(boardNum) + .teamInfo(teamInfo) + .build(); + } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java index 616b0d31..b397a9e9 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java @@ -6,16 +6,13 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.util.Objects; @Service @Transactional @RequiredArgsConstructor public class CheckLeaderUserCase { public boolean isTeamLeader(Member member, Team team) { - if (member.getMemberId() == team.getLeaderId()) { - return true; - } else { - return false; - } + return Objects.equals(member.getMemberId(), team.getLeaderId()); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java index 56ba881a..30266ad4 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java @@ -1,13 +1,20 @@ package com.moing.backend.domain.team.application.service; +import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.application.dto.response.GetTeamDetailResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; +import com.moing.backend.domain.team.application.mapper.TeamMapper; +import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.util.List; @Service @Transactional @@ -15,9 +22,20 @@ public class GetTeamUserCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; + private final BoardGetService boardGetService; + private final TeamMemberGetService teamMemberGetService; + private final TeamMapper teamMapper; public GetTeamResponse getTeam(String socialId) { Member member = memberGetService.getMemberBySocialId(socialId); return teamGetService.getTeamByMember(member); } + + public GetTeamDetailResponse getTeamDetailResponse(String socialId, Long teamId) { + Member member = memberGetService.getMemberBySocialId(socialId); + Integer boardNum = boardGetService.getUnReadBoardNum(teamId, member.getMemberId()); + List teamMemberInfoList = teamMemberGetService.getTeamMemberInfo(teamId); + Team team = teamGetService.getTeamByTeamId(teamId); + return teamMapper.toTeamDetailResponse(team, boardNum, teamMemberInfoList); + } } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index 3a2921d4..fdbd1a88 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.team.domain.repository; +import com.moing.backend.domain.team.application.dto.response.GetTeamDetailResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index 21664917..f1642ab7 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -1,8 +1,7 @@ package com.moing.backend.domain.team.domain.repository; -import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; -import com.moing.backend.domain.team.application.dto.response.QTeamBlock; -import com.moing.backend.domain.team.application.dto.response.TeamBlock; +import com.moing.backend.domain.member.domain.entity.QMember; +import com.moing.backend.domain.team.application.dto.response.*; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.moing.backend.domain.team.domain.entity.Team; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -50,6 +49,7 @@ public List findTeamIdByMemberId(Long memberId){ .orderBy(team.approvalTime.asc()) .fetch(); } + private List getTeamBlock(Long memberId) { return queryFactory .select(new QTeamBlock(team.teamId, diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index 624e2615..907fef05 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -2,15 +2,11 @@ import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; import com.moing.backend.domain.team.application.dto.request.UpdateTeamRequest; -import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; -import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; -import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; -import com.moing.backend.domain.team.application.dto.response.UpdateTeamResponse; +import com.moing.backend.domain.team.application.dto.response.*; import com.moing.backend.domain.team.application.service.*; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; -import org.checkerframework.checker.units.qual.A; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; @@ -42,7 +38,7 @@ public ResponseEntity> createTeam(@Authentic } /** - * 소모임 조회하기 (소모임 홈화면) : 인증사진 제외 + * 소모임 전체 조회하기 (소모임 홈화면) : 인증사진 제외 * [GET] api/team * 작성자 : 김민수 */ @@ -51,6 +47,17 @@ public ResponseEntity> getTeam(@AuthenticationP return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_SUCCESS.getMessage(), this.getTeamUserCase.getTeam(user.getSocialId()))); } + /** + * 소모임 하나만 조회하기 (목표보드) : 소모임 레벨, 상태 바 제외 + * [GET] api/team/{teamId} + * 작성자: 김민수 + */ + @GetMapping("/{teamId}") + public ResponseEntity> getTeamDetail(@AuthenticationPrincipal User user, + @PathVariable Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_DETAIL_SUCCESS.getMessage(), this.getTeamUserCase.getTeamDetailResponse(user.getSocialId(), teamId))); + } + /** * 소모임 가입하기 (소모임원으로 입장) * [POST] api/team/{teamId} diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 2ed8320a..d9d08180 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -8,6 +8,7 @@ public enum TeamResponseMessage { CREATE_TEAM_SUCCESS("소모임을 생성하였습니다"), GET_TEAM_SUCCESS("홈 화면에서 내 소모임을 모두 조회했습니다."), + GET_TEAM_DETAIL_SUCCESS("목표보드를 조회했습니다"), SIGNIN_TEAM_SUCCESS("소모임에 가입하였습니다"), DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."), UPDATE_TEAM_SUCCESS("[소모임장 권한] 소모임을 수정했습니다"), diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index 725b70e1..fdfc1193 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -1,5 +1,7 @@ package com.moing.backend.domain.teamMember.domain.repository; +import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; + import java.util.List; import java.util.Optional; @@ -7,4 +9,5 @@ public interface TeamMemberCustomRepository { List findMemberIdsByTeamId(Long teamId); Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId); Optional> findFcmTokensByTeamId(Long teamId); + List findTeamMemberInfoByTeamId(Long teamId); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index 40f64eaa..cd5cbaf2 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -1,5 +1,8 @@ package com.moing.backend.domain.teamMember.domain.repository; +import com.moing.backend.domain.team.application.dto.response.QTeamMemberInfo; +import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; +import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.moing.backend.domain.team.domain.entity.QTeam; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -7,6 +10,7 @@ import java.util.List; import java.util.Optional; +import static com.moing.backend.domain.team.domain.entity.QTeam.team; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; public class TeamMemberCustomRepositoryImpl implements TeamMemberCustomRepository { @@ -21,27 +25,47 @@ public List findMemberIdsByTeamId(Long teamId) { return queryFactory .select(teamMember.member.memberId) .from(teamMember) - .where(teamMember.team.teamId.eq(teamId)) - .where(teamMember.team.isDeleted.eq(false)) + .where(teamMember.team.teamId.eq(teamId) + .and(teamMember.team.isDeleted.eq(false))) .fetch(); } @Override public Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId) { - return Optional.ofNullable(queryFactory.select(teamMember.member.fcmToken) + List result = queryFactory.select(teamMember.member.fcmToken) .from(teamMember) - .where(teamMember.team.teamId.eq(teamId)) //해당 소모임에 참여하고 있고 - .where(teamMember.member.isNewUploadPush.eq(true)) //알림 설정 on해 있고 - .where(teamMember.member.memberId.ne(memberId)) //지금 유저가 아닌 경우 - .fetch()); + .where(teamMember.team.teamId.eq(teamId) + .and(teamMember.member.isNewUploadPush.eq(true)) + .and(teamMember.member.memberId.ne(memberId))) + .fetch(); + + return result.isEmpty() ? Optional.empty() : Optional.of(result); } @Override public Optional> findFcmTokensByTeamId(Long teamId) { - return Optional.ofNullable(queryFactory.select(teamMember.member.fcmToken) + List result = queryFactory.select(teamMember.member.fcmToken) + .from(teamMember) + .where(teamMember.team.teamId.eq(teamId) + .and(teamMember.member.isNewUploadPush.eq(true))) + .fetch(); + + return result.isEmpty() ? Optional.empty() : Optional.of(result); + } + + @Override + public List findTeamMemberInfoByTeamId(Long teamId){ + return queryFactory + .select(new QTeamMemberInfo( + teamMember.member.memberId, + teamMember.member.nickName, + teamMember.member.profileImage, + teamMember.member.introduction, + teamMember.team.leaderId)) .from(teamMember) - .where(teamMember.team.teamId.eq(teamId)) //해당 소모임에 참여하고 있고 - .where(teamMember.member.isNewUploadPush.eq(true)) //알림 설정 on해 있고 - .fetch()); + .innerJoin(teamMember.team, team) // innerJoin을 사용하여 최적화 + .where(teamMember.team.teamId.eq(teamId) // where 절을 하나로 합침 + .and(teamMember.isDeleted.eq(false))) + .fetch(); } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index 6ba8f3db..ba86c2f7 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.teamMember.domain.service; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.exception.NotFoundByTeamIdException; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; @@ -32,4 +33,7 @@ public Optional> getFcmTokens(Long teamId) { return teamMemberRepository.findFcmTokensByTeamId(teamId); } + public List getTeamMemberInfo(Long teamId){ + return teamMemberRepository.findTeamMemberInfoByTeamId(teamId); + } } From bbc8d4659fd00a488dd42d7abc2bda15cd92c14d Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 20 Oct 2023 00:49:34 +0900 Subject: [PATCH 150/619] =?UTF-8?q?feat:=20=EB=AA=A9=ED=91=9C=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Team-API.adoc | 4 ++ .../dto/response/TeamMemberInfo.java | 2 + .../team/presentation/TeamControllerTest.java | 72 +++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc index 0fe3436e..32e55c69 100644 --- a/src/docs/asciidoc/Team-API.adoc +++ b/src/docs/asciidoc/Team-API.adoc @@ -37,6 +37,10 @@ operation::team-controller-test/sign-in_team[snippets='http-request,path-paramet === Team 소모임 조회 operation::team-controller-test/get_team[snippets='http-request,http-response,response-fields'] +[[Team-목표보드-조회]] +=== Team 목표보드_소모임 단건_조회 +operation::team-controller-test/get_team_detail[snippets='http-request,path-parameters,http-response,response-fields'] + [[Team-소모임-수정]] === Team 소모임 수정 operation::team-controller-test/update_team[snippets='http-request,path-parameters,http-response,request-fields,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamMemberInfo.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamMemberInfo.java index f3d647ea..cc42df33 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamMemberInfo.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamMemberInfo.java @@ -2,10 +2,12 @@ import com.querydsl.core.annotations.QueryProjection; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; @Getter @AllArgsConstructor +@Builder public class TeamMemberInfo { private Long memberId; private String nickName; diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 0b96c84d..4f84f31a 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.team.application.dto.request.UpdateTeamRequest; import com.moing.backend.domain.team.application.dto.response.*; import com.moing.backend.domain.team.application.service.*; +import com.moing.backend.domain.team.domain.constant.Category; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -165,6 +166,76 @@ public void get_team() throws Exception { ); } + @Test + public void get_team_detail() throws Exception { + //given + Long teamId = 1L; + List teamMemberInfoList = new ArrayList<>(); + TeamMemberInfo teamMemberInfo = TeamMemberInfo.builder() + .memberId(1L) + .nickName("소모임원 닉네임") + .profileImage("소모임원 프로필 사진") + .introduction("소모임원 소개") + .isLeader(true) + .build(); + teamMemberInfoList.add(teamMemberInfo); + + TeamInfo teamInfo = TeamInfo + .builder() + .teamName("소모임 이름") + .numOfMember(1) + .category(Category.ETC) + .introduction("소모임 소개글") + .teamMemberInfoList(teamMemberInfoList).build(); + + GetTeamDetailResponse output = GetTeamDetailResponse + .builder() + .boardNum(1) + .teamInfo(teamInfo) + .build(); + + + given(getTeamUserCase.getTeamDetailResponse(any(),any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/{teamId}", teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("목표보드를 조회했습니다."), + fieldWithPath("data.boardNum").description("안 읽은 공지/게시글"), + fieldWithPath("data.teamInfo.teamName").description("소모임 이름"), + fieldWithPath("data.teamInfo.numOfMember").description("모임원 명 수"), + fieldWithPath("data.teamInfo.category").description("카테고리"), + fieldWithPath("data.teamInfo.introduction").description("모임 소개"), + fieldWithPath("data.teamInfo.teamMemberInfoList[0].memberId").description("유저 아이디"), + fieldWithPath("data.teamInfo.teamMemberInfoList[0].nickName").description("유저 닉네임"), + fieldWithPath("data.teamInfo.teamMemberInfoList[0].profileImage").description("유저 프로필 이미지"), + fieldWithPath("data.teamInfo.teamMemberInfoList[0].introduction").description("유저 소개"), + fieldWithPath("data.teamInfo.teamMemberInfoList[0].isLeader").description("유저 소모임장 여부") + ) + + ) + ); + } + @Test public void disband_team() throws Exception { //given @@ -276,6 +347,7 @@ public void signIn_team() throws Exception { } + @Test public void update_team() throws Exception { From 463a58984c7cf8ff561dc6d4e2e5afb92a91119e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 20 Oct 2023 01:12:45 +0900 Subject: [PATCH 151/619] =?UTF-8?q?feat=20:=20findRepeatMissionByMemberId?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionCustomRepositoryImpl.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index dea7900e..d458b1fd 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -47,16 +47,15 @@ public Optional> findRepeatMissionByMemberId(Long m missionArchive.count().stringValue() )) - .from(mission) - .leftJoin(missionArchive) - .on(missionArchive.mission.id.eq(mission.id), - missionArchive.member.memberId.eq(memberId)) + .from(mission,missionArchive) .where( + missionArchive.mission.eq(mission), + missionArchive.member.memberId.eq(memberId), mission.team.teamId.in(teams), mission.status.eq(MissionStatus.ONGOING), mission.type.eq(MissionType.REPEAT) ) -// .groupBy(mission.id) + .groupBy(mission.id) .fetch()); } From 08fd57925c1e1b921d45138cecbef27ffecf45d4 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 20 Oct 2023 13:53:52 +0900 Subject: [PATCH 152/619] =?UTF-8?q?feat=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=EC=9D=B8=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- .../domain/repository/MissionCustomRepositoryImpl.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 74e6afc1..7554674c 100644 --- a/.gitignore +++ b/.gitignore @@ -40,7 +40,7 @@ out/ application.yml application-local.yml .DS_Store -firebase-key.json +src/main/resources/firebase-key.json src/test/resources/ .jpb diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index d458b1fd..5cb5a266 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -47,10 +47,10 @@ public Optional> findRepeatMissionByMemberId(Long m missionArchive.count().stringValue() )) - .from(mission,missionArchive) + .from(mission) + .leftJoin(missionArchive) + .on(missionArchive.mission.eq(mission), missionArchive.member.memberId.eq(memberId)) .where( - missionArchive.mission.eq(mission), - missionArchive.member.memberId.eq(memberId), mission.team.teamId.in(teams), mission.status.eq(MissionStatus.ONGOING), mission.type.eq(MissionType.REPEAT) From 164d525d175826e234477a2d0f5d56ee64dbaae7 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 20 Oct 2023 14:09:19 +0900 Subject: [PATCH 153/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0=20MissionGatherControllerT?= =?UTF-8?q?est?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionGatherControllerTest.java | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java new file mode 100644 index 00000000..dfccb93b --- /dev/null +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -0,0 +1,130 @@ +package com.moing.backend.domain.missionArchive.representation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.mission.application.dto.res.*; +import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; +import com.moing.backend.domain.missionArchive.presentation.MissionGatherController; +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.List; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; + +@WebMvcTest(MissionGatherController.class) +public class MissionGatherControllerTest extends CommonControllerTest { + + + @MockBean + private MissionGatherBoardUseCase missionGatherBoardUseCase; + + @Test + public void 미션_모아보기_단일_미션() throws Exception { + //given + + List output = Lists.newArrayList(GatherSingleMissionRes.builder() + .missionId(1L) + .dueTo("2023-09-03T21:32:33.888") + .teamName("team name") + .missionTitle("mission title") + .build()); + + given(missionGatherBoardUseCase.getAllActiveSingleMissions(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/my-once") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage()), + fieldWithPath("data[].missionId").description("미션 아이디"), + fieldWithPath("data[].dueTo").description("미션 마감 시각"), + fieldWithPath("data[].teamName").description("팀 이름"), + fieldWithPath("data[].missionTitle").description("미션 제목") + + ) + ) + ) + .andReturn(); + + } + + @Test + public void 미션_모아보기_반복_미션() throws Exception { + //given + + List output = Lists.newArrayList(GatherRepeatMissionRes.builder() + .missionId(1L) + .teamName("team name") + .missionTitle("mission title") + .doneNum("0") + .totalNum("0") + .build()); + + given(missionGatherBoardUseCase.getAllActiveRepeatMissions(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/my-repeat") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage()), + fieldWithPath("data[].missionId").description("미션 아이디"), + fieldWithPath("data[].teamName").description("팀 이름"), + fieldWithPath("data[].missionTitle").description("미션 제목"), + fieldWithPath("data[].doneNum").description("완료한 횟수"), + fieldWithPath("data[].totalNum").description("전체 횟수") + + + ) + ) + ) + .andReturn(); + + } + + + +} \ No newline at end of file From 7ce8f36e5668840a46172cf13b13b096c55e2fce Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 20 Oct 2023 14:34:26 +0900 Subject: [PATCH 154/619] =?UTF-8?q?feat=20:=20missionArchiveControlleTest?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveResponseMessage.java | 1 + .../MissionArchiveController.java | 2 +- .../presentation/MissionGatherController.java | 24 +----- .../MissionArchiveControllerTest.java | 76 ++++++++++--------- 4 files changed, 43 insertions(+), 60 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java index 9dec4edf..665b9444 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java @@ -8,6 +8,7 @@ public enum MissionArchiveResponseMessage { CREATE_ARCHIVE_SUCCESS("미션 인증을 완료 했습니다."), + UPDATE_ARCHIVE_SUCCESS("미션 재인증을 완료 했습니다."), READ_MY_ARCHIVE_SUCCESS("나의 미션 인증 현황 조회를 완료 했습니다."), READ_TEAM_ARCHIVE_SUCCESS("팀원 미션 인증 현황 조회를 완료 했습니다."), HEART_UPDATE_SUCCESS("미션 인증 좋아요를 성공적으로 눌렀습니다."), diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 944a36e5..c8af182b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -56,7 +56,7 @@ public ResponseEntity> updateArchive(@Authent @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId, @RequestBody MissionArchiveReq missionArchiveReq) { - return ResponseEntity.ok(SuccessResponse.create(CREATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveUpdateUseCase.updateArchive(user.getSocialId(), missionId,missionArchiveReq))); + return ResponseEntity.ok(SuccessResponse.create(UPDATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveUpdateUseCase.updateArchive(user.getSocialId(), missionId,missionArchiveReq))); } /** diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java index 0d86fe4a..7a964bd6 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java @@ -33,7 +33,7 @@ public class MissionGatherController { * 작성자 : 정승연 */ - @GetMapping("/my-single") + @GetMapping("/my-once") public ResponseEntity>> getMyActiveSingleMission(@AuthenticationPrincipal User user) { return ResponseEntity.ok(SuccessResponse.create(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getAllActiveSingleMissions(user.getSocialId()))); } @@ -49,27 +49,5 @@ public ResponseEntity>> getMyActive return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getAllActiveRepeatMissions( user.getSocialId()))); } - /** - * 모임별 미션 - 단일 미션 - * [GET] {teamId}/missions/board/repeat - * 작성자 : 정승연 - */ -// @GetMapping("/{teamId}/mission/single") -// public ResponseEntity>> geActiveRepeatMissionByTeam(@AuthenticationPrincipal User user, -// @PathVariable("teamId") Long teamId) { -// return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); -// } - /** - * 모임별 미션 - 반복 미션 - * [GET] {teamId}/missions/board/repeat - * 작성자 : 정승연 - */ -// @GetMapping("/{teamId}/mission/repeat") -// public ResponseEntity>> getActiveRepeatMissionByTeam(@AuthenticationPrincipal User user, -// @PathVariable("teamId") Long teamId) { -// return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionArchiveBoardUseCase.getActiveRepeatMissions(teamId, user.getSocialId()))); -// } - - } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index ae58b41c..1114ec38 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -60,9 +60,10 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .archiveId(1L) .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") - .hearts(3) .status("COMPLETE/SKIP") .count(1L) + .heartStatus("[True/False]") + .hearts(1L) .build(); given(missionArchiveCreateUseCase.createArchive(any(),any(),any())).willReturn(output); @@ -71,7 +72,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - post("/api/{teamId}/missions/{missionId}/archive",teamId,missionId) + post("/api/team/{teamId}/missions/{missionId}/archive",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) .content(body) @@ -124,9 +125,10 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .archiveId(1L) .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") - .hearts(3) .status("COMPLETE/SKIP") .count(1L) + .heartStatus("[True/False]") + .hearts(1L) .build(); given(missionArchiveUpdateUseCase.updateArchive(any(),any(),any())).willReturn(output); @@ -135,7 +137,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - put("/api/{teamId}/missions/{missionId}/archive",teamId,missionId) + put("/api/team/{teamId}/missions/{missionId}/archive",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) .content(body) @@ -159,14 +161,15 @@ public class MissionArchiveControllerTest extends CommonControllerTest { ), responseFields( fieldWithPath("isSuccess").description("true"), - fieldWithPath("message").description("미션 인증을 완료 했습니다."), + fieldWithPath("message").description(UPDATE_ARCHIVE_SUCCESS), fieldWithPath("data.archiveId").description("미션 인증 아이디"), fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data.createdDate").description("미션 제출 시각"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), fieldWithPath("data.status").description("미션 인증 상태"), - fieldWithPath("data.count").description("미션 인증 횟수") -// fieldWithPath("data.heartsStatus").description("미션 인증 좋아요 상태"), + fieldWithPath("data.count").description("미션 인증 횟수"), + fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태"), + fieldWithPath("data.hearts").description("미션 인증 좋아요 수") ) ) ) @@ -182,9 +185,10 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .archiveId(1L) .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") - .hearts(0) .status("COMPLETE/SKIP") - .count(1L) + .count(1L) + .heartStatus("[True/False]") + .hearts(1L) .build()); given(missionArchiveReadUseCase.getMyArchive(any(),any())).willReturn(output); @@ -193,7 +197,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/{teamId}/missions/{missionId}/archive",teamId,missionId) + get("/api/team/{teamId}/missions/{missionId}/archive",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) @@ -217,11 +221,13 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data[].archiveId").description("미션 인증 아이디"), fieldWithPath("data[].archive").description("미션 인증물 [s3URL/text/링크]"), fieldWithPath("data[].createdDate").description("미션 제출 시각"), - fieldWithPath("data[].hearts").description("미션 인증 좋아요 수"), fieldWithPath("data[].status").description("미션 인증 상태"), - fieldWithPath("data[].count").description("미션 인증 횟수") + fieldWithPath("data[].count").description("미션 인증 횟수"), + fieldWithPath("data[].heartStatus").description("미션 인증 좋아요 상태"), + fieldWithPath("data[].hearts").description("미션 인증 좋아요 수") - ) + + ) ) ) .andReturn(); @@ -238,9 +244,10 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .profileImg("[s3 Link]") .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") - .hearts(3) .status("COMPLETE/SKIP") - .count(1L) + .count(1L) + .heartStatus("[True/False]") + .hearts(3) .build()); given(missionArchiveReadUseCase.getPersonalArchive(any(),any())).willReturn(output); @@ -249,7 +256,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/{teamId}/missions/{missionId}/archive/others",teamId,missionId) + get("/api/team/{teamId}/missions/{missionId}/archive/others",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) @@ -269,17 +276,19 @@ public class MissionArchiveControllerTest extends CommonControllerTest { ), responseFields( fieldWithPath("isSuccess").description("true"), - fieldWithPath("message").description("팀원 미션 인증 현황 조회를 완료 했습니다."), + fieldWithPath("message").description(READ_TEAM_ARCHIVE_SUCCESS), fieldWithPath("data[].archiveId").description("미션 인증 아이디"), fieldWithPath("data[].nickname").description("미션 인증자 닉네임 "), fieldWithPath("data[].profileImg").description("미션 인증자 프로필 이미지 "), fieldWithPath("data[].archive").description("미션 인증물 [s3URL/text/링크] "), fieldWithPath("data[].createdDate").description("미션 인증 날짜 "), - fieldWithPath("data[].hearts").description("미션 인증 좋아요 수 "), fieldWithPath("data[].status").description("미션 인증 상태"), - fieldWithPath("data[].count").description("미션 인증 횟수") + fieldWithPath("data[].count").description("미션 인증 횟수"), + fieldWithPath("data[].heartStatus").description("미션 인증 좋아요 상태 "), + fieldWithPath("data[].hearts").description("미션 인증 좋아요 수 ") - ) + + ) ) ) .andReturn(); @@ -301,7 +310,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/{teamId}/missions/{missionId}/archive/status",teamId,missionId) + get("/api/team/{teamId}/missions/{missionId}/archive/status",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) @@ -334,16 +343,11 @@ public class MissionArchiveControllerTest extends CommonControllerTest { @Test public void 미션_인증물_좋아요() throws Exception { //given - MissionArchiveHeartReq input = MissionArchiveHeartReq.builder() - .archiveId(1L) - .heartStatus("content[s3 Link / text / link]") - .build(); - String body = objectMapper.writeValueAsString(input); MissionHeartRes output = MissionHeartRes.builder() .missionArchiveId(1L) - .missionHeartStatus("content[s3 Link / text / link]") + .missionHeartStatus("[True/False]") .hearts(3) .build(); @@ -351,12 +355,13 @@ public class MissionArchiveControllerTest extends CommonControllerTest { Long teamId = 1L; Long missionId = 1L; + Long archiveId = 1L; + String missionHeartStatus = "False"; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - post("/api/{teamId}/missions/{missionId}/archive/hearts", teamId, missionId) + put("/api/team/{teamId}/missions/{missionId}/archive/{archiveId}/heart/{missionHeartStatus}", teamId, missionId,archiveId,missionHeartStatus) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) - .content(body) ); //then @@ -369,17 +374,16 @@ public class MissionArchiveControllerTest extends CommonControllerTest { ), pathParameters( parameterWithName("teamId").description("팀 아이디"), - parameterWithName("missionId").description("미션 아이디") + parameterWithName("missionId").description("미션 아이디"), + parameterWithName("archiveId").description("미션 인증물 아이디"), + parameterWithName("missionHeartStatus").description("미션 인증물 좋아요 상태") ), - requestFields( - fieldWithPath("archiveId").description("미션 인증 아이디"), - fieldWithPath("heartStatus").description("미션 인증물 좋아요 상태 [True]") - ), + responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description(HEART_UPDATE_SUCCESS.getMessage()), - fieldWithPath("data.archiveId").description("미션 인증 아이디"), - fieldWithPath("data.heartStatus").description("미션 인증물 좋아요 상태 [True]"), + fieldWithPath("data.missionArchiveId").description("미션 인증 아이디"), + fieldWithPath("data.missionHeartStatus").description("미션 인증물 좋아요 상태 [True]"), fieldWithPath("data.hearts").description("미션 인증물 좋아요 수") ) From e4bbb77cd2eeb8bc62e18b746ca6a41043ef09d5 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 20 Oct 2023 14:36:45 +0900 Subject: [PATCH 155/619] =?UTF-8?q?feat=20:=20base=20url=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EB=B3=B8=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/representation/MissionControllerTest.java | 8 ++++---- .../representation/MissionBoardControllerTest.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index 6b7424de..ed9391ee 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -86,7 +86,7 @@ public class MissionControllerTest extends CommonControllerTest { Long teamId = 2L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - post("/api/{teamId}/missions",teamId) + post("/api/team/{teamId}/missions",teamId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) .content(body) @@ -164,7 +164,7 @@ public class MissionControllerTest extends CommonControllerTest { //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - put("/api/{teamId}/missions/{missionId}",teamId,missionId) + put("/api/team/{teamId}/missions/{missionId}",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) .content(body) @@ -231,7 +231,7 @@ public class MissionControllerTest extends CommonControllerTest { Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/{teamId}/missions/{missionId}",teamId,missionId) + get("/api/team/{teamId}/missions/{missionId}",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) @@ -275,7 +275,7 @@ public class MissionControllerTest extends CommonControllerTest { Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - delete("/api/{teamId}/missions/{missionId}",teamId,missionId) + delete("/api/team/{teamId}/missions/{missionId}",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) ); diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java index e2361a30..5cdfd3fe 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java @@ -53,7 +53,7 @@ public class MissionBoardControllerTest extends CommonControllerTest { Long teamId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/{teamId}/missions/board/single",teamId) + get("/api/team/{teamId}/missions/board/single",teamId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) @@ -103,7 +103,7 @@ public class MissionBoardControllerTest extends CommonControllerTest { Long teamId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/{teamId}/missions/board/repeat",teamId) + get("/api/team/{teamId}/missions/board/repeat",teamId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) @@ -153,7 +153,7 @@ public class MissionBoardControllerTest extends CommonControllerTest { Long teamId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/{teamId}/missions/board/finish",teamId) + get("/api/team/{teamId}/missions/board/finish",teamId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) From b0a8754fc0875824898f0edba57df440d33c49c9 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 20 Oct 2023 14:44:14 +0900 Subject: [PATCH 156/619] =?UTF-8?q?feat=20:=20MissionGatherBoard-API.adoc?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1=20=EB=B0=8F=20api.adoc=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionGatherBoard-API.adoc | 16 ++++++++++++++++ src/docs/asciidoc/api.adoc | 2 ++ 2 files changed, 18 insertions(+) create mode 100644 src/docs/asciidoc/MissionGatherBoard-API.adoc diff --git a/src/docs/asciidoc/MissionGatherBoard-API.adoc b/src/docs/asciidoc/MissionGatherBoard-API.adoc new file mode 100644 index 00000000..4e78a299 --- /dev/null +++ b/src/docs/asciidoc/MissionGatherBoard-API.adoc @@ -0,0 +1,16 @@ + + +[[MissionGatherBoard-API]] += MissionBoard API + +[[MissionBoard-미션-모아보기-단일]] +=== 미션_모아보기_단일_미션 +operation::mission-gather-controller-test/미션_모아보기_단일_미션[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +[[MissionBoard-미션-모아보기-반복]] +=== 미션_모아보기_반복_미션 +operation::mission-gather-controller-test/미션_모아보기_반복_미션[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 12774927..5279620f 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -22,6 +22,8 @@ include::MissionArchive-API.adoc[] include::MissionBoard-API.adoc[] +include::MissionGatherBoard-API.adoc[] + include::Fire-API.adoc[] include::Board-API.adoc[] From eeab55efd6cbf5d9e0c5d90696d8daddc21c09ed Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 20 Oct 2023 15:44:00 +0900 Subject: [PATCH 157/619] =?UTF-8?q?feat=20:=20getTeamIdByMemberId=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionGatherBoardUseCase.java | 1 + .../mission/domain/service/MissionQueryService.java | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java index 57c2b51e..ba04e12d 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.mission.application.service; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 7b497908..2bd9070b 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -1,11 +1,14 @@ package com.moing.backend.domain.mission.domain.service; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.exception.NotFoundMissionException; import com.moing.backend.domain.mission.domain.repository.MissionRepository; +import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -19,6 +22,7 @@ public class MissionQueryService { private final MissionRepository missionRepository; + private final TeamGetService teamGetService; public Mission findMissionById(Long missionId) { return missionRepository.findById(missionId).orElseThrow(NotFoundMissionException::new); @@ -29,17 +33,12 @@ public Long findMissionsCountByTeam(Long teamId) { } public List findAllRepeatMission(Long memberId) { - List teams = new ArrayList<>(); - teams.add(1L); - teams.add(2L); + List teams = teamGetService.getTeamIdByMemberId(memberId); return missionRepository.findRepeatMissionByMemberId(memberId,teams).orElseThrow(NotFoundMissionException::new); } public List findAllSingleMission(Long memberId) { - - List teams = new ArrayList<>(); - teams.add(1L); - teams.add(2L); + List teams = teamGetService.getTeamIdByMemberId(memberId); return missionRepository.findSingleMissionByMemberId(memberId, teams).orElseThrow(NotFoundMissionException::new); } } From c590fdbcb5d6e27249c1acf8884196ec4b48dbc1 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 21 Oct 2023 12:11:26 +0900 Subject: [PATCH 158/619] =?UTF-8?q?feat:=20=ED=8C=80=20=EA=B0=95=EC=A0=9C?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=EC=8B=9C=20=ED=8C=80=EC=9B=90=20=EB=AA=A8?= =?UTF-8?q?=EB=91=90=20isDeleted=20true?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/DeleteTeamResponse.java | 5 +++++ .../application/service/DisbandTeamUserCase.java | 5 +++-- .../domain/repository/TeamMemberRepository.java | 7 +++++++ .../domain/service/TeamMemberDeleteService.java | 16 ++++++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberDeleteService.java diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java index 92ed9017..8cc78bb2 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java @@ -11,4 +11,9 @@ @NoArgsConstructor public class DeleteTeamResponse { private Long teamId; + private String teamName; + private Integer numOfMember; + private Long duration; //걸린시간(단위:날짜) + private Long numOfMission; + private Integer levelOfFire; //불꽃 레벨 } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java index 77ef8c86..cf4515be 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.team.exception.NotAuthByTeamException; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberDeleteService; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -21,14 +22,14 @@ public class DisbandTeamUserCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; private final CheckLeaderUserCase checkLeaderUserCase; - private final TeamMemberGetService teamMemberGetService; + private final TeamMemberDeleteService teamMemberDeleteService; public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); if (checkLeaderUserCase.isTeamLeader(member, team)) { - //TODO: 팀의 모든 멤버 isDeleted true 해주환 + teamMemberDeleteService.deleteAllTeamMembers(team.getTeamId()); team.deleteTeam(); } else { throw new NotAuthByTeamException(); diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java index 6bcc3808..eff05c34 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java @@ -4,10 +4,17 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import javax.swing.text.html.Option; import java.util.Optional; public interface TeamMemberRepository extends JpaRepository, TeamMemberCustomRepository{ Optional findTeamMemberByTeamAndMember(Team team, Member member); + + @Modifying + @Query("update TeamMember t set t.isDeleted = true where t.team.teamId = :teamId") + void deleteTeamMembers(Long teamId); + } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberDeleteService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberDeleteService.java new file mode 100644 index 00000000..5cdef8ac --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberDeleteService.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.teamMember.domain.service; + +import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class TeamMemberDeleteService { + + private final TeamMemberRepository teamMemberRepository; + + public void deleteAllTeamMembers(Long teamId){ + teamMemberRepository.deleteTeamMembers(teamId); + } +} From 209073aa3f42c425fd911bf6feed4fe1a36664e2 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 21 Oct 2023 14:26:39 +0900 Subject: [PATCH 159/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=ED=83=88=ED=87=B4,=20=EA=B0=95=EC=A0=9C=EC=A2=85=EB=A3=8C=20re?= =?UTF-8?q?sponse=20dto=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/domain/entity/Member.java | 7 ------ .../team/application/mapper/TeamMapper.java | 22 +++++++++++++++++++ .../service/DisbandTeamUserCase.java | 6 ++++- .../service/WithdrawTeamUserCase.java | 8 +++++-- .../domain/team/domain/entity/Team.java | 4 ++++ .../teamMember/domain/entity/TeamMember.java | 3 ++- 6 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index 2899fbbd..06bef64f 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -156,11 +156,4 @@ public Member(LocalDate birthDate, String email, String fcmToken, Gender gender, this.socialId = socialId; } - public void deleteTeamMember(){ - List teamMemberList=this.getTeamMembers(); - for(TeamMember teamMember:teamMemberList){ - teamMember.deleteMember(); - } - } - } diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index 6debf056..b658b662 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; +import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamDetailResponse; import com.moing.backend.domain.team.application.dto.response.TeamInfo; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; @@ -10,6 +11,9 @@ import com.moing.backend.domain.team.domain.entity.Team; import org.springframework.stereotype.Component; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.ChronoUnit; import java.util.List; @Component @@ -36,4 +40,22 @@ public GetTeamDetailResponse toTeamDetailResponse(Team team, Integer boardNum, L .teamInfo(teamInfo) .build(); } + + public DeleteTeamResponse toDeleteTeamResponse(Long numOfMission, Team team){ + return DeleteTeamResponse.builder() + .teamId(team.getTeamId()) + .teamName(team.getName()) + .numOfMember(team.getNumOfMember()) + .levelOfFire(team.getLevelOfFire()) + .duration(calculateDuration(team.getApprovalTime())) + .numOfMission(numOfMission) + .build(); + } + + private Long calculateDuration(LocalDateTime approvalTime) { + ZoneId seoulZoneId = ZoneId.of("Asia/Seoul"); + LocalDateTime currentSeoulTime = LocalDateTime.now(seoulZoneId).withSecond(0).withNano(0); + LocalDateTime adjustedApprovalTime = approvalTime.withSecond(0).withNano(0); + return ChronoUnit.DAYS.between(adjustedApprovalTime, currentSeoulTime); + } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java index cf4515be..a0c7a7ee 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java @@ -2,7 +2,9 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; +import com.moing.backend.domain.team.application.mapper.TeamMapper; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.team.exception.NotAuthByTeamException; @@ -23,6 +25,8 @@ public class DisbandTeamUserCase { private final TeamGetService teamGetService; private final CheckLeaderUserCase checkLeaderUserCase; private final TeamMemberDeleteService teamMemberDeleteService; + private final MissionQueryService missionQueryService; + private final TeamMapper teamMapper; public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); @@ -34,6 +38,6 @@ public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { } else { throw new NotAuthByTeamException(); } - return new DeleteTeamResponse(team.getTeamId()); + return teamMapper.toDeleteTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()), team); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java index 46c42dfa..15538b62 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java @@ -2,7 +2,9 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; +import com.moing.backend.domain.team.application.mapper.TeamMapper; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; @@ -20,12 +22,14 @@ public class WithdrawTeamUserCase { private final TeamMemberGetService teamMemberGetService; private final MemberGetService memberGetService; private final TeamGetService teamGetService; + private final MissionQueryService missionQueryService; + private final TeamMapper teamMapper; public DeleteTeamResponse withdrawTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); - teamMember.deleteMember(); - return new DeleteTeamResponse(team.getTeamId()); + teamMember.deleteMember(team); + return teamMapper.toDeleteTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()),team); } } diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java index 1b4f531e..8d5e1989 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -87,4 +87,8 @@ public void deleteTeam() { public void addTeamMember(){ numOfMember++; } + + public void deleteTeamMember(){ + numOfMember--; + } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java index c30cf2ed..9769d51f 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java @@ -42,7 +42,8 @@ public void updateMember(Member member) { member.getTeamMembers().add(this); } - public void deleteMember() { + public void deleteMember(Team team) { this.isDeleted = true; + team.deleteTeamMember(); } } From 69f2f4e596077bdc85e653853cf41536ebe2a228 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 21 Oct 2023 19:40:30 +0900 Subject: [PATCH 160/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=ED=83=88=ED=87=B4,=20=EA=B0=95=EC=A0=9C=EC=A2=85=EB=A3=8C=20te?= =?UTF-8?q?st=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/presentation/TeamControllerTest.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 4f84f31a..f5e85a83 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -157,7 +157,7 @@ public void get_team() throws Exception { fieldWithPath("data.teamBlocks[0].duration").description("소모임과 함께한 시간"), fieldWithPath("data.teamBlocks[0].levelOfFire").description("불꽃 레벨"), fieldWithPath("data.teamBlocks[0].teamName").description("소모임 이름"), - fieldWithPath("data.teamBlocks[0].numOfMember").description("소모임원 숫자"), + fieldWithPath("data.teamBlocks[0].numOfMember").description("소모임원 명 수"), fieldWithPath("data.teamBlocks[0].category").description("소모임 카테고리"), fieldWithPath("data.teamBlocks[0].startDate").description("소모임 시작일") ) @@ -242,6 +242,11 @@ public void disband_team() throws Exception { Long teamId = 1L; // 예시 ID DeleteTeamResponse output = DeleteTeamResponse.builder() .teamId(teamId) + .teamName("팀 이름") + .numOfMember(9) + .duration(30L) + .numOfMission(90L) + .levelOfFire(3) .build(); given(disbandTeamUserCase.disbandTeam(any(), any())).willReturn(output); @@ -267,7 +272,12 @@ public void disband_team() throws Exception { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("[소모임장 권한] 소모임을 강제 종료했습니다."), - fieldWithPath("data.teamId").description("강제종료한 소모임 id") + fieldWithPath("data.teamId").description("강제종료한 소모임 id"), + fieldWithPath("data.teamName").description("소모임 이름"), + fieldWithPath("data.numOfMember").description("모임원 명 수"), + fieldWithPath("data.duration").description("소모임과 함께한 시간"), + fieldWithPath("data.levelOfFire").description("소모임 불꽃 레벨"), + fieldWithPath("data.numOfMission").description("미션 총 개수") ) ) ); @@ -278,6 +288,11 @@ public void withdraw_team() throws Exception { Long teamId = 1L; // 예시 ID DeleteTeamResponse output = DeleteTeamResponse.builder() .teamId(teamId) + .teamName("팀 이름") + .numOfMember(9) + .duration(30L) + .numOfMission(90L) + .levelOfFire(3) .build(); given(withdrawTeamUserCase.withdrawTeam(any(), any())).willReturn(output); @@ -303,7 +318,12 @@ public void withdraw_team() throws Exception { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("[소모임원 권한] 소모임을 탈퇴하였습니다"), - fieldWithPath("data.teamId").description("탈퇴한 소모임 id") + fieldWithPath("data.teamId").description("탈퇴한 소모임 id"), + fieldWithPath("data.teamName").description("소모임 이름"), + fieldWithPath("data.numOfMember").description("모임원 명 수"), + fieldWithPath("data.duration").description("소모임과 함께한 시간"), + fieldWithPath("data.levelOfFire").description("소모임 불꽃 레벨"), + fieldWithPath("data.numOfMission").description("미션 총 개수") ) ) ); From 156534af636707eecb171a0ffbe93053379bfeef Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 21 Oct 2023 20:06:55 +0900 Subject: [PATCH 161/619] =?UTF-8?q?fix:=20=EB=82=A0=EC=A7=9C=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/team/application/dto/response/TeamBlock.java | 8 +++++--- .../domain/team/application/mapper/TeamMapper.java | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java index 763d9248..4580219b 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java @@ -7,6 +7,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; @@ -38,9 +39,10 @@ public TeamBlock(Long teamId, LocalDateTime approvalTime, Integer levelOfFire, S private Long calculateDuration(LocalDateTime approvalTime) { ZoneId seoulZoneId = ZoneId.of("Asia/Seoul"); - LocalDateTime currentSeoulTime = LocalDateTime.now(seoulZoneId).withSecond(0).withNano(0); - LocalDateTime adjustedApprovalTime = approvalTime.withSecond(0).withNano(0); - return ChronoUnit.DAYS.between(adjustedApprovalTime, currentSeoulTime); + LocalDate currentDate = LocalDate.now(seoulZoneId); + LocalDate approvalDate = approvalTime.toLocalDate(); + return ChronoUnit.DAYS.between(approvalDate, currentDate); } + } diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index b658b662..4f4b2080 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -11,6 +11,7 @@ import com.moing.backend.domain.team.domain.entity.Team; import org.springframework.stereotype.Component; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.temporal.ChronoUnit; @@ -54,8 +55,9 @@ public DeleteTeamResponse toDeleteTeamResponse(Long numOfMission, Team team){ private Long calculateDuration(LocalDateTime approvalTime) { ZoneId seoulZoneId = ZoneId.of("Asia/Seoul"); - LocalDateTime currentSeoulTime = LocalDateTime.now(seoulZoneId).withSecond(0).withNano(0); - LocalDateTime adjustedApprovalTime = approvalTime.withSecond(0).withNano(0); - return ChronoUnit.DAYS.between(adjustedApprovalTime, currentSeoulTime); + LocalDate currentDate = LocalDate.now(seoulZoneId); + LocalDate approvalDate = approvalTime.toLocalDate(); + return ChronoUnit.DAYS.between(approvalDate, currentDate); } + } From 84c04c8847483895b671dd63965e89132b86a9de Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 22 Oct 2023 10:07:29 +0900 Subject: [PATCH 162/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EA=B0=95=EC=A0=9C=EC=A2=85=EB=A3=8C=20=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/TeamBlock.java | 15 ++++++---- .../application/dto/response/TeamInfo.java | 3 ++ .../team/application/mapper/TeamMapper.java | 13 +++++---- .../service/DisbandTeamUserCase.java | 5 ---- .../domain/team/domain/entity/Team.java | 2 +- .../repository/TeamCustomRepositoryImpl.java | 29 ++++++++++++++----- .../repository/TeamMemberRepository.java | 4 --- .../service/TeamMemberDeleteService.java | 16 ---------- .../team/presentation/TeamControllerTest.java | 10 ++++++- 9 files changed, 52 insertions(+), 45 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberDeleteService.java diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java index 4580219b..c4988a47 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java @@ -25,9 +25,10 @@ public class TeamBlock { private Integer numOfMember; private String category; private String startDate; + private LocalDateTime deletionTime; @QueryProjection - public TeamBlock(Long teamId, LocalDateTime approvalTime, Integer levelOfFire, String teamName, Integer numOfMember, Category category){ + public TeamBlock(Long teamId, LocalDateTime approvalTime, Integer levelOfFire, String teamName, Integer numOfMember, Category category, LocalDateTime deletionTime){ this.teamId=teamId; this.duration=calculateDuration(approvalTime); this.levelOfFire=levelOfFire; @@ -35,13 +36,17 @@ public TeamBlock(Long teamId, LocalDateTime approvalTime, Integer levelOfFire, S this.numOfMember=numOfMember; this.category=category.getMessage(); this.startDate=approvalTime.toLocalDate().format(DateTimeFormatter.ofPattern("yyyy.MM.dd")); + this.deletionTime=deletionTime; } - private Long calculateDuration(LocalDateTime approvalTime) { + public Long calculateDuration(LocalDateTime approvalTime) { ZoneId seoulZoneId = ZoneId.of("Asia/Seoul"); - LocalDate currentDate = LocalDate.now(seoulZoneId); - LocalDate approvalDate = approvalTime.toLocalDate(); - return ChronoUnit.DAYS.between(approvalDate, currentDate); + LocalDateTime currentDateTime = LocalDateTime.now(seoulZoneId); + + long hoursBetween = ChronoUnit.HOURS.between(approvalTime, currentDateTime); + long daysBetween = hoursBetween / 24; + + return daysBetween; } } diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java index 63574fd6..77dc2c8c 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java @@ -5,6 +5,7 @@ import lombok.Builder; import lombok.Getter; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -12,6 +13,8 @@ @Getter @Builder public class TeamInfo { + private Boolean isDeleted; + private LocalDateTime deletionTime; private String teamName; //소모임 이름 private Integer numOfMember; //소모임원 수 private Category category; //카테고리 diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index 4f4b2080..ec4ba6ac 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -35,7 +35,7 @@ public Team createTeam(CreateTeamRequest createTeamRequest, Member member) { } public GetTeamDetailResponse toTeamDetailResponse(Team team, Integer boardNum, List teamMemberInfoList) { - TeamInfo teamInfo = new TeamInfo(team.getName(), teamMemberInfoList.size(), team.getCategory(), team.getIntroduction(), teamMemberInfoList); + TeamInfo teamInfo = new TeamInfo(team.isDeleted(), team.getDeletionTime(), team.getName(), teamMemberInfoList.size(), team.getCategory(), team.getIntroduction(), teamMemberInfoList); return GetTeamDetailResponse.builder() .boardNum(boardNum) .teamInfo(teamInfo) @@ -53,11 +53,14 @@ public DeleteTeamResponse toDeleteTeamResponse(Long numOfMission, Team team){ .build(); } - private Long calculateDuration(LocalDateTime approvalTime) { + public Long calculateDuration(LocalDateTime approvalTime) { ZoneId seoulZoneId = ZoneId.of("Asia/Seoul"); - LocalDate currentDate = LocalDate.now(seoulZoneId); - LocalDate approvalDate = approvalTime.toLocalDate(); - return ChronoUnit.DAYS.between(approvalDate, currentDate); + LocalDateTime currentDateTime = LocalDateTime.now(seoulZoneId); + + long hoursBetween = ChronoUnit.HOURS.between(approvalTime, currentDateTime); + long daysBetween = hoursBetween / 24; + + return daysBetween; } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java index a0c7a7ee..f0e88b2e 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java @@ -8,9 +8,6 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.team.exception.NotAuthByTeamException; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberDeleteService; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -24,7 +21,6 @@ public class DisbandTeamUserCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; private final CheckLeaderUserCase checkLeaderUserCase; - private final TeamMemberDeleteService teamMemberDeleteService; private final MissionQueryService missionQueryService; private final TeamMapper teamMapper; @@ -33,7 +29,6 @@ public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { Team team = teamGetService.getTeamByTeamId(teamId); if (checkLeaderUserCase.isTeamLeader(member, team)) { - teamMemberDeleteService.deleteAllTeamMembers(team.getTeamId()); team.deleteTeam(); } else { throw new NotAuthByTeamException(); diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java index 8d5e1989..a028794e 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -80,7 +80,7 @@ public void updateTeam(String name, String introduction, String profileImgUrl) { } public void deleteTeam() { - this.isDeleted = true; + this.isDeleted=true; this.deletionTime = LocalDateTime.now(ZoneId.of("Asia/Seoul")).withNano(0); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index f1642ab7..be1b15ab 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -4,9 +4,12 @@ import com.moing.backend.domain.team.application.dto.response.*; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.moing.backend.domain.team.domain.entity.Team; +import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; +import java.sql.Timestamp; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -30,40 +33,50 @@ public GetTeamResponse findTeamByMemberId(Long memberId) { @Override public Optional findTeamByTeamId(Long teamId) { + LocalDateTime threeDaysAgo = LocalDateTime.now().minusDays(3); + return Optional.ofNullable(queryFactory.selectFrom(team) .where(team.teamId.eq(teamId)) - .where(team.isDeleted.eq(false)) + .where(team.isDeleted.eq(false) // 강제종료되지 않았거나 + .or(team.deletionTime.after(threeDaysAgo))) // 강제종료된 경우 3일이 지나지 않았다면 .fetchOne()); } @Override public List findTeamIdByMemberId(Long memberId){ + LocalDateTime threeDaysAgo = LocalDateTime.now().minusDays(3); + return queryFactory .select(team.teamId) .from(teamMember) .innerJoin(teamMember.team, team) .on(teamMember.member.memberId.eq(memberId)) - .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) //승인 되었고 - .where(team.isDeleted.eq(false)) //강제종료되었는지 - .where(teamMember.isDeleted.eq(false)) //탈퇴했는지 + .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) // 승인 되었고 + .where(teamMember.isDeleted.eq(false)) // 탈퇴하지 않았다면 + .where(team.isDeleted.eq(false) // 강제종료되지 않았거나 + .or(team.deletionTime.after(threeDaysAgo))) // 강제종료된 경우 3일이 지나지 않았다면 .orderBy(team.approvalTime.asc()) .fetch(); } private List getTeamBlock(Long memberId) { + LocalDateTime threeDaysAgo = LocalDateTime.now().minusDays(3); + return queryFactory .select(new QTeamBlock(team.teamId, team.approvalTime, team.levelOfFire, team.name, team.numOfMember, - team.category)) + team.category, + team.deletionTime)) .from(teamMember) .innerJoin(teamMember.team, team) .on(teamMember.member.memberId.eq(memberId)) - .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) //승인 되었고 - .where(team.isDeleted.eq(false)) //강제종료되었는지 - .where(teamMember.isDeleted.eq(false)) //탈퇴했는지 + .where(teamMember.isDeleted.eq(false)) // 탈퇴하지 않았다면 + .where(team.isDeleted.eq(false) // 강제종료되지 않았거나 + .or(team.deletionTime.isNotNull() + .or(team.deletionTime.after(threeDaysAgo)))) // 강제종료된 경우 3일이 지나지 않았다면 .orderBy(team.approvalTime.asc()) .fetch(); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java index eff05c34..42d665b9 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java @@ -13,8 +13,4 @@ public interface TeamMemberRepository extends JpaRepository, TeamMemberCustomRepository{ Optional findTeamMemberByTeamAndMember(Team team, Member member); - @Modifying - @Query("update TeamMember t set t.isDeleted = true where t.team.teamId = :teamId") - void deleteTeamMembers(Long teamId); - } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberDeleteService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberDeleteService.java deleted file mode 100644 index 5cdef8ac..00000000 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberDeleteService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.moing.backend.domain.teamMember.domain.service; - -import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; -import com.moing.backend.global.annotation.DomainService; -import lombok.RequiredArgsConstructor; - -@DomainService -@RequiredArgsConstructor -public class TeamMemberDeleteService { - - private final TeamMemberRepository teamMemberRepository; - - public void deleteAllTeamMembers(Long teamId){ - teamMemberRepository.deleteTeamMembers(teamId); - } -} diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index f5e85a83..615b0557 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -13,6 +13,7 @@ import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; import org.springframework.test.web.servlet.ResultActions; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -108,6 +109,7 @@ public void get_team() throws Exception { .numOfMember(10) .category("ETC") .startDate("2023.09.05") + .deletionTime(LocalDateTime.now().withNano(0)) .build(); TeamBlock teamBlock2=TeamBlock.builder() @@ -118,6 +120,7 @@ public void get_team() throws Exception { .numOfMember(8) .category("SPORTS") .startDate("2023.09.01") + .deletionTime(LocalDateTime.now().withNano(0)) .build(); teamBlocks.add(teamBlock1); @@ -159,7 +162,8 @@ public void get_team() throws Exception { fieldWithPath("data.teamBlocks[0].teamName").description("소모임 이름"), fieldWithPath("data.teamBlocks[0].numOfMember").description("소모임원 명 수"), fieldWithPath("data.teamBlocks[0].category").description("소모임 카테고리"), - fieldWithPath("data.teamBlocks[0].startDate").description("소모임 시작일") + fieldWithPath("data.teamBlocks[0].startDate").description("소모임 시작일"), + fieldWithPath("data.teamBlocks[0].deletionTime").description("소모임 삭제 시간 (삭제 안했으면 null)") ) ) @@ -182,6 +186,8 @@ public void get_team_detail() throws Exception { TeamInfo teamInfo = TeamInfo .builder() + .isDeleted(true) + .deletionTime(LocalDateTime.now()) .teamName("소모임 이름") .numOfMember(1) .category(Category.ETC) @@ -225,6 +231,8 @@ public void get_team_detail() throws Exception { fieldWithPath("data.teamInfo.numOfMember").description("모임원 명 수"), fieldWithPath("data.teamInfo.category").description("카테고리"), fieldWithPath("data.teamInfo.introduction").description("모임 소개"), + fieldWithPath("data.teamInfo.isDeleted").description("삭제여부"), + fieldWithPath("data.teamInfo.deletionTime").description("삭제 시간 (삭제 안했으면 null)"), fieldWithPath("data.teamInfo.teamMemberInfoList[0].memberId").description("유저 아이디"), fieldWithPath("data.teamInfo.teamMemberInfoList[0].nickName").description("유저 닉네임"), fieldWithPath("data.teamInfo.teamMemberInfoList[0].profileImage").description("유저 프로필 이미지"), From 1e892f4d72edbad31e01ae714c04647d5e2bdd22 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 22 Oct 2023 14:15:15 +0900 Subject: [PATCH 163/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EC=B2=9C=EC=9D=84=20=EC=9C=84=ED=95=9C=20=ED=8C=80=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=A6=AC=ED=84=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionReadUseCase.java | 9 ++++ .../domain/repository/MissionRepository.java | 2 + .../presentation/MissionController.java | 19 +++++++-- .../constant/MissionResponseMessage.java | 3 +- .../representation/MissionControllerTest.java | 41 +++++++++++++++++++ 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java index 0bc52c51..7092685a 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java @@ -7,6 +7,8 @@ import com.moing.backend.domain.mission.application.mapper.MissionMapper; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.global.util.SecurityUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,6 +22,8 @@ public class MissionReadUseCase { private final MissionQueryService missionQueryService; private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + public MissionReadRes getMission(String userSocialId, Long missionId) { Member member = memberGetService.getMemberBySocialId(userSocialId); @@ -28,4 +32,9 @@ public MissionReadRes getMission(String userSocialId, Long missionId) { return MissionMapper.mapToMissionReadRes(mission); } + public String getTeamCategory(Long teamId) { + Team team = teamGetService.getTeamByTeamId(teamId); + return team.getCategory().name(); + } + } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java index 5244df48..28dc00ec 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionRepository.java @@ -2,6 +2,8 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface MissionRepository extends JpaRepository,MissionCustomRepository { } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index f2a33bd5..12362a25 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -32,7 +32,7 @@ public class MissionController { /** * 미션 조회 - * [GET] {teamId}/mission/{missionId} + * [GET] {teamId}/missions/{missionId} * 작성자 : 정승연 */ @@ -45,7 +45,7 @@ public ResponseEntity> getMission(@Authenticatio /** * 미션 생성 - * [POST] {teamId}/mission + * [POST] {teamId}/missions * 작성자 : 정승연 */ @@ -56,7 +56,7 @@ public ResponseEntity> createMission(@Authenti /** * 미션 수정 - * [PUT] {teamId}/mission/{missionId} + * [PUT] {teamId}/missions/{missionId} * 작성자 : 정승연 */ @PutMapping("/{missionId}") @@ -66,7 +66,7 @@ public ResponseEntity> updateMission(@Authenti /** * 미션 삭제 - * [DELETE] {teamId}/mission/{missionId} + * [DELETE] {teamId}/missions/{missionId} * 작성자 : 정승연 */ @DeleteMapping("/{missionId}") @@ -74,5 +74,16 @@ public ResponseEntity> deleteMission(@AuthenticationPrinci return ResponseEntity.ok(SuccessResponse.create(DELETE_MISSION_SUCCESS.getMessage(), this.missionDeleteUseCase.deleteMission(user.getSocialId(),missionId))); } + /** + * 미션 추천 + * [GET] {teamId}/missions/recommend + * 작성자 : 정승연 + */ + + @GetMapping("/recommend") + public ResponseEntity> recommendMission(@AuthenticationPrincipal User user,@PathVariable Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getTeamCategory(teamId))); + } + } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java b/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java index 4e11314c..757a41d4 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java @@ -9,7 +9,8 @@ public enum MissionResponseMessage { CREATE_MISSION_SUCCESS("미션 생성을 완료 했습니다"), READ_MISSION_SUCCESS("미션 조회를 완료 했습니다"), UPDATE_MISSION_SUCCESS("미션 수정을 완료 했습니다"), - DELETE_MISSION_SUCCESS("미션 삭제를 완료 했습니다"); + DELETE_MISSION_SUCCESS("미션 삭제를 완료 했습니다"), + RECOMMEND_MISSION_SUCCESS("미션 추천을 위한 팀 카테고리를 조회 했습니다"); private final String message; } diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index ed9391ee..d036c41b 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -23,6 +23,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.RECOMMEND_MISSION_SUCCESS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.http.ResponseEntity.status; @@ -301,4 +302,44 @@ public class MissionControllerTest extends CommonControllerTest { ) .andReturn(); } + + @Test + public void 미션_추천() throws Exception { + //given + + + String output = "" ; + + given(missionReadUseCase.getTeamCategory(any())).willReturn(output); + + Long teamId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/{teamId}/missions/recommend",teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(RECOMMEND_MISSION_SUCCESS), + fieldWithPath("data").description("팀 카테고리 [SPORTS/HABIT/TEST/STUDY/READING/ETC] ") + ) + ) + ) + .andReturn(); + + } } From c3763e2040dee16327249da6af2408ca47e4cbcc Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 22 Oct 2023 14:18:27 +0900 Subject: [PATCH 164/619] =?UTF-8?q?feat=20:=20mission=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20adoc=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Mission-API.adoc | 7 +++++++ src/docs/asciidoc/MissionGatherBoard-API.adoc | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/docs/asciidoc/Mission-API.adoc b/src/docs/asciidoc/Mission-API.adoc index 2485c8fb..86669d71 100644 --- a/src/docs/asciidoc/Mission-API.adoc +++ b/src/docs/asciidoc/Mission-API.adoc @@ -27,3 +27,10 @@ operation::mission-controller-test/미션_삭제[snippets='http-request,path-par --- + +[[Mission-추천]] +=== Mission 추천 +operation::mission-controller-test/미션_추천[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + diff --git a/src/docs/asciidoc/MissionGatherBoard-API.adoc b/src/docs/asciidoc/MissionGatherBoard-API.adoc index 4e78a299..b4716751 100644 --- a/src/docs/asciidoc/MissionGatherBoard-API.adoc +++ b/src/docs/asciidoc/MissionGatherBoard-API.adoc @@ -1,7 +1,7 @@ [[MissionGatherBoard-API]] -= MissionBoard API += MissionGatherBoard API [[MissionBoard-미션-모아보기-단일]] === 미션_모아보기_단일_미션 From f6dabae40f8f013e9abc0d2ffc4796d4de01cf2b Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 22 Oct 2023 15:07:43 +0900 Subject: [PATCH 165/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=83=81=ED=83=9C=20=EC=A0=80=EC=9E=A5=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20MissionState=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionTerminationUseCase.java | 5 ++-- .../MissionArchiveCustomRepositoryImpl.java | 2 +- .../application/dto/MissionStatusRes.java | 2 +- .../domain/entity/MissionState.java} | 9 +++--- .../missionState/domain/entity/Status.java | 5 ++++ .../MissionStateCustomRepository.java | 4 +++ .../MissionStateCustomRepositoryImpl.java | 27 +++++++++++++++++ .../repository/MissionStateRepository.java | 7 +++++ .../service/MissionStateSaveService.java | 29 ++++++++++++++++++ .../missionStatus/domain/entity/Status.java | 5 ---- .../MissionStatusCustomRepository.java | 4 --- .../MissionStatusCustomRepositoryImpl.java | 30 ------------------- .../repository/MissionStatusRepository.java | 7 ----- .../service/MissionStatusSaveService.java | 28 ----------------- 14 files changed, 81 insertions(+), 83 deletions(-) rename src/main/java/com/moing/backend/domain/{missionStatus => missionState}/application/dto/MissionStatusRes.java (56%) rename src/main/java/com/moing/backend/domain/{missionStatus/domain/entity/MissionStatus.java => missionState/domain/entity/MissionState.java} (68%) create mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java create mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java delete mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/entity/Status.java delete mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepository.java delete mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepositoryImpl.java delete mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusRepository.java delete mode 100644 src/main/java/com/moing/backend/domain/missionStatus/domain/service/MissionStatusSaveService.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java index ecd93df0..f49ba964 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java @@ -4,7 +4,6 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.missionStatus.domain.repository.MissionStatusRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,10 +30,10 @@ public void terminateMission() { ); } - // 미션 점수 반영 -> MissionStatus + // 미션 점수 반영 -> MissionState - // MissionStatus 조회 해서 미션 점수 현황조회 + // MissionState 조회 해서 미션 점수 현황조회 public void getMissionScoreStatus() { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 95a8dedd..96f89feb 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -122,7 +122,7 @@ public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) // @Override -// public Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status) { +// public Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionState status) { // return Optional.ofNullable(queryFactory // .select(Projections.constructor(RepeatMissionBoardRes.class, // missionArchive.mission.id, diff --git a/src/main/java/com/moing/backend/domain/missionStatus/application/dto/MissionStatusRes.java b/src/main/java/com/moing/backend/domain/missionState/application/dto/MissionStatusRes.java similarity index 56% rename from src/main/java/com/moing/backend/domain/missionStatus/application/dto/MissionStatusRes.java rename to src/main/java/com/moing/backend/domain/missionState/application/dto/MissionStatusRes.java index d3f50d40..0e12354f 100644 --- a/src/main/java/com/moing/backend/domain/missionStatus/application/dto/MissionStatusRes.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/dto/MissionStatusRes.java @@ -1,4 +1,4 @@ -package com.moing.backend.domain.missionStatus.application.dto; +package com.moing.backend.domain.missionState.application.dto; public class MissionStatusRes { diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/MissionStatus.java b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java similarity index 68% rename from src/main/java/com/moing/backend/domain/missionStatus/domain/entity/MissionStatus.java rename to src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java index 0ebe1d94..baa650a6 100644 --- a/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/MissionStatus.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java @@ -1,7 +1,8 @@ -package com.moing.backend.domain.missionStatus.domain.entity; +package com.moing.backend.domain.missionState.domain.entity; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; import lombok.Builder; @@ -15,10 +16,10 @@ @AllArgsConstructor @Getter @Builder -public class MissionStatus extends BaseTimeEntity { +public class MissionState extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "missionStatus_id") + @Column(name = "missionState_id") private Long id; @OneToOne @@ -26,6 +27,6 @@ public class MissionStatus extends BaseTimeEntity { @OneToOne private Member member; - private Status status; + private MissionStatus status; } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java b/src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java new file mode 100644 index 00000000..56f082a8 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.missionState.domain.entity; + +public enum Status { + SUCCESS,FAIL +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java new file mode 100644 index 00000000..0ed34995 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java @@ -0,0 +1,4 @@ +package com.moing.backend.domain.missionState.domain.repository; + +public interface MissionStateCustomRepository { +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java new file mode 100644 index 00000000..72a46d94 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.missionState.domain.repository; + +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; + +public class MissionStateCustomRepositoryImpl implements MissionStateCustomRepository { + + private final JPAQueryFactory queryFactory; + + public MissionStateCustomRepositoryImpl(EntityManager entityManager) { + this.queryFactory = new JPAQueryFactory(entityManager); + } + +// public MissionStatusRes getMissionStatus() { +// +// queryFactory +// .select() +// .from(MissionState) +// .where( +// +// ) +// } + + + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java new file mode 100644 index 00000000..0f91a080 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.missionState.domain.repository; + +import com.moing.backend.domain.missionState.domain.entity.MissionState; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MissionStateRepository extends JpaRepository { +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java new file mode 100644 index 00000000..dd74132c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java @@ -0,0 +1,29 @@ +package com.moing.backend.domain.missionState.domain.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.missionState.domain.entity.MissionState; +import com.moing.backend.domain.missionState.domain.entity.Status; +import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionStateSaveService { + + private final MissionStateRepository missionStateRepository; + + public void saveMissionState(Member member, Mission mission, MissionStatus status) { + missionStateRepository.save(MissionState.builder() + .mission(mission) + .member(member) + .status(status) + .build()); + } + +} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/Status.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/Status.java deleted file mode 100644 index 7472cd49..00000000 --- a/src/main/java/com/moing/backend/domain/missionStatus/domain/entity/Status.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.moing.backend.domain.missionStatus.domain.entity; - -public enum Status { - SUCCESS,FAIL -} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepository.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepository.java deleted file mode 100644 index 83d16141..00000000 --- a/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepository.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.moing.backend.domain.missionStatus.domain.repository; - -public interface MissionStatusCustomRepository { -} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepositoryImpl.java deleted file mode 100644 index 628f53bf..00000000 --- a/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusCustomRepositoryImpl.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.moing.backend.domain.missionStatus.domain.repository; - -import com.moing.backend.domain.missionStatus.application.dto.MissionStatusRes; -import com.moing.backend.domain.missionStatus.domain.entity.MissionStatus; -import com.querydsl.jpa.impl.JPAQueryFactory; - -import javax.persistence.EntityManager; -import java.util.List; - -public class MissionStatusCustomRepositoryImpl implements MissionStatusCustomRepository { - - private final JPAQueryFactory queryFactory; - - public MissionStatusCustomRepositoryImpl(EntityManager entityManager) { - this.queryFactory = new JPAQueryFactory(entityManager); - } - -// public MissionStatusRes getMissionStatus() { -// -// queryFactory -// .select() -// .from(MissionStatus) -// .where( -// -// ) -// } - - - -} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusRepository.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusRepository.java deleted file mode 100644 index 2891e664..00000000 --- a/src/main/java/com/moing/backend/domain/missionStatus/domain/repository/MissionStatusRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.moing.backend.domain.missionStatus.domain.repository; - -import com.moing.backend.domain.missionStatus.domain.entity.MissionStatus; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface MissionStatusRepository extends JpaRepository { -} diff --git a/src/main/java/com/moing/backend/domain/missionStatus/domain/service/MissionStatusSaveService.java b/src/main/java/com/moing/backend/domain/missionStatus/domain/service/MissionStatusSaveService.java deleted file mode 100644 index 7a39ce4f..00000000 --- a/src/main/java/com/moing/backend/domain/missionStatus/domain/service/MissionStatusSaveService.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.moing.backend.domain.missionStatus.domain.service; - -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.missionStatus.domain.entity.MissionStatus; -import com.moing.backend.domain.missionStatus.domain.entity.Status; -import com.moing.backend.domain.missionStatus.domain.repository.MissionStatusRepository; -import com.moing.backend.global.annotation.DomainService; -import lombok.RequiredArgsConstructor; - -import javax.transaction.Transactional; - -@DomainService -@Transactional -@RequiredArgsConstructor -public class MissionStatusSaveService { - - private final MissionStatusRepository missionStatusRepository; - - public void saveMissionStatus(Member member, Mission mission, Status status) { - missionStatusRepository.save(MissionStatus.builder() - .mission(mission) - .member(member) - .status(status) - .build()); - } - -} From 9c3a141214e79a5977528bb2126698a298d8145a Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 22 Oct 2023 15:35:36 +0900 Subject: [PATCH 166/619] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=A1=B0=ED=9A=8C=20=EB=B0=8F=20=EC=86=8C?= =?UTF-8?q?=EB=AA=A8=EC=9E=84=20=EC=83=9D=EC=84=B1=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/BoardCustomRepositoryImpl.java | 10 +++-- .../dto/response/GetMyPageResponse.java | 23 +++++++++++ .../dto/response/GetMyPageTeamBlock.java | 14 +++++++ .../application/mapper/MyPageMapper.java | 25 ++++++++++++ .../service/GetMyPageUserCase.java | 40 +++++++++++++++++++ .../mypage/presentation/MyPageController.java | 19 ++++++--- .../constant/MypageResponseMessage.java | 1 + .../repository/TeamCustomRepository.java | 2 + .../repository/TeamCustomRepositoryImpl.java | 22 ++++++++-- .../team/domain/service/TeamGetService.java | 5 +++ .../exception/AlreadyJoinTeamException.java | 11 +++++ .../AlreadyWithdrawTeamException.java | 11 +++++ .../domain/service/TeamMemberSaveService.java | 26 +++++++++--- .../backend/global/response/ErrorCode.java | 2 + 14 files changed, 193 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageResponse.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/team/exception/AlreadyJoinTeamException.java create mode 100644 src/main/java/com/moing/backend/domain/team/exception/AlreadyWithdrawTeamException.java diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index 8a3001a5..7dbf0074 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -70,16 +70,18 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { public Integer findUnReadBoardNum(Long teamId, Long memberId) { // 전체 게시글 수 Long allBoards = queryFactory - .selectFrom(board) + .select(board.count()) + .from(board) .where(board.team.teamId.eq(teamId)) - .fetchCount(); + .fetchFirst(); // 멤버가 읽은 게시글 수 Long readBoards = queryFactory - .selectFrom(boardRead) + .select(boardRead.count()) + .from(boardRead) .where(boardRead.member.memberId.eq(memberId)) .where(boardRead.board.team.teamId.eq(teamId)) - .fetchCount(); + .fetchFirst(); return Math.toIntExact(allBoards - readBoards); } diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageResponse.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageResponse.java new file mode 100644 index 00000000..79baebbd --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageResponse.java @@ -0,0 +1,23 @@ +package com.moing.backend.domain.mypage.application.dto.response; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.constant.Category; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class GetMyPageResponse { + private String profileImage; + private String nickName; + private String introduction; + private List categories=new ArrayList<>(); + private List getMyPageTeamBlocks = new ArrayList<>(); +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java new file mode 100644 index 00000000..a05783c9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.mypage.application.dto.response; + +import com.moing.backend.domain.team.domain.constant.Category; +import lombok.*; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class GetMyPageTeamBlock { + private Long teamId; + private String teamName; + private Category category; +} diff --git a/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java b/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java new file mode 100644 index 00000000..fd09f4ed --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java @@ -0,0 +1,25 @@ +package com.moing.backend.domain.mypage.application.mapper; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mypage.application.dto.response.GetMyPageResponse; +import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; +import com.moing.backend.domain.team.domain.constant.Category; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@RequiredArgsConstructor +public class MyPageMapper { + + public GetMyPageResponse toGetMyPageResponse(Member member, List categories, List blocks) { + return GetMyPageResponse.builder() + .profileImage(member.getProfileImage()) + .nickName(member.getNickName()) + .introduction(member.getIntroduction()) + .categories(categories) + .getMyPageTeamBlocks(blocks) + .build(); + } +} diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUserCase.java new file mode 100644 index 00000000..818d1843 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUserCase.java @@ -0,0 +1,40 @@ +package com.moing.backend.domain.mypage.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mypage.application.dto.response.GetMyPageResponse; +import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; +import com.moing.backend.domain.mypage.application.mapper.MyPageMapper; +import com.moing.backend.domain.team.domain.constant.Category; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@Transactional +@RequiredArgsConstructor +public class GetMyPageUserCase { + + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final MyPageMapper myPageMapper; + + public GetMyPageResponse getMyPageResponse(String socialId) { + Member member = memberGetService.getMemberBySocialId(socialId); + List getMyPageTeamBlocks = teamGetService.getMyPageTeamBlockByMemberId(member.getMemberId()); + return myPageMapper.toGetMyPageResponse(member, calculateCategory(getMyPageTeamBlocks), getMyPageTeamBlocks); + } + + private List calculateCategory(List getMyPageTeamBlocks) { + return getMyPageTeamBlocks.stream() + .map(GetMyPageTeamBlock::getCategory) + .distinct() + .limit(2) + .collect(Collectors.toList()); + } + +} diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java index bfc89771..928980fc 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java @@ -3,11 +3,9 @@ import com.moing.backend.domain.mypage.application.dto.request.UpdateProfileRequest; import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; import com.moing.backend.domain.mypage.application.dto.response.GetAlarmResponse; +import com.moing.backend.domain.mypage.application.dto.response.GetMyPageResponse; import com.moing.backend.domain.mypage.application.dto.response.GetProfileResponse; -import com.moing.backend.domain.mypage.application.service.AlarmUserCase; -import com.moing.backend.domain.mypage.application.service.ProfileUserCase; -import com.moing.backend.domain.mypage.application.service.SignOutUserCase; -import com.moing.backend.domain.mypage.application.service.WithdrawUserCase; +import com.moing.backend.domain.mypage.application.service.*; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -28,8 +26,9 @@ public class MyPageController { private final WithdrawUserCase withdrawService; private final ProfileUserCase profileUserCase; private final AlarmUserCase alarmUserCase; + private final GetMyPageUserCase getMyPageUserCase; - //TODO 마이페이지 조회, 알림설정 수정 + //TODO 알림설정 수정 /** * 로그아웃 @@ -54,6 +53,16 @@ public ResponseEntity withdraw(@AuthenticationPrincipal User us return ResponseEntity.ok(SuccessResponse.create(WITHDRAWAL_SUCCESS.getMessage())); } + /** + * 마이페이지 조회 + * [GET] api/mypage + * 작성자: 김민수 + */ + @GetMapping + public ResponseEntity> getMyPage(@AuthenticationPrincipal User user){ + return ResponseEntity.ok(SuccessResponse.create(GET_MYPAGE_SUCCESS.getMessage(), this.getMyPageUserCase.getMyPageResponse(user.getSocialId()))); + } + /** * 프로필 조회 * [GET] api/mypage/profile diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java b/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java index 463f5ddb..085033a7 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java @@ -8,6 +8,7 @@ public enum MypageResponseMessage { SIGN_OUT_SUCCESS("로그아웃을 했습니다"), WITHDRAWAL_SUCCESS("회원탈퇴를 했습니다"), + GET_MYPAGE_SUCCESS("마이페이지를 조회했습니다"), GET_PROFILE_SUCCESS("프로필을 조회했습니다"), UPDATE_PROFILE_SUCCESS("프로필을 수정했습니다"), GET_ALARM_SUCCESS("알람 정보를 조회했습니다"), diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index fdbd1a88..43d7b559 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.team.domain.repository; +import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.team.application.dto.response.GetTeamDetailResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; @@ -11,4 +12,5 @@ public interface TeamCustomRepository { GetTeamResponse findTeamByMemberId(Long memberId); Optional findTeamByTeamId(Long TeamId); List findTeamIdByMemberId(Long memberId); + List findMyPageTeamByMemberId(Long memberId); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index be1b15ab..6d14e618 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -1,14 +1,15 @@ package com.moing.backend.domain.team.domain.repository; -import com.moing.backend.domain.member.domain.entity.QMember; -import com.moing.backend.domain.team.application.dto.response.*; +import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; +import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.team.application.dto.response.QTeamBlock; +import com.moing.backend.domain.team.application.dto.response.TeamBlock; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.moing.backend.domain.team.domain.entity.Team; -import com.querydsl.jpa.JPAExpressions; +import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; -import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -59,6 +60,19 @@ public List findTeamIdByMemberId(Long memberId){ .fetch(); } + @Override + public List findMyPageTeamByMemberId(Long memberId) { + return queryFactory + .select(Projections.constructor(GetMyPageTeamBlock.class, + team.teamId, team.name, team.category)) + .from(teamMember) + .innerJoin(teamMember.team, team) + .on(teamMember.member.memberId.eq(memberId)) + .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) // 승인 되었고 + .orderBy(team.missions.size().desc()) + .fetch(); + } + private List getTeamBlock(Long memberId) { LocalDateTime threeDaysAgo = LocalDateTime.now().minusDays(3); diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index 56e9e372..90e530fd 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.team.domain.service; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.repository.TeamRepository; @@ -28,4 +29,8 @@ public List getTeamIdByMemberId(Long memberId) { public Team getTeamByTeamId(Long teamId){ return teamRepository.findTeamByTeamId(teamId).orElseThrow(()->new NotFoundByTeamIdException()); } + + public List getMyPageTeamBlockByMemberId(Long memberId){ + return teamRepository.findMyPageTeamByMemberId(memberId); + } } diff --git a/src/main/java/com/moing/backend/domain/team/exception/AlreadyJoinTeamException.java b/src/main/java/com/moing/backend/domain/team/exception/AlreadyJoinTeamException.java new file mode 100644 index 00000000..4c12a0ac --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/exception/AlreadyJoinTeamException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.team.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class AlreadyJoinTeamException extends TeamException{ + public AlreadyJoinTeamException(){ + super(ErrorCode.ALREADY_JOIN_ERROR, + HttpStatus.UNAUTHORIZED); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/exception/AlreadyWithdrawTeamException.java b/src/main/java/com/moing/backend/domain/team/exception/AlreadyWithdrawTeamException.java new file mode 100644 index 00000000..218d7e3b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/exception/AlreadyWithdrawTeamException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.team.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class AlreadyWithdrawTeamException extends TeamException{ + public AlreadyWithdrawTeamException(){ + super(ErrorCode.ALREADY_WITHDRAW_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java index 13e6851a..f3ca19d0 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java @@ -2,20 +2,36 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.exception.AlreadyJoinTeamException; +import com.moing.backend.domain.team.exception.AlreadyWithdrawTeamException; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; +import javax.transaction.Transactional; +import java.util.Optional; + @DomainService @RequiredArgsConstructor +@Transactional public class TeamMemberSaveService { private final TeamMemberRepository teamMemberRepository; public void addTeamMember(Team team, Member member){ - TeamMember teamMember=new TeamMember(); - teamMember.updateMember(member); - teamMember.updateTeam(team); - team.addTeamMember(); - this.teamMemberRepository.save(teamMember); + Optional existingTeamMemberOpt = teamMemberRepository.findTeamMemberByTeamAndMember(team, member); + + TeamMember teamMember = existingTeamMemberOpt.orElseGet(() -> { + TeamMember newMember = new TeamMember(); + newMember.updateMember(member); + newMember.updateTeam(team); + team.addTeamMember(); + return teamMemberRepository.save(newMember); + }); + + if (teamMember.isDeleted()) { + throw new AlreadyWithdrawTeamException(); + } else { + throw new AlreadyJoinTeamException(); + } } } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index d3ffc8dd..45b306d2 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -39,6 +39,8 @@ public enum ErrorCode { //팀 관련 에러 코드 NOT_FOUND_BY_TEAM_ID_ERROR("T0001", "해당 teamId인 팀이 존재하지 않습니다."), NOT_AUTH_BY_TEAM_ERROR("T0002","권한이 없습니다."), + ALREADY_WITHDRAW_ERROR("T0003","이미 탈퇴한 회원입니다."), + ALREADY_JOIN_ERROR("T0004","이미 가입한 회원입니다."), //게시글 관련 에러 코드 NOT_FOUND_BY_BOARD_ID_ERROR("B0001","해당 boardId인 게시글이 존재하지 않습니다."), From 5b2da5ccc853695e8a5a015eaac3d37d388e6527 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 22 Oct 2023 15:48:57 +0900 Subject: [PATCH 167/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/domain/repository/TeamCustomRepositoryImpl.java | 3 +++ .../domain/repository/TeamMemberCustomRepositoryImpl.java | 1 + 2 files changed, 4 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index 6d14e618..f0132576 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -56,6 +56,7 @@ public List findTeamIdByMemberId(Long memberId){ .where(teamMember.isDeleted.eq(false)) // 탈퇴하지 않았다면 .where(team.isDeleted.eq(false) // 강제종료되지 않았거나 .or(team.deletionTime.after(threeDaysAgo))) // 강제종료된 경우 3일이 지나지 않았다면 + .groupBy(team.teamId) .orderBy(team.approvalTime.asc()) .fetch(); } @@ -70,6 +71,7 @@ public List findMyPageTeamByMemberId(Long memberId) { .on(teamMember.member.memberId.eq(memberId)) .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) // 승인 되었고 .orderBy(team.missions.size().desc()) + .groupBy(team.teamId) .fetch(); } @@ -92,6 +94,7 @@ private List getTeamBlock(Long memberId) { .or(team.deletionTime.isNotNull() .or(team.deletionTime.after(threeDaysAgo)))) // 강제종료된 경우 3일이 지나지 않았다면 .orderBy(team.approvalTime.asc()) + .groupBy(team.teamId) .fetch(); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index cd5cbaf2..c8d7cf6b 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -66,6 +66,7 @@ public List findTeamMemberInfoByTeamId(Long teamId){ .innerJoin(teamMember.team, team) // innerJoin을 사용하여 최적화 .where(teamMember.team.teamId.eq(teamId) // where 절을 하나로 합침 .and(teamMember.isDeleted.eq(false))) + .groupBy(teamMember.member.memberId) .fetch(); } } From d413ef91ca9ba8649884ec05b6bd37f610c256d9 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 22 Oct 2023 16:00:32 +0900 Subject: [PATCH 168/619] =?UTF-8?q?feat:=20test=20docs=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Mypage-API.adoc | 4 ++ .../presentation/MypageControllerTest.java | 69 +++++++++++++++++-- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/docs/asciidoc/Mypage-API.adoc b/src/docs/asciidoc/Mypage-API.adoc index 58e5ef94..59e4d843 100644 --- a/src/docs/asciidoc/Mypage-API.adoc +++ b/src/docs/asciidoc/Mypage-API.adoc @@ -11,6 +11,10 @@ operation::mypage-controller-test/sign_out[snippets='http-request,http-response, === Mypage 회원탈퇴 operation::mypage-controller-test/withdraw[snippets='http-request,request-fields,http-response,response-fields'] +[[Mypage-전체-조회]] +=== Mypage 전체 조회 +operation::mypage-controller-test/get_mypage[snippets='http-request,http-response,response-fields'] + [[Mypage-프로필-조회]] === Mypage 프로필 조회 operation::mypage-controller-test/get_profile[snippets='http-request,http-response,response-fields'] diff --git a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java index 277100a0..161680db 100644 --- a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java @@ -3,18 +3,21 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.mypage.application.dto.request.UpdateProfileRequest; import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; +import com.moing.backend.domain.mypage.application.dto.response.GetMyPageResponse; +import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.mypage.application.dto.response.GetProfileResponse; -import com.moing.backend.domain.mypage.application.service.AlarmUserCase; -import com.moing.backend.domain.mypage.application.service.ProfileUserCase; -import com.moing.backend.domain.mypage.application.service.SignOutUserCase; -import com.moing.backend.domain.mypage.application.service.WithdrawUserCase; +import com.moing.backend.domain.mypage.application.service.*; import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; +import com.moing.backend.domain.team.domain.constant.Category; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.ResultActions; +import java.util.ArrayList; +import java.util.List; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; @@ -37,6 +40,9 @@ public class MypageControllerTest extends CommonControllerTest { @MockBean private AlarmUserCase alarmUserCase; + @MockBean + private GetMyPageUserCase getMyPageUserCase; + @Test public void sign_out() throws Exception { //when @@ -101,6 +107,61 @@ public void withdraw() throws Exception { ); } + @Test + public void get_mypage() throws Exception{ + //given + List categoryList=new ArrayList<>(); + categoryList.add(Category.SPORTS); + + List getMyPageTeamBlocks=new ArrayList<>(); + GetMyPageTeamBlock blocks= GetMyPageTeamBlock.builder() + .teamId(1L) + .teamName("소모임이름") + .category(Category.SPORTS) + .build(); + getMyPageTeamBlocks.add(blocks); + + GetMyPageResponse output = GetMyPageResponse.builder() + .profileImage("PROFILE_IMAGE_URL") + .introduction("INTRODUCTION") + .nickName("NICKNAME") + .categories(categoryList) + .getMyPageTeamBlocks(getMyPageTeamBlocks) + .build(); + + given(getMyPageUserCase.getMyPageResponse(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + get("/api/mypage") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("마이페이지를 조회했습니다"), + fieldWithPath("data.profileImage").description("프로필 이미지 URL"), + fieldWithPath("data.nickName").description("닉네임"), + fieldWithPath("data.introduction").description("한줄 소개"), + fieldWithPath("data.categories[0]").description("내 열정의 불 해시태그"), + fieldWithPath("data.getMyPageTeamBlocks[0].teamId").description("소모임 아이디"), + fieldWithPath("data.getMyPageTeamBlocks[0].teamName").description("소모임 이름"), + fieldWithPath("data.getMyPageTeamBlocks[0].category").description("소모임 카테고리") + ) + ) + ); + } + @Test public void get_profile() throws Exception { //given From f8c2606417832b2b9b0211fa6d15873aa71727df Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 22 Oct 2023 16:01:12 +0900 Subject: [PATCH 169/619] =?UTF-8?q?feat=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=99=84=EB=A3=8C=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?(=EC=A0=90=EC=88=98=20=EB=B0=98=EC=98=81=EC=A0=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mission/domain/entity/Mission.java | 2 +- .../service/MissionArchiveCreateUseCase.java | 36 ++++++++++--------- .../service/MissionArchiveUpdateUseCase.java | 27 +++++++++++--- .../service/MissionStateUseCase.java | 34 ++++++++++++++++++ .../domain/entity/MissionState.java | 3 +- .../MissionStateCustomRepository.java | 7 ++++ .../MissionStateCustomRepositoryImpl.java | 29 ++++++++++----- .../repository/MissionStateRepository.java | 4 ++- .../service/MissionStateQueryService.java | 19 ++++++++++ .../service/MissionStateSaveService.java | 4 ++- 10 files changed, 132 insertions(+), 33 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index 39aece59..66177310 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -81,7 +81,7 @@ public void setTeam(Team team) { this.team = team; } - public void setStatus(MissionStatus missionStatus) { + public void updateStatus(MissionStatus missionStatus) { this.status = missionStatus; } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 22ee82de..a794c825 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -10,10 +10,14 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; +import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -27,12 +31,12 @@ public class MissionArchiveCreateUseCase { private final MissionArchiveSaveService missionArchiveSaveService; private final MissionArchiveQueryService missionArchiveQueryService; private final MissionArchiveDeleteService missionArchiveDeleteService; - private final MissionQueryService missionQueryService; - private final MemberGetService memberGetService; - private final MissionArchiveScoreService missionArchiveScoreService; + private final MissionStateSaveService missionStateSaveService; + private final MissionStateUseCase missionStateUseCase; + // 미션 인증 public MissionArchiveRes createArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { @@ -45,18 +49,29 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss MissionArchive newArchive = MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission); + // 인증 완료한 미션인지 확인 if (isDoneMission(memberId,mission)) { throw new NoMoreMissionArchiveException(); } + // 단일 미션 && 미션 종료 직전인지 확인 + if (mission.getType() == MissionType.ONCE && missionStateUseCase.isAbleToEnd(missionId)) { + mission.updateStatus(MissionStatus.SUCCESS); + // 점수 반영 로직 + + } + + // 단일 미션 if (mission.getType().equals(MissionType.ONCE)) { - // missionArchive 2개 이상일 때 예외처리 -// missionArchiveScoreService.addScore(team); newArchive.updateCount(1L); } + + // 반복 미션 else { newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); } + + missionStateSaveService.saveMissionState(member,mission, MissionArchiveStatus.COMPLETE); return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive)); } @@ -66,18 +81,7 @@ public Boolean isDoneMission(Long memberId,Mission mission) { return missionArchiveQueryService.findMyDoneArchives(memberId, mission.getId()) >= mission.getNumber(); } - // 이 미션을 완료 했는지 - public Boolean isEndMission(Member member,Mission mission) { - Team team = mission.getTeam(); - - Long missionsCountByTeam = missionQueryService.findMissionsCountByTeam(team.getTeamId()); - if (missionsCountByTeam == team.getNumOfMember()-1) { - mission.setStatus(MissionStatus.END); - return true; - } - return false; - } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index 8c670092..5dc8691f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -12,9 +12,14 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; +import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; +import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -37,11 +42,15 @@ public class MissionArchiveUpdateUseCase { private final IssuePresignedUrlUseCase getPresignedUrlUseCase; + private final MissionStateSaveService missionStateSaveService; + private final MissionStateUseCase missionStateUseCase; + // 미션 재인증 (수정하기도 포함됨) public MissionArchiveRes updateArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); + Long memberId = member.getMemberId(); Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); @@ -49,15 +58,20 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(member.getMemberId(), missionId)) { //s3삭제 + } MissionArchive updateArchive = missionArchiveQueryService.findMyArchive(member.getMemberId(), missionId).get(0); + // 단일 미션 && 미션 종료 직전인지 확인 + if (mission.getType() == MissionType.ONCE && missionStateUseCase.isAbleToEnd(missionId)) { + mission.updateStatus(MissionStatus.SUCCESS); + // 점수 반영 로직 + + } + + if (mission.getType().equals(MissionType.ONCE)) { - // missionArchive 2개 이상일 때 예외처리 필요 -// if (isDoneSingleMission(mission)) { -// missionArchiveScoreService.addScore(team); -// } updateArchive.updateCount(1L); } else{ @@ -65,9 +79,14 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss } updateArchive.updateArchive(missionReq); + missionStateSaveService.saveMissionState(member,mission, MissionArchiveStatus.COMPLETE); return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(updateArchive)); } + // 이 미션을 완료 했는지 + public Boolean isDoneMission(Long memberId,Mission mission) { + return missionArchiveQueryService.findMyDoneArchives(memberId, mission.getId()) >= mission.getNumber(); + } } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java new file mode 100644 index 00000000..0279fce2 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -0,0 +1,34 @@ +package com.moing.backend.domain.missionState.application.service; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.team.domain.entity.Team; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionStateUseCase { + + // 미션 종료 직전인지 확인 + // missionId, missionstate num mission.team.personum + + private final MissionQueryService missionQueryService; + private final MissionStateQueryService missionStateQueryService; + + + public boolean isAbleToEnd(Long missionId) { + + Mission mission = missionQueryService.findMissionById(missionId); + Long totalPerson = Long.valueOf(mission.getTeam().getNumOfMember()); + Long donePerson = missionStateQueryService.stateCountByMissionId(missionId); + + return donePerson == totalPerson-1; + + } + + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java index baa650a6..d347bda6 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; import lombok.Builder; @@ -27,6 +28,6 @@ public class MissionState extends BaseTimeEntity { @OneToOne private Member member; - private MissionStatus status; + private MissionArchiveStatus status; } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java index 0ed34995..a3dad296 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java @@ -1,4 +1,11 @@ package com.moing.backend.domain.missionState.domain.repository; +import org.springframework.stereotype.Repository; + +@Repository public interface MissionStateCustomRepository { + + Long getCountsByMissionId(Long missionId) ; + + } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index 72a46d94..55d7dedb 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -1,9 +1,12 @@ package com.moing.backend.domain.missionState.domain.repository; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; +import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; + public class MissionStateCustomRepositoryImpl implements MissionStateCustomRepository { private final JPAQueryFactory queryFactory; @@ -12,15 +15,23 @@ public MissionStateCustomRepositoryImpl(EntityManager entityManager) { this.queryFactory = new JPAQueryFactory(entityManager); } -// public MissionStatusRes getMissionStatus() { -// -// queryFactory -// .select() -// .from(MissionState) -// .where( -// -// ) -// } + + @Override + public Long getCountsByMissionId(Long missionId) { + return queryFactory + .select(missionState) + .from(missionState) + .where( + missionState.mission.id.eq(missionId), + missionState.status.eq(MissionArchiveStatus.COMPLETE) + .or( missionState.status.eq(MissionArchiveStatus.SKIP)) + ) + .fetchCount(); + } + + + + diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java index 0f91a080..32d06a99 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java @@ -2,6 +2,8 @@ import com.moing.backend.domain.missionState.domain.entity.MissionState; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; -public interface MissionStateRepository extends JpaRepository { +@Repository +public interface MissionStateRepository extends JpaRepository,MissionStateCustomRepository { } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java new file mode 100644 index 00000000..29252ce7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.missionState.domain.service; + +import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionStateQueryService { + + private final MissionStateRepository missionStateRepository; + + public Long stateCountByMissionId(Long missionId) { + return missionStateRepository.getCountsByMissionId(missionId); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java index dd74132c..1a1fc6e9 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java @@ -3,6 +3,8 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.missionState.domain.entity.Status; import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; @@ -18,7 +20,7 @@ public class MissionStateSaveService { private final MissionStateRepository missionStateRepository; - public void saveMissionState(Member member, Mission mission, MissionStatus status) { + public void saveMissionState(Member member, Mission mission, MissionArchiveStatus status) { missionStateRepository.save(MissionState.builder() .mission(mission) .member(member) From 20a98990d980dbb6361860a5ff3e4d5ae7eb0284 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 22 Oct 2023 16:17:30 +0900 Subject: [PATCH 170/619] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Overview.adoc | 20 +++++++++++++++++++ .../backend/global/response/ErrorCode.java | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/docs/asciidoc/Overview.adoc b/src/docs/asciidoc/Overview.adoc index 5f488cc2..318e4f2e 100644 --- a/src/docs/asciidoc/Overview.adoc +++ b/src/docs/asciidoc/Overview.adoc @@ -94,6 +94,15 @@ | `T0002` | 소모임을 수정, 삭제하려고 할 때 | 소모임장이 아님 (권한 없음) + +| `T0003` +| 소모임을 가입할 때 +| 소모임을 이미 탈퇴함 + +| `T0004` +| 소모임을 가입할 때 +| 소모임을 이미 가입함 + |=== === Board ErrorCode @@ -108,6 +117,17 @@ | 작성자가 아님 (권한 없음) |=== +|=== +| ErrorCode | Scope | Description +| `BC0001` +| API PATH에 boardId가 있을 때 +| boardId가 유효하지 않음 (존재하지 않음) + +| `BC0002` +| 게시글을 수정, 삭제하려고 할 때 +| 작성자가 아님 (권한 없음) +|=== + === Mission ErrorCode |=== | ErrorCode | Scope | Description diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 45b306d2..3e6834e3 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -47,8 +47,8 @@ public enum ErrorCode { NOT_AUTH_BY_BOARD_ID_ERROR("B0002","권한이 없습니다."), //게시글 댓글 관련 에러 코드 - NOT_FOUND_BY_BOARD_COMMENT_ID_ERROR("B0001","해당 boardCommentId인 댓글이 존재하지 않습니다."), - NOT_AUTH_BY_BOARD_COMMENT_ID_ERROR("B0002","권한이 없습니다."); + NOT_FOUND_BY_BOARD_COMMENT_ID_ERROR("BC0001","해당 boardCommentId인 댓글이 존재하지 않습니다."), + NOT_AUTH_BY_BOARD_COMMENT_ID_ERROR("BC0002","권한이 없습니다."); private String errorCode; private String message; From 0a9de8bc8dbacfe00ceccd1fd7ec9eafffde9520 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 22 Oct 2023 16:51:03 +0900 Subject: [PATCH 171/619] =?UTF-8?q?feat=20:=20=ED=8C=80=20=EC=A0=90?= =?UTF-8?q?=EC=88=98=20=EB=B0=98=EC=98=81(=EC=A7=84=ED=96=89=EC=A4=91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionTerminationUseCase.java | 2 +- .../service/MissionArchiveHeartUseCase.java | 1 - .../service/MissionArchiveScoreService.java | 24 ------------- .../application/service/ScoreSaveUseCase.java | 10 ------ .../service/ScoreUpdateUseCase.java | 17 ---------- .../domain/score/domain/entity/Score.java | 22 ------------ .../domain/repository/ScoreRepository.java | 15 -------- .../domain/service/ScoreQueryService.java | 18 ---------- .../domain/service/ScoreSaveService.java | 20 ----------- .../teamScore/domain/entity/TeamScore.java | 34 +++++++++++++++++++ .../repository/TeamScoreCustomRepository.java | 5 +++ .../TeamScoreCustomRepositoryImpl.java | 23 +++++++++++++ .../repository/TeamScoreRepository.java | 7 ++++ .../domain/service/TeamScoreQueryService.java | 27 +++++++++++++++ .../domain/service/TeamScoreSaveService.java | 30 ++++++++++++++++ .../service/TeamScoreUpdateService.java | 32 +++++++++++++++++ 16 files changed, 159 insertions(+), 128 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java delete mode 100644 src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java delete mode 100644 src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java delete mode 100644 src/main/java/com/moing/backend/domain/score/domain/entity/Score.java delete mode 100644 src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java delete mode 100644 src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java delete mode 100644 src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java create mode 100644 src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreRepository.java create mode 100644 src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java create mode 100644 src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java index f49ba964..18866d60 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java @@ -25,7 +25,7 @@ public void terminateMission() { missionByDueTo.stream().forEach( // 미션 종료 처리 - mission -> mission.setStatus(MissionStatus.END) + mission -> mission.updateStatus(MissionStatus.END) ); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveHeartUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveHeartUseCase.java index 0cca0fd8..e2f8ab56 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveHeartUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveHeartUseCase.java @@ -29,7 +29,6 @@ public class MissionArchiveHeartUseCase { private final MemberGetService memberGetService; - private final MissionArchiveScoreService missionArchiveScoreService; public MissionArchiveHeartRes pushHeart(MissionArchiveHeartReq missionArchiveHeartReq) { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java deleted file mode 100644 index 89d12f78..00000000 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.moing.backend.domain.missionArchive.application.service; - -import com.moing.backend.domain.score.domain.entity.Score; -import com.moing.backend.domain.score.domain.service.ScoreQueryService; -import com.moing.backend.domain.score.domain.service.ScoreSaveService; -import com.moing.backend.domain.team.domain.entity.Team; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class MissionArchiveScoreService { - - private final ScoreQueryService scoreQueryService; - - public void addScore(Team team) { - // steps - // 단계별 - Score score = scoreQueryService.findByTeamId(team.getTeamId()); - score.updateScore(20); - - } - -} diff --git a/src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java b/src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java deleted file mode 100644 index b9403968..00000000 --- a/src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.moing.backend.domain.score.application.service; - -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; - -public class ScoreSaveUseCase { - - - -} diff --git a/src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java deleted file mode 100644 index 9e5a60e5..00000000 --- a/src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.moing.backend.domain.score.application.service; - -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; - -public class ScoreUpdateUseCase { - - public int singleMissionDone(Mission mission) { - - if (mission.getStatus() == MissionStatus.END) { - - - } - - return 3; - } -} diff --git a/src/main/java/com/moing/backend/domain/score/domain/entity/Score.java b/src/main/java/com/moing/backend/domain/score/domain/entity/Score.java deleted file mode 100644 index 257e500f..00000000 --- a/src/main/java/com/moing/backend/domain/score/domain/entity/Score.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.moing.backend.domain.score.domain.entity; - -import lombok.Getter; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; - -@Entity -@Getter -public class Score { - - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - private Long teamId; - private int score; - - public int updateScore(int score) { - return this.score += score; - } -} diff --git a/src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java b/src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java deleted file mode 100644 index 67d1b303..00000000 --- a/src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.moing.backend.domain.score.domain.repository; - -import com.moing.backend.domain.score.domain.entity.Score; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; - -import java.util.Optional; - - -public interface ScoreRepository extends JpaRepository { - - @Query("select s from Score s where s.teamId = :teamId ") - Score findByTeamId(Long teamId); - -} diff --git a/src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java b/src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java deleted file mode 100644 index 983f3604..00000000 --- a/src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.moing.backend.domain.score.domain.service; - -import com.moing.backend.domain.score.domain.entity.Score; -import com.moing.backend.domain.score.domain.repository.ScoreRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class ScoreQueryService { - - private final ScoreRepository scoreRepository; - - public Score findByTeamId(Long teamId) { - return scoreRepository.findByTeamId(teamId); - } - -} diff --git a/src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java b/src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java deleted file mode 100644 index c2ae310e..00000000 --- a/src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.moing.backend.domain.score.domain.service; - -import com.moing.backend.domain.score.domain.entity.Score; -import com.moing.backend.domain.score.domain.repository.ScoreRepository; -import com.moing.backend.global.annotation.DomainService; -import lombok.RequiredArgsConstructor; -import org.springframework.transaction.annotation.Transactional; - -@DomainService -@Transactional -@RequiredArgsConstructor -public class ScoreSaveService { - - private final ScoreRepository scoreRepository; - - public Score save(Score score) { - return scoreRepository.save(score); - } - -} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java new file mode 100644 index 00000000..1f0db924 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -0,0 +1,34 @@ +package com.moing.backend.domain.teamScore.domain.entity; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.RequiredArgsConstructor; + +import javax.persistence.*; + +@Entity +@RequiredArgsConstructor +public class TeamScore extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "mission_id") + private Long id; + + @OneToOne + private Team team; + + private Long score; + + @Builder + public TeamScore(Team team, Long score) { + this.team = team; + this.score = score; + } + + public void updateScore(Long score) { + this.score = score; + } +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java new file mode 100644 index 00000000..107e2df3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.teamScore.domain.repository; + + +public interface TeamScoreCustomRepository { +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java new file mode 100644 index 00000000..73e4aab2 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java @@ -0,0 +1,23 @@ +package com.moing.backend.domain.teamScore.domain.repository; + +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; + +public class TeamScoreCustomRepositoryImpl implements TeamScoreCustomRepository { + + + private final JPAQueryFactory queryFactory; + + public TeamScoreCustomRepositoryImpl(EntityManager entityManager) { + this.queryFactory = new JPAQueryFactory(entityManager); + } + +// public TeamScore findTeamScoreByTeamId(Long teamId) { +// return queryFactory +// .selectFrom(TeamSc) +// } + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreRepository.java b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreRepository.java new file mode 100644 index 00000000..14771e08 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.teamScore.domain.repository; + +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TeamScoreRepository extends JpaRepository , TeamScoreCustomRepository{ +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java new file mode 100644 index 00000000..5c1d1371 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.teamScore.domain.service; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + + +@DomainService +@Transactional +@RequiredArgsConstructor +public class TeamScoreQueryService { + + private final TeamScoreRepository teamScoreRepository; + private final TeamGetService teamGetService; + +// public TeamScore findTeamScoreByTeamId(Long teamId, Long score) { +// Team team = teamGetService.getTeamByTeamId(teamId); +// +// return teamScoreRepository.findByTeam(team); +// } + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java new file mode 100644 index 00000000..c265cef9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java @@ -0,0 +1,30 @@ +package com.moing.backend.domain.teamScore.domain.service; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + + +@DomainService +@Transactional +@RequiredArgsConstructor +public class TeamScoreSaveService { + + private final TeamScoreRepository teamScoreRepository; + private final TeamGetService teamGetService; + + public TeamScore save(Long teamId, Long score) { + Team team = teamGetService.getTeamByTeamId(teamId); + + return teamScoreRepository.save(TeamScore.builder() + .team(team) + .score(score) + .build()); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java new file mode 100644 index 00000000..b0693c22 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java @@ -0,0 +1,32 @@ +package com.moing.backend.domain.teamScore.domain.service; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + + +@DomainService +@Transactional +@RequiredArgsConstructor +public class TeamScoreUpdateService { + + private final TeamScoreRepository teamScoreRepository; + private final TeamGetService teamGetService; + + public TeamScore update(Long teamId, Long score) { + Team team = teamGetService.getTeamByTeamId(teamId); + + + + return teamScoreRepository.save(TeamScore.builder() + .team(team) + .score(score) + .build()); + } + + +} From eacdf8caeb3562b73e4a48e5c435f10bb8213ec4 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 22 Oct 2023 17:13:37 +0900 Subject: [PATCH 172/619] =?UTF-8?q?fix=20:=20GlobalExceptionHandler=20?= =?UTF-8?q?=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/GlobalExceptionHandler.java | 128 +++++++++--------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java b/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java index 154c0557..7a5b3529 100644 --- a/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java @@ -1,64 +1,64 @@ -//package com.moing.backend.global.exception; -// -//import com.moing.backend.global.response.ErrorCode; -//import com.moing.backend.global.response.ErrorResponse; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.http.HttpStatus; -//import org.springframework.http.ResponseEntity; -//import org.springframework.http.converter.HttpMessageNotReadableException; -//import org.springframework.web.HttpRequestMethodNotSupportedException; -//import org.springframework.web.bind.MethodArgumentNotValidException; -//import org.springframework.web.bind.annotation.ExceptionHandler; -//import org.springframework.web.bind.annotation.RestControllerAdvice; -//import org.springframework.context.support.DefaultMessageSourceResolvable; -// -//import java.util.function.Consumer; -//import java.util.regex.PatternSyntaxException; -//import java.util.stream.Collectors; -// -//@RestControllerAdvice -//@Slf4j -//public class GlobalExceptionHandler { -// -// private static final String LOG_FORMAT = "Class : {}, Code : {}, Message : {}"; -// -// @ExceptionHandler(ApplicationException.class) -// public ResponseEntity handleApplicationException(ApplicationException ex) { -// return handleException(ex, ex.getErrorCode(), ex.getMessage(), ex.getHttpStatus(), log::warn); -// } -// -// @ExceptionHandler(MethodArgumentNotValidException.class) -// public ResponseEntity inputMethodArgumentInvalidExceptionHandler (MethodArgumentNotValidException ex) { -// String message = ex.getBindingResult().getFieldErrors().stream() -// .map(DefaultMessageSourceResolvable::getDefaultMessage) -// .collect(Collectors.joining(", ")); -// return handleException(ex, ErrorCode.BAD_REQUEST, message, HttpStatus.BAD_REQUEST, log::warn); -// } -// -// @ExceptionHandler(PatternSyntaxException.class) -// public ResponseEntity inputPatternSyntaxExceptionHandler(PatternSyntaxException ex) { -// return handleException(ex, ErrorCode.BAD_REQUEST, ErrorCode.BAD_REQUEST.getMessage(), HttpStatus.BAD_REQUEST, log::warn); -// } -// -// @ExceptionHandler(HttpMessageNotReadableException.class) -// public ResponseEntity jsonParseExceptionHandler(HttpMessageNotReadableException ex) { -// return handleException(ex, ErrorCode.BAD_REQUEST, ErrorCode.BAD_REQUEST.getMessage(), HttpStatus.BAD_REQUEST, log::warn); -// } -// -// @ExceptionHandler(HttpRequestMethodNotSupportedException.class) -// public ResponseEntity httpRequestNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException ex) { -// return handleException(ex, ErrorCode.METHOD_NOT_ALLOWED, ErrorCode.METHOD_NOT_ALLOWED.getMessage(), HttpStatus.METHOD_NOT_ALLOWED, log::warn); -// } -// -// @ExceptionHandler(Exception.class) -// public ResponseEntity internalServerErrorHandler(Exception ex) { -// return handleException(ex, ErrorCode.INTERNAL_SERVER_ERROR, ErrorCode.INTERNAL_SERVER_ERROR.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR, log::error); -// } -// -// private ResponseEntity handleException(Exception ex, ErrorCode errorCode, String message, HttpStatus httpStatus, Consumer logger) { -// log.error(LOG_FORMAT, ex.getClass().getSimpleName(), errorCode.getErrorCode(), ex.getMessage()); -// ErrorResponse errorResponse = new ErrorResponse(errorCode, message); -// return ResponseEntity.status(httpStatus.value()).body(errorResponse); -// } -// -//} \ No newline at end of file +package com.moing.backend.global.exception; + +import com.moing.backend.global.response.ErrorCode; +import com.moing.backend.global.response.ErrorResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.context.support.DefaultMessageSourceResolvable; + +import java.util.function.Consumer; +import java.util.regex.PatternSyntaxException; +import java.util.stream.Collectors; + +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + + private static final String LOG_FORMAT = "Class : {}, Code : {}, Message : {}"; + + @ExceptionHandler(ApplicationException.class) + public ResponseEntity handleApplicationException(ApplicationException ex) { + return handleException(ex, ex.getErrorCode(), ex.getMessage(), ex.getHttpStatus(), log::warn); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity inputMethodArgumentInvalidExceptionHandler (MethodArgumentNotValidException ex) { + String message = ex.getBindingResult().getFieldErrors().stream() + .map(DefaultMessageSourceResolvable::getDefaultMessage) + .collect(Collectors.joining(", ")); + return handleException(ex, ErrorCode.BAD_REQUEST, message, HttpStatus.BAD_REQUEST, log::warn); + } + + @ExceptionHandler(PatternSyntaxException.class) + public ResponseEntity inputPatternSyntaxExceptionHandler(PatternSyntaxException ex) { + return handleException(ex, ErrorCode.BAD_REQUEST, ErrorCode.BAD_REQUEST.getMessage(), HttpStatus.BAD_REQUEST, log::warn); + } + + @ExceptionHandler(HttpMessageNotReadableException.class) + public ResponseEntity jsonParseExceptionHandler(HttpMessageNotReadableException ex) { + return handleException(ex, ErrorCode.BAD_REQUEST, ErrorCode.BAD_REQUEST.getMessage(), HttpStatus.BAD_REQUEST, log::warn); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public ResponseEntity httpRequestNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException ex) { + return handleException(ex, ErrorCode.METHOD_NOT_ALLOWED, ErrorCode.METHOD_NOT_ALLOWED.getMessage(), HttpStatus.METHOD_NOT_ALLOWED, log::warn); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity internalServerErrorHandler(Exception ex) { + return handleException(ex, ErrorCode.INTERNAL_SERVER_ERROR, ErrorCode.INTERNAL_SERVER_ERROR.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR, log::error); + } + + private ResponseEntity handleException(Exception ex, ErrorCode errorCode, String message, HttpStatus httpStatus, Consumer logger) { + log.error(LOG_FORMAT, ex.getClass().getSimpleName(), errorCode.getErrorCode(), ex.getMessage()); + ErrorResponse errorResponse = new ErrorResponse(errorCode, message); + return ResponseEntity.status(httpStatus.value()).body(errorResponse); + } + +} \ No newline at end of file From 111ed774d8636380574bd42b8c43e035cfa6bbd9 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 22 Oct 2023 17:21:35 +0900 Subject: [PATCH 173/619] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=95=8C=EB=9E=8C=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/domain/entity/Member.java | 3 +++ .../application/service/AlarmUserCase.java | 27 ++++++++++++++++--- .../exception/AlarmInvalidException.java | 11 ++++++++ .../mypage/exception/MyPageException.java | 11 ++++++++ .../mypage/presentation/MyPageController.java | 14 ++++++++-- .../backend/global/response/ErrorCode.java | 4 ++- 6 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mypage/exception/AlarmInvalidException.java create mode 100644 src/main/java/com/moing/backend/domain/mypage/exception/MyPageException.java diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index 06bef64f..79825c9a 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -101,6 +101,9 @@ public void signUp(SignUpRequest signUpRequest) { this.birthDate = LocalDate.parse(signUpRequest.getBirthDate(), DateTimeFormatter.ISO_DATE);; this.fcmToken = signUpRequest.getFcmToken(); this.registrationStatus = RegistrationStatus.COMPLETED; + this.isNewUploadPush=true; + this.isFirePush=true; + this.isRemindPush=true; } @Builder diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java index b535db5f..55e3a6ca 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java @@ -1,12 +1,11 @@ package com.moing.backend.domain.mypage.application.service; -import com.moing.backend.domain.member.application.mapper.MemberMapper; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mypage.application.dto.response.GetAlarmResponse; +import com.moing.backend.domain.mypage.exception.AlarmInvalidException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import org.springframework.web.bind.annotation.RequestBody; import javax.transaction.Transactional; @@ -15,10 +14,32 @@ @RequiredArgsConstructor public class AlarmUserCase { - private MemberGetService memberGetService; + private final MemberGetService memberGetService; public GetAlarmResponse getAlarm(String socialId){ Member member=memberGetService.getMemberBySocialId(socialId); return new GetAlarmResponse(member.isNewUploadPush(),member.isRemindPush(), member.isFirePush()); } + + public void updateAlarm(String socialId, String type, String status) { + Member member = memberGetService.getMemberBySocialId(socialId); + boolean push = "on".equals(status); + + switch (type) { + case "all": + member.updateAllPush(push); + break; + case "isNewUploadPush": + member.updateNewUploadPush(push); + break; + case "isRemindPush": + member.updateRemindPush(push); + break; + case "isFirePush": + member.updateFirePush(push); + break; + default: + throw new AlarmInvalidException(); + } + } } diff --git a/src/main/java/com/moing/backend/domain/mypage/exception/AlarmInvalidException.java b/src/main/java/com/moing/backend/domain/mypage/exception/AlarmInvalidException.java new file mode 100644 index 00000000..6fd3c4d2 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/exception/AlarmInvalidException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.mypage.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class AlarmInvalidException extends MyPageException { + public AlarmInvalidException() { + super(ErrorCode.INVALID_ALARM_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/mypage/exception/MyPageException.java b/src/main/java/com/moing/backend/domain/mypage/exception/MyPageException.java new file mode 100644 index 00000000..20aabdc1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/exception/MyPageException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.mypage.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class MyPageException extends ApplicationException { + protected MyPageException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java index 928980fc..6eb2532f 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java @@ -28,8 +28,6 @@ public class MyPageController { private final AlarmUserCase alarmUserCase; private final GetMyPageUserCase getMyPageUserCase; - //TODO 알림설정 수정 - /** * 로그아웃 * [POST] api/mypage/signOut @@ -95,4 +93,16 @@ public ResponseEntity> getAlarm(@Authenticatio return ResponseEntity.ok(SuccessResponse.create(GET_ALARM_SUCCESS.getMessage(), this.alarmUserCase.getAlarm(user.getSocialId()))); } + /** + * 알림정보 수정 + * [POST] api/mypage/alarm?type=all || isNewUploadPush || isRemindPush || isFirePush && status= on || off + */ + @PutMapping("/alarm") + public ResponseEntity updateAlarm(@AuthenticationPrincipal User user, + @RequestParam(name = "type") String type, + @RequestParam(name = "status") String status) { + this.alarmUserCase.updateAlarm(user.getSocialId(), type, status); + return ResponseEntity.ok(SuccessResponse.create(UPDATE_PROFILE_SUCCESS.getMessage())); + } + } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 3e6834e3..129e9f03 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -42,6 +42,9 @@ public enum ErrorCode { ALREADY_WITHDRAW_ERROR("T0003","이미 탈퇴한 회원입니다."), ALREADY_JOIN_ERROR("T0004","이미 가입한 회원입니다."), + //마이페이지 관련 에러 코드 + INVALID_ALARM_ERROR("MP0001","유효하지 않는 알람 입력값입니다"), + //게시글 관련 에러 코드 NOT_FOUND_BY_BOARD_ID_ERROR("B0001","해당 boardId인 게시글이 존재하지 않습니다."), NOT_AUTH_BY_BOARD_ID_ERROR("B0002","권한이 없습니다."), @@ -49,7 +52,6 @@ public enum ErrorCode { //게시글 댓글 관련 에러 코드 NOT_FOUND_BY_BOARD_COMMENT_ID_ERROR("BC0001","해당 boardCommentId인 댓글이 존재하지 않습니다."), NOT_AUTH_BY_BOARD_COMMENT_ID_ERROR("BC0002","권한이 없습니다."); - private String errorCode; private String message; From 07a68246dbf8f186b762e4d2b25d3b445ae58578 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 22 Oct 2023 17:30:43 +0900 Subject: [PATCH 174/619] =?UTF-8?q?feat=20:=20TeamScore=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=A4=80=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/TeamScoreLogicUseCase.java | 16 ++++++++++++++++ .../teamScore/domain/entity/TeamScore.java | 1 - .../repository/TeamScoreCustomRepository.java | 6 ++++++ .../TeamScoreCustomRepositoryImpl.java | 13 +++++++++---- .../domain/service/TeamScoreQueryService.java | 9 ++++----- .../domain/service/TeamScoreUpdateService.java | 9 +++++---- 6 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java new file mode 100644 index 00000000..b8ec0d46 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.teamScore.application.service; + + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class TeamScoreLogicUseCase { + + public Long getScore(Long teamLevel) { + return 1L; + } +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index 1f0db924..ca0df886 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -2,7 +2,6 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.entity.BaseTimeEntity; -import lombok.AllArgsConstructor; import lombok.Builder; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java index 107e2df3..8d7c5b2f 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java @@ -1,5 +1,11 @@ package com.moing.backend.domain.teamScore.domain.repository; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; + public interface TeamScoreCustomRepository { + + TeamScore findTeamScoreByTeam(Team team); + } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java index 73e4aab2..ba7b7191 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java @@ -1,5 +1,8 @@ package com.moing.backend.domain.teamScore.domain.repository; +import static com.moing.backend.domain.teamScore.domain.entity.QTeamScore.teamScore; + +import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamScore.domain.entity.TeamScore; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -14,10 +17,12 @@ public TeamScoreCustomRepositoryImpl(EntityManager entityManager) { this.queryFactory = new JPAQueryFactory(entityManager); } -// public TeamScore findTeamScoreByTeamId(Long teamId) { -// return queryFactory -// .selectFrom(TeamSc) -// } + @Override + public TeamScore findTeamScoreByTeam(Team team) { + return queryFactory + .selectFrom(teamScore) + .where(teamScore.team.eq(team)).fetchFirst(); + } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java index 5c1d1371..85b6fe0d 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java @@ -17,11 +17,10 @@ public class TeamScoreQueryService { private final TeamScoreRepository teamScoreRepository; private final TeamGetService teamGetService; -// public TeamScore findTeamScoreByTeamId(Long teamId, Long score) { -// Team team = teamGetService.getTeamByTeamId(teamId); -// -// return teamScoreRepository.findByTeam(team); -// } + public TeamScore findTeamScoreByTeam(Team team) { + + return teamScoreRepository.findTeamScoreByTeam(team); + } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java index b0693c22..b6244817 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java @@ -16,16 +16,17 @@ public class TeamScoreUpdateService { private final TeamScoreRepository teamScoreRepository; private final TeamGetService teamGetService; + private final TeamScoreQueryService teamScoreQueryService; public TeamScore update(Long teamId, Long score) { Team team = teamGetService.getTeamByTeamId(teamId); + TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team); + teamScore.updateScore(score); + + return teamScore; - return teamScoreRepository.save(TeamScore.builder() - .team(team) - .score(score) - .build()); } From b30b2d37fb888d299afcd7be58a7a2eb18111a24 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 22 Oct 2023 17:47:43 +0900 Subject: [PATCH 175/619] =?UTF-8?q?feat:=20=EC=95=8C=EB=9E=8C=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20test=20docs=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Mypage-API.adoc | 11 +++ .../application/service/AlarmUserCase.java | 3 +- .../mypage/presentation/MyPageController.java | 5 +- .../presentation/MypageControllerTest.java | 87 ++++++++++++++++++- 4 files changed, 101 insertions(+), 5 deletions(-) diff --git a/src/docs/asciidoc/Mypage-API.adoc b/src/docs/asciidoc/Mypage-API.adoc index 59e4d843..adb5aa3b 100644 --- a/src/docs/asciidoc/Mypage-API.adoc +++ b/src/docs/asciidoc/Mypage-API.adoc @@ -33,3 +33,14 @@ Host: localhost:8080 { "profileImage" : "PROFILE_IMAGE_URL" } + + +[[Mypage-알람설정_조회]] +=== Mypage 알람설정 조회 +operation::mypage-controller-test/get_alarm[snippets='http-request,http-response,response-fields'] + + +[[Mypage-알람설정_수정]] +=== Mypage 알람설정 수정 +operation::mypage-controller-test/update_alarm[snippets='http-request,http-response,request-parameters,response-fields'] + diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java index 55e3a6ca..1d9c7a6e 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java @@ -21,7 +21,7 @@ public GetAlarmResponse getAlarm(String socialId){ return new GetAlarmResponse(member.isNewUploadPush(),member.isRemindPush(), member.isFirePush()); } - public void updateAlarm(String socialId, String type, String status) { + public GetAlarmResponse updateAlarm(String socialId, String type, String status) { Member member = memberGetService.getMemberBySocialId(socialId); boolean push = "on".equals(status); @@ -41,5 +41,6 @@ public void updateAlarm(String socialId, String type, String status) { default: throw new AlarmInvalidException(); } + return new GetAlarmResponse(member.isNewUploadPush(),member.isRemindPush(), member.isFirePush()); } } diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java index 6eb2532f..daeb6ffb 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java @@ -98,11 +98,10 @@ public ResponseEntity> getAlarm(@Authenticatio * [POST] api/mypage/alarm?type=all || isNewUploadPush || isRemindPush || isFirePush && status= on || off */ @PutMapping("/alarm") - public ResponseEntity updateAlarm(@AuthenticationPrincipal User user, + public ResponseEntity> updateAlarm(@AuthenticationPrincipal User user, @RequestParam(name = "type") String type, @RequestParam(name = "status") String status) { - this.alarmUserCase.updateAlarm(user.getSocialId(), type, status); - return ResponseEntity.ok(SuccessResponse.create(UPDATE_PROFILE_SUCCESS.getMessage())); + return ResponseEntity.ok(SuccessResponse.create(UPDATE_PROFILE_SUCCESS.getMessage(), this.alarmUserCase.updateAlarm(user.getSocialId(), type, status))); } } diff --git a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java index 161680db..d8364020 100644 --- a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java @@ -3,11 +3,11 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.mypage.application.dto.request.UpdateProfileRequest; import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; +import com.moing.backend.domain.mypage.application.dto.response.GetAlarmResponse; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageResponse; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.mypage.application.dto.response.GetProfileResponse; import com.moing.backend.domain.mypage.application.service.*; -import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; import com.moing.backend.domain.team.domain.constant.Category; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -23,6 +23,8 @@ import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -240,4 +242,87 @@ public void update_profile() throws Exception { ) ); } + + + @Test + public void get_alarm() throws Exception { + //given + GetAlarmResponse output = GetAlarmResponse.builder() + .isNewUploadPush(true) + .isFirePush(true) + .isRemindPush(true) + .build(); + + given(alarmUserCase.getAlarm(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + get("/api/mypage/alarm") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("알람 정보를 조회했습니다"), + fieldWithPath("data.newUploadPush").description("신규 공지 알림"), + fieldWithPath("data.remindPush").description("미션 리마인드 알림"), + fieldWithPath("data.firePush").description("불 던지기 알림") + ) + ) + ); + } + + @Test + public void update_alarm() throws Exception { + //given + GetAlarmResponse output = GetAlarmResponse.builder() + .isNewUploadPush(true) + .isFirePush(true) + .isRemindPush(true) + .build(); + + given(alarmUserCase.updateAlarm(any(),any(),any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + put("/api/mypage/alarm") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .param("type", "all") // 파라미터 추가 + .param("status", "on") // 파라미터 추가 + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + requestParameters( // 요청 파라미터 문서화 + parameterWithName("type").description("all || isNewUploadPush || isRemindPush || isFirePush"), + parameterWithName("status").description("on || off") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("알람 정보를 수정했습니다"), + fieldWithPath("data.newUploadPush").description("신규 공지 알림"), + fieldWithPath("data.remindPush").description("미션 리마인드 알림"), + fieldWithPath("data.firePush").description("불 던지기 알림") + ) + ) + ); + } } From 92caa139ebde220a80483a3d40f83d96027f1136 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 23 Oct 2023 03:15:35 +0900 Subject: [PATCH 176/619] =?UTF-8?q?fix:=20=ED=8C=80=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/service/TeamMemberSaveService.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java index f3ca19d0..8d432399 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java @@ -18,20 +18,19 @@ public class TeamMemberSaveService { private final TeamMemberRepository teamMemberRepository; public void addTeamMember(Team team, Member member){ - Optional existingTeamMemberOpt = teamMemberRepository.findTeamMemberByTeamAndMember(team, member); - - TeamMember teamMember = existingTeamMemberOpt.orElseGet(() -> { + Optional teamMember = teamMemberRepository.findTeamMemberByTeamAndMember(team, member); + if (teamMember.isPresent()) { + if (teamMember.get().isDeleted()) { + throw new AlreadyWithdrawTeamException(); + } else { + throw new AlreadyJoinTeamException(); + } + } else { TeamMember newMember = new TeamMember(); newMember.updateMember(member); newMember.updateTeam(team); team.addTeamMember(); - return teamMemberRepository.save(newMember); - }); - - if (teamMember.isDeleted()) { - throw new AlreadyWithdrawTeamException(); - } else { - throw new AlreadyJoinTeamException(); + this.teamMemberRepository.save(newMember); } } } From d3444aa5c6d4729b85c060a095a0c42e033838e8 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 23 Oct 2023 06:45:55 +0900 Subject: [PATCH 177/619] =?UTF-8?q?refactor:=20TeamMemberSaveService=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/service/TeamMemberSaveService.java | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java index 8d432399..d60d33a2 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java @@ -17,20 +17,30 @@ @Transactional public class TeamMemberSaveService { private final TeamMemberRepository teamMemberRepository; - public void addTeamMember(Team team, Member member){ + public void addTeamMember(Team team, Member member) { Optional teamMember = teamMemberRepository.findTeamMemberByTeamAndMember(team, member); + if (teamMember.isPresent()) { - if (teamMember.get().isDeleted()) { - throw new AlreadyWithdrawTeamException(); - } else { - throw new AlreadyJoinTeamException(); - } + handleExistingMember(teamMember.get()); + } else { + addNewTeamMember(team, member); + } + } + + private void handleExistingMember(TeamMember teamMember) { + if (teamMember.isDeleted()) { + throw new AlreadyWithdrawTeamException(); } else { - TeamMember newMember = new TeamMember(); - newMember.updateMember(member); - newMember.updateTeam(team); - team.addTeamMember(); - this.teamMemberRepository.save(newMember); + throw new AlreadyJoinTeamException(); } } + + private void addNewTeamMember(Team team, Member member) { + TeamMember newMember = new TeamMember(); + newMember.updateMember(member); + newMember.updateTeam(team); + team.addTeamMember(); + this.teamMemberRepository.save(newMember); + } + } From b7e520cd5419f7ca083cf38f263c71bea61a0aeb Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 23 Oct 2023 21:27:06 +0900 Subject: [PATCH 178/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=ED=83=88=ED=87=B4=20=EC=A0=84=20=ED=9A=8C=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EB=AA=BB=ED=95=98=EA=B2=8C=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Overview.adoc | 15 +++++++++++++++ .../application/service/SignOutUserCase.java | 1 - .../application/service/WithdrawUserCase.java | 16 ++++++++++++---- .../mypage/exception/ExistingTeamException.java | 12 ++++++++++++ .../repository/TeamMemberCustomRepository.java | 3 +++ .../TeamMemberCustomRepositoryImpl.java | 9 +++++++++ .../domain/service/TeamMemberGetService.java | 4 ++++ .../moing/backend/global/response/ErrorCode.java | 1 + 8 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mypage/exception/ExistingTeamException.java diff --git a/src/docs/asciidoc/Overview.adoc b/src/docs/asciidoc/Overview.adoc index 318e4f2e..fc4553d3 100644 --- a/src/docs/asciidoc/Overview.adoc +++ b/src/docs/asciidoc/Overview.adoc @@ -105,6 +105,18 @@ |=== +=== MyPage ErrorCode +|=== +| ErrorCode | Scope | Description +| `MP0001` +| 알람을 수정할 때 +| 알람 입력값이 유효하지 않음 + +| `MP0002` +| 회원 탈퇴할 때 +| 탈퇴되지 않은 소모임이 있음 +|=== + === Board ErrorCode |=== | ErrorCode | Scope | Description @@ -117,6 +129,7 @@ | 작성자가 아님 (권한 없음) |=== +=== BoardComment ErrorCode |=== | ErrorCode | Scope | Description | `BC0001` @@ -128,6 +141,8 @@ | 작성자가 아님 (권한 없음) |=== + + === Mission ErrorCode |=== | ErrorCode | Scope | Description diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java index cbb14594..441a6db7 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java @@ -15,7 +15,6 @@ public class SignOutUserCase { private final MemberGetService memberGetService; public void signOut(String socialId){ - //TODO: teamMember가 isDeleted가 아닌게 한개라도 있으면 error 반환 tokenUtil.expireRefreshToken(socialId); } } diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java index 54931f44..4a0dbf16 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java @@ -5,6 +5,8 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; import com.moing.backend.domain.mypage.domain.service.FeedbackSaveService; +import com.moing.backend.domain.mypage.exception.ExistingTeamException; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.global.config.security.jwt.TokenUtil; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -12,19 +14,25 @@ @Service @RequiredArgsConstructor public class WithdrawUserCase { + private final MemberGetService memberGetService; private final FeedbackSaveService feedbackSaveService; private final TokenUtil tokenUtil; private final MemberDeleteService memberDeleteService; + private final TeamMemberGetService teamMemberGetService; public void withdraw(String socialId, WithdrawRequest withdrawRequest) { - //1. 멤버 삭제 Member member = memberGetService.getMemberBySocialId(socialId); + checkMemberIsNotPartOfAnyTeam(member); memberDeleteService.deleteMember(member); - //TODO: 애플과 카카오 회원탈퇴 - //2. 피드백 저장 feedbackSaveService.saveFeedback(member, withdrawRequest); - //3. 리프레시 토큰 만료 tokenUtil.expireRefreshToken(socialId); } + + private void checkMemberIsNotPartOfAnyTeam(Member member) { + if (!teamMemberGetService.getNotDeletedTeamMember(member.getMemberId()).isEmpty()) { + throw new ExistingTeamException(); + } + } } + diff --git a/src/main/java/com/moing/backend/domain/mypage/exception/ExistingTeamException.java b/src/main/java/com/moing/backend/domain/mypage/exception/ExistingTeamException.java new file mode 100644 index 00000000..e5f87913 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mypage/exception/ExistingTeamException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mypage.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class ExistingTeamException extends ApplicationException { + public ExistingTeamException() { + super(ErrorCode.EXISTING_TEAM_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index fdfc1193..ff212d46 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -1,6 +1,8 @@ package com.moing.backend.domain.teamMember.domain.repository; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import java.util.List; import java.util.Optional; @@ -10,4 +12,5 @@ public interface TeamMemberCustomRepository { Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId); Optional> findFcmTokensByTeamId(Long teamId); List findTeamMemberInfoByTeamId(Long teamId); + List findTeamMemberByMemberId(Long memberId); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index c8d7cf6b..b692fcee 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.moing.backend.domain.team.domain.entity.QTeam; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -69,4 +70,12 @@ public List findTeamMemberInfoByTeamId(Long teamId){ .groupBy(teamMember.member.memberId) .fetch(); } + + @Override + public List findTeamMemberByMemberId(Long memberId) { + return queryFactory.selectFrom(teamMember) + .where(teamMember.member.memberId.eq(memberId) + .and(teamMember.isDeleted.eq(false))) + .fetch(); + } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index ba86c2f7..138d8d0f 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -36,4 +36,8 @@ public Optional> getFcmTokens(Long teamId) { public List getTeamMemberInfo(Long teamId){ return teamMemberRepository.findTeamMemberInfoByTeamId(teamId); } + + public List getNotDeletedTeamMember(Long memberId){ + return teamMemberRepository.findTeamMemberByMemberId(memberId); + } } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 129e9f03..2f5ddd21 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -44,6 +44,7 @@ public enum ErrorCode { //마이페이지 관련 에러 코드 INVALID_ALARM_ERROR("MP0001","유효하지 않는 알람 입력값입니다"), + EXISTING_TEAM_ERROR("MP0002","탈퇴되지 않은 소모임이 있습니다."), //게시글 관련 에러 코드 NOT_FOUND_BY_BOARD_ID_ERROR("B0001","해당 boardId인 게시글이 존재하지 않습니다."), From 33f239451822d35c1a8e20860f3662b1c6c7a471 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 26 Oct 2023 21:46:38 +0900 Subject: [PATCH 179/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=A0=84=20=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Auth-API.adoc | 14 +++--- src/docs/asciidoc/Board-API.adoc | 12 ++--- src/docs/asciidoc/BoardComment_API.adoc | 8 ++-- src/docs/asciidoc/Fire-API.adoc | 8 ++-- src/docs/asciidoc/Image-API.adoc | 2 +- src/docs/asciidoc/Mission-API.adoc | 12 ++--- src/docs/asciidoc/MissionArchive-API.adoc | 18 ++++---- src/docs/asciidoc/MissionBoard-API.adoc | 16 +++---- src/docs/asciidoc/MissionGatherBoard-API.adoc | 9 ++-- src/docs/asciidoc/Mypage-API.adoc | 14 +++--- src/docs/asciidoc/Team-API.adoc | 20 ++++---- src/docs/asciidoc/api.adoc | 2 +- .../response/GetCurrentStatusResponse.java | 17 +++++++ .../team/application/mapper/TeamMapper.java | 14 ++++-- .../application/service/GetTeamUserCase.java | 6 +++ .../team/presentation/TeamController.java | 12 ++++- .../constant/TeamResponseMessage.java | 7 +-- .../team/presentation/TeamControllerTest.java | 46 ++++++++++++++++++- 18 files changed, 161 insertions(+), 76 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/GetCurrentStatusResponse.java diff --git a/src/docs/asciidoc/Auth-API.adoc b/src/docs/asciidoc/Auth-API.adoc index 2795415a..7c5b3d49 100644 --- a/src/docs/asciidoc/Auth-API.adoc +++ b/src/docs/asciidoc/Auth-API.adoc @@ -2,7 +2,7 @@ = Auth API [[Auth-Kako-소셜-로그인]] -=== Auth Kakao 소셜 로그인 +== Auth Kakao 소셜 로그인 operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-request,request-fields'] operation::auth-controller-test/kakao_소셜_로그인_회원가입_전[snippets='http-response,response-fields'] operation::auth-controller-test/kakao_소셜_로그인_회원가입_후[snippets='http-response,response-fields'] @@ -10,14 +10,14 @@ operation::auth-controller-test/kakao_소셜_로그인_회원가입_후[snippets --- [[Auth-Apple-소셜-로그인]] -=== Auth Apple 소셜 로그인 +== Auth Apple 소셜 로그인 operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-request,request-fields'] operation::auth-controller-test/apple_소셜_로그인_회원가입_전[snippets='http-response,response-fields'] operation::auth-controller-test/apple_소셜_로그인_회원가입_후[snippets='http-response,response-fields'] [[Auth-Google-소셜-로그인]] -=== Auth Google 소셜 로그인 +== Auth Google 소셜 로그인 operation::auth-controller-test/google_소셜_로그인_회원가입_전[snippets='http-request,request-fields'] operation::auth-controller-test/google_소셜_로그인_회원가입_전[snippets='http-response,response-fields'] operation::auth-controller-test/google_소셜_로그인_회원가입_후[snippets='http-response,response-fields'] @@ -35,15 +35,15 @@ operation::auth-controller-test/sign_up[snippets='http-request,request-fields,ht [[Auth-토큰-재발급]] -=== Auth 토큰 재발급 +== Auth 토큰 재발급 operation::auth-controller-test/reissue_token[snippets='http-request,http-response,response-fields'] [[Auth-닉네임-검사]] -=== Auth 닉네임 중복검사 요청 +== Auth 닉네임 중복검사 요청 operation::auth-controller-test/check_nickname_중복o[snippets='http-request,path-parameters'] -=== Auth 닉네임 중복인 경우 +== Auth 닉네임 중복인 경우 operation::auth-controller-test/check_nickname_중복o[snippets='http-response,response-fields'] -=== Auth 닉네임 중복이 아닌 경우 +== Auth 닉네임 중복이 아닌 경우 operation::auth-controller-test/check_nickname_중복x[snippets='http-response,response-fields'] diff --git a/src/docs/asciidoc/Board-API.adoc b/src/docs/asciidoc/Board-API.adoc index 8e0de4ca..87e99f01 100644 --- a/src/docs/asciidoc/Board-API.adoc +++ b/src/docs/asciidoc/Board-API.adoc @@ -2,26 +2,26 @@ = Board API [[Board-게시글-생성]] -=== Board 게시글 생성 +== Board 게시글 생성 operation::board-controller-test/create_board[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- [[Board-게시글-수정]] -=== Board 게시글 수정 +== Board 게시글 수정 operation::board-controller-test/update_board[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- [[Board-게시글-삭제]] -=== Board 게시글 삭제 -operation::board-controller-test/delete_board[snippets='http-request,path-parameters,request-fields,response-fields'] +== Board 게시글 삭제 +operation::board-controller-test/delete_board[snippets='http-request,path-parameters,response-fields'] --- [[Board-게시글-전체-조회]] -=== Board 게시글 전체 조회 +== Board 게시글 전체 조회 operation::board-controller-test/get_board_all[snippets='http-request,path-parameters,http-response,response-fields'] --- [[Board-게시글-상제-조회]] -=== Board 게시글 상세 조회 +== Board 게시글 상세 조회 operation::board-controller-test/get_board_detail[snippets='http-request,path-parameters,http-response,response-fields'] --- \ No newline at end of file diff --git a/src/docs/asciidoc/BoardComment_API.adoc b/src/docs/asciidoc/BoardComment_API.adoc index 7704d36b..f9a2ac25 100644 --- a/src/docs/asciidoc/BoardComment_API.adoc +++ b/src/docs/asciidoc/BoardComment_API.adoc @@ -2,16 +2,16 @@ = Board Comment API [[Board-Comment-댓글-생성]] -=== Board Comment 댓글 생성 +== Board Comment 댓글 생성 operation::board-comment-controller-test/create_board_comment[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- [[Board-Comment-댓글-삭제]] -=== Board Comment 댓글 삭제 -operation::board-comment-controller-test/delete_board_comment[snippets='http-request,path-parameters,request-fields,response-fields'] +== Board Comment 댓글 삭제 +operation::board-comment-controller-test/delete_board_comment[snippets='http-request,path-parameters,response-fields'] --- [[Board-Comment-댓글-전체-조회]] -=== Board Comment 댓글 전체 조회 +== Board Comment 댓글 전체 조회 operation::board-comment-controller-test/get_board_comment_all[snippets='http-request,path-parameters,http-response,response-fields'] --- diff --git a/src/docs/asciidoc/Fire-API.adoc b/src/docs/asciidoc/Fire-API.adoc index 3da56ea5..554c28ac 100644 --- a/src/docs/asciidoc/Fire-API.adoc +++ b/src/docs/asciidoc/Fire-API.adoc @@ -4,13 +4,13 @@ = Fire API [[Fire-불던지기]] -=== 불 던지기 -operation::fire-controller-test/불_던지기[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== 불 던지기 +operation::fire-controller-test/불_던지기[snippets='http-request,path-parameters,http-response,response-fields'] --- [[Fire-불던질사람조회]] -=== 불 던질 사람 조회 -operation::fire-controller-test/불_던질_사람_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== 불 던질 사람 조회 +operation::fire-controller-test/불_던질_사람_조회[snippets='http-request,path-parameters,http-response,response-fields'] --- diff --git a/src/docs/asciidoc/Image-API.adoc b/src/docs/asciidoc/Image-API.adoc index d2bb8996..488ce5be 100644 --- a/src/docs/asciidoc/Image-API.adoc +++ b/src/docs/asciidoc/Image-API.adoc @@ -2,7 +2,7 @@ = Image API [[Presigned-Url-발급]] -=== Presigned Url 발급 +== Presigned Url 발급 operation::image-controller-test/create_presigned_url[snippets='http-request,http-response,request-fields,response-fields'] === imageFileExtension diff --git a/src/docs/asciidoc/Mission-API.adoc b/src/docs/asciidoc/Mission-API.adoc index 2485c8fb..6f504637 100644 --- a/src/docs/asciidoc/Mission-API.adoc +++ b/src/docs/asciidoc/Mission-API.adoc @@ -4,26 +4,26 @@ = Mission API [[Mission-생성]] -=== Mission 생성 +== Mission 생성 operation::mission-controller-test/미션_생성[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- [[Mission-조회]] -=== Mission 조회 -operation::mission-controller-test/미션_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== Mission 조회 +operation::mission-controller-test/미션_조회[snippets='http-request,path-parameters,http-response,response-fields'] --- [[Mission-수정]] -=== Mission 수정 +== Mission 수정 operation::mission-controller-test/미션_수정[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- [[Mission-삭제]] -=== Mission 삭제 -operation::mission-controller-test/미션_삭제[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== Mission 삭제 +operation::mission-controller-test/미션_삭제[snippets='http-request,path-parameters,http-response,response-fields'] --- diff --git a/src/docs/asciidoc/MissionArchive-API.adoc b/src/docs/asciidoc/MissionArchive-API.adoc index 8d287be0..e60833cf 100644 --- a/src/docs/asciidoc/MissionArchive-API.adoc +++ b/src/docs/asciidoc/MissionArchive-API.adoc @@ -4,37 +4,37 @@ = MissionArchive API [[MissionArchive-인증하기]] -=== 미션 인증하기 +== 미션 인증하기 operation::mission-archive-controller-test/미션_인증하기[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- [[MissionArchive-재인증하기]] -=== 미션 재인증하기 +== 미션 재인증하기 operation::mission-archive-controller-test/미션_재인증하기[snipipets='http-request,path-parameters,request-fields,http-response,response-fields'] --- [[MissionArchive-나의미션인증조회]] -=== 나의 미션 인증 조회 -operation::mission-archive-controller-test/나의_미션_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== 나의 미션 인증 조회 +operation::mission-archive-controller-test/나의_미션_인증_조회[snippets='http-request,path-parameters,http-response,response-fields'] --- [[MissionArchive-모임원미션인증조회]] -=== 모임원 미션 인증 조회 -operation::mission-archive-controller-test/모임원_미션_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== 모임원 미션 인증 조회 +operation::mission-archive-controller-test/모임원_미션_인증_조회[snippets='http-request,path-parameters,http-response,response-fields'] --- [[MissionArchive-인증성공인원조회]] -=== 인증 성공 인원 조회 ( n/n명 ) -operation::mission-archive-controller-test/인증_성공_인원_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== 인증 성공 인원 조회 ( n/n명 ) +operation::mission-archive-controller-test/인증_성공_인원_조회[snippets='http-request,path-parameters,http-response,response-fields'] --- [[MissionArchive-미션인증물좋아요]] -=== 미션 인증물 좋아요 +== 미션 인증물 좋아요 operation::mission-archive-controller-test/미션_인증물_좋아요[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- diff --git a/src/docs/asciidoc/MissionBoard-API.adoc b/src/docs/asciidoc/MissionBoard-API.adoc index fb985bf0..f63edbd8 100644 --- a/src/docs/asciidoc/MissionBoard-API.adoc +++ b/src/docs/asciidoc/MissionBoard-API.adoc @@ -4,25 +4,25 @@ = MissionBoard API [[MissionBoard-단일미션인증조회]] -=== 단일 미션 인증 조회 -operation::mission-board-controller-test/단일_미션_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== 단일 미션 인증 조회 +operation::mission-board-controller-test/단일_미션_인증_조회[snippets='http-request,path-parameters,http-response,response-fields'] --- [[MissionBoard-반복미션인증조회]] -=== 반복 미션 인증 조회 -operation::mission-board-controller-test/반복 미션 인증 조회[snipipets='http-request,path-parameters,request-fields,http-response,response-fields'] +== 반복 미션 인증 조회 +operation::mission-board-controller-test/반복_미션_인증_조회[snipipets='http-request,path-parameters,request-fields,http-response,response-fields'] --- [[MissionBoard-나의미션인증조회]] -=== 나의 미션 인증 조회 -operation::mission-archive-controller-test/나의_미션_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== 나의 미션 인증 조회 +operation::mission-archive-controller-test/나의_미션_인증_조회[snippets='http-request,path-parameters,http-response,response-fields'] --- [[MissionBoard-종료된인증조회]] -=== 종료된 인증 조회 -operation::mission-board-controller-test/종료된_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== 종료된 인증 조회 +operation::mission-board-controller-test/종료된_인증_조회[snippets='http-request,path-parameters,http-response,response-fields'] --- diff --git a/src/docs/asciidoc/MissionGatherBoard-API.adoc b/src/docs/asciidoc/MissionGatherBoard-API.adoc index 4e78a299..691b3aec 100644 --- a/src/docs/asciidoc/MissionGatherBoard-API.adoc +++ b/src/docs/asciidoc/MissionGatherBoard-API.adoc @@ -4,13 +4,12 @@ = MissionBoard API [[MissionBoard-미션-모아보기-단일]] -=== 미션_모아보기_단일_미션 -operation::mission-gather-controller-test/미션_모아보기_단일_미션[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] - +== 미션_모아보기_단일_미션 +operation::mission-gather-controller-test/미션_모아보기_단일_미션[snippets='http-request,http-response,response-fields'] --- [[MissionBoard-미션-모아보기-반복]] -=== 미션_모아보기_반복_미션 -operation::mission-gather-controller-test/미션_모아보기_반복_미션[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +== 미션_모아보기_반복_미션 +operation::mission-gather-controller-test/미션_모아보기_반복_미션[snippets='http-request,http-response,response-fields'] --- diff --git a/src/docs/asciidoc/Mypage-API.adoc b/src/docs/asciidoc/Mypage-API.adoc index adb5aa3b..b5b9e9c8 100644 --- a/src/docs/asciidoc/Mypage-API.adoc +++ b/src/docs/asciidoc/Mypage-API.adoc @@ -2,26 +2,26 @@ = Mypage API [[Mypage-로그아웃]] -=== Mypage 로그아웃 +== Mypage 로그아웃 operation::mypage-controller-test/sign_out[snippets='http-request,http-response,response-fields'] --- [[Mypage-회원탈퇴]] -=== Mypage 회원탈퇴 +== Mypage 회원탈퇴 operation::mypage-controller-test/withdraw[snippets='http-request,request-fields,http-response,response-fields'] [[Mypage-전체-조회]] -=== Mypage 전체 조회 +== Mypage 전체 조회 operation::mypage-controller-test/get_mypage[snippets='http-request,http-response,response-fields'] [[Mypage-프로필-조회]] -=== Mypage 프로필 조회 +== Mypage 프로필 조회 operation::mypage-controller-test/get_profile[snippets='http-request,http-response,response-fields'] IMPORTANT: Response Fields (profileImage, nickName, introduction)이 "undef" 인 경우는 사용자가 아직 입력을 안 한 경우임 [[Mypage-프로필-수정]] -=== Mypage 프로필 수정 +== Mypage 프로필 수정 operation::mypage-controller-test/update_profile[snippets='http-request,http-response,request-fields,response-fields'] IMPORTANT: Request Fileds는 반드시 세 값이 모두 들어가야 하는 것이 아니고, 업데이트할 값만 입력해도 됨, 따라서 아래와 같은 예시 가능 + @@ -36,11 +36,11 @@ Host: localhost:8080 [[Mypage-알람설정_조회]] -=== Mypage 알람설정 조회 +== Mypage 알람설정 조회 operation::mypage-controller-test/get_alarm[snippets='http-request,http-response,response-fields'] [[Mypage-알람설정_수정]] -=== Mypage 알람설정 수정 +== Mypage 알람설정 수정 operation::mypage-controller-test/update_alarm[snippets='http-request,http-response,request-parameters,response-fields'] diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc index 32e55c69..db7316f9 100644 --- a/src/docs/asciidoc/Team-API.adoc +++ b/src/docs/asciidoc/Team-API.adoc @@ -2,10 +2,10 @@ = Team API [[Team-소모임-개설]] -=== Team 소모임 개설 +== Team 소모임 개설 operation::team-controller-test/create_team[snippets='http-request,request-fields,http-response,response-fields'] -=== Team Category +== Team Category |=== | Category | Description @@ -30,25 +30,29 @@ operation::team-controller-test/create_team[snippets='http-request,request-field [[Team-소모임-가입]] -=== Team 소모임 가입 +== Team 소모임 가입 operation::team-controller-test/sign-in_team[snippets='http-request,path-parameters,http-response,response-fields'] [[Team-소모임-조회]] -=== Team 소모임 조회 +== Team 소모임 조회 operation::team-controller-test/get_team[snippets='http-request,http-response,response-fields'] [[Team-목표보드-조회]] -=== Team 목표보드_소모임 단건_조회 +== Team 목표보드_소모임 단건_조회 operation::team-controller-test/get_team_detail[snippets='http-request,path-parameters,http-response,response-fields'] [[Team-소모임-수정]] -=== Team 소모임 수정 +== Team 소모임 수정 operation::team-controller-test/update_team[snippets='http-request,path-parameters,http-response,request-fields,response-fields'] +[[Team-소모임-수정전-조회]] +== Team 소모임 수정 전 조회 +operation::team-controller-test/get_current_status[snippets='http-request,path-parameters,http-response,response-fields'] + [[Team-소모임-강제종료]] -=== Team 소모임 강제종료 +== Team 소모임 강제종료 operation::team-controller-test/disband_team[snippets='http-request,path-parameters,http-response,response-fields'] [[Team-소모임-탈퇴]] -=== Team 소모임원 강제종료 +== Team 소모임원 강제종료 operation::team-controller-test/withdraw_team[snippets='http-request,path-parameters,http-response,response-fields'] diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 5279620f..07a4bc65 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -3,7 +3,7 @@ :icons: font :source-highlighter: highlightjs :toc: left -:toclevels: 2 +:toclevels: 1 :sectlinks: include::Overview.adoc[] diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetCurrentStatusResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetCurrentStatusResponse.java new file mode 100644 index 00000000..32fa1745 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetCurrentStatusResponse.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.team.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class GetCurrentStatusResponse { + + private String name; + + private String introduction; + + private String profileImgUrl; +} diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index ec4ba6ac..7b8ce92d 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -2,16 +2,12 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; -import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; -import com.moing.backend.domain.team.application.dto.response.GetTeamDetailResponse; -import com.moing.backend.domain.team.application.dto.response.TeamInfo; -import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; +import com.moing.backend.domain.team.application.dto.response.*; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.moing.backend.domain.team.domain.constant.Category; import com.moing.backend.domain.team.domain.entity.Team; import org.springframework.stereotype.Component; -import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.temporal.ChronoUnit; @@ -63,4 +59,12 @@ public Long calculateDuration(LocalDateTime approvalTime) { return daysBetween; } + public GetCurrentStatusResponse toCurrentStatusResponse(Team team) { + return GetCurrentStatusResponse.builder() + .name(team.getName()) + .introduction(team.getIntroduction()) + .profileImgUrl(team.getProfileImgUrl()) + .build(); + } + } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java index 30266ad4..a19b000f 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.team.application.dto.response.GetCurrentStatusResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamDetailResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; @@ -38,4 +39,9 @@ public GetTeamDetailResponse getTeamDetailResponse(String socialId, Long teamId) Team team = teamGetService.getTeamByTeamId(teamId); return teamMapper.toTeamDetailResponse(team, boardNum, teamMemberInfoList); } + + public GetCurrentStatusResponse getCurrentStatus(Long teamId) { + Team team=teamGetService.getTeamByTeamId(teamId); + return teamMapper.toCurrentStatusResponse(team); + } } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index 907fef05..21675d8a 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -52,7 +52,7 @@ public ResponseEntity> getTeam(@AuthenticationP * [GET] api/team/{teamId} * 작성자: 김민수 */ - @GetMapping("/{teamId}") + @GetMapping("/board/{teamId}") public ResponseEntity> getTeamDetail(@AuthenticationPrincipal User user, @PathVariable Long teamId) { return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_DETAIL_SUCCESS.getMessage(), this.getTeamUserCase.getTeamDetailResponse(user.getSocialId(), teamId))); @@ -104,4 +104,14 @@ public ResponseEntity> updateTeam(@Valid @Re return ResponseEntity.ok(SuccessResponse.create(UPDATE_TEAM_SUCCESS.getMessage(), this.updateTeamUserCase.updateTeam(updateTeamRequest, user.getSocialId(), teamId))); } + /** + * 소모임 수정 전 조회 + * [GET] api/team/{teamid} + */ + @GetMapping("/{teamId}") + public ResponseEntity> getCurrentStatus(@AuthenticationPrincipal User user, + @PathVariable Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(GET_CURRENT_STATUS_SUCCESS.getMessage(), this.getTeamUserCase.getCurrentStatus(teamId))); + } + } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index d9d08180..6a9846e6 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -6,10 +6,11 @@ @Getter @RequiredArgsConstructor public enum TeamResponseMessage { - CREATE_TEAM_SUCCESS("소모임을 생성하였습니다"), + CREATE_TEAM_SUCCESS("소모임을 생성하였습니다."), GET_TEAM_SUCCESS("홈 화면에서 내 소모임을 모두 조회했습니다."), - GET_TEAM_DETAIL_SUCCESS("목표보드를 조회했습니다"), - SIGNIN_TEAM_SUCCESS("소모임에 가입하였습니다"), + GET_TEAM_DETAIL_SUCCESS("목표보드를 조회했습니다."), + SIGNIN_TEAM_SUCCESS("소모임에 가입하였습니다."), + GET_CURRENT_STATUS_SUCCESS("소모임 수정 전 조회했습니다."), DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."), UPDATE_TEAM_SUCCESS("[소모임장 권한] 소모임을 수정했습니다"), WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"), diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 615b0557..0b807654 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -206,7 +206,7 @@ public void get_team_detail() throws Exception { //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/team/{teamId}", teamId) + get("/api/team/board/{teamId}", teamId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) ); @@ -431,5 +431,49 @@ public void update_team() throws Exception { ); } + @Test + public void get_current_status() throws Exception { + + // given + Long teamId = 1L; + + GetCurrentStatusResponse output = GetCurrentStatusResponse.builder() + .name("팀 이름") + .introduction("소개") + .profileImgUrl("프로필 이미지") + .build(); + + given(getTeamUserCase.getCurrentStatus(any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/{teamId}", teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("소모임을 수정했습니다."), + fieldWithPath("data.name").description("소모임 이름"), + fieldWithPath("data.introduction").description("소모임 소개글"), + fieldWithPath("data.profileImgUrl").description("소모임 대표 사진") + ) + ) + ); + } } From 69fff58ebfa595c26e01a73737c871a2a275c97f Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 29 Oct 2023 23:04:21 +0900 Subject: [PATCH 180/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=A0=84=20=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- src/docs/asciidoc/Auth-API.adoc | 2 +- src/docs/asciidoc/Team-API.adoc | 4 ++ .../dto/response/DeleteTeamResponse.java | 5 -- .../dto/response/ReviewTeamResponse.java | 19 ++++++ .../team/application/mapper/TeamMapper.java | 5 +- .../service/DisbandTeamUserCase.java | 4 +- .../service/ReviewTeamUserCase.java | 27 ++++++++ .../service/WithdrawTeamUserCase.java | 4 +- .../team/presentation/TeamController.java | 13 ++++ .../constant/TeamResponseMessage.java | 1 + .../filter/JwtAuthenticationEntryPoint.java | 38 +++++++---- .../team/presentation/TeamControllerTest.java | 67 +++++++++++++------ 13 files changed, 143 insertions(+), 48 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUserCase.java diff --git a/.gitignore b/.gitignore index 7554674c..b603f75b 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,4 @@ data.sql #### docs #### !**/src/main/resources/static/docs/ -*.html +*.html \ No newline at end of file diff --git a/src/docs/asciidoc/Auth-API.adoc b/src/docs/asciidoc/Auth-API.adoc index 7c5b3d49..40d5aec1 100644 --- a/src/docs/asciidoc/Auth-API.adoc +++ b/src/docs/asciidoc/Auth-API.adoc @@ -24,7 +24,7 @@ operation::auth-controller-test/google_소셜_로그인_회원가입_후[snippet [[Auth-회원가입]] -=== Auth 회원가입 +== Auth 회원가입 |=== | 성별 | `MAN` diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc index db7316f9..b6e71d0d 100644 --- a/src/docs/asciidoc/Team-API.adoc +++ b/src/docs/asciidoc/Team-API.adoc @@ -49,6 +49,10 @@ operation::team-controller-test/update_team[snippets='http-request,path-paramete == Team 소모임 수정 전 조회 operation::team-controller-test/get_current_status[snippets='http-request,path-parameters,http-response,response-fields'] +[[Team-소모임-삭제전-조회]] +== Team 소모임 삭제 전 조회 +operation::team-controller-test/review_team[snippets='http-request,path-parameters,http-response,response-fields'] + [[Team-소모임-강제종료]] == Team 소모임 강제종료 operation::team-controller-test/disband_team[snippets='http-request,path-parameters,http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java index 8cc78bb2..92ed9017 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/DeleteTeamResponse.java @@ -11,9 +11,4 @@ @NoArgsConstructor public class DeleteTeamResponse { private Long teamId; - private String teamName; - private Integer numOfMember; - private Long duration; //걸린시간(단위:날짜) - private Long numOfMission; - private Integer levelOfFire; //불꽃 레벨 } diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java new file mode 100644 index 00000000..f3b86539 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.team.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ReviewTeamResponse { + private Long teamId; + private String teamName; + private Integer numOfMember; + private Long duration; //걸린시간(단위:날짜) + private Long numOfMission; + private Integer levelOfFire; //불꽃 레벨 +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index 7b8ce92d..be62dc70 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -38,8 +38,9 @@ public GetTeamDetailResponse toTeamDetailResponse(Team team, Integer boardNum, L .build(); } - public DeleteTeamResponse toDeleteTeamResponse(Long numOfMission, Team team){ - return DeleteTeamResponse.builder() + public ReviewTeamResponse toReviewTeamResponse(Long numOfMission, Team team){ + return ReviewTeamResponse + .builder() .teamId(team.getTeamId()) .teamName(team.getName()) .numOfMember(team.getNumOfMember()) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java index f0e88b2e..82fdae48 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java @@ -21,8 +21,6 @@ public class DisbandTeamUserCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; private final CheckLeaderUserCase checkLeaderUserCase; - private final MissionQueryService missionQueryService; - private final TeamMapper teamMapper; public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); @@ -33,6 +31,6 @@ public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { } else { throw new NotAuthByTeamException(); } - return teamMapper.toDeleteTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()), team); + return new DeleteTeamResponse(teamId); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUserCase.java new file mode 100644 index 00000000..3c7c477e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUserCase.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.team.application.dto.response.ReviewTeamResponse; +import com.moing.backend.domain.team.application.mapper.TeamMapper; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +public class ReviewTeamUserCase { + + private final TeamGetService teamGetService; + private final TeamMapper teamMapper; + private final MissionQueryService missionQueryService; + + + public ReviewTeamResponse reviewTeam(String socialId, Long teamId){ + Team team=teamGetService.getTeamByTeamId(teamId); + return teamMapper.toReviewTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()),team); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java index 15538b62..3e3a162d 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java @@ -22,14 +22,12 @@ public class WithdrawTeamUserCase { private final TeamMemberGetService teamMemberGetService; private final MemberGetService memberGetService; private final TeamGetService teamGetService; - private final MissionQueryService missionQueryService; - private final TeamMapper teamMapper; public DeleteTeamResponse withdrawTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); teamMember.deleteMember(team); - return teamMapper.toDeleteTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()),team); + return new DeleteTeamResponse(teamId); } } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index 21675d8a..137cc77b 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -25,6 +25,7 @@ public class TeamController { private final DisbandTeamUserCase disbandTeamUserCase; private final WithdrawTeamUserCase withdrawTeamUserCase; private final UpdateTeamUserCase updateTeamUserCase; + private final ReviewTeamUserCase reviewTeamUserCase; /** * 소모임 생성 (only 개설만) @@ -92,6 +93,18 @@ public ResponseEntity> withdrawTeam(@Authent return ResponseEntity.ok(SuccessResponse.create(WITHDRAW_TEAM_SUCCESS.getMessage(), this.withdrawTeamUserCase.withdrawTeam(user.getSocialId(),teamId))); } + /** + * 소모임 강제 종료, 탈퇴 전 정보 보여주기 + * [GET] api/team/{teamId}/review + * 작성자: 김민수 + */ + @GetMapping("/{teamId}/review") + public ResponseEntity> reviewTeam(@AuthenticationPrincipal User user, + @PathVariable Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(REVIEW_TEAM_SUCCESS.getMessage(), this.reviewTeamUserCase.reviewTeam(user.getSocialId(), teamId))); + } + + /** * 소모임 수정 (소모임장) * [POST] api/team/{teamId} diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 6a9846e6..d400e9f4 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -11,6 +11,7 @@ public enum TeamResponseMessage { GET_TEAM_DETAIL_SUCCESS("목표보드를 조회했습니다."), SIGNIN_TEAM_SUCCESS("소모임에 가입하였습니다."), GET_CURRENT_STATUS_SUCCESS("소모임 수정 전 조회했습니다."), + REVIEW_TEAM_SUCCESS("소모임 삭제 전 조회했습니다."), DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."), UPDATE_TEAM_SUCCESS("[소모임장 권한] 소모임을 수정했습니다"), WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"), diff --git a/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthenticationEntryPoint.java b/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthenticationEntryPoint.java index 89133842..eef927a8 100644 --- a/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthenticationEntryPoint.java +++ b/src/main/java/com/moing/backend/global/config/security/filter/JwtAuthenticationEntryPoint.java @@ -22,27 +22,37 @@ public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { String exception = String.valueOf(request.getAttribute("exception")); - log.info("commonce:" + exception); + log.info("commence:" + exception); - if (exception.equals(JwtExceptionList.ADDITIONAL_REQUIRED_TOKEN.getErrorCode())) - setResponse(response, JwtExceptionList.ADDITIONAL_REQUIRED_TOKEN); + switch (exception) { + case "J0007": + setResponse(response, JwtExceptionList.ADDITIONAL_REQUIRED_TOKEN); + break; - else if (exception.equals(JwtExceptionList.UNKNOWN_ERROR.getErrorCode())) - setResponse(response, JwtExceptionList.UNKNOWN_ERROR); + case "J0001": + setResponse(response, JwtExceptionList.UNKNOWN_ERROR); + break; - else if (exception.equals(JwtExceptionList.MAL_FORMED_TOKEN.getErrorCode())) - setResponse(response, JwtExceptionList.MAL_FORMED_TOKEN); + case "J0002": + setResponse(response, JwtExceptionList.MAL_FORMED_TOKEN); + break; - else if (exception.equals(JwtExceptionList.ILLEGAL_TOKEN.getErrorCode())) - setResponse(response, JwtExceptionList.ILLEGAL_TOKEN); + case "J0006": + setResponse(response, JwtExceptionList.ILLEGAL_TOKEN); + break; - else if (exception.equals(JwtExceptionList.EXPIRED_TOKEN.getErrorCode())) - setResponse(response, JwtExceptionList.EXPIRED_TOKEN); + case "J0003": + setResponse(response, JwtExceptionList.EXPIRED_TOKEN); + break; - else if (exception.equals(JwtExceptionList.UNSUPPORTED_TOKEN.getErrorCode())) - setResponse(response, JwtExceptionList.UNSUPPORTED_TOKEN); + case "J0004": + setResponse(response, JwtExceptionList.UNSUPPORTED_TOKEN); + break; - else setResponse(response, JwtExceptionList.ACCESS_DENIED); + default: + setResponse(response, JwtExceptionList.ACCESS_DENIED); + break; + } } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 0b807654..869e763c 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -42,6 +42,8 @@ public class TeamControllerTest extends CommonControllerTest { private SignInTeamUserCase signInTeamUserCase; @MockBean private UpdateTeamUserCase updateTeamUserCase; + @MockBean + private ReviewTeamUserCase reviewTeamUserCase; @Test public void create_team() throws Exception { @@ -245,10 +247,10 @@ public void get_team_detail() throws Exception { } @Test - public void disband_team() throws Exception { + public void review_team() throws Exception { //given Long teamId = 1L; // 예시 ID - DeleteTeamResponse output = DeleteTeamResponse.builder() + ReviewTeamResponse output = ReviewTeamResponse.builder() .teamId(teamId) .teamName("팀 이름") .numOfMember(9) @@ -257,13 +259,13 @@ public void disband_team() throws Exception { .levelOfFire(3) .build(); - given(disbandTeamUserCase.disbandTeam(any(), any())).willReturn(output); + given(reviewTeamUserCase.reviewTeam(any(), any())).willReturn(output); //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - delete("/api/team/{teamId}/disband", teamId) - .header("Authorization", "Bearer ACCESS_TOKEN") - .contentType(MediaType.APPLICATION_JSON) + get("/api/team/{teamId}/review", teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) ); //then @@ -279,8 +281,8 @@ public void disband_team() throws Exception { ), responseFields( fieldWithPath("isSuccess").description("true"), - fieldWithPath("message").description("[소모임장 권한] 소모임을 강제 종료했습니다."), - fieldWithPath("data.teamId").description("강제종료한 소모임 id"), + fieldWithPath("message").description("소모임 삭제 전 조회했습니다."), + fieldWithPath("data.teamId").description("삭제할 소모임 id"), fieldWithPath("data.teamName").description("소모임 이름"), fieldWithPath("data.numOfMember").description("모임원 명 수"), fieldWithPath("data.duration").description("소모임과 함께한 시간"), @@ -290,17 +292,49 @@ public void disband_team() throws Exception { ) ); } + + @Test + public void disband_team() throws Exception { + //given + Long teamId = 1L; // 예시 ID + DeleteTeamResponse output = DeleteTeamResponse.builder() + .teamId(teamId) + .build(); + + given(disbandTeamUserCase.disbandTeam(any(), any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/team/{teamId}/disband", teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("[소모임장 권한] 소모임을 강제 종료했습니다."), + fieldWithPath("data.teamId").description("강제종료한 소모임 id") + ) + ) + ); + } @Test public void withdraw_team() throws Exception { //given Long teamId = 1L; // 예시 ID DeleteTeamResponse output = DeleteTeamResponse.builder() .teamId(teamId) - .teamName("팀 이름") - .numOfMember(9) - .duration(30L) - .numOfMission(90L) - .levelOfFire(3) .build(); given(withdrawTeamUserCase.withdrawTeam(any(), any())).willReturn(output); @@ -326,12 +360,7 @@ public void withdraw_team() throws Exception { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("[소모임원 권한] 소모임을 탈퇴하였습니다"), - fieldWithPath("data.teamId").description("탈퇴한 소모임 id"), - fieldWithPath("data.teamName").description("소모임 이름"), - fieldWithPath("data.numOfMember").description("모임원 명 수"), - fieldWithPath("data.duration").description("소모임과 함께한 시간"), - fieldWithPath("data.levelOfFire").description("소모임 불꽃 레벨"), - fieldWithPath("data.numOfMission").description("미션 총 개수") + fieldWithPath("data.teamId").description("탈퇴한 소모임 id") ) ) ); From da3e44e3e261507eeaa2afe269d1d0224a0d1052 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Mon, 30 Oct 2023 23:41:35 +0900 Subject: [PATCH 181/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=20=EC=8B=9C=20=EC=8A=A4=EC=BD=94=EC=96=B4=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20=EA=B5=AC=ED=98=84=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionStateUseCase.java | 24 ++++++++++++-- .../service/MissionStateQueryService.java | 2 ++ .../service/TeamScoreLogicUseCase.java | 32 +++++++++++++++++++ .../teamScore/domain/entity/TeamScore.java | 20 +++++++++++- .../repository/TeamScoreCustomRepository.java | 2 +- .../TeamScoreCustomRepositoryImpl.java | 4 +-- .../domain/service/TeamScoreQueryService.java | 4 +-- .../service/TeamScoreUpdateService.java | 2 +- 8 files changed, 80 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 0279fce2..41bf4fc2 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -23,12 +23,30 @@ public class MissionStateUseCase { public boolean isAbleToEnd(Long missionId) { Mission mission = missionQueryService.findMissionById(missionId); - Long totalPerson = Long.valueOf(mission.getTeam().getNumOfMember()); - Long donePerson = missionStateQueryService.stateCountByMissionId(missionId); + Long total = totalPeople(mission); + Long done = donePeople(mission); - return donePerson == totalPerson-1; + return done == total-1; } + public Long getScoreByMission(Mission mission) { + Long total = totalPeople(mission); + Long done = donePeople(mission); + + return (done / total * 100) / 5 ; + + } + + public Long donePeople(Mission mission) { + return missionStateQueryService.stateCountByMissionId(mission.getId()); + } + + public Long totalPeople(Mission mission) { + return Long.valueOf(mission.getTeam().getNumOfMember()); + + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java index 29252ce7..b5130ee6 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java @@ -16,4 +16,6 @@ public class MissionStateQueryService { public Long stateCountByMissionId(Long missionId) { return missionStateRepository.getCountsByMissionId(missionId); } + + } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index b8ec0d46..a1bf91e2 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -1,6 +1,13 @@ package com.moing.backend.domain.teamScore.application.service; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -10,7 +17,32 @@ @RequiredArgsConstructor public class TeamScoreLogicUseCase { + private final TeamGetService teamGetService; + private final MissionQueryService missionQueryService; + private final TeamScoreQueryService teamScoreQueryService; + private final MissionStateUseCase missionStateUseCase; + public Long getScore(Long teamLevel) { return 1L; } + + public Integer getLevel(Long teamId) { + return teamGetService.getTeamByTeamId(teamId).getLevelOfFire(); + } + + public Long updateSingleScore(Long missionId) { + Mission mission = missionQueryService.findMissionById(missionId); + Team team = mission.getTeam(); + TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); + teamScore.updateScore(missionStateUseCase.getScoreByMission(mission)); + teamScore.levelUp(); + return teamScore.getScore(); + } + + + + + + + } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index ca0df886..81d0278a 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -3,11 +3,13 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.Builder; +import lombok.Getter; import lombok.RequiredArgsConstructor; import javax.persistence.*; @Entity +@Getter @RequiredArgsConstructor public class TeamScore extends BaseTimeEntity { @@ -21,13 +23,29 @@ public class TeamScore extends BaseTimeEntity { private Long score; + private Long level; + @Builder - public TeamScore(Team team, Long score) { + public TeamScore(Team team, Long score,Long level) { this.team = team; this.score = score; + this.level = level; } public void updateScore(Long score) { this.score = score; } + + public void levelUp() { + final int[] steps = {0, 2, 10, 25, 45, 100}; + + for (int i = 0; i < 4; i++) { + if (steps[i] < this.level && this.level < steps[i + 1]) { + if (20 + i * 15 <= score) { + this.level+=1; + } + } + } + + } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java index 8d7c5b2f..1b08b750 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java @@ -6,6 +6,6 @@ public interface TeamScoreCustomRepository { - TeamScore findTeamScoreByTeam(Team team); + TeamScore findTeamScoreByTeam(Long teamId); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java index ba7b7191..8e038986 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java @@ -18,10 +18,10 @@ public TeamScoreCustomRepositoryImpl(EntityManager entityManager) { } @Override - public TeamScore findTeamScoreByTeam(Team team) { + public TeamScore findTeamScoreByTeam(Long teamId) { return queryFactory .selectFrom(teamScore) - .where(teamScore.team.eq(team)).fetchFirst(); + .where(teamScore.team.teamId.eq(teamId)).fetchFirst(); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java index 85b6fe0d..9f1f1e29 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java @@ -17,9 +17,9 @@ public class TeamScoreQueryService { private final TeamScoreRepository teamScoreRepository; private final TeamGetService teamGetService; - public TeamScore findTeamScoreByTeam(Team team) { + public TeamScore findTeamScoreByTeam(Long teamId) { - return teamScoreRepository.findTeamScoreByTeam(team); + return teamScoreRepository.findTeamScoreByTeam(teamId); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java index b6244817..4ec692e1 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java @@ -21,7 +21,7 @@ public class TeamScoreUpdateService { public TeamScore update(Long teamId, Long score) { Team team = teamGetService.getTeamByTeamId(teamId); - TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team); + TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); teamScore.updateScore(score); From 3e1dc8c16b54af777af2efd86d8cda2b617d46e3 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 31 Oct 2023 00:56:24 +0900 Subject: [PATCH 182/619] =?UTF-8?q?feat=20:=20mission=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20dto=20=EA=B0=9D=EC=B2=B4=20lombok=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20=ED=8C=80=EB=B3=84=20=EB=AF=B8=EC=85=98=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=EB=AC=BC=20=EB=A6=AC=ED=84=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/req/MissionReq.java | 7 +-- .../service/MissionGatherBoardUseCase.java | 15 ++++++ .../dto/req/MissionArchiveReq.java | 9 ++-- .../dto/res/MissionArchivePhotoRes.java | 17 +++++++ .../dto/res/MissionArchiveRes.java | 8 ++- .../dto/res/MissionArchiveStatusRes.java | 6 ++- .../dto/res/PersonalArchiveRes.java | 9 ++-- .../service/MissionArchiveReadUseCase.java | 10 ++-- .../MissionArchiveResponseMessage.java | 3 +- .../MissionArchiveCustomRepository.java | 4 +- .../MissionArchiveCustomRepositoryImpl.java | 43 +++++++++++++--- .../service/MissionArchiveQueryService.java | 4 ++ .../MissionArchiveController.java | 3 ++ .../presentation/MissionGatherController.java | 12 +++++ .../application/dto/MissionHeartRes.java | 6 ++- .../representation/MissionControllerTest.java | 42 ++++++++-------- .../MissionGatherControllerTest.java | 49 ++++++++++++++++++- 17 files changed, 192 insertions(+), 55 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchivePhotoRes.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java index 98962c87..083474cb 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java @@ -1,10 +1,11 @@ package com.moing.backend.domain.mission.application.dto.req; -import lombok.Builder; -import lombok.Getter; +import lombok.*; -@Getter +@AllArgsConstructor @Builder +@NoArgsConstructor +@Getter public class MissionReq { private String title; diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java index ba04e12d..f1727911 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java @@ -5,6 +5,10 @@ import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -17,7 +21,9 @@ public class MissionGatherBoardUseCase { private final MissionQueryService missionQueryService; + private final MissionArchiveQueryService missionArchiveQueryService; private final MemberGetService memberGetService; + private final TeamGetService teamGetService; public List getAllActiveSingleMissions(String userId) { Long memberId = memberGetService.getMemberBySocialId(userId).getMemberId(); @@ -30,6 +36,15 @@ public List getAllActiveRepeatMissions(String userId) { } + public List getArchivePhotoByTeamRes(String userId) { + Long memberId = memberGetService.getMemberBySocialId(userId).getMemberId(); + + List teamIdByMemberId = teamGetService.getTeamIdByMemberId(memberId); + + return missionArchiveQueryService.findTop5ArchivesByTeam(teamIdByMemberId); + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java index 8b5b7223..972479bb 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java @@ -1,12 +1,11 @@ package com.moing.backend.domain.missionArchive.application.dto.req; -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; +import lombok.*; -@Getter -@Setter +@AllArgsConstructor @Builder +@NoArgsConstructor +@Getter public class MissionArchiveReq { private String status; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchivePhotoRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchivePhotoRes.java new file mode 100644 index 00000000..331ae3e1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchivePhotoRes.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.missionArchive.application.dto.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Builder +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class MissionArchivePhotoRes { + Long teamId; + List photo; +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index fb041759..b976e42a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -1,15 +1,13 @@ package com.moing.backend.domain.missionArchive.application.dto.res; -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; +import lombok.*; import javax.annotation.Nullable; import java.util.List; - +@AllArgsConstructor @Builder +@NoArgsConstructor @Getter -@Setter public class MissionArchiveRes { private Long archiveId; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveStatusRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveStatusRes.java index 67216a52..89c30696 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveStatusRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveStatusRes.java @@ -1,10 +1,14 @@ package com.moing.backend.domain.missionArchive.application.dto.res; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; -@Getter +@AllArgsConstructor @Builder +@NoArgsConstructor +@Getter public class MissionArchiveStatusRes { private String total; private String done; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java index cdd4a2d3..01f630d8 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java @@ -1,12 +1,11 @@ package com.moing.backend.domain.missionArchive.application.dto.res; -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; +import lombok.*; -@Getter -@Setter +@AllArgsConstructor @Builder +@NoArgsConstructor +@Getter public class PersonalArchiveRes { private Long archiveId; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java index ceac49f3..afd6c0aa 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; @@ -11,6 +12,7 @@ import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.repository.TeamRepository; +import com.moing.backend.domain.team.domain.service.TeamGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -27,7 +29,7 @@ public class MissionArchiveReadUseCase { private final MemberGetService memberGetService; private final MissionQueryService missionQueryService; private final MissionArchiveQueryService missionArchiveQueryService; - private final TeamRepository teamRepository; + private final TeamGetService teamGetService; // 미션 인증 조회 @@ -35,7 +37,7 @@ public List getMyArchive(String userSocialId, Long missionId) Long memberId = memberGetService.getMemberBySocialId(userSocialId).getMemberId(); - return MissionArchiveMapper.mapToMissionArchiveResList(missionArchiveQueryService.findMyArchive(memberId, missionId),memberId); + return MissionArchiveMapper.mapToMissionArchiveResList(missionArchiveQueryService.findMyArchive(memberId, missionId), memberId); } // 모두의 미션 인증 목록 조회 @@ -44,7 +46,7 @@ public List getPersonalArchive(String userSocialId, Long mis List personalArchives = new ArrayList<>(); Long memberId = memberGetService.getMemberBySocialId(userSocialId).getMemberId(); - return MissionArchiveMapper.mapToPersonalArchiveList(missionArchiveQueryService.findOthersArchive(memberId, missionId),memberId); + return MissionArchiveMapper.mapToPersonalArchiveList(missionArchiveQueryService.findOthersArchive(memberId, missionId), memberId); } public MissionArchiveStatusRes getMissionDoneStatus(Long missionId) { @@ -59,4 +61,6 @@ public MissionArchiveStatusRes getMissionDoneStatus(Long missionId) { } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java index 665b9444..c2ef9ad9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java @@ -15,7 +15,8 @@ public enum MissionArchiveResponseMessage { MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS("미션 인증 성공한 인원 상태 조회를 완료 했습니다."), ACTIVE_SINGLE_MISSION_SUCCESS("진행 중인 한번 인증 미션 조회를 완료 했습니다."), ACTIVE_REPEAT_MISSION_SUCCESS("진행 중인 반복 인증 미션 조회를 완료 했습니다."), - FINISH_ALL_MISSION_SUCCESS("종료된 미션 조회를 완료하였습니다."); + FINISH_ALL_MISSION_SUCCESS("종료된 미션 조회를 완료하였습니다."), + MISSION_ARCHIVE_BY_TEAM("팀별 미션 인증물 사진 조회를 완료했습니더."); private final String message; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 06d642b1..fe6014d9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -1,9 +1,9 @@ package com.moing.backend.domain.missionArchive.domain.repository; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; -import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import org.springframework.stereotype.Repository; @@ -24,5 +24,7 @@ public interface MissionArchiveCustomRepository { Optional> findFinishMissionsByStatus(Long memberId, Long teamId); + Optional> findTop5ArchivesByTeam(List teamIds); + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 6949157a..a572ae9f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -1,23 +1,19 @@ package com.moing.backend.domain.missionArchive.domain.repository; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; -import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; -import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.domain.team.domain.entity.Team; +import com.querydsl.core.Tuple; import com.querydsl.core.types.Expression; import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.impl.JPAQueryFactory; -import feign.Param; -import org.springframework.data.jpa.repository.Query; import javax.persistence.EntityManager; import java.util.ArrayList; @@ -26,7 +22,6 @@ import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; -import static com.moing.backend.domain.missionHeart.domain.entity.QMissionHeart.missionHeart; import static javax.swing.Spring.constant; public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { @@ -181,4 +176,38 @@ public Optional> findFinishMissionsByStatus(Long mem } + public Optional> findTop5ArchivesByTeam(List teamIds) { + List queryResults = queryFactory + .select(missionArchive.mission.team.teamId, missionArchive.archive) + .from(missionArchive) + .where(missionArchive.mission.team.teamId.in(teamIds)) + .orderBy(missionArchive.createdDate.desc()) + .limit(14) + .fetch(); + + List resultDTOs = new ArrayList<>(); + + for (Tuple tuple : queryResults) { + Long teamId = tuple.get(missionArchive.mission.team.teamId); + String photo = tuple.get(missionArchive.archive); + + // Check if a TeamPhotoDTO with the same teamId already exists in the list + MissionArchivePhotoRes existingDTO = resultDTOs.stream() + .filter(dto -> dto.getTeamId().equals(teamId)) + .findFirst() + .orElse(null); + + if (existingDTO != null) { + existingDTO.getPhoto().add(photo); + } else { + List photoList = new ArrayList<>(); + photoList.add(photo); + resultDTOs.add(new MissionArchivePhotoRes(teamId, photoList)); + } + } + + return Optional.ofNullable(resultDTOs); + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index ff10c3bd..5054882e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.repository.MissionRepository; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; import com.moing.backend.domain.missionArchive.exception.NotFoundMissionArchiveException; @@ -99,6 +100,9 @@ public List findMyFinishMissions(Long memberId, Long team return missionArchiveRepository.findFinishMissionsByStatus(memberId, teamId).orElseThrow(NotFoundMissionArchiveException::new); } + public List findTop5ArchivesByTeam(List teamIds) { + return missionArchiveRepository.findTop5ArchivesByTeam(teamIds).orElse(null); + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index c8af182b..88625bb8 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.presentation; +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; @@ -131,4 +132,6 @@ public ResponseEntity> getMyMissionDone + + } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java index 7a964bd6..639c329a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java @@ -5,6 +5,8 @@ import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveReadUseCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -50,4 +52,14 @@ public ResponseEntity>> getMyActive } + @GetMapping("/my-teams") + public ResponseEntity>> getArchivesByTeam(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_BY_TEAM.getMessage(), this.missionGatherBoardUseCase.getArchivePhotoByTeamRes(user.getSocialId()))); + } + + + + + + } diff --git a/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java b/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java index ee0634a9..8f403439 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/application/dto/MissionHeartRes.java @@ -1,10 +1,14 @@ package com.moing.backend.domain.missionHeart.application.dto; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; -@Getter +@AllArgsConstructor @Builder +@NoArgsConstructor +@Getter public class MissionHeartRes { private Long missionArchiveId; private String missionHeartStatus; diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index d036c41b..095fc040 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -64,8 +64,8 @@ public class MissionControllerTest extends CommonControllerTest { .rule("rule") .content("content") .number(1) - .type("ONCE") - .way("TEXT") + .type("ONCE/REPEAT") + .way("TEXT/PHOTO/LINK") .build(); String body = objectMapper.writeValueAsString(input); @@ -73,13 +73,13 @@ public class MissionControllerTest extends CommonControllerTest { MissionCreateRes output = MissionCreateRes.builder() .missionId(1L) .title("title") - .dueTo("dueTo") + .dueTo("2023-12-31 23:39:22.333") .rule("rule") .content("content") .number(1) - .type("TEXT") - .status("WAIT") - .way("TEXT") + .type("ONCE/REPEAT") + .status("END/ONGOING/SUCCESS/FAIL") + .way("TEXT/PHOTO/LINK") .build(); given(missionCreateUseCase.createMission(any(),any(),any())).willReturn(output); @@ -110,7 +110,7 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("rule").description("미션 규칙"), fieldWithPath("content").description("미션 내용"), fieldWithPath("number").description("미션 반복 횟수"), - fieldWithPath("type").description("미션 타입"), + fieldWithPath("type").description("미션 유형(단일/반복)"), fieldWithPath("way").description("미션 진행 방법") ), responseFields( @@ -122,8 +122,8 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.rule").description("미션 규칙"), fieldWithPath("data.content").description("미션 내용"), fieldWithPath("data.number").description("미션 반복 횟수"), - fieldWithPath("data.type").description("미션 타입"), - fieldWithPath("data.way").description("미션 진행 방법"), + fieldWithPath("data.type").description("미션 유형(단일/반복)"), + fieldWithPath("data.way").description("미션 진행 방법(사진/글/링크)"), fieldWithPath("data.status").description("미션 진행 상태") ) ) @@ -137,7 +137,7 @@ public class MissionControllerTest extends CommonControllerTest { //given MissionReq input = MissionReq.builder() .title("title") - .dueTo("dueTo") + .dueTo("2023-12-31 23:39:22.333") .rule("rule") .content("content") .number(1) @@ -150,12 +150,12 @@ public class MissionControllerTest extends CommonControllerTest { MissionCreateRes output = MissionCreateRes.builder() .missionId(1L) .title("title") - .dueTo("dueTo") + .dueTo("2023-12-31 23:39:22.333") .rule("rule") .content("content") .number(1) - .type("TEXT") - .status("WAIT") + .type("ONCE") + .status("END") .way("TEXT") .build(); @@ -201,9 +201,9 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.rule").description("미션 규칙"), fieldWithPath("data.content").description("미션 내용"), fieldWithPath("data.number").description("미션 반복 횟수"), - fieldWithPath("data.type").description("미션 타입"), - fieldWithPath("data.way").description("미션 진행 방법"), - fieldWithPath("data.status").description("미션 진행 상태") + fieldWithPath("data.type").description("미션 유형(ONCE/REPEAT)"), + fieldWithPath("data.way").description("미션 진행 방법(TEXT/PHOTO/LINK)"), + fieldWithPath("data.status").description("미션 진행 상태(END/ONGOING/SUCCESS/FAIL)") ) ) @@ -219,10 +219,10 @@ public class MissionControllerTest extends CommonControllerTest { MissionReadRes output = MissionReadRes.builder() .title("title") - .dueTo("dueTo") + .dueTo("2023-12-31 23:39:22.333") .rule("rule") .content("content") - .type("TEXT") + .type("ONCE") .way("TEXT") .build(); @@ -257,8 +257,8 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.dueTo").description("미션 마감 날짜"), fieldWithPath("data.rule").description("미션 규칙"), fieldWithPath("data.content").description("미션 내용"), - fieldWithPath("data.type").description("미션 타입"), - fieldWithPath("data.way").description("미션 진행 방법") + fieldWithPath("data.way").description("미션 진행 방법(TEXT/PHOTO/LINK)"), + fieldWithPath("data.type").description("미션 유형(ONCE/REPEAT)") ) ) @@ -308,7 +308,7 @@ public class MissionControllerTest extends CommonControllerTest { //given - String output = "" ; + String output = "SPORTS/HABIT/TEST/STUDY/READING/ETC" ; given(missionReadUseCase.getTeamCategory(any())).willReturn(output); diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index dfccb93b..0985af75 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -3,6 +3,8 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.mission.application.dto.res.*; import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveReadUseCase; import com.moing.backend.domain.missionArchive.presentation.MissionGatherController; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; @@ -13,6 +15,7 @@ import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import java.util.ArrayList; import java.util.List; import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; @@ -20,8 +23,7 @@ import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; @@ -124,6 +126,49 @@ public class MissionGatherControllerTest extends CommonControllerTest { .andReturn(); } + @Test + public void 미션_모아보기_팀별() throws Exception { + //given + + List objects = new ArrayList<>(); + objects.add("1"); + objects.add("2"); + + List output = Lists.newArrayList(MissionArchivePhotoRes.builder() + .teamId(1L) + .photo(objects) + .build()); + + given(missionGatherBoardUseCase.getArchivePhotoByTeamRes(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/my-teams") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(MISSION_ARCHIVE_BY_TEAM.getMessage()), + fieldWithPath("data[].teamId").description("팀 아이디"), + fieldWithPath("data[].photo[]").description("팀별 미션 인증물 사진들") + ) + ) + ) + .andReturn(); + + } From 70542bb852ab2b634bea671142fb9eebcbb50b1d Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Thu, 2 Nov 2023 16:20:20 +0900 Subject: [PATCH 183/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=EB=AA=A8?= =?UTF-8?q?=EC=95=84=EB=B3=B4=EA=B8=B0-=ED=8C=80=EB=B3=84=20adoc=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionGatherBoard-API.adoc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/docs/asciidoc/MissionGatherBoard-API.adoc b/src/docs/asciidoc/MissionGatherBoard-API.adoc index c2312081..bb06d09b 100644 --- a/src/docs/asciidoc/MissionGatherBoard-API.adoc +++ b/src/docs/asciidoc/MissionGatherBoard-API.adoc @@ -13,3 +13,9 @@ operation::mission-gather-controller-test/미션_모아보기_단일_미션[snip operation::mission-gather-controller-test/미션_모아보기_반복_미션[snippets='http-request,http-response,response-fields'] --- + +[[MissionBoard-미션-모아보기-팀별]] +== 미션_모아보기_팀별 +operation::mission-gather-controller-test/미션_모아보기_팀별[snippets='http-request,http-response,response-fields'] + +--- From f62640f99e9046f4ac9dadb70ff9d78652bcb040 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Thu, 2 Nov 2023 18:08:41 +0900 Subject: [PATCH 184/619] =?UTF-8?q?feat=20:=20=ED=8C=80=20=EB=B3=84=20?= =?UTF-8?q?=EB=B6=88=20=EB=A0=88=EB=B2=A8=20=EA=B2=BD=ED=97=98=EC=B9=98=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20&=20=ED=8C=80=20=EB=B3=84=20=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=EC=99=84=EB=A3=8C=EC=8B=9C=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/TeamScore-API.adoc | 10 +++ .../service/MissionArchiveCreateUseCase.java | 19 ++--- .../service/MissionArchiveUpdateUseCase.java | 2 +- .../presentation/MissionGatherController.java | 5 +- .../service/MissionStateUseCase.java | 25 ++++++ .../application/dto/TeamScoreRes.java | 16 ++++ .../service/TeamScoreLogicUseCase.java | 22 +++-- .../teamScore/domain/entity/TeamScore.java | 3 +- .../presentation/TeamScoreController.java | 46 +++++++++++ .../constant/TeamScoreResponseMessage.java | 13 +++ .../presentation/TeamScoreControllerTest.java | 81 +++++++++++++++++++ 11 files changed, 219 insertions(+), 23 deletions(-) create mode 100644 src/docs/asciidoc/TeamScore-API.adoc create mode 100644 src/main/java/com/moing/backend/domain/teamScore/application/dto/TeamScoreRes.java create mode 100644 src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java create mode 100644 src/main/java/com/moing/backend/domain/teamScore/presentation/constant/TeamScoreResponseMessage.java create mode 100644 src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java diff --git a/src/docs/asciidoc/TeamScore-API.adoc b/src/docs/asciidoc/TeamScore-API.adoc new file mode 100644 index 00000000..12268c8e --- /dev/null +++ b/src/docs/asciidoc/TeamScore-API.adoc @@ -0,0 +1,10 @@ + + +[[TeamScore-API]] += TeamScore API + +[[TeamScore-팀별-불-레벨-경험치-조회]] +=== 팀별_불_레벨_경험치_조회 +operation::team-score-controller-test/팀별_불_레벨_경험치_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 15341d7f..03a7b8d3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -19,6 +19,7 @@ import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -40,13 +41,12 @@ public class MissionArchiveCreateUseCase { private final MissionStateSaveService missionStateSaveService; private final MissionStateUseCase missionStateUseCase; + private final TeamScoreLogicUseCase teamScoreLogicUseCase; - // 미션 인증 public MissionArchiveRes createArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); Long memberId = member.getMemberId(); - Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); @@ -56,21 +56,12 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss if (isDoneMission(memberId,mission)) { throw new NoMoreMissionArchiveException(); } - - // 단일 미션 && 미션 종료 직전인지 확인 - if (mission.getType() == MissionType.ONCE && missionStateUseCase.isAbleToEnd(missionId)) { - mission.updateStatus(MissionStatus.SUCCESS); - // 점수 반영 로직 - - } - - // 반복 미션 - else { + // 반복 미션일 경우 + if (mission.getType() == MissionType.REPEAT) { newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); } - missionStateSaveService.saveMissionState(member,mission, MissionArchiveStatus.COMPLETE); - + missionStateUseCase.updateMissionState(member, mission, newArchive); return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive),memberId); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index 75145f4e..f9b19412 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -82,7 +82,7 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss } updateArchive.updateArchive(missionReq); - missionStateSaveService.saveMissionState(member,mission, MissionArchiveStatus.COMPLETE); + missionStateSaveService.saveMissionState(member,mission, updateArchive.getStatus()); return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(updateArchive),memberId); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java index 2342432c..b35cea63 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java @@ -2,15 +2,14 @@ import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; -import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; +import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; 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; @@ -49,4 +48,6 @@ public ResponseEntity>> getMyActive } + + } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 41bf4fc2..7948c5a8 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -1,9 +1,15 @@ package com.moing.backend.domain.missionState.application.service; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -18,6 +24,9 @@ public class MissionStateUseCase { private final MissionQueryService missionQueryService; private final MissionStateQueryService missionStateQueryService; + private final MissionStateSaveService missionStateSaveService; + + private final TeamScoreLogicUseCase teamScoreLogicUseCase; public boolean isAbleToEnd(Long missionId) { @@ -47,6 +56,22 @@ public Long totalPeople(Mission mission) { } + public void updateMissionState(Member member, Mission mission, MissionArchive missionArchive) { + + // 마지막 인증 시 + if (isAbleToEnd(mission.getId())) { + mission.updateStatus(MissionStatus.SUCCESS); + teamScoreLogicUseCase.updateSingleScore(mission.getId()); + } + + // 미션 인증 상태 저장 + missionStateSaveService.saveMissionState(member,mission, missionArchive.getStatus()); + + + + + } + } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/dto/TeamScoreRes.java b/src/main/java/com/moing/backend/domain/teamScore/application/dto/TeamScoreRes.java new file mode 100644 index 00000000..149cd63c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/application/dto/TeamScoreRes.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.teamScore.application.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class TeamScoreRes { + + private Long score; + private Long level; +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index a1bf91e2..651fd75d 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -6,6 +6,7 @@ import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; import com.moing.backend.domain.teamScore.domain.entity.TeamScore; import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; import lombok.RequiredArgsConstructor; @@ -22,23 +23,34 @@ public class TeamScoreLogicUseCase { private final TeamScoreQueryService teamScoreQueryService; private final MissionStateUseCase missionStateUseCase; - public Long getScore(Long teamLevel) { - return 1L; - } + public TeamScoreRes getTeamScoreInfo(Long teamId) { - public Integer getLevel(Long teamId) { - return teamGetService.getTeamByTeamId(teamId).getLevelOfFire(); + return TeamScoreRes.builder() + .score(getScore(teamId)) + .level(getLevel(teamId)) + .build() + ; } public Long updateSingleScore(Long missionId) { Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); + TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); + teamScore.updateScore(missionStateUseCase.getScoreByMission(mission)); teamScore.levelUp(); return teamScore.getScore(); } + public Long getScore(Long teamId) { + return teamScoreQueryService.findTeamScoreByTeam(teamId).getScore(); + } + + public Long getLevel(Long teamId) { + return teamScoreQueryService.findTeamScoreByTeam(teamId).getLevel(); + } + diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index 81d0278a..3de97e05 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -39,10 +39,11 @@ public void updateScore(Long score) { public void levelUp() { final int[] steps = {0, 2, 10, 25, 45, 100}; - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 5; i++) { if (steps[i] < this.level && this.level < steps[i + 1]) { if (20 + i * 15 <= score) { this.level+=1; + this.score -= score-(20 + i * 15); } } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java b/src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java new file mode 100644 index 00000000..fe4ddf53 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java @@ -0,0 +1,46 @@ +package com.moing.backend.domain.teamScore.presentation; + +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; +import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; +import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; +import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +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; + +import java.util.List; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_REPEAT_MISSION_SUCCESS; +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_SINGLE_MISSION_SUCCESS; +import static com.moing.backend.domain.teamScore.presentation.constant.TeamScoreResponseMessage.GET_TEAMSCORE_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/team/{teamId}") +public class TeamScoreController { + + private final TeamScoreLogicUseCase teamScoreLogicUseCase; + + /** + * 팀별 불 레벨/경험치 조회 + * [GET] my-repeat + * 작성자 : 정승연 + */ + + @GetMapping("/my-fire") + public ResponseEntity> getTeamScore(@PathVariable("teamId") Long teamId, @AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(GET_TEAMSCORE_SUCCESS.getMessage(), this.teamScoreLogicUseCase.getTeamScoreInfo(teamId))); + } + + + + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/presentation/constant/TeamScoreResponseMessage.java b/src/main/java/com/moing/backend/domain/teamScore/presentation/constant/TeamScoreResponseMessage.java new file mode 100644 index 00000000..21d75493 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/presentation/constant/TeamScoreResponseMessage.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.teamScore.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum TeamScoreResponseMessage { + GET_TEAMSCORE_SUCCESS("팀 경험치/레벨 조회를 완료 했습니다"); + + private final String message; +} + diff --git a/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java b/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java new file mode 100644 index 00000000..1ac4977b --- /dev/null +++ b/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java @@ -0,0 +1,81 @@ +package com.moing.backend.domain.teamScore.presentation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; +import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; +import com.moing.backend.domain.missionArchive.presentation.MissionGatherController; +import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; +import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.List; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_REPEAT_MISSION_SUCCESS; +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_SINGLE_MISSION_SUCCESS; +import static com.moing.backend.domain.teamScore.presentation.constant.TeamScoreResponseMessage.GET_TEAMSCORE_SUCCESS; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; + +@WebMvcTest(TeamScoreController.class) +public class TeamScoreControllerTest extends CommonControllerTest { + + + @MockBean + private TeamScoreLogicUseCase teamScoreLogicUseCase; + + @Test + public void 팀별_불_레벨_경험치_조회() throws Exception { + //given + + TeamScoreRes output = TeamScoreRes.builder() + .score(1L) + .level(1L) + .build(); + + given(teamScoreLogicUseCase.getTeamScoreInfo(any())).willReturn(output); + + Long teamId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/{teamId}/my-fire",teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(GET_TEAMSCORE_SUCCESS.getMessage()), + fieldWithPath("data.score").description("팀 경험치"), + fieldWithPath("data.level").description("팀 불 레벨") + + ) + ) + ) + .andReturn(); + + } + + +} \ No newline at end of file From f39c720d269fc456dc30908a83577253c45eebce Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Thu, 2 Nov 2023 22:49:58 +0900 Subject: [PATCH 185/619] =?UTF-8?q?fix=20:=20=EC=A4=91=EB=B3=B5=20API=20do?= =?UTF-8?q?cs=20=EC=9E=91=EC=84=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionBoard-API.adoc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/docs/asciidoc/MissionBoard-API.adoc b/src/docs/asciidoc/MissionBoard-API.adoc index fb985bf0..c2ea3570 100644 --- a/src/docs/asciidoc/MissionBoard-API.adoc +++ b/src/docs/asciidoc/MissionBoard-API.adoc @@ -15,11 +15,6 @@ operation::mission-board-controller-test/반복 미션 인증 조회[snipipets=' --- -[[MissionBoard-나의미션인증조회]] -=== 나의 미션 인증 조회 -operation::mission-archive-controller-test/나의_미션_인증_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] - ---- [[MissionBoard-종료된인증조회]] === 종료된 인증 조회 From 19385637258cc5eb4518a83c4aeed92ce8a4dfa2 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Thu, 2 Nov 2023 22:50:44 +0900 Subject: [PATCH 186/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=20=ED=9B=84=20=EC=A0=90=EC=88=98=20=EB=B0=98?= =?UTF-8?q?=EC=98=81=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/req/MissionReq.java | 4 +++ .../service/MissionArchiveCreateUseCase.java | 2 ++ .../service/MissionStateUseCase.java | 13 +++---- .../domain/entity/MissionState.java | 1 + .../MissionStateCustomRepository.java | 4 +++ .../MissionStateCustomRepositoryImpl.java | 15 +++++--- .../service/TeamScoreLogicUseCase.java | 27 ++++++++++++-- .../teamScore/domain/entity/TeamScore.java | 8 +++-- .../service/MissionStateQueryServiceTest.java | 35 +++++++++++++++++++ 9 files changed, 89 insertions(+), 20 deletions(-) create mode 100644 src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java index 98962c87..7af668ce 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java @@ -1,10 +1,14 @@ package com.moing.backend.domain.mission.application.dto.req; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter @Builder +@NoArgsConstructor +@AllArgsConstructor public class MissionReq { private String title; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 03a7b8d3..79ad517c 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -59,6 +59,8 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss // 반복 미션일 경우 if (mission.getType() == MissionType.REPEAT) { newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); + }else { + newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)); } missionStateUseCase.updateMissionState(member, mission, newArchive); diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 7948c5a8..babacbe9 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -11,9 +11,10 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; - +@Slf4j @Service @Transactional @RequiredArgsConstructor @@ -35,17 +36,12 @@ public boolean isAbleToEnd(Long missionId) { Long total = totalPeople(mission); Long done = donePeople(mission); + log.info("done/total -> "+ done+ total); + return done == total-1; } - public Long getScoreByMission(Mission mission) { - Long total = totalPeople(mission); - Long done = donePeople(mission); - - return (done / total * 100) / 5 ; - - } public Long donePeople(Mission mission) { return missionStateQueryService.stateCountByMissionId(mission.getId()); @@ -61,7 +57,6 @@ public void updateMissionState(Member member, Mission mission, MissionArchive mi // 마지막 인증 시 if (isAbleToEnd(mission.getId())) { mission.updateStatus(MissionStatus.SUCCESS); - teamScoreLogicUseCase.updateSingleScore(mission.getId()); } // 미션 인증 상태 저장 diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java index d347bda6..83f3c91d 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java @@ -28,6 +28,7 @@ public class MissionState extends BaseTimeEntity { @OneToOne private Member member; + @Enumerated(value = EnumType.STRING) private MissionArchiveStatus status; } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java index a3dad296..8ee3ce0d 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java @@ -1,7 +1,11 @@ package com.moing.backend.domain.missionState.domain.repository; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.missionState.domain.entity.MissionState; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface MissionStateCustomRepository { diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index 55d7dedb..114a82cf 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -5,6 +5,7 @@ import javax.persistence.EntityManager; + import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; public class MissionStateCustomRepositoryImpl implements MissionStateCustomRepository { @@ -19,14 +20,15 @@ public MissionStateCustomRepositoryImpl(EntityManager entityManager) { @Override public Long getCountsByMissionId(Long missionId) { return queryFactory - .select(missionState) + .select(missionState.count()) .from(missionState) .where( - missionState.mission.id.eq(missionId), - missionState.status.eq(MissionArchiveStatus.COMPLETE) - .or( missionState.status.eq(MissionArchiveStatus.SKIP)) + missionState.mission.id.eq(missionId)) + .where( + (missionState.status.eq(MissionArchiveStatus.COMPLETE) + .or( missionState.status.eq(MissionArchiveStatus.SKIP))) ) - .fetchCount(); + .fetchFirst(); } @@ -35,4 +37,7 @@ public Long getCountsByMissionId(Long missionId) { + + + } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index 651fd75d..7ade209a 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -4,15 +4,17 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; import com.moing.backend.domain.teamScore.domain.entity.TeamScore; import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; - +@Slf4j @Service @Transactional @RequiredArgsConstructor @@ -21,7 +23,7 @@ public class TeamScoreLogicUseCase { private final TeamGetService teamGetService; private final MissionQueryService missionQueryService; private final TeamScoreQueryService teamScoreQueryService; - private final MissionStateUseCase missionStateUseCase; + private final MissionStateQueryService missionStateQueryService; public TeamScoreRes getTeamScoreInfo(Long teamId) { @@ -38,7 +40,7 @@ public Long updateSingleScore(Long missionId) { TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); - teamScore.updateScore(missionStateUseCase.getScoreByMission(mission)); + teamScore.updateScore(getScoreByMission(mission)); teamScore.levelUp(); return teamScore.getScore(); } @@ -51,6 +53,25 @@ public Long getLevel(Long teamId) { return teamScoreQueryService.findTeamScoreByTeam(teamId).getLevel(); } + public Long getScoreByMission(Mission mission) { + Long total = totalPeople(mission); + Long done = donePeople(mission); + + return (done / total * 100) / 5 ; + + } + + public Long donePeople(Mission mission) { + + log.info("done people-> {}", missionStateQueryService.stateCountByMissionId(mission.getId())); + return missionStateQueryService.stateCountByMissionId(mission.getId()); + } + + public Long totalPeople(Mission mission) { + return Long.valueOf(mission.getTeam().getNumOfMember()); + + } + diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index 3de97e05..3b40e6ea 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -15,7 +15,7 @@ public class TeamScore extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "mission_id") + @Column(name = "teamScore_id") private Long id; @OneToOne @@ -33,7 +33,8 @@ public TeamScore(Team team, Long score,Long level) { } public void updateScore(Long score) { - this.score = score; + + this.score += score; } public void levelUp() { @@ -43,7 +44,8 @@ public void levelUp() { if (steps[i] < this.level && this.level < steps[i + 1]) { if (20 + i * 15 <= score) { this.level+=1; - this.score -= score-(20 + i * 15); + this.score -= score - (20 + i * 15); + return; } } } diff --git a/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java b/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java new file mode 100644 index 00000000..91a716c3 --- /dev/null +++ b/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java @@ -0,0 +1,35 @@ +package com.moing.backend.domain.missionState.domain.service; + +import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.missionState.domain.repository.MissionStateCustomRepository; +import com.moing.backend.domain.missionState.domain.repository.MissionStateCustomRepositoryImpl; +import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.persistence.EntityManager; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class MissionStateQueryServiceTest { + + + @MockBean + MissionStateQueryService missionStateQueryService ; + @MockBean + MissionStateCustomRepositoryImpl missionStateCustomRepository ; + + + @Test + public void missionDonePeople() { + System.out.println(missionStateQueryService.stateCountByMissionId(4L)); + } + + + + + +} \ No newline at end of file From 015fb0b2e008f0ba534bb1a40daa53411dc0b2da Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 3 Nov 2023 00:08:34 +0900 Subject: [PATCH 187/619] =?UTF-8?q?feat=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=A1=B0=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/req/MissionReq.java | 1 + .../dto/res/SingleMissionBoardRes.java | 3 + .../service/MissionArchiveBoardUseCase.java | 3 +- .../MissionArchiveCustomRepository.java | 4 +- .../MissionArchiveCustomRepositoryImpl.java | 63 +++++++++++++++---- .../service/MissionArchiveQueryService.java | 8 ++- .../domain/entity/MissionState.java | 2 +- 7 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java index 8b3c37eb..520a41a5 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java @@ -10,6 +10,7 @@ @AllArgsConstructor @Builder @NoArgsConstructor +@Getter public class MissionReq { private String title; diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java index e7d1ad93..d26f76b2 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java @@ -1,12 +1,15 @@ package com.moing.backend.domain.mission.application.dto.res; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.Setter; +import org.checkerframework.checker.units.qual.A; @Getter @Setter @Builder +@AllArgsConstructor public class SingleMissionBoardRes { private Long missionId; private String dueTo; // 날짜 diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveBoardUseCase.java index 256f0733..2a4d71ef 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveBoardUseCase.java @@ -45,8 +45,7 @@ public List getActiveSingleMissions(Long teamId, String m Member member = memberGetService.getMemberBySocialId(memberId); - List mySingleMissionArchives = missionArchiveQueryService.findMySingleMissionArchives(member.getMemberId(), teamId, MissionStatus.ONGOING); - return MissionArchiveMapper.mapToSingleMissionBoardResList(mySingleMissionArchives); + return missionArchiveQueryService.findMySingleMissionArchives(member.getMemberId(), teamId, MissionStatus.ONGOING); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index fe6014d9..b6fec1f3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; @@ -12,7 +13,8 @@ import java.util.Optional; @Repository public interface MissionArchiveCustomRepository { - Optional> findSingleMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status, MissionArchiveStatus archiveStatus, OrderCondition orderCondition); + Optional> findSingleMissionInComplete(Long memberId, Long teamId, MissionStatus status,OrderCondition orderCondition); + Optional> findSingleMissionComplete(Long memberId, Long teamId, MissionStatus status,OrderCondition orderCondition); Optional> findMyArchives(Long memberId,Long missionId); Optional> findOthersArchives(Long memberId, Long missionId) ; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index a572ae9f..0a5ca489 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; @@ -13,6 +14,7 @@ import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -22,6 +24,7 @@ import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; +import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; import static javax.swing.Spring.constant; public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { @@ -33,21 +36,57 @@ public MissionArchiveCustomRepositoryImpl(EntityManager em) { } @Override - public Optional> findSingleMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status, - MissionArchiveStatus archiveStatus, OrderCondition orderCondition) { + public Optional> findSingleMissionInComplete(Long memberId, Long teamId, MissionStatus status, + OrderCondition orderCondition) { OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); + String missionArchiveStatus = "INCOMPLETE"; return Optional.ofNullable(queryFactory - .select(missionArchive) - .from(missionArchive) + .select(Projections.constructor(SingleMissionBoardRes.class, + mission.id, + mission.dueTo.stringValue(), + mission.title, + Expressions.constant(missionArchiveStatus), + mission.type.stringValue() + )) + .from(mission) + .where(mission.notIn + (JPAExpressions + .select(missionState.mission) + .from(missionState) + .where(missionState.member.memberId.eq(memberId), + missionState.mission.team.teamId.eq(teamId), + missionState.mission.type.eq(MissionType.ONCE), + missionState.mission.status.eq(MissionStatus.SUCCESS) + .or(missionState.mission.status.eq(MissionStatus.ONGOING)) + )), + mission.type.eq(MissionType.ONCE), + mission.team.teamId.eq(teamId)) + .orderBy(orderSpecifiers).fetch()); + + + } + @Override + public Optional> findSingleMissionComplete(Long memberId, Long teamId, MissionStatus status, + OrderCondition orderCondition) { + OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); + return Optional.ofNullable(queryFactory + .select(Projections.constructor(SingleMissionBoardRes.class, + mission.id, + mission.dueTo.stringValue(), + mission.title, + missionArchive.status.stringValue(), + mission.type.stringValue() + )) + .from(mission) + .join(mission.missionArchiveList,missionArchive) + .on(missionArchive.member.memberId.eq(memberId)) .where( - missionArchive.mission.team.teamId.eq(teamId), - missionArchive.member.memberId.eq(memberId), - missionArchive.mission.status.eq(status), - missionArchive.mission.type.eq(MissionType.ONCE), - missionArchive.status.eq(archiveStatus) + mission.team.teamId.eq(teamId), + mission.type.eq(MissionType.ONCE), + mission.status.eq(MissionStatus.ONGOING) ) - .orderBy(orderSpecifiers) - .fetch()); + .orderBy(orderSpecifiers).fetch()); + } @@ -56,7 +95,7 @@ private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { List orderSpecifiers = new ArrayList<>(); if (orderCondition.equals(OrderCondition.DUETO)) { - orderSpecifiers.add(new OrderSpecifier(Order.DESC, missionArchive.mission.dueTo)); + orderSpecifiers.add(new OrderSpecifier(Order.ASC, mission.dueTo)); } else if (orderCondition.equals(OrderCondition.CREATED)) { orderSpecifiers.add(new OrderSpecifier(Order.ASC, missionArchive.createdDate)); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 5054882e..c3b9c62f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; @@ -70,12 +71,13 @@ public Boolean isDone(Long memberId, Long missionId) { /** * mission.getTeam() 팀의 단일미션 미션 인증 보드 */ - public List findMySingleMissionArchives(Long memberId, Long teamId, MissionStatus missionStatus) { + public List findMySingleMissionArchives(Long memberId, Long teamId, MissionStatus missionStatus) { + // INCOMPLETE - List incompleteList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, teamId, missionStatus, INCOMPLETE, OrderCondition.DUETO) + List incompleteList = missionArchiveRepository.findSingleMissionInComplete(memberId, teamId, missionStatus, OrderCondition.DUETO) .orElseThrow(NotFoundMissionArchiveException::new); - List completeList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, teamId, missionStatus, COMPLETE, OrderCondition.CREATED) + List completeList = missionArchiveRepository.findSingleMissionComplete(memberId, teamId, missionStatus, OrderCondition.CREATED) .orElseThrow(NotFoundMissionArchiveException::new); incompleteList.addAll(completeList); diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java index 83f3c91d..788b602c 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java @@ -23,7 +23,7 @@ public class MissionState extends BaseTimeEntity { @Column(name = "missionState_id") private Long id; - @OneToOne + @OneToOne(fetch = FetchType.LAZY) private Mission mission; @OneToOne private Member member; From cbe7473c02f497b3266b8a5cd5400bbfdb1a3fe0 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 3 Nov 2023 00:27:02 +0900 Subject: [PATCH 188/619] =?UTF-8?q?fix=20:=20=EB=82=98=EC=9D=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=A1=B0=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 3 +++ .../domain/service/MissionArchiveQueryService.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 0a5ca489..1860601d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -16,6 +16,8 @@ import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; +import feign.Param; +import org.springframework.data.jpa.repository.Query; import javax.persistence.EntityManager; import java.util.ArrayList; @@ -118,6 +120,7 @@ public Optional> findMyArchives(Long memberId,Long missionI ); } + @Override public Optional> findOthersArchives(Long memberId, Long missionId) { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index c3b9c62f..d219ef00 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -40,7 +40,7 @@ public MissionArchive findArchive(Long memberId, Long missionId) { public List findMyArchive(Long memberId, Long missionId) { - Optional> optional = missionArchiveRepository.findArchivesByMissionIdAndMemberId(memberId, missionId); + Optional> optional = missionArchiveRepository.findMyArchives(memberId, missionId); if (optional.isPresent() && optional.get().size() == 0) { return new ArrayList<>(); // throw new NotFoundMissionArchiveException(); From 7d12468a3f76af19a3cdf088401052d085dbd70b Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 3 Nov 2023 01:32:29 +0900 Subject: [PATCH 189/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=EB=AC=BC=20=ED=83=80=EC=9E=85=20=EB=A6=AC?= =?UTF-8?q?=ED=84=B4=EA=B0=92=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EB=82=98?= =?UTF-8?q?=EC=9D=98=20=EC=84=B1=EA=B3=B5=20=ED=9A=9F=EC=88=98=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20adoc=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionArchive-API.adoc | 6 +++ .../dto/res/MissionArchiveRes.java | 8 +-- .../dto/res/PersonalArchiveRes.java | 1 + .../mapper/MissionArchiveMapper.java | 2 + .../MissionArchiveCustomRepositoryImpl.java | 3 +- .../MissionArchiveControllerTest.java | 53 +++++++++++++++++++ 6 files changed, 65 insertions(+), 8 deletions(-) diff --git a/src/docs/asciidoc/MissionArchive-API.adoc b/src/docs/asciidoc/MissionArchive-API.adoc index e60833cf..e70060cb 100644 --- a/src/docs/asciidoc/MissionArchive-API.adoc +++ b/src/docs/asciidoc/MissionArchive-API.adoc @@ -33,6 +33,12 @@ operation::mission-archive-controller-test/인증_성공_인원_조회[snippets= --- +[[MissionArchive-나의성공횟수조회]] +== 나의 성공 횟수 조회 ( n/n번 ) +operation::mission-archive-controller-test/나의_성공_횟수_조회[snippets='http-request,path-parameters,http-response,response-fields'] + +--- + [[MissionArchive-미션인증물좋아요]] == 미션 인증물 좋아요 operation::mission-archive-controller-test/미션_인증물_좋아요[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index b976e42a..b154c6ce 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -12,19 +12,13 @@ public class MissionArchiveRes { private Long archiveId; private String archive; + private String way; private String createdDate; private String status; private Long count; private String heartStatus; private Long hearts; - public void updateHeartStatus(boolean status) { - if (status) { - this.heartStatus = "True"; - }else{ - this.heartStatus = "False"; - } - } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java index 01f630d8..70dc9df0 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java @@ -14,6 +14,7 @@ public class PersonalArchiveRes { private String archive; private String createdDate; + private String way; private String heartStatus; private int hearts; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index bf857493..47e2b5a7 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -34,6 +34,7 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc return MissionArchiveRes.builder() .archiveId(missionArchive.getId()) .archive(missionArchive.getArchive()) + .way(missionArchive.getMission().getWay().toString()) .createdDate(missionArchive.getCreatedDate().toString()) .status(missionArchive.getStatus().name()) .count(missionArchive.getCount()) @@ -64,6 +65,7 @@ public static PersonalArchiveRes mapToPersonalArchive(MissionArchive missionArch .nickname(member.getNickName()) .profileImg(member.getProfileImage()) .archive(missionArchive.getArchive()) + .way(missionArchive.getMission().getWay().toString()) .createdDate(missionArchive.getCreatedDate().toString()) .status(missionArchive.getStatus().name()) .count(missionArchive.getCount()) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 1860601d..d3f37843 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -141,11 +141,12 @@ public Optional> findOthersArchives(Long memberId, Long mis @Override public Optional findDonePeopleByMissionId(Long missionId) { return Optional.ofNullable(queryFactory - .select(missionArchive.count()) + .select(missionArchive.member.count()) .from(missionArchive) .where( missionArchive.mission.id.eq(missionId) ) + .groupBy(missionArchive.member) .fetchFirst() ); diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 1114ec38..eb60edd5 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -60,6 +60,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .archiveId(1L) .archive("content[s3 Link / text / link]") .createdDate("2023-09-03T21:32:33.888") + .way("TEXT/LINK/PHOTO") .status("COMPLETE/SKIP") .count(1L) .heartStatus("[True/False]") @@ -99,6 +100,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("message").description("미션 인증을 완료 했습니다."), fieldWithPath("data.archiveId").description("미션 인증 아이디"), fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), + fieldWithPath("data.way").description("미션 인증물 방식"), fieldWithPath("data.createdDate").description("미션 제출 시각"), fieldWithPath("data.status").description("미션 인증 상태"), fieldWithPath("data.count").description("미션 인증 횟수"), @@ -124,6 +126,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { MissionArchiveRes output = MissionArchiveRes.builder() .archiveId(1L) .archive("content[s3 Link / text / link]") + .way("TEXT/LINK/PHOTO") .createdDate("2023-09-03T21:32:33.888") .status("COMPLETE/SKIP") .count(1L) @@ -164,6 +167,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("message").description(UPDATE_ARCHIVE_SUCCESS), fieldWithPath("data.archiveId").description("미션 인증 아이디"), fieldWithPath("data.archive").description("미션 인증물 [s3URL/text/링크]"), + fieldWithPath("data.way").description("미션 인증물 방식"), fieldWithPath("data.createdDate").description("미션 제출 시각"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), fieldWithPath("data.status").description("미션 인증 상태"), @@ -184,6 +188,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { List output = Lists.newArrayList(MissionArchiveRes.builder() .archiveId(1L) .archive("content[s3 Link / text / link]") + .way("TEXT/LINK/PHOTO") .createdDate("2023-09-03T21:32:33.888") .status("COMPLETE/SKIP") .count(1L) @@ -220,6 +225,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("message").description(READ_MY_ARCHIVE_SUCCESS.getMessage()), fieldWithPath("data[].archiveId").description("미션 인증 아이디"), fieldWithPath("data[].archive").description("미션 인증물 [s3URL/text/링크]"), + fieldWithPath("data[].way").description("미션 인증물 방식"), fieldWithPath("data[].createdDate").description("미션 제출 시각"), fieldWithPath("data[].status").description("미션 인증 상태"), fieldWithPath("data[].count").description("미션 인증 횟수"), @@ -243,6 +249,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .nickname("modagbul_tester1") .profileImg("[s3 Link]") .archive("content[s3 Link / text / link]") + .way("TEXT/LINK/PHOTO") .createdDate("2023-09-03T21:32:33.888") .status("COMPLETE/SKIP") .count(1L) @@ -281,6 +288,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data[].nickname").description("미션 인증자 닉네임 "), fieldWithPath("data[].profileImg").description("미션 인증자 프로필 이미지 "), fieldWithPath("data[].archive").description("미션 인증물 [s3URL/text/링크] "), + fieldWithPath("data[].way").description("미션 인증물 방식 "), fieldWithPath("data[].createdDate").description("미션 인증 날짜 "), fieldWithPath("data[].status").description("미션 인증 상태"), fieldWithPath("data[].count").description("미션 인증 횟수"), @@ -339,6 +347,51 @@ public class MissionArchiveControllerTest extends CommonControllerTest { ) .andReturn(); + } + @Test + public void 나의_성공_횟수_조회() throws Exception { + //given + + MissionArchiveStatusRes output = MissionArchiveStatusRes.builder() + .total("8") + .done("3") + .build(); + + given(repeatMissionArchiveReadUseCase.getMyMissionDoneStatus(any(),any())).willReturn(output); + + Long teamId = 1L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/{teamId}/missions/{missionId}/archive/my-status",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage()), + fieldWithPath("data.total").description("전체 미션 참여자"), + fieldWithPath("data.done").description("미션 인증 완료한 미션 참여자 ") + + ) + ) + ) + .andReturn(); + } @Test public void 미션_인증물_좋아요() throws Exception { From 0e7d890e5f748c1ba27cbd9c01021ec13e95296d Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 3 Nov 2023 02:13:33 +0900 Subject: [PATCH 190/619] =?UTF-8?q?feat=20:=20=EC=A2=85=EB=A3=8C=EB=90=9C?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98=20status=20Null=20=EB=93=A4=EC=96=B4?= =?UTF-8?q?=EA=B0=80=EB=8A=94=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionArchiveCustomRepositoryImpl.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index d3f37843..5c0bffaf 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -172,7 +172,7 @@ public Optional> findRepeatMissionArchivesByMemberId .select(Projections.constructor(RepeatMissionBoardRes.class, mission.id, mission.title, - missionArchive.count.coalesce(0L).as("num"), + missionArchive.count.coalesce(0L).as("done"), mission.number )) .from(mission) @@ -182,10 +182,8 @@ public Optional> findRepeatMissionArchivesByMemberId .where( mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT) -// missionArchive.member.memberId.eq(memberId), -// missionArchive.mission.status.eq(status) ) - .groupBy(mission.id) +// .groupBy(missionArchive.mission) .fetch()); @@ -200,11 +198,11 @@ public Optional> findFinishMissionsByStatus(Long mem return Optional.ofNullable(queryFactory - .select(Projections.constructor(FinishMissionBoardRes.class, + .selectDistinct(Projections.constructor(FinishMissionBoardRes.class, mission.id, mission.dueTo.stringValue(), mission.title, - missionArchive.status.stringValue(), + missionArchive.status.stringValue().coalesce("INCOMPLETE").as("status"), mission.type.stringValue() )) .from(mission) From 52971a08f7f5d35c78755fb9e2a518037948c693 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 3 Nov 2023 02:21:36 +0900 Subject: [PATCH 191/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=ED=98=84=ED=99=A9=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?-=20=EC=9D=B8=EC=A6=9D=ED=95=9C=20=EC=82=AC=EB=9E=8C=20?= =?UTF-8?q?=EC=88=98=20=EB=B2=84=EA=B7=B8=20count=20->=20count()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 5c0bffaf..43ee924a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -172,7 +172,7 @@ public Optional> findRepeatMissionArchivesByMemberId .select(Projections.constructor(RepeatMissionBoardRes.class, mission.id, mission.title, - missionArchive.count.coalesce(0L).as("done"), + missionArchive.count().coalesce(0L).as("done"), mission.number )) .from(mission) From 3d4a62598ac7aebf48317d3814a90eb840efee99 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 3 Nov 2023 02:43:01 +0900 Subject: [PATCH 192/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=84=B1=EA=B3=B5=ED=95=9C=20=EC=9D=B8?= =?UTF-8?q?=EC=9B=90=20=EC=83=81=ED=83=9C=20=EC=A1=B0=ED=9A=8C=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionArchiveCustomRepositoryImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 43ee924a..70aea54a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -140,14 +140,14 @@ public Optional> findOthersArchives(Long memberId, Long mis @Override public Optional findDonePeopleByMissionId(Long missionId) { - return Optional.ofNullable(queryFactory - .select(missionArchive.member.count()) + return Optional.of(queryFactory + .select(missionArchive) .from(missionArchive) .where( missionArchive.mission.id.eq(missionId) ) .groupBy(missionArchive.member) - .fetchFirst() + .fetchCount() ); } From 86002ad55aa52aca4f305376d78435d0fa28b302 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 3 Nov 2023 03:40:00 +0900 Subject: [PATCH 193/619] =?UTF-8?q?feat=20:=20=ED=8C=80=20=EC=8A=A4?= =?UTF-8?q?=EC=BD=94=EC=96=B4=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveCreateUseCase.java | 2 +- .../service/MissionArchiveUpdateUseCase.java | 12 +----------- .../service/MissionStateUseCase.java | 19 +++++++++++++++---- .../MissionStateCustomRepository.java | 3 ++- .../MissionStateCustomRepositoryImpl.java | 10 +++------- .../service/MissionStateQueryService.java | 2 +- .../service/TeamScoreLogicUseCase.java | 7 +++++-- .../teamScore/domain/entity/TeamScore.java | 12 ++++++------ .../domain/service/TeamScoreSaveService.java | 8 ++------ 9 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 79ad517c..d61baf2a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -60,7 +60,7 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss if (mission.getType() == MissionType.REPEAT) { newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); }else { - newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)); + newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); } missionStateUseCase.updateMissionState(member, mission, newArchive); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index f9b19412..cd465770 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -73,20 +73,10 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss } - - if (mission.getType().equals(MissionType.ONCE)) { - updateArchive.updateCount(1L); - } - else{ - updateArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); - } - updateArchive.updateArchive(missionReq); - missionStateSaveService.saveMissionState(member,mission, updateArchive.getStatus()); - +// missionStateUseCase.updateMissionState(member, mission, updateArchive); return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(updateArchive),memberId); - } // 이 미션을 완료 했는지 public Boolean isDoneMission(Long memberId,Mission mission) { diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index babacbe9..80f65496 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -41,10 +41,21 @@ public boolean isAbleToEnd(Long missionId) { return done == total-1; } + public boolean isAbleToScoreUp(Long missionId) { + + Mission mission = missionQueryService.findMissionById(missionId); + Long total = totalPeople(mission); + Long done = donePeople(mission); + + log.info("done/total -> "+ done+ total); + + return done >= total; + + } public Long donePeople(Mission mission) { - return missionStateQueryService.stateCountByMissionId(mission.getId()); + return Long.valueOf(missionStateQueryService.stateCountByMissionId(mission.getId())); } public Long totalPeople(Mission mission) { @@ -58,11 +69,11 @@ public void updateMissionState(Member member, Mission mission, MissionArchive mi if (isAbleToEnd(mission.getId())) { mission.updateStatus(MissionStatus.SUCCESS); } - - // 미션 인증 상태 저장 missionStateSaveService.saveMissionState(member,mission, missionArchive.getStatus()); - + if (isAbleToScoreUp(mission.getId())) { + teamScoreLogicUseCase.updateTeamScore(mission.getId()); + } } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java index 8ee3ce0d..c423be6a 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionState.domain.repository; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.missionState.domain.entity.MissionState; import org.springframework.stereotype.Repository; @@ -9,7 +10,7 @@ @Repository public interface MissionStateCustomRepository { - Long getCountsByMissionId(Long missionId) ; + int getCountsByMissionId(Long missionId) ; } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index 114a82cf..9ae3dc7b 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -18,17 +18,13 @@ public MissionStateCustomRepositoryImpl(EntityManager entityManager) { @Override - public Long getCountsByMissionId(Long missionId) { + public int getCountsByMissionId(Long missionId) { return queryFactory - .select(missionState.count()) + .select(missionState) .from(missionState) .where( missionState.mission.id.eq(missionId)) - .where( - (missionState.status.eq(MissionArchiveStatus.COMPLETE) - .or( missionState.status.eq(MissionArchiveStatus.SKIP))) - ) - .fetchFirst(); + .fetch().size(); } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java index b5130ee6..8375ca5c 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java @@ -13,7 +13,7 @@ public class MissionStateQueryService { private final MissionStateRepository missionStateRepository; - public Long stateCountByMissionId(Long missionId) { + public int stateCountByMissionId(Long missionId) { return missionStateRepository.getCountsByMissionId(missionId); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index 7ade209a..c48f0333 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -10,6 +10,7 @@ import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; import com.moing.backend.domain.teamScore.domain.entity.TeamScore; import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; +import com.moing.backend.domain.teamScore.domain.service.TeamScoreSaveService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -23,6 +24,7 @@ public class TeamScoreLogicUseCase { private final TeamGetService teamGetService; private final MissionQueryService missionQueryService; private final TeamScoreQueryService teamScoreQueryService; + private final TeamScoreSaveService teamScoreSaveService; private final MissionStateQueryService missionStateQueryService; public TeamScoreRes getTeamScoreInfo(Long teamId) { @@ -34,7 +36,7 @@ public TeamScoreRes getTeamScoreInfo(Long teamId) { ; } - public Long updateSingleScore(Long missionId) { + public Long updateTeamScore(Long missionId) { Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); @@ -42,6 +44,7 @@ public Long updateSingleScore(Long missionId) { teamScore.updateScore(getScoreByMission(mission)); teamScore.levelUp(); + teamScoreSaveService.save(teamScore); return teamScore.getScore(); } @@ -64,7 +67,7 @@ public Long getScoreByMission(Mission mission) { public Long donePeople(Mission mission) { log.info("done people-> {}", missionStateQueryService.stateCountByMissionId(mission.getId())); - return missionStateQueryService.stateCountByMissionId(mission.getId()); + return Long.valueOf(missionStateQueryService.stateCountByMissionId(mission.getId())); } public Long totalPeople(Mission mission) { diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index 3b40e6ea..728664c4 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -33,18 +33,18 @@ public TeamScore(Team team, Long score,Long level) { } public void updateScore(Long score) { - this.score += score; } public void levelUp() { - final int[] steps = {0, 2, 10, 25, 45, 100}; + final int[] steps = {1, 2, 10, 25, 45, 100}; +// 0부터 시작하기 때문에 무조건 0에서 걸림. - for (int i = 0; i < 5; i++) { - if (steps[i] < this.level && this.level < steps[i + 1]) { - if (20 + i * 15 <= score) { + for (int i = 5; i > 0; i--) { + if (steps[i] <= this.level && this.level <= steps[i - 1]) { + if (20 + (i-1) * 15 <= score) { this.level+=1; - this.score -= score - (20 + i * 15); + this.score -= (20 + (i-1) * 15); return; } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java index c265cef9..869d9c76 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java @@ -17,13 +17,9 @@ public class TeamScoreSaveService { private final TeamScoreRepository teamScoreRepository; private final TeamGetService teamGetService; - public TeamScore save(Long teamId, Long score) { - Team team = teamGetService.getTeamByTeamId(teamId); + public TeamScore save(TeamScore teamScore) { - return teamScoreRepository.save(TeamScore.builder() - .team(team) - .score(score) - .build()); + return teamScoreRepository.save(teamScore); } From 586e3c14b193d957ee84d7f663fc4a72a81b6df4 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sat, 4 Nov 2023 07:41:36 +0900 Subject: [PATCH 194/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=20=ED=9B=84=20=EB=A1=9C=EC=A7=81=20-=20?= =?UTF-8?q?=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionCustomRepository.java | 1 + .../MissionCustomRepositoryImpl.java | 11 ++++ .../domain/service/MissionQueryService.java | 6 +- .../NotFoundOngoingMissionException.java | 12 ++++ .../service/MissionStateScheduleUseCase.java | 60 +++++++++++++++++++ .../MissionStateCustomRepository.java | 2 + .../MissionStateCustomRepositoryImpl.java | 17 ++++-- .../service/MissionStateDeleteService.java | 22 +++++++ .../service/MissionStateQueryService.java | 6 ++ .../teamScore/domain/entity/TeamScore.java | 2 +- 10 files changed, 132 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/exception/NotFoundOngoingMissionException.java create mode 100644 src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index 61867e4e..e545111e 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -20,5 +20,6 @@ public interface MissionCustomRepository { Optional> findMissionByDueTo(); + Optional> findOngoingRepeatMissions(); } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index b9e1ec6c..f04a8c12 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -72,6 +72,17 @@ public Optional> findMissionByDueTo() { mission.dueTo.after(oneHourAgo) ).fetch()); } + + @Override + public Optional> findOngoingRepeatMissions() { + return Optional.ofNullable(queryFactory + .select(mission.id) + .from(mission) + .where(mission.status.eq(MissionStatus.ONGOING), + mission.type.eq(MissionType.REPEAT)) + .fetch()); + } + @Override public Optional> findSingleMissionByMemberId(Long memberId, List teams) { return Optional.ofNullable(queryFactory diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 4d4045d4..6d1e4f10 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -5,7 +5,7 @@ import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -import com.moing.backend.domain.mission.exception.NotFoundEndMissionException; +import com.moing.backend.domain.mission.exception.*; import com.moing.backend.domain.mission.exception.NotFoundMissionException; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; @@ -50,4 +50,8 @@ public List findAllSingleMission(Long memberId) { public List findMissionByDueTo() { return missionRepository.findMissionByDueTo().orElseThrow(NotFoundEndMissionException::new); } + + public List findOngoingRepeatMissions() { + return missionRepository.findOngoingRepeatMissions().orElseThrow(NotFoundOngoingMissionException::new); + } } diff --git a/src/main/java/com/moing/backend/domain/mission/exception/NotFoundOngoingMissionException.java b/src/main/java/com/moing/backend/domain/mission/exception/NotFoundOngoingMissionException.java new file mode 100644 index 00000000..428458cf --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/exception/NotFoundOngoingMissionException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mission.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundOngoingMissionException extends MissionException { + + public NotFoundOngoingMissionException() { + super(ErrorCode.NOT_FOUND_MISSION, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java new file mode 100644 index 00000000..05953ae1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -0,0 +1,60 @@ +package com.moing.backend.domain.missionState.application.service; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionState.domain.entity.MissionState; +import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; + +@Slf4j +@Service +@Transactional +@RequiredArgsConstructor +public class MissionStateScheduleUseCase { + + private final MissionStateUseCase missionStateUseCase; + private final MissionQueryService missionQueryService; + private final MissionStateQueryService missionStateQueryService; + private final MissionStateDeleteService missionStateDeleteService; + + private final TeamScoreLogicUseCase teamScoreLogicUseCase; + + // 스케쥴러에 쓰면 됨. + public void sundayRepeatMissionRoutine() { + + // 모든 진행중인 반복 미션 모아서 + List ongoingRepeatMissions = missionQueryService.findOngoingRepeatMissions(); + + // 팀 스코어 반영 ( 배치 처리 해야하는데 ) + for (Long id : ongoingRepeatMissions) { + teamScoreLogicUseCase.updateTeamScore(id); + } + // 미션 state 에서 지우기 ( 이것도 대용량 ) + missionStateReset(ongoingRepeatMissions); + } + public void missionStateReset(List missionIds) { + List missionStates = missionStateQueryService.findByMissionId(missionIds); + missionStateDeleteService.deleteMissionState(missionStates); + } + + // 한시간마다 실행 + public void singleMissionEndRoutine() { + + Mission mission = new Mission(); + + LocalDateTime now = LocalDateTime.now(); + + if (mission.getDueTo().isAfter(now)) { + mission.updateStatus(MissionStatus.END); + } + } +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java index c423be6a..2ffe75bd 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java @@ -12,5 +12,7 @@ public interface MissionStateCustomRepository { int getCountsByMissionId(Long missionId) ; + List findByMissionId(List missionId); + } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index 9ae3dc7b..5f93de16 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -1,11 +1,14 @@ package com.moing.backend.domain.missionState.domain.repository; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; +import java.util.List; + import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; public class MissionStateCustomRepositoryImpl implements MissionStateCustomRepository { @@ -27,13 +30,17 @@ public int getCountsByMissionId(Long missionId) { .fetch().size(); } + @Override + public List findByMissionId(List missionId) { + return queryFactory + .select(missionState) + .from(missionState) + .where( + missionState.mission.id.in(missionId) + ).fetch(); - - - - - + } } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java new file mode 100644 index 00000000..b0674fd5 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java @@ -0,0 +1,22 @@ +package com.moing.backend.domain.missionState.domain.service; + +import com.moing.backend.domain.missionState.domain.entity.MissionState; +import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; +import java.util.List; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionStateDeleteService { + + private final MissionStateRepository missionStateRepository; + + public void deleteMissionState(List missionStates) { + + missionStateRepository.deleteAll(missionStates); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java index 8375ca5c..4b4e6287 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java @@ -1,10 +1,12 @@ package com.moing.backend.domain.missionState.domain.service; +import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import javax.transaction.Transactional; +import java.util.List; @DomainService @Transactional @@ -17,5 +19,9 @@ public int stateCountByMissionId(Long missionId) { return missionStateRepository.getCountsByMissionId(missionId); } + public List findByMissionId(List missionId) { + return missionStateRepository.findByMissionId(missionId); + } + } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index 728664c4..a37f311e 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -42,7 +42,7 @@ public void levelUp() { for (int i = 5; i > 0; i--) { if (steps[i] <= this.level && this.level <= steps[i - 1]) { - if (20 + (i-1) * 15 <= score) { + if (20 + (i-1) * 15 <= score) { // 여길 들어가질 않음 this.level+=1; this.score -= (20 + (i-1) * 15); return; From f894641bd10fb6606dce23e9dcf43dd35cfb2b9c Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 4 Nov 2023 13:37:38 +0900 Subject: [PATCH 195/619] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20fcmToken=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EB=90=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/SignInRequest.java | 8 +++- .../dto/request/SignUpRequest.java | 4 -- .../application/dto/request/TestRequest.java | 1 + .../service/MemberAuthUserCase.java | 3 +- .../application/service/SignInUserCase.java | 11 ++--- .../auth/presentation/AuthController.java | 4 +- .../domain/member/domain/entity/Member.java | 6 ++- .../domain/service/MemberSaveService.java | 1 + .../config/security/SecurityConfig.java | 1 - .../auth/presentation/AuthControllerTest.java | 40 ++++++++++++------- 10 files changed, 48 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java index 980fa113..57ea1a77 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignInRequest.java @@ -9,7 +9,11 @@ @NoArgsConstructor @Getter public class SignInRequest { - @NotBlank(message="token 을 입력해주세요.") - private String token; + @NotBlank(message="socialToken 을 입력해주세요.") + private String socialToken; + + @NotBlank(message = "fcmToken 을 입력해주세요.") + private String fcmToken; + } diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java index bfa735c3..96d182d1 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java @@ -26,8 +26,4 @@ public class SignUpRequest { @NotNull(message="birthDate 을 입력해주세요.") @Pattern(regexp = "^\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$", message = "날짜 형식이 잘못되었습니다. YYYY-MM-DD 형식으로 입력해주세요.") private String birthDate; - - @NotBlank(message = "fcmToken 을 입력해주세요.") - private String fcmToken; - } diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/TestRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/TestRequest.java index 7bb94c4e..372994b3 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/request/TestRequest.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/TestRequest.java @@ -12,4 +12,5 @@ public class TestRequest { private String socialId; + private String fcmToken; } diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java index b8cc7982..9413d73d 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java @@ -17,7 +17,8 @@ public class MemberAuthUserCase { private final MemberSaveService memberSaveService; @Transactional - public Member auth(Member member, String providerInfo) { + public Member auth(String fcmToken, Member member, String providerInfo) { + member.updateFcmToken(fcmToken); Member signInMember = memberSaveService.saveMember(member); checkRegistration(signInMember, providerInfo); return signInMember; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java index 290968d0..9f4fb63f 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.auth.application.service; +import com.moing.backend.domain.auth.application.dto.request.SignInRequest; import com.moing.backend.domain.auth.application.dto.response.SignInResponse; import com.moing.backend.domain.member.domain.constant.RegistrationStatus; import com.moing.backend.domain.member.domain.entity.Member; @@ -23,11 +24,11 @@ public class SignInUserCase { private final Map signInProviders; private final MemberGetService memberGetService; - public SignInResponse signIn(String token, String providerInfo) { + public SignInResponse signIn(SignInRequest signInRequest, String providerInfo) { //1. 사용자 정보 가져오기 - Member member = getUserDataFromPlatform(token, providerInfo); + Member member = getUserDataFromPlatform(signInRequest.getSocialToken(), providerInfo); //2. 로그인 및 회원가입 - Member authenticatedMember = internalAuthService.auth(member, providerInfo); + Member authenticatedMember = internalAuthService.auth(signInRequest.getFcmToken(), member, providerInfo); //3. security 처리 AuthenticationUtil.makeAuthentication(authenticatedMember); //4. token 만들기 @@ -46,11 +47,11 @@ private Member getUserDataFromPlatform(String accessToken, String providerInfo) return signInProvider.getUserData(accessToken); } - public SignInResponse testSignIn(String socialId, String providerInfo) { + public SignInResponse testSignIn(String fcmToken, String socialId, String providerInfo) { //1. 사용자 정보 가져오기 Member member = memberGetService.getMemberBySocialId(socialId); //2. 로그인 - Member authenticatedMember = internalAuthService.auth(member, providerInfo); + Member authenticatedMember = internalAuthService.auth(fcmToken, member, providerInfo); //3. security 처리 AuthenticationUtil.makeAuthentication(authenticatedMember); //4. token 만들기 diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java index e82a8d0f..5ecd6ec9 100644 --- a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java @@ -47,7 +47,7 @@ public class AuthController { @PostMapping("/signIn/{provider}") public ResponseEntity> signIn(@PathVariable String provider, @Valid @RequestBody SignInRequest signInRequest) { - return ResponseEntity.ok(SuccessResponse.create(SIGN_IN_SUCCESS.getMessage(), this.authService.signIn(signInRequest.getToken(), provider))); + return ResponseEntity.ok(SuccessResponse.create(SIGN_IN_SUCCESS.getMessage(), this.authService.signIn(signInRequest, provider))); } /** @@ -90,6 +90,6 @@ public ResponseEntity> checkNickname(@Pat @PostMapping("/test/{provider}") public ResponseEntity> testLogin(@PathVariable String provider, @RequestBody TestRequest testRequest){ - return ResponseEntity.ok(SuccessResponse.create(SIGN_IN_SUCCESS.getMessage(), this.authService.testSignIn(testRequest.getSocialId(),provider))); + return ResponseEntity.ok(SuccessResponse.create(SIGN_IN_SUCCESS.getMessage(), this.authService.testSignIn(testRequest.getFcmToken(), testRequest.getSocialId(),provider))); } } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index ad9370f8..dc3a96a4 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -99,8 +99,8 @@ public void signUp(SignUpRequest signUpRequest) { this.nickName = signUpRequest.getNickName(); this.gender = signUpRequest.getGender(); this.birthDate = LocalDate.parse(signUpRequest.getBirthDate(), DateTimeFormatter.ISO_DATE);; - this.fcmToken = signUpRequest.getFcmToken(); this.registrationStatus = RegistrationStatus.COMPLETED; + updateAllPush(true); } @Builder @@ -142,6 +142,10 @@ public void updateAllPush(boolean allPush) { this.isFirePush = allPush; } + public void updateFcmToken(String fcmToken) { + this.fcmToken = fcmToken; + } + public Member(LocalDate birthDate, String email, String fcmToken, Gender gender, String introduction, String nickName, String profileImage, SocialProvider provider, RegistrationStatus registrationStatus, Role role, String socialId) { this.birthDate = birthDate; this.email = email; diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java index 6427010a..ca6480f0 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java @@ -20,6 +20,7 @@ public Member saveMember(Member member) { if(findMember.isEmpty()){ return memberRepository.save(member); } else { + findMember.get().updateFcmToken(member.getFcmToken()); return findMember.get(); } } diff --git a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java index 93e8f902..e4b390f3 100644 --- a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java +++ b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java @@ -53,7 +53,6 @@ protected void configure(HttpSecurity http) throws Exception { .antMatchers("/webjars/**").permitAll() .antMatchers("/v3/api-docs").permitAll() .antMatchers("/api/auth/**", "/docs/**", "/api/image/**").permitAll() - .antMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .apply(new JwtSecurityConfig(tokenUtil, memberQueryService)); diff --git a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java index 38eec2b7..825d2ff9 100644 --- a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java +++ b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java @@ -48,7 +48,8 @@ class AuthControllerTest extends CommonControllerTest { public void Kakao_소셜_로그인_회원가입_전() throws Exception { //given SignInRequest input = SignInRequest.builder() - .token("KAKAO_ACCESS_TOKEN") + .fcmToken("FCM_TOKEN") + .socialToken("KAKAO_ACCESS_TOKEN") .build(); String body = objectMapper.writeValueAsString(input); @@ -74,7 +75,8 @@ class AuthControllerTest extends CommonControllerTest { .andDo( restDocs.document( requestFields( - fieldWithPath("token").description("카카오 액세스 토큰") + fieldWithPath("fcmToken").description("FCM TOKEN"), + fieldWithPath("socialToken").description("카카오 액세스 토큰") ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -91,7 +93,8 @@ class AuthControllerTest extends CommonControllerTest { public void Kakao_소셜_로그인_회원가입_후() throws Exception { //given SignInRequest input = SignInRequest.builder() - .token("KAKAO_ACCESS_TOKEN") + .fcmToken("FCM_TOKEN") + .socialToken("KAKAO_ACCESS_TOKEN") .build(); String body = objectMapper.writeValueAsString(input); @@ -117,7 +120,8 @@ class AuthControllerTest extends CommonControllerTest { .andDo( restDocs.document( requestFields( - fieldWithPath("token").description("카카오 액세스 토큰") + fieldWithPath("fcmToken").description("FCM TOKEN"), + fieldWithPath("socialToken").description("카카오 액세스 토큰") ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -134,7 +138,8 @@ class AuthControllerTest extends CommonControllerTest { public void Apple_소셜_로그인_회원가입_전() throws Exception { //given SignInRequest input = SignInRequest.builder() - .token("APPLE_IDENTITY_TOKEN") + .fcmToken("FCM_TOKEN") + .socialToken("APPLE_IDENTITY_TOKEN") .build(); String body = objectMapper.writeValueAsString(input); @@ -160,7 +165,8 @@ class AuthControllerTest extends CommonControllerTest { .andDo( restDocs.document( requestFields( - fieldWithPath("token").description("애플 아이디 토큰") + fieldWithPath("fcmToken").description("FCM TOKEN"), + fieldWithPath("socialToken").description("애플 아이디 토큰") ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -177,7 +183,8 @@ class AuthControllerTest extends CommonControllerTest { public void Apple_소셜_로그인_회원가입_후() throws Exception { //given SignInRequest input = SignInRequest.builder() - .token("APPLE_IDENTITY_TOKEN") + .fcmToken("FCM_TOKEN") + .socialToken("APPLE_IDENTITY_TOKEN") .build(); String body = objectMapper.writeValueAsString(input); @@ -203,7 +210,8 @@ class AuthControllerTest extends CommonControllerTest { .andDo( restDocs.document( requestFields( - fieldWithPath("token").description("애플 아이디 토큰") + fieldWithPath("fcmToken").description("FCM TOKEN"), + fieldWithPath("socialToken").description("애플 아이디 토큰") ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -220,7 +228,8 @@ class AuthControllerTest extends CommonControllerTest { public void GOOGLE_소셜_로그인_회원가입_전() throws Exception { //given SignInRequest input = SignInRequest.builder() - .token("APPLE_IDENTITY_TOKEN") + .fcmToken("FCM_TOKEN") + .socialToken("APPLE_IDENTITY_TOKEN") .build(); String body = objectMapper.writeValueAsString(input); @@ -246,7 +255,8 @@ class AuthControllerTest extends CommonControllerTest { .andDo( restDocs.document( requestFields( - fieldWithPath("token").description("구글 아이디 토큰") + fieldWithPath("fcmToken").description("FCM TOKEN"), + fieldWithPath("socialToken").description("애플 아이디 토큰") ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -263,7 +273,8 @@ class AuthControllerTest extends CommonControllerTest { public void GOOGLE_소셜_로그인_회원가입_후() throws Exception { //given SignInRequest input = SignInRequest.builder() - .token("APPLE_IDENTITY_TOKEN") + .fcmToken("FCM_TOKEN") + .socialToken("APPLE_IDENTITY_TOKEN") .build(); String body = objectMapper.writeValueAsString(input); @@ -289,7 +300,8 @@ class AuthControllerTest extends CommonControllerTest { .andDo( restDocs.document( requestFields( - fieldWithPath("token").description("구글 아이디 토큰") + fieldWithPath("fcmToken").description("FCM TOKEN"), + fieldWithPath("socialToken").description("애플 아이디 토큰") ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -310,7 +322,6 @@ public void sign_up() throws Exception { .nickName("NICKNAME") .gender(Gender.MAN) .birthDate("2000-03-28") - .fcmToken("FCMTOKEN") .build(); String body = objectMapper.writeValueAsString(input); @@ -344,8 +355,7 @@ public void sign_up() throws Exception { requestFields( fieldWithPath("nickName").description("유저 닉네임"), fieldWithPath("gender").description("성별"), - fieldWithPath("birthDate").description("태어난 날짜(YYYY-MM-DD)"), - fieldWithPath("fcmToken").description("FCM TOKEN") + fieldWithPath("birthDate").description("태어난 날짜(YYYY-MM-DD)") ), responseFields( fieldWithPath("isSuccess").description("true"), From 3bb711bd38a6ca322ec651d0304efddb4b00ef49 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 4 Nov 2023 13:44:26 +0900 Subject: [PATCH 196/619] =?UTF-8?q?fix:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moing/backend/domain/member/domain/entity/Member.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index aa38da28..42508835 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -160,11 +160,4 @@ public Member(LocalDate birthDate, String email, String fcmToken, Gender gender, this.socialId = socialId; } - public void deleteTeamMember(){ - List teamMemberList=this.getTeamMembers(); - for(TeamMember teamMember:teamMemberList){ - teamMember.deleteMember(); - } - } - } From 6baeaedc652752f3b1d368fd1e146755cc73e710 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 4 Nov 2023 22:30:09 +0900 Subject: [PATCH 197/619] =?UTF-8?q?fix:=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20API=20=EC=97=B0=EB=8F=99=ED=95=98=EA=B2=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/SignInUserCase.java | 2 +- .../application/service/WithdrawProvider.java | 7 ++ .../service/apple/AppleSignInUserCase.java | 2 +- .../service/apple/AppleTokenUserCase.java | 10 +- .../service/apple/AppleWithdrawUserCase.java | 95 +++++++++++++++++++ .../service/apple/feign/AppleFeignClient.java | 17 ---- .../service/apple/utils/AppleClient.java | 17 ++++ .../service/apple/utils/AppleToken.java | 47 +++++++++ .../apple/{feign/response => utils}/Keys.java | 2 +- .../service/google/GoogleSignInUserCase.java | 6 +- .../service/google/GoogleTokenUserCase.java | 2 +- .../google/GoogleWithdrawUserCase.java | 20 ++++ .../service/google/utils/GoogleClient.java | 12 +++ .../service/kakao/KakaoSignInUserCase.java | 2 +- .../service/kakao/KakaoTokenUserCase.java | 2 +- .../service/kakao/KakaoWithdrawUserCase.java | 20 ++++ .../service/kakao/utils/KakaoClient.java | 12 +++ .../kakao/utils/KakaoUnlinkResponse.java | 8 ++ .../dto/request/WithdrawRequest.java | 3 + .../application/service/WithdrawUserCase.java | 17 +++- .../mypage/presentation/MyPageController.java | 9 +- .../global/util/FeignClientConfig.java | 7 ++ 22 files changed, 282 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/WithdrawProvider.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java delete mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/AppleFeignClient.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleClient.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleToken.java rename src/main/java/com/moing/backend/domain/auth/application/service/apple/{feign/response => utils}/Keys.java (96%) create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleWithdrawUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/google/utils/GoogleClient.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoWithdrawUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoClient.java create mode 100644 src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoUnlinkResponse.java create mode 100644 src/main/java/com/moing/backend/global/util/FeignClientConfig.java diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java index 9f4fb63f..205bfbd1 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java @@ -40,7 +40,7 @@ public SignInResponse signIn(SignInRequest signInRequest, String providerInfo) { } private Member getUserDataFromPlatform(String accessToken, String providerInfo) { - SignInProvider signInProvider = signInProviders.get(providerInfo); + SignInProvider signInProvider = signInProviders.get(providerInfo+"SignIn"); if (signInProvider == null) { throw new IllegalArgumentException("Unknown provider: " + providerInfo); } diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/WithdrawProvider.java b/src/main/java/com/moing/backend/domain/auth/application/service/WithdrawProvider.java new file mode 100644 index 00000000..b67996b0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/WithdrawProvider.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.auth.application.service; + +import java.io.IOException; + +public interface WithdrawProvider { + void withdraw(String token) throws IOException; +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java index 2f512ee2..05b1f179 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java @@ -8,7 +8,7 @@ import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; -@Service("apple") +@Service("appleSignIn") @AllArgsConstructor public class AppleSignInUserCase implements SignInProvider { diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java index 945f5250..1b2826c1 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java @@ -1,7 +1,7 @@ package com.moing.backend.domain.auth.application.service.apple; -import com.moing.backend.domain.auth.application.service.apple.feign.AppleFeignClient; -import com.moing.backend.domain.auth.application.service.apple.feign.response.Keys; +import com.moing.backend.domain.auth.application.service.apple.utils.AppleClient; +import com.moing.backend.domain.auth.application.service.apple.utils.Keys; import com.moing.backend.domain.auth.exception.TokenInvalidException; import com.moing.backend.global.exception.InternalServerErrorException; import io.jsonwebtoken.*; @@ -21,10 +21,10 @@ @RequiredArgsConstructor public class AppleTokenUserCase { - @Value("${app-id.apple}") + @Value("${oauth2.apple.teamId}") private String appId; - private final AppleFeignClient appleFeignClient; + private final AppleClient appleClient; public Jws sigVerificationAndGetJws(String unverifiedToken) { @@ -34,7 +34,7 @@ public Jws sigVerificationAndGetJws(String unverifiedToken) { "https://appleid.apple.com", appId); - Keys keys = appleFeignClient.getKeys(); + Keys keys = appleClient.getKeys(); Keys.PubKey pubKey = keys.getKeys().stream() .filter((key) -> key.getKid().equals(kid)) .findAny() diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java new file mode 100644 index 00000000..645c6e4a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java @@ -0,0 +1,95 @@ +package com.moing.backend.domain.auth.application.service.apple; + +import com.moing.backend.domain.auth.application.service.WithdrawProvider; +import com.moing.backend.domain.auth.application.service.apple.utils.AppleClient; +import com.moing.backend.domain.auth.application.service.apple.utils.AppleToken; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import lombok.RequiredArgsConstructor; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Service; +import org.springframework.util.FileCopyUtils; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.security.Key; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Service("appleWithdraw") +@RequiredArgsConstructor +public class AppleWithdrawUserCase implements WithdrawProvider { + + @Value("${oauth2.apple.keyId}") + private String keyId; + + @Value("${oauth2.apple.teamId}") + private String teamId; + + @Value("${oauth2.apple.clientId}") + private String clientId; + + @Value("${oauth2.apple.keyPath}") + private String keyPath; + + private final AppleClient appleClient; + + public void withdraw(String token) throws IOException { + AppleToken.Response response = generateAuthToken(token); + + if (response.getAccess_token() != null) { + appleClient.revoke(AppleToken.RevokeRequest.of( + clientId, + createClientSecret(), + response.getAccess_token() + ) + ); + } + } + + public AppleToken.Response generateAuthToken(String authorizationCode) throws IOException { + + return appleClient.getToken(AppleToken.Request.of( + authorizationCode, + clientId, + createClientSecret(), + "authorization_code" + )); + } + + public String createClientSecret() throws IOException { + Date expirationDate = Date.from(LocalDateTime.now().plusDays(30).atZone(ZoneId.systemDefault()).toInstant()); + Map jwtHeader = new HashMap<>(); + jwtHeader.put("kid", keyId); + jwtHeader.put("alg", "ES256"); + + return Jwts.builder() + .setHeaderParams(jwtHeader) + .setIssuer(teamId) // Apple Developer 페이지에 명시되어 있는 Team ID (우측 상단에 있음) + .setIssuedAt(new Date(System.currentTimeMillis())) + .setExpiration(expirationDate) + .setAudience("https://appleid.apple.com") + .setSubject(clientId) // Apple Developer 페이지에 App Bundle ID (com.xxx.xxx 형식) + .signWith(getPrivateKey(), SignatureAlgorithm.ES256) + .compact(); + } + + private Key getPrivateKey() throws IOException { + ClassPathResource resource = new ClassPathResource(keyPath); + String privateKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); + + Reader pemReader = new StringReader(privateKey); + PEMParser pemParser = new PEMParser(pemReader); + JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); + PrivateKeyInfo object = (PrivateKeyInfo) pemParser.readObject(); + return converter.getPrivateKey(object); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/AppleFeignClient.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/AppleFeignClient.java deleted file mode 100644 index 2c230bdc..00000000 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/AppleFeignClient.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.moing.backend.domain.auth.application.service.apple.feign; - -import com.moing.backend.domain.auth.application.service.apple.feign.response.Keys; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.GetMapping; - -@FeignClient(name = "appleClient", url = "https://appleid.apple.com/auth") -public interface AppleFeignClient { - - @Cacheable(cacheNames = "appleOICD", cacheManager = "oidcCacheManager") - @GetMapping(value = "/keys") - Keys getKeys(); - - @GetMapping(value = "/token") - String getAccessToken(); -} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleClient.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleClient.java new file mode 100644 index 00000000..de75629d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleClient.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.auth.application.service.apple.utils; + +import com.moing.backend.global.util.FeignClientConfig; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; + +@FeignClient(name = "appleClient", url = "https://appleid.apple.com/auth", configuration = FeignClientConfig.class) +public interface AppleClient { + @GetMapping(value = "/keys") + Keys getKeys(); + @PostMapping(value = "/token", consumes = "application/x-www-form-urlencoded") + AppleToken.Response getToken(AppleToken.Request request); + + @PostMapping(value = "/revoke", consumes = "application/x-www-form-urlencoded") + void revoke(AppleToken.RevokeRequest request); +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleToken.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleToken.java new file mode 100644 index 00000000..2fabd74a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleToken.java @@ -0,0 +1,47 @@ +package com.moing.backend.domain.auth.application.service.apple.utils; + +import lombok.Getter; + +public class AppleToken { + + public static class Request { + private String code; + private String client_id; + private String client_secret; + private String grant_type; + + public static Request of(String code, String clientId, String clientSecret, String grantType) { + Request request = new Request(); + request.code = code; + request.client_id = clientId; + request.client_secret = clientSecret; + request.grant_type = grantType; + return request; + } + } + + @Getter + public static class Response { + private String access_token; + private String expires_in; + private String id_token; + private String refresh_token; + private String token_type; + private String error; + } + + @Getter + public static class RevokeRequest { + private String client_id; + private String client_secret; + private String token; + + public static RevokeRequest of(String clientId, String clientSecret, String token) { + RevokeRequest request = new RevokeRequest(); + request.client_id = clientId; + request.client_secret = clientSecret; + request.token = token; + return request; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/response/Keys.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/Keys.java similarity index 96% rename from src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/response/Keys.java rename to src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/Keys.java index 2741263b..9261d011 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/feign/response/Keys.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/Keys.java @@ -1,4 +1,4 @@ -package com.moing.backend.domain.auth.application.service.apple.feign.response; +package com.moing.backend.domain.auth.application.service.apple.utils; import lombok.Data; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java index 9dac6637..13c452d9 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java @@ -2,21 +2,17 @@ import com.moing.backend.domain.auth.application.dto.response.GoogleUserResponse; import com.moing.backend.domain.auth.application.service.SignInProvider; -import com.moing.backend.domain.auth.exception.AppIdInvalidException; import com.moing.backend.domain.auth.exception.TokenInvalidException; import com.moing.backend.domain.member.application.mapper.MemberMapper; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.global.exception.InternalServerErrorException; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; -import java.util.Arrays; - -@Service("google") +@Service("googleSignIn") @RequiredArgsConstructor public class GoogleSignInUserCase implements SignInProvider { diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java index 167889f3..b61cf800 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java @@ -12,7 +12,7 @@ @RequiredArgsConstructor public class GoogleTokenUserCase { - @Value("${app-id.google}") + @Value("${oauth2.google.appId}") private String appId; public void verifyAccessToken(String aud) { diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleWithdrawUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleWithdrawUserCase.java new file mode 100644 index 00000000..7fddb5b9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleWithdrawUserCase.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.auth.application.service.google; + +import com.moing.backend.domain.auth.application.service.WithdrawProvider; +import com.moing.backend.domain.auth.application.service.google.utils.GoogleClient; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.io.IOException; + +@Service("googleWithdraw") +@RequiredArgsConstructor +public class GoogleWithdrawUserCase implements WithdrawProvider { + + private final GoogleClient googleClient; + + public void withdraw(String token) throws IOException { + googleClient.revoke(token); + } + +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/utils/GoogleClient.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/utils/GoogleClient.java new file mode 100644 index 00000000..dd83003c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/utils/GoogleClient.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.auth.application.service.google.utils; + +import com.moing.backend.global.util.FeignClientConfig; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient(name = "googleClient", url = "https://oauth2.googleapis.com", configuration = FeignClientConfig.class) +public interface GoogleClient { + @PostMapping(value = "/revoke", consumes = "application/x-www-form-urlencoded") + void revoke(@RequestParam("token") String token); +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java index 77b163d0..ef939b37 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java @@ -12,7 +12,7 @@ import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; -@Service("kakao") +@Service("kakaoSignIn") @RequiredArgsConstructor public class KakaoSignInUserCase implements SignInProvider { diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java index 09a7dbea..8f6d3766 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java @@ -15,7 +15,7 @@ @RequiredArgsConstructor public class KakaoTokenUserCase { - @Value("${app-id.kakao}") + @Value("${oauth2.kakao.appId}") private String appId; private final WebClient webClient; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoWithdrawUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoWithdrawUserCase.java new file mode 100644 index 00000000..f4525ba7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoWithdrawUserCase.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.auth.application.service.kakao; + +import com.moing.backend.domain.auth.application.service.WithdrawProvider; +import com.moing.backend.domain.auth.application.service.kakao.utils.KakaoClient; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.io.IOException; + +@Service("kakaoWithdraw") +@RequiredArgsConstructor +public class KakaoWithdrawUserCase implements WithdrawProvider { + + private final KakaoClient kakaoClient; + + public void withdraw(String token) throws IOException { + + kakaoClient.unlinkUser("Bearer " + token); + } +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoClient.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoClient.java new file mode 100644 index 00000000..a02b0d21 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoClient.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.auth.application.service.kakao.utils; + +import com.moing.backend.global.util.FeignClientConfig; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestHeader; + +@FeignClient(name = "kakaoClient", url = "https://kapi.kakao.com", configuration = FeignClientConfig.class) +public interface KakaoClient { + @PostMapping("/v1/user/unlink") + KakaoUnlinkResponse unlinkUser(@RequestHeader("Authorization") String accessToken); +} diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoUnlinkResponse.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoUnlinkResponse.java new file mode 100644 index 00000000..de0e8333 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoUnlinkResponse.java @@ -0,0 +1,8 @@ +package com.moing.backend.domain.auth.application.service.kakao.utils; + +import lombok.Getter; + +@Getter +public class KakaoUnlinkResponse { + private String id; +} diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/request/WithdrawRequest.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/request/WithdrawRequest.java index 78067857..1b07d726 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/dto/request/WithdrawRequest.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/request/WithdrawRequest.java @@ -16,4 +16,7 @@ public class WithdrawRequest { @NotBlank(message = "reason 을 입력해주세요.") @Size(min = 1, max = 500, message="reason 은 최소 1개, 최대 500개의 문자만 입력 가능합니다.") private String reason; + + @NotBlank(message = "socialToken 을 입력해주세요.") + private String socialToken; } diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java index 4a0dbf16..df959b27 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java @@ -1,5 +1,7 @@ package com.moing.backend.domain.mypage.application.service; +import com.moing.backend.domain.auth.application.service.SignInProvider; +import com.moing.backend.domain.auth.application.service.WithdrawProvider; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberDeleteService; import com.moing.backend.domain.member.domain.service.MemberGetService; @@ -11,6 +13,9 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.io.IOException; +import java.util.Map; + @Service @RequiredArgsConstructor public class WithdrawUserCase { @@ -20,15 +25,25 @@ public class WithdrawUserCase { private final TokenUtil tokenUtil; private final MemberDeleteService memberDeleteService; private final TeamMemberGetService teamMemberGetService; + private final Map withdrawProviders; - public void withdraw(String socialId, WithdrawRequest withdrawRequest) { + public void withdraw(String socialId, String providerInfo, WithdrawRequest withdrawRequest) throws IOException { Member member = memberGetService.getMemberBySocialId(socialId); checkMemberIsNotPartOfAnyTeam(member); + withdraw(providerInfo, withdrawRequest.getSocialToken()); memberDeleteService.deleteMember(member); feedbackSaveService.saveFeedback(member, withdrawRequest); tokenUtil.expireRefreshToken(socialId); } + private void withdraw(String providerInfo, String token) throws IOException { + WithdrawProvider withdrawProvider=withdrawProviders.get(providerInfo+"Withdraw"); + if (withdrawProvider == null) { + throw new IllegalArgumentException("Unknown provider: " + providerInfo); + } + withdrawProvider.withdraw(token); + } + private void checkMemberIsNotPartOfAnyTeam(Member member) { if (!teamMemberGetService.getNotDeletedTeamMember(member.getMemberId()).isEmpty()) { throw new ExistingTeamException(); diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java index daeb6ffb..deb82e9b 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java @@ -15,6 +15,8 @@ import javax.validation.Valid; +import java.io.IOException; + import static com.moing.backend.domain.mypage.presentation.constant.MypageResponseMessage.*; @RestController @@ -44,10 +46,11 @@ public ResponseEntity signOut(@AuthenticationPrincipal User use * [DELETE] api/mypage/withdrawal * 작성자 : 김민수 */ - @DeleteMapping("/withdrawal") + @DeleteMapping("/withdrawal/{provider}") public ResponseEntity withdraw(@AuthenticationPrincipal User user, - @Valid @RequestBody WithdrawRequest withdrawRequest) { - this.withdrawService.withdraw(user.getSocialId(), withdrawRequest); + @PathVariable String provider, + @Valid @RequestBody WithdrawRequest withdrawRequest) throws IOException { + this.withdrawService.withdraw(user.getSocialId(), provider, withdrawRequest); return ResponseEntity.ok(SuccessResponse.create(WITHDRAWAL_SUCCESS.getMessage())); } diff --git a/src/main/java/com/moing/backend/global/util/FeignClientConfig.java b/src/main/java/com/moing/backend/global/util/FeignClientConfig.java new file mode 100644 index 00000000..a9b6bd75 --- /dev/null +++ b/src/main/java/com/moing/backend/global/util/FeignClientConfig.java @@ -0,0 +1,7 @@ +package com.moing.backend.global.util; + +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FeignClientConfig { +} \ No newline at end of file From 10495de5e59fb39d0059ec2bc1c0e1351c735e2b Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 5 Nov 2023 11:21:27 +0900 Subject: [PATCH 198/619] =?UTF-8?q?fix:=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20API=20=EB=AA=85=EC=84=B8=EC=84=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Mypage-API.adoc | 2 +- .../mypage/presentation/MypageControllerTest.java | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/docs/asciidoc/Mypage-API.adoc b/src/docs/asciidoc/Mypage-API.adoc index b5b9e9c8..76317426 100644 --- a/src/docs/asciidoc/Mypage-API.adoc +++ b/src/docs/asciidoc/Mypage-API.adoc @@ -9,7 +9,7 @@ operation::mypage-controller-test/sign_out[snippets='http-request,http-response, [[Mypage-회원탈퇴]] == Mypage 회원탈퇴 -operation::mypage-controller-test/withdraw[snippets='http-request,request-fields,http-response,response-fields'] +operation::mypage-controller-test/withdraw[snippets='path-parameters,http-request,request-fields,http-response,response-fields'] [[Mypage-전체-조회]] == Mypage 전체 조회 diff --git a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java index d8364020..0e811495 100644 --- a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java @@ -13,6 +13,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; import org.springframework.test.web.servlet.ResultActions; import java.util.ArrayList; @@ -23,8 +24,7 @@ import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.payload.PayloadDocumentation.*; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.restdocs.request.RequestDocumentation.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -76,14 +76,15 @@ public void withdraw() throws Exception { //given WithdrawRequest input = WithdrawRequest.builder() .reason("REASON_TO_LEAVE") + .socialToken("SOCIAL_TOKEN") .build(); String body = objectMapper.writeValueAsString(input); //when - ResultActions actions = mockMvc.perform( - delete("/api/mypage/withdrawal") + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/mypage/withdrawal/{provider}","google,kakao,apple") .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) .content(body) @@ -98,7 +99,11 @@ public void withdraw() throws Exception { requestHeaders( headerWithName("Authorization").description("접근 토큰") ), + pathParameters( + parameterWithName("provider").description("google, kakao, apple") + ), requestFields( + fieldWithPath("socialToken").description("google:accessToken/ kakao:accessToken/ apple:authorization code"), fieldWithPath("reason").description("회원탈퇴하는 이유") ), responseFields( From 3df934fae0180ad87e640bd64000a33dc85a3c1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 5 Nov 2023 15:39:16 +0900 Subject: [PATCH 199/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=EB=A6=AC=ED=84=B4=EC=97=90=20?= =?UTF-8?q?way=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/FinishMissionBoardRes.java | 5 ++++- .../application/dto/res/RepeatMissionBoardRes.java | 7 +++++-- .../repository/MissionArchiveCustomRepositoryImpl.java | 6 ++++-- .../representation/MissionBoardControllerTest.java | 8 ++++++-- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java index ecd0c0b3..824246b7 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/FinishMissionBoardRes.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import lombok.Builder; import lombok.Getter; @@ -18,12 +19,14 @@ public class FinishMissionBoardRes { private String title; private String status; private String missionType; + private String missionWay; - public FinishMissionBoardRes(Long missionId, String dueTo, String title, String status, String missionType) { + public FinishMissionBoardRes(Long missionId, String dueTo, String title, String status, String missionType,String missionWay) { this.missionId = missionId; this.dueTo = dueTo; this.title = title; this.status = status; this.missionType = missionType; + this.missionWay = missionWay; } } diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java index 099c187c..3cff40f6 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java @@ -15,22 +15,25 @@ public class RepeatMissionBoardRes { // private String status; private Long done; private int number; + private String way; - public RepeatMissionBoardRes(Long missionId, String title, Long done,int number) { + public RepeatMissionBoardRes(Long missionId, String title, Long done,int number,String way) { this.missionId = missionId; this.title = title; this.dueTo="False"; this.number = number; this.done = done; + this.way = way; } @Builder - public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long done, int number) { + public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long done, int number,String way) { this.missionId = missionId; this.title = title; this.dueTo = "False"; this.done = done; this.number = number; + this.way = way; } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 70aea54a..8da611d4 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -173,7 +173,8 @@ public Optional> findRepeatMissionArchivesByMemberId mission.id, mission.title, missionArchive.count().coalesce(0L).as("done"), - mission.number + mission.number, + mission.way )) .from(mission) .leftJoin(mission.missionArchiveList,missionArchive) @@ -203,7 +204,8 @@ public Optional> findFinishMissionsByStatus(Long mem mission.dueTo.stringValue(), mission.title, missionArchive.status.stringValue().coalesce("INCOMPLETE").as("status"), - mission.type.stringValue() + mission.type.stringValue(), + mission.way )) .from(mission) .leftJoin(mission.missionArchiveList,missionArchive) diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java index 953a9d2b..91fae242 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java @@ -94,6 +94,7 @@ public class MissionBoardControllerTest extends CommonControllerTest { .dueTo("True/False") .done(1L) .number(3) + .way("TEXT/PHOTO/LINK") .build()); given(missionArchiveBoardUseCase.getActiveRepeatMissions(any(),any())).willReturn(output); @@ -125,7 +126,8 @@ public class MissionBoardControllerTest extends CommonControllerTest { fieldWithPath("data[].title").description("미션 제목"), fieldWithPath("data[].dueTo").description("내일 리셋 상태 리턴, 일요일이면 true[True/False]"), fieldWithPath("data[].number").description("전체 횟수"), - fieldWithPath("data[].done").description("인증한 횟수") + fieldWithPath("data[].done").description("인증한 횟수"), + fieldWithPath("data[].way").description("인증 방법") ) ) @@ -144,6 +146,7 @@ public class MissionBoardControllerTest extends CommonControllerTest { .dueTo("2023-09-03T21:32:33.888") .status("SUCCESS/FAIL") .missionType("ONCE/REPEAT") + .missionWay("TEXT/PHOTO/LINK") .build()); given(missionArchiveBoardUseCase.getFinishMissions(any(),any())).willReturn(output); @@ -175,7 +178,8 @@ public class MissionBoardControllerTest extends CommonControllerTest { fieldWithPath("data[].title").description("미션 제목"), fieldWithPath("data[].dueTo").description("내일 리셋 상태 리턴, 일요일이면 true[True/False]"), fieldWithPath("data[].status").description("미션 종료된 상태 (성공/실패)"), - fieldWithPath("data[].missionType").description("미션 타입 (한번/반복)") + fieldWithPath("data[].missionType").description("미션 타입 (한번/반복)"), + fieldWithPath("data[].missionWay").description("미션 인증 방식 ") ) ) From c78593af51ef7d14796184625d09acb108094a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 5 Nov 2023 16:33:36 +0900 Subject: [PATCH 200/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A1=B0=ED=9A=8C=20mission.way.toStringvalue()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 8da611d4..81d2e212 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -174,7 +174,7 @@ public Optional> findRepeatMissionArchivesByMemberId mission.title, missionArchive.count().coalesce(0L).as("done"), mission.number, - mission.way + mission.way.stringValue() )) .from(mission) .leftJoin(mission.missionArchiveList,missionArchive) @@ -205,7 +205,7 @@ public Optional> findFinishMissionsByStatus(Long mem mission.title, missionArchive.status.stringValue().coalesce("INCOMPLETE").as("status"), mission.type.stringValue(), - mission.way + mission.way.stringValue() )) .from(mission) .leftJoin(mission.missionArchiveList,missionArchive) From a6ac5e8a92ddc0b91deb914f9890954b72277f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 5 Nov 2023 19:28:38 +0900 Subject: [PATCH 201/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionArchiveCustomRepositoryImpl.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 81d2e212..2f9046fb 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -172,18 +172,19 @@ public Optional> findRepeatMissionArchivesByMemberId .select(Projections.constructor(RepeatMissionBoardRes.class, mission.id, mission.title, - missionArchive.count().coalesce(0L).as("done"), + missionArchive.count.coalesce(0L).as("done"), mission.number, mission.way.stringValue() )) .from(mission) .leftJoin(mission.missionArchiveList,missionArchive) - .on( missionArchive.member.memberId.eq(memberId), - missionArchive.mission.status.eq(status)) + .on( missionArchive.member.memberId.eq(memberId)) .where( mission.team.teamId.eq(teamId), - mission.type.eq(MissionType.REPEAT) + mission.type.eq(MissionType.REPEAT), + mission.status.eq(MissionStatus.ONGOING) ) + // .groupBy(missionArchive.mission) .fetch()); From fa06912f55a5d2e151d2c2dc44941f2d55249d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 6 Nov 2023 03:20:18 +0900 Subject: [PATCH 202/619] =?UTF-8?q?feat=20:=20=EB=82=98=EC=9D=98=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=8B=9C=20=EB=8B=B9=EC=9D=BC=EC=9D=B8=EC=A6=9D=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EB=8B=B9=EC=9D=BC?= =?UTF-8?q?=20=EC=A4=91=EB=B3=B5=20=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=20=EB=B6=88=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/MyMissionArchiveRes.java | 31 +++++++++++++++++ .../service/MissionArchiveCreateUseCase.java | 7 +++- .../service/MissionArchiveReadUseCase.java | 17 ++++++---- .../service/MissionArchiveUpdateUseCase.java | 7 ++++ .../MissionArchiveCustomRepository.java | 1 + .../MissionArchiveCustomRepositoryImpl.java | 33 ++++++++++++++++--- .../service/MissionArchiveQueryService.java | 14 ++++++++ .../MissionArchiveController.java | 7 ++-- .../MissionArchiveControllerTest.java | 27 ++++++++++----- 9 files changed, 120 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyMissionArchiveRes.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyMissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyMissionArchiveRes.java new file mode 100644 index 00000000..3d15bd08 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyMissionArchiveRes.java @@ -0,0 +1,31 @@ +package com.moing.backend.domain.missionArchive.application.dto.res; + +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class MyMissionArchiveRes { + private String today; + private List archives; + + public void updateArchives(List archives) { + this.archives = archives; + } + + public void updateTodayStatus(Boolean bo) { + if (bo) { + this.today = "True"; + } else { + this.today = "False"; + } + } + +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index d61baf2a..c66694a3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -58,7 +58,12 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss } // 반복 미션일 경우 if (mission.getType() == MissionType.REPEAT) { - newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); + // 당일 1회 인증만 가능 + if(!missionArchiveQueryService.findDoneTodayArchive(memberId,missionId)) + newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); + else + throw new NoMoreMissionArchiveException(); + }else { newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java index afd6c0aa..4b018484 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java @@ -4,10 +4,7 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; -import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.*; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.team.domain.entity.Team; @@ -33,11 +30,19 @@ public class MissionArchiveReadUseCase { // 미션 인증 조회 - public List getMyArchive(String userSocialId, Long missionId) { + public MyMissionArchiveRes getMyArchive(String userSocialId, Long missionId) { Long memberId = memberGetService.getMemberBySocialId(userSocialId).getMemberId(); - return MissionArchiveMapper.mapToMissionArchiveResList(missionArchiveQueryService.findMyArchive(memberId, missionId), memberId); + MyMissionArchiveRes myMissionArchiveRes = new MyMissionArchiveRes(); + + List missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveResList(missionArchiveQueryService.findMyArchive(memberId, missionId), memberId); + myMissionArchiveRes.updateArchives(missionArchiveRes); + + myMissionArchiveRes.updateTodayStatus(missionArchiveQueryService.findDoneTodayArchive(memberId, missionId)); + + return myMissionArchiveRes; + } // 모두의 미션 인증 목록 조회 diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index cd465770..4340b120 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -8,6 +8,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.mission.exception.NoAccessCreateMission; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; @@ -22,11 +23,13 @@ import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; +import com.moing.backend.domain.missionState.exception.NoAccessMissionArchiveException; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; import java.util.List; @Service @@ -72,6 +75,10 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss // 점수 반영 로직 } + // 반복미션의 경우 당일이 지나면 업데이트 불가능 + if (!(updateArchive.getLastModifiedDate().getDayOfWeek().equals(LocalDateTime.now().getDayOfWeek()))) { + throw new NoAccessMissionArchiveException(); + } updateArchive.updateArchive(missionReq); // missionStateUseCase.updateMissionState(member, mission, updateArchive); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index b6fec1f3..1818b2ed 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -28,5 +28,6 @@ public interface MissionArchiveCustomRepository { Optional> findTop5ArchivesByTeam(List teamIds); + Boolean findMyArchivesToday(Long memberId,Long missionId); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 2f9046fb..efa04b7f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -17,9 +17,11 @@ import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; import feign.Param; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.jpa.repository.Query; import javax.persistence.EntityManager; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -28,7 +30,7 @@ import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; import static javax.swing.Spring.constant; - +@Slf4j public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { private final JPAQueryFactory queryFactory; @@ -172,7 +174,7 @@ public Optional> findRepeatMissionArchivesByMemberId .select(Projections.constructor(RepeatMissionBoardRes.class, mission.id, mission.title, - missionArchive.count.coalesce(0L).as("done"), + missionArchive.count.max().coalesce(0L).as("done"), mission.number, mission.way.stringValue() )) @@ -184,11 +186,9 @@ public Optional> findRepeatMissionArchivesByMemberId mission.type.eq(MissionType.REPEAT), mission.status.eq(MissionStatus.ONGOING) ) - -// .groupBy(missionArchive.mission) + .groupBy(mission) .fetch()); - } @Override @@ -254,4 +254,27 @@ public Optional> findTop5ArchivesByTeam(List } + public Boolean findMyArchivesToday(Long memberId, Long missionId) { + LocalDateTime today = LocalDateTime.now(); + LocalDateTime startOfToday = today.withHour(0).withMinute(0).withSecond(0).withNano(0); + LocalDateTime endOfToday = today.withHour(23).withMinute(59).withSecond(59).withNano(999999999); + + log.info("today"+ today); + log.info("startToday"+startOfToday); + log.info("endToday"+endOfToday); + + long count = queryFactory + .selectFrom(missionArchive) + .where( + missionArchive.member.memberId.eq(memberId), + missionArchive.mission.id.eq(missionId), + missionArchive.lastModifiedDate.between(startOfToday, endOfToday) // createdDate와 오늘의 시작과 끝을 비교 + ) + .fetchCount(); + + return count > 0; + } + + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index d219ef00..04f924c3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -66,6 +66,16 @@ public Boolean isDone(Long memberId, Long missionId) { } } + public Boolean isTodayDone(Long memberId, Long missionId) { + Optional> byMemberId = missionArchiveRepository.findArchivesByMissionIdAndMemberId(memberId, missionId); + if (byMemberId.isPresent()) { + + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + // team의 mission id 들 가져와서 나의 mission archive 리턴 /** @@ -106,6 +116,10 @@ public List findTop5ArchivesByTeam(List teamIds) { return missionArchiveRepository.findTop5ArchivesByTeam(teamIds).orElse(null); } + public boolean findDoneTodayArchive(Long memberId, Long missionId) { + return missionArchiveRepository.findMyArchivesToday(memberId, missionId); + } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 88625bb8..6cbcb7e1 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MyMissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.service.*; import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; @@ -67,9 +68,9 @@ public ResponseEntity> updateArchive(@Authent **/ @GetMapping() - public ResponseEntity>> getMyArchive(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId) { + public ResponseEntity> getMyArchive(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { return ResponseEntity.ok(SuccessResponse.create(READ_MY_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getMyArchive(user.getSocialId(), missionId))); } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index eb60edd5..410119f4 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MyMissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.service.*; import com.moing.backend.domain.missionArchive.presentation.MissionArchiveController; @@ -185,7 +186,9 @@ public class MissionArchiveControllerTest extends CommonControllerTest { public void 나의_미션_인증_조회() throws Exception { //given - List output = Lists.newArrayList(MissionArchiveRes.builder() + + + List archives = Lists.newArrayList(MissionArchiveRes.builder() .archiveId(1L) .archive("content[s3 Link / text / link]") .way("TEXT/LINK/PHOTO") @@ -196,6 +199,11 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .hearts(1L) .build()); + MyMissionArchiveRes output = MyMissionArchiveRes.builder() + .archives(archives) + .today("True/False") + .build(); + given(missionArchiveReadUseCase.getMyArchive(any(),any())).willReturn(output); Long teamId = 1L; @@ -223,14 +231,15 @@ public class MissionArchiveControllerTest extends CommonControllerTest { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description(READ_MY_ARCHIVE_SUCCESS.getMessage()), - fieldWithPath("data[].archiveId").description("미션 인증 아이디"), - fieldWithPath("data[].archive").description("미션 인증물 [s3URL/text/링크]"), - fieldWithPath("data[].way").description("미션 인증물 방식"), - fieldWithPath("data[].createdDate").description("미션 제출 시각"), - fieldWithPath("data[].status").description("미션 인증 상태"), - fieldWithPath("data[].count").description("미션 인증 횟수"), - fieldWithPath("data[].heartStatus").description("미션 인증 좋아요 상태"), - fieldWithPath("data[].hearts").description("미션 인증 좋아요 수") + fieldWithPath("data.today").description("오늘 인증 여부"), + fieldWithPath("data.archives[].archiveId").description("미션 인증 아이디"), + fieldWithPath("data.archives[].archive").description("미션 인증물 [s3URL/text/링크]"), + fieldWithPath("data.archives[].way").description("미션 인증물 방식"), + fieldWithPath("data.archives[].createdDate").description("미션 제출 시각"), + fieldWithPath("data.archives[].status").description("미션 인증 상태"), + fieldWithPath("data.archives[].count").description("미션 인증 횟수"), + fieldWithPath("data.archives[].heartStatus").description("미션 인증 좋아요 상태"), + fieldWithPath("data.archives[].hearts").description("미션 인증 좋아요 수") ) From d208b67eef358003dd8048427dc55713fb81aae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 6 Nov 2023 03:27:35 +0900 Subject: [PATCH 203/619] =?UTF-8?q?fix=20:=20NoAccessMissionArchiveExcepti?= =?UTF-8?q?on.java=20=EC=9C=84=EC=B9=98=20=EC=97=90=EB=9F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveUpdateUseCase.java | 8 +------- .../exception/NoAccessMissionArchiveException.java | 12 ++++++++++++ 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/exception/NoAccessMissionArchiveException.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index 4340b120..60a84e88 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -8,29 +8,23 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.mission.exception.NoAccessCreateMission; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; -import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; -import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; -import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; -import com.moing.backend.domain.missionState.exception.NoAccessMissionArchiveException; +import com.moing.backend.domain.missionArchive.exception.NoAccessMissionArchiveException; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; -import java.util.List; @Service @Transactional diff --git a/src/main/java/com/moing/backend/domain/missionArchive/exception/NoAccessMissionArchiveException.java b/src/main/java/com/moing/backend/domain/missionArchive/exception/NoAccessMissionArchiveException.java new file mode 100644 index 00000000..6ce6ada1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/exception/NoAccessMissionArchiveException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.missionArchive.exception; + +import com.moing.backend.domain.missionState.exception.MissionStateException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NoAccessMissionArchiveException extends MissionStateException { + public NoAccessMissionArchiveException() { + super(ErrorCode.NO_MORE_ARCHIVE_ERROR, HttpStatus.NOT_FOUND); + + } +} From dc650b6456135a3e939994ac3fc0d678b59ae0e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 6 Nov 2023 03:31:25 +0900 Subject: [PATCH 204/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EB=A7=88=EA=B0=90=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A5=B4=EB=9F=AC=20=EA=B5=AC=ED=98=84=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- firebase-key.json | 12 ++++++++++++ .../service/MissionStateScheduleUseCase.java | 9 ++++++++- .../repository/MissionStateCustomRepository.java | 3 +++ .../MissionStateCustomRepositoryImpl.java | 16 ++++++++++++++++ .../domain/service/MissionStateQueryService.java | 6 +++++- .../exception/MissionStateException.java | 11 +++++++++++ .../exception/NotFoundMissionStateException.java | 11 +++++++++++ 7 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 firebase-key.json create mode 100644 src/main/java/com/moing/backend/domain/missionState/exception/MissionStateException.java create mode 100644 src/main/java/com/moing/backend/domain/missionState/exception/NotFoundMissionStateException.java diff --git a/firebase-key.json b/firebase-key.json new file mode 100644 index 00000000..a048f082 --- /dev/null +++ b/firebase-key.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "moing-affa0", + "private_key_id": "46f914da7d8ca5be4d7ce4b23eff66a928a6aa63", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDj9sr74AXpq2l7\nYScCyGorjAb9KqTpAoC/NutcWTT4Ec1fNMUMylVaQCmUK3ktUQ/moRgzUKOjPvmb\nuYqYVfIthBMCqAgOUlR2v1Bt7C9+zSVpA5bznXIBcd4NNriZjS3z2ZzuMj8au9SC\nHb+beJSlYp59RSa222Wptg2v6d+sc+25ubhqPNhXEHt7TquWFskk0aY7VSnrB3AX\n78LbknttxG9kP9m/vdXEGCs/mDIPEaW6Pp6pWg8K7NRdBBEsU8m/rK7SyUwKR+p+\nXFfYvkmaFoIBMd9P9ne6hgLK6c+Hph/1s+wR5tyAaa+DB0xiZlzlCk/dD4f8ilTs\n/8+6bxjNAgMBAAECggEAFcqm5G//BgjW7a6U/5ean+y5UvnWHNjFPOzU5UA5J4jw\nHxdDdPG3Ogg4e/ZclZU9ALjKlZvc9gMpnOtze796MJlXsIvRL/6fyLWIzJE6MxQM\n7PPPuhxaucJMTeq6t8xT+w5aNDeaalr6jrD6+t41JiAoyA8ptcDVquUBJvKjk++s\n4gcJfazL/d6mgZBP3JWaHpjYNqUMQ39mLUzzIIjCuL2L6XO0T1QNDXJsAWUg0Wgg\nWKMEEMirYt9NGeR1rscQBwoeaBlTyvhbwo10FV2eMz7g2Q4587Ug4zHanhnzB27T\ndjm6BjqtE/uL5Cr2jPtuTaP+jSFcr6lN7xMbUwyQwwKBgQDyZwJOMXVK3XviVKln\nHCyzabn9vyTaKamvNxfD7rMAx1jczyhXolnkpMpDi99Z5BGbvwvvzEycSYpQWP2c\nY0KYRJ64Otjavum7u+mQcc8SNLzOTEtCJPnIhlp/dJaPmnLE3nYAzbphEYhCFpnZ\ncPPkCGFb17GvHOeNqfpouJh8owKBgQDwwHGZhpPm2yDYXvSXq7ba0ZNKRp7IGhR6\nmW/vLFn4GzdX6rHyNt/J+AI+ChnbrkZeFkZ+TJXZUCVPj2STA6zVubSHqXW8PtZS\n+0C60tvrZy+fdHTyQtPMC/Nt7UN933aC/c3Cn36R+ely1EJ1f9QKlVeDHj+32vUZ\njtx388B7zwKBgA3UWKpTYgi6aCX6hIuwbNBzmLvkWtrjg53Oe9me1bGWrfgzDW8q\ngQxtZmjCIyUCwQpstOaidkB4ZZ695QI2G4eKaq/CE7svJzChwOqPw6ubPKZcbfLB\nH0sUdzdMVIau3htjQcI7+oUtNePnXDGuowuAeuV9gdKmyIMpjnLJDVIXAoGBAImr\nQkqsbj8A51NTWUKx6qpOVY+PupRqdXN18lAuaHQ7+/XGO2NqhaYUsBOR6x94FL0Q\nt9bZLIdMEUnhkX2QCHFe9CDvgmfW9vAUxPsQQLnoE493JLi0BjEUVGtz1bhQ5JAb\nWmIEmngXFKuZPTe7lSFILPbJgV49UxL+YowlUth5AoGBAN+EYFZMdWUbkfyPKDbJ\nh7MkbGTk8Wphlt293DzBZ8JDGsAq4eEDTM9sOBxFc0L9GXInZ2+t0x4sLLtGIiXh\nTZ+R8z1PnLff9R9qBPEzhbaGs8S9N5k4D4FDizJAUxBxw/JWKcs27rP3FyV2cITs\nItBrkmaDdy7Dt238xxhQImLq\n-----END PRIVATE KEY-----\n", + "client_email": "firebase-adminsdk-9885y@moing-affa0.iam.gserviceaccount.com", + "client_id": "104671629105051491236", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-9885y%40moing-affa0.iam.gserviceaccount.com" +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 05953ae1..833f3a4c 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -47,7 +47,8 @@ public void missionStateReset(List missionIds) { } // 한시간마다 실행 - public void singleMissionEndRoutine() { + // 미션 단위 + public void singleMissionEndRoutineByMission() { Mission mission = new Mission(); @@ -56,5 +57,11 @@ public void singleMissionEndRoutine() { if (mission.getDueTo().isAfter(now)) { mission.updateStatus(MissionStatus.END); } + } + + public void singleMissionEndRoutine() { + + + } } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java index 2ffe75bd..8493bcdb 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java @@ -6,6 +6,7 @@ import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Optional; @Repository public interface MissionStateCustomRepository { @@ -14,5 +15,7 @@ public interface MissionStateCustomRepository { List findByMissionId(List missionId); + Optional> findFinishMission(); + } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index 5f93de16..3529e333 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionState.domain.repository; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -7,7 +8,9 @@ import javax.persistence.EntityManager; +import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; @@ -42,5 +45,18 @@ public List findByMissionId(List missionId) { } + @Override + public Optional> findFinishMission() { + return Optional.ofNullable(queryFactory + .select(missionState) + .from(missionState) + .where( + missionState.mission.dueTo.ne(LocalDateTime.now()), + missionState.mission.status.eq(MissionStatus.ONGOING) + + ).fetch() + ); + } + } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java index 4b4e6287..d6c87892 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java @@ -4,7 +4,7 @@ import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; - +import com.moing.backend.domain.missionState.exception.NotFoundMissionStateException; import javax.transaction.Transactional; import java.util.List; @@ -23,5 +23,9 @@ public List findByMissionId(List missionId) { return missionStateRepository.findByMissionId(missionId); } + public List findFinishMission() { + return missionStateRepository.findFinishMission().orElseThrow(NotFoundMissionStateException::new); + } + } diff --git a/src/main/java/com/moing/backend/domain/missionState/exception/MissionStateException.java b/src/main/java/com/moing/backend/domain/missionState/exception/MissionStateException.java new file mode 100644 index 00000000..54c72e46 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/exception/MissionStateException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.missionState.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class MissionStateException extends ApplicationException { + protected MissionStateException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionState/exception/NotFoundMissionStateException.java b/src/main/java/com/moing/backend/domain/missionState/exception/NotFoundMissionStateException.java new file mode 100644 index 00000000..2baae393 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/exception/NotFoundMissionStateException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.missionState.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundMissionStateException extends MissionStateException{ + public NotFoundMissionStateException() { + super(ErrorCode.NOT_FOUND_END_MISSION, HttpStatus.NOT_FOUND); + + } +} From 20d7ddaa705741f4bd36e921e0fca5204c596e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 6 Nov 2023 04:28:14 +0900 Subject: [PATCH 205/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0-teamId=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/dto/res/GatherRepeatMissionRes.java | 1 + .../mission/application/dto/res/GatherSingleMissionRes.java | 1 + .../domain/repository/MissionCustomRepositoryImpl.java | 2 ++ .../representation/MissionGatherControllerTest.java | 4 ++++ 4 files changed, 8 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java index bfedd3d8..5249ce34 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java @@ -10,6 +10,7 @@ public class GatherRepeatMissionRes { private Long missionId; + private Long teamId; private String teamName; private String missionTitle; private String totalNum; diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java index fba77c0a..1afe2085 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java @@ -9,6 +9,7 @@ @AllArgsConstructor public class GatherSingleMissionRes { private Long missionId; + private Long teamId; private String teamName; private String missionTitle; private String dueTo; diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index f04a8c12..9cb1ff84 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -42,6 +42,7 @@ public Optional> findRepeatMissionByMemberId(Long m return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherRepeatMissionRes.class, mission.id, + mission.team.teamId, mission.team.name, mission.title, mission.number.stringValue(), @@ -88,6 +89,7 @@ public Optional> findSingleMissionByMemberId(Long m return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherSingleMissionRes.class, mission.id, + mission.team.teamId, mission.team.name, mission.title, mission.dueTo.stringValue() diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index 0985af75..523cc66f 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -40,6 +40,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { List output = Lists.newArrayList(GatherSingleMissionRes.builder() .missionId(1L) + .teamId(1L) .dueTo("2023-09-03T21:32:33.888") .teamName("team name") .missionTitle("mission title") @@ -68,6 +69,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage()), fieldWithPath("data[].missionId").description("미션 아이디"), + fieldWithPath("data[].teamId").description("팀 아이디"), fieldWithPath("data[].dueTo").description("미션 마감 시각"), fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목") @@ -85,6 +87,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { List output = Lists.newArrayList(GatherRepeatMissionRes.builder() .missionId(1L) + .teamId(1L) .teamName("team name") .missionTitle("mission title") .doneNum("0") @@ -114,6 +117,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage()), fieldWithPath("data[].missionId").description("미션 아이디"), + fieldWithPath("data[].teamId").description("팀 아이디"), fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목"), fieldWithPath("data[].doneNum").description("완료한 횟수"), From 4daae30ad7ec17ccf85c30a13644f6bf490a81cb Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Mon, 6 Nov 2023 09:33:22 +0900 Subject: [PATCH 206/619] =?UTF-8?q?feat=20:=20=EB=82=B4=EA=B0=80=20?= =?UTF-8?q?=EC=86=8D=ED=95=9C=20=ED=8C=80=20(=EC=95=84=EC=9D=B4=EB=94=94,?= =?UTF-8?q?=EC=9D=B4=EB=A6=84)=20=EC=A1=B0=ED=9A=8C=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- firebase-key.json | 12 ------------ .../domain/repository/TeamCustomRepository.java | 2 ++ .../domain/repository/TeamCustomRepositoryImpl.java | 13 +++++++++++++ .../domain/team/domain/service/TeamGetService.java | 5 +++++ 5 files changed, 22 insertions(+), 13 deletions(-) delete mode 100644 firebase-key.json diff --git a/.gitignore b/.gitignore index b603f75b..9b5677c4 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,5 @@ data.sql #### docs #### !**/src/main/resources/static/docs/ -*.html \ No newline at end of file +*.html +firebase-key.json \ No newline at end of file diff --git a/firebase-key.json b/firebase-key.json deleted file mode 100644 index a048f082..00000000 --- a/firebase-key.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "service_account", - "project_id": "moing-affa0", - "private_key_id": "46f914da7d8ca5be4d7ce4b23eff66a928a6aa63", - "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDj9sr74AXpq2l7\nYScCyGorjAb9KqTpAoC/NutcWTT4Ec1fNMUMylVaQCmUK3ktUQ/moRgzUKOjPvmb\nuYqYVfIthBMCqAgOUlR2v1Bt7C9+zSVpA5bznXIBcd4NNriZjS3z2ZzuMj8au9SC\nHb+beJSlYp59RSa222Wptg2v6d+sc+25ubhqPNhXEHt7TquWFskk0aY7VSnrB3AX\n78LbknttxG9kP9m/vdXEGCs/mDIPEaW6Pp6pWg8K7NRdBBEsU8m/rK7SyUwKR+p+\nXFfYvkmaFoIBMd9P9ne6hgLK6c+Hph/1s+wR5tyAaa+DB0xiZlzlCk/dD4f8ilTs\n/8+6bxjNAgMBAAECggEAFcqm5G//BgjW7a6U/5ean+y5UvnWHNjFPOzU5UA5J4jw\nHxdDdPG3Ogg4e/ZclZU9ALjKlZvc9gMpnOtze796MJlXsIvRL/6fyLWIzJE6MxQM\n7PPPuhxaucJMTeq6t8xT+w5aNDeaalr6jrD6+t41JiAoyA8ptcDVquUBJvKjk++s\n4gcJfazL/d6mgZBP3JWaHpjYNqUMQ39mLUzzIIjCuL2L6XO0T1QNDXJsAWUg0Wgg\nWKMEEMirYt9NGeR1rscQBwoeaBlTyvhbwo10FV2eMz7g2Q4587Ug4zHanhnzB27T\ndjm6BjqtE/uL5Cr2jPtuTaP+jSFcr6lN7xMbUwyQwwKBgQDyZwJOMXVK3XviVKln\nHCyzabn9vyTaKamvNxfD7rMAx1jczyhXolnkpMpDi99Z5BGbvwvvzEycSYpQWP2c\nY0KYRJ64Otjavum7u+mQcc8SNLzOTEtCJPnIhlp/dJaPmnLE3nYAzbphEYhCFpnZ\ncPPkCGFb17GvHOeNqfpouJh8owKBgQDwwHGZhpPm2yDYXvSXq7ba0ZNKRp7IGhR6\nmW/vLFn4GzdX6rHyNt/J+AI+ChnbrkZeFkZ+TJXZUCVPj2STA6zVubSHqXW8PtZS\n+0C60tvrZy+fdHTyQtPMC/Nt7UN933aC/c3Cn36R+ely1EJ1f9QKlVeDHj+32vUZ\njtx388B7zwKBgA3UWKpTYgi6aCX6hIuwbNBzmLvkWtrjg53Oe9me1bGWrfgzDW8q\ngQxtZmjCIyUCwQpstOaidkB4ZZ695QI2G4eKaq/CE7svJzChwOqPw6ubPKZcbfLB\nH0sUdzdMVIau3htjQcI7+oUtNePnXDGuowuAeuV9gdKmyIMpjnLJDVIXAoGBAImr\nQkqsbj8A51NTWUKx6qpOVY+PupRqdXN18lAuaHQ7+/XGO2NqhaYUsBOR6x94FL0Q\nt9bZLIdMEUnhkX2QCHFe9CDvgmfW9vAUxPsQQLnoE493JLi0BjEUVGtz1bhQ5JAb\nWmIEmngXFKuZPTe7lSFILPbJgV49UxL+YowlUth5AoGBAN+EYFZMdWUbkfyPKDbJ\nh7MkbGTk8Wphlt293DzBZ8JDGsAq4eEDTM9sOBxFc0L9GXInZ2+t0x4sLLtGIiXh\nTZ+R8z1PnLff9R9qBPEzhbaGs8S9N5k4D4FDizJAUxBxw/JWKcs27rP3FyV2cITs\nItBrkmaDdy7Dt238xxhQImLq\n-----END PRIVATE KEY-----\n", - "client_email": "firebase-adminsdk-9885y@moing-affa0.iam.gserviceaccount.com", - "client_id": "104671629105051491236", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-9885y%40moing-affa0.iam.gserviceaccount.com" -} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index 43d7b559..7df50396 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.team.domain.repository; +import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.team.application.dto.response.GetTeamDetailResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; @@ -13,4 +14,5 @@ public interface TeamCustomRepository { Optional findTeamByTeamId(Long TeamId); List findTeamIdByMemberId(Long memberId); List findMyPageTeamByMemberId(Long memberId); + List findTeamNameByTeamId(List teamId); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index f0132576..8fa7606e 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.team.domain.repository; +import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.application.dto.response.QTeamBlock; @@ -98,4 +99,16 @@ private List getTeamBlock(Long memberId) { .fetch(); } + @Override + public List findTeamNameByTeamId(List teamId) { + return queryFactory + .select(Projections.constructor(MyTeamsRes.class, + team.teamId, + team.name)) + .from(team) + .where(team.teamId.in(teamId)) + .fetch(); + } + + } diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index 90e530fd..e5583318 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.team.domain.service; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; @@ -33,4 +34,8 @@ public Team getTeamByTeamId(Long teamId){ public List getMyPageTeamBlockByMemberId(Long memberId){ return teamRepository.findMyPageTeamByMemberId(memberId); } + + public List getTeamNameByTeamId(List teamId) { + return teamRepository.findTeamNameByTeamId(teamId); + } } From 72feb491736d26ce0bedf4b5ccef0de3146032e6 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Mon, 6 Nov 2023 09:33:37 +0900 Subject: [PATCH 207/619] =?UTF-8?q?feat=20:=20=EB=82=B4=EA=B0=80=20?= =?UTF-8?q?=EC=86=8D=20=ED=95=9C=20=ED=8C=80=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionGatherBoard-API.adoc | 7 ++++ .../service/MissionGatherBoardUseCase.java | 10 +++++ .../application/dto/res/MyTeamsRes.java | 15 +++++++ .../MissionArchiveResponseMessage.java | 3 +- .../presentation/MissionGatherController.java | 8 ++++ .../MissionGatherControllerTest.java | 42 +++++++++++++++++++ 6 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyTeamsRes.java diff --git a/src/docs/asciidoc/MissionGatherBoard-API.adoc b/src/docs/asciidoc/MissionGatherBoard-API.adoc index bb06d09b..d19a5ccf 100644 --- a/src/docs/asciidoc/MissionGatherBoard-API.adoc +++ b/src/docs/asciidoc/MissionGatherBoard-API.adoc @@ -19,3 +19,10 @@ operation::mission-gather-controller-test/미션_모아보기_반복_미션[snip operation::mission-gather-controller-test/미션_모아보기_팀별[snippets='http-request,http-response,response-fields'] --- + + +[[MissionBoard-내가-속한-팀-조회]] +== 내가_속한_팀_조회 +operation::mission-gather-controller-test/내가_속한_팀_조회[snippets='http-request,http-response,response-fields'] + +--- diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java index f1727911..f808dd6c 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java @@ -6,6 +6,7 @@ import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; @@ -45,6 +46,15 @@ public List getArchivePhotoByTeamRes(String userId) { } + public List getMyTeams(String userId) { + Long memberId = memberGetService.getMemberBySocialId(userId).getMemberId(); + List teamIdByMemberId = teamGetService.getTeamIdByMemberId(memberId); + + return teamGetService.getTeamNameByTeamId(teamIdByMemberId); + + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyTeamsRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyTeamsRes.java new file mode 100644 index 00000000..e665c563 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyTeamsRes.java @@ -0,0 +1,15 @@ +package com.moing.backend.domain.missionArchive.application.dto.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Builder +public class MyTeamsRes { + private Long teamId; + private String teamName; +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java index c2ef9ad9..d6d623b1 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java @@ -16,7 +16,8 @@ public enum MissionArchiveResponseMessage { ACTIVE_SINGLE_MISSION_SUCCESS("진행 중인 한번 인증 미션 조회를 완료 했습니다."), ACTIVE_REPEAT_MISSION_SUCCESS("진행 중인 반복 인증 미션 조회를 완료 했습니다."), FINISH_ALL_MISSION_SUCCESS("종료된 미션 조회를 완료하였습니다."), - MISSION_ARCHIVE_BY_TEAM("팀별 미션 인증물 사진 조회를 완료했습니더."); + MISSION_ARCHIVE_BY_TEAM("팀별 미션 인증물 사진 조회를 완료했습니다."), + GET_MY_TEAM_LIST_SUCCESS("내가 속한 팀을 모두 조회했습니다."); private final String message; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java index 9895c774..2c798a35 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java @@ -6,6 +6,7 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -55,6 +56,13 @@ public ResponseEntity>> getArchives return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_BY_TEAM.getMessage(), this.missionGatherBoardUseCase.getArchivePhotoByTeamRes(user.getSocialId()))); } + @GetMapping("/my-teamList") + public ResponseEntity>> getMyTeams(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(GET_MY_TEAM_LIST_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getMyTeams(user.getSocialId()))); + } + + + diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index 523cc66f..487a7d8a 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.mission.application.dto.res.*; import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; import com.moing.backend.domain.missionArchive.application.service.MissionArchiveReadUseCase; import com.moing.backend.domain.missionArchive.presentation.MissionGatherController; import org.assertj.core.util.Lists; @@ -174,6 +175,47 @@ public class MissionGatherControllerTest extends CommonControllerTest { } + @Test + public void 내가_속한_팀_조회() throws Exception { + //given + + + List output = Lists.newArrayList(MyTeamsRes.builder() + .teamId(1L) + .teamName("teamname") + .build()); + + given(missionGatherBoardUseCase.getMyTeams(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/my-teamList") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(MISSION_ARCHIVE_BY_TEAM.getMessage()), + fieldWithPath("data[].teamId").description("팀 아이디"), + fieldWithPath("data[].teamName").description("팀 이름") + ) + ) + ) + .andReturn(); + + } + } \ No newline at end of file From 0279a8e54533cbc6142f80017863dac71ed6b4e6 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Mon, 6 Nov 2023 20:09:13 +0900 Subject: [PATCH 208/619] =?UTF-8?q?deploy:=20apple=5Fkey=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-cd.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 76670219..2c3bec49 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -14,7 +14,7 @@ jobs: working-directory: ./ APPLICATION: ${{ secrets.APPLICATION }} GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }} - DATA_SQL: ${{ secrets.DATA_SQl }} + APPLE_KEY: ${{ secrets.APPLE_KEY }} steps: # 소스 코드 체크아웃 @@ -46,6 +46,8 @@ jobs: echo "${{env.APPLICATION}}" > ./application.yml touch ./firebase-key.json echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json + touch ./apple-key.p8 + echo "${{env.APPLE_KEY}}" > ./apple-key.p8 # 설정 파일을 작업공간에 저장 - uses: actions/upload-artifact@v2 @@ -58,6 +60,11 @@ jobs: name: firebase-key.json path: ./src/main/resources/firebase-key.json + - uses: actions/upload-artifact@v2 + with: + name: apple-key.p8 + path: ./src/main/resources/apple-key.p8 + # gradlew 권한 설정 - name: Grant execute permission for gradlew run: chmod +x gradlew From 1a5fec0bd883f07da120515a34cd8e053b074771 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 6 Nov 2023 20:10:22 +0900 Subject: [PATCH 209/619] =?UTF-8?q?fix:=20=EB=B3=80=EC=88=98=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/service/apple/AppleTokenUserCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java index 1b2826c1..20d9218d 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java @@ -21,7 +21,7 @@ @RequiredArgsConstructor public class AppleTokenUserCase { - @Value("${oauth2.apple.teamId}") + @Value("${oauth2.apple.clientId}") private String appId; private final AppleClient appleClient; From 284f7ac9ca596ea5cb2d095b3f4c8c3f3e7597d2 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 6 Nov 2023 20:18:29 +0900 Subject: [PATCH 210/619] =?UTF-8?q?fix:=20=EC=93=B8=EB=AA=A8=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EC=A3=BC=EC=84=9D=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/service/apple/AppleWithdrawUserCase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java index 645c6e4a..910519a3 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java @@ -73,11 +73,11 @@ public String createClientSecret() throws IOException { return Jwts.builder() .setHeaderParams(jwtHeader) - .setIssuer(teamId) // Apple Developer 페이지에 명시되어 있는 Team ID (우측 상단에 있음) + .setIssuer(teamId) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(expirationDate) .setAudience("https://appleid.apple.com") - .setSubject(clientId) // Apple Developer 페이지에 App Bundle ID (com.xxx.xxx 형식) + .setSubject(clientId) .signWith(getPrivateKey(), SignatureAlgorithm.ES256) .compact(); } From 218b95a52ff3c68d3fe6d7a6645d810b8d2c532e Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 7 Nov 2023 00:05:40 +0900 Subject: [PATCH 211/619] =?UTF-8?q?feat=20:=20=EB=AA=A8=EC=9E=89=EB=B6=88?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20api=20=EB=AC=B8=EC=84=9C=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/api.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 07a4bc65..5d102566 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -30,3 +30,5 @@ include::Board-API.adoc[] include::BoardComment_API.adoc[] +include::TeamScore-API.adoc[] + From 89db894b9f6d359ea8c6bc9e0168a55d58cea893 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 7 Nov 2023 01:40:40 +0900 Subject: [PATCH 212/619] =?UTF-8?q?feat=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=83=9D=EC=84=B1=20=EC=A0=9C=ED=95=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionCreateUseCase.java | 5 +++++ .../mission/exception/NoMoreCreateMission.java | 12 ++++++++++++ .../com/moing/backend/global/response/ErrorCode.java | 3 ++- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/exception/NoMoreCreateMission.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index dd4756e7..850b9dbb 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -11,6 +11,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionSaveService; import com.moing.backend.domain.mission.exception.NoAccessCreateMission; +import com.moing.backend.domain.mission.exception.NoMoreCreateMission; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.repository.TeamRepository; import com.moing.backend.global.util.SecurityUtils; @@ -36,6 +37,9 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR if (member.getMemberId().equals(team.getLeaderId())) { Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.ONGOING); // teamRepository 변경 예정 + if (team.getMissions().size() > 3) { + throw new NoMoreCreateMission(); + } mission.setTeam(team); missionSaveService.save(mission); return MissionMapper.mapToMissionCreateRes(mission); @@ -46,6 +50,7 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR + } } diff --git a/src/main/java/com/moing/backend/domain/mission/exception/NoMoreCreateMission.java b/src/main/java/com/moing/backend/domain/mission/exception/NoMoreCreateMission.java new file mode 100644 index 00000000..76c525f4 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/exception/NoMoreCreateMission.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mission.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NoMoreCreateMission extends MissionException { + + public NoMoreCreateMission() { + super(ErrorCode.NO_MORE_CREATE_MISSION, + HttpStatus.UNAUTHORIZED); + } +} diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index f3f29b6f..548f26fe 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -28,7 +28,8 @@ public enum ErrorCode { //미션 관련 에러코드 NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), NOT_FOUND_MISSION("M0002", "미션을 찾을 수 없습니다."), - NOT_FOUND_END_MISSION("M0002", "기한이 지난 미션을 찾을 수 없습니다."), + NOT_FOUND_END_MISSION("M0003", "기한이 지난 미션을 찾을 수 없습니다."), + NO_MORE_CREATE_MISSION("M0004", "반복미션은 3개까지 생성할 수 없습니다."), NOT_FOUND_MISSION_ARCHIVE("MA0001", "아직 미션을 제출하지 않았습니다."), NO_MORE_ARCHIVE_ERROR("MA0001", "지정한 횟수 이상 미션을 인증할 수 없습니다."), From a12865ceedc15dbc2552aaaafa8cd9132e0f2dcf Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 7 Nov 2023 01:41:16 +0900 Subject: [PATCH 213/619] =?UTF-8?q?feat=20:=20=ED=8C=80=EB=B3=84=20?= =?UTF-8?q?=EB=AA=A8=EB=93=A0=20=EC=A7=84=ED=96=89=EC=A4=91=EC=9D=B8=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=A1=B0=ED=9A=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionGatherBoard-API.adoc | 10 ++ .../service/MissionGatherBoardUseCase.java | 11 +++ .../repository/MissionCustomRepository.java | 1 - .../domain/service/MissionQueryService.java | 12 +++ .../MissionArchiveResponseMessage.java | 6 +- .../presentation/MissionGatherController.java | 25 ++++- .../MissionGatherControllerTest.java | 99 +++++++++++++++++++ 7 files changed, 160 insertions(+), 4 deletions(-) diff --git a/src/docs/asciidoc/MissionGatherBoard-API.adoc b/src/docs/asciidoc/MissionGatherBoard-API.adoc index d19a5ccf..8a29140e 100644 --- a/src/docs/asciidoc/MissionGatherBoard-API.adoc +++ b/src/docs/asciidoc/MissionGatherBoard-API.adoc @@ -12,6 +12,16 @@ operation::mission-gather-controller-test/미션_모아보기_단일_미션[snip == 미션_모아보기_반복_미션 operation::mission-gather-controller-test/미션_모아보기_반복_미션[snippets='http-request,http-response,response-fields'] +--- +[[MissionBoard-팀별-미션-모아보기-단일]] +== 팀별_미션_모아보기_단일_미션 +operation::mission-gather-controller-test/팀별_미션_모아보기_단일_미션[snippets='http-request,http-response,response-fields'] +--- + +[[MissionBoard-팀별-미션-모아보기-반복]] +== 팀별_미션_모아보기_반복_미션 +operation::mission-gather-controller-test/팀별_미션_모아보기_반복_미션[snippets='http-request,http-response,response-fields'] + --- [[MissionBoard-미션-모아보기-팀별]] diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java index f808dd6c..0b502fea 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionGatherBoardUseCase.java @@ -37,6 +37,17 @@ public List getAllActiveRepeatMissions(String userId) { } + public List getTeamActiveSingleMissions(String userId,Long teamId) { + Long memberId = memberGetService.getMemberBySocialId(userId).getMemberId(); + return missionQueryService.findTeamSingleMission(memberId,teamId); + + } + public List getTeamActiveRepeatMissions(String userId,Long teamId) { + Long memberId = memberGetService.getMemberBySocialId(userId).getMemberId(); + return missionQueryService.findTeamRepeatMission(memberId,teamId); + + } + public List getArchivePhotoByTeamRes(String userId) { Long memberId = memberGetService.getMemberBySocialId(userId).getMemberId(); diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index e545111e..c98198f6 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -17,7 +17,6 @@ public interface MissionCustomRepository { Optional> findRepeatMissionByMemberId(Long memberId, Listteams); - Optional> findMissionByDueTo(); Optional> findOngoingRepeatMissions(); diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 6d1e4f10..08d13f14 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -43,6 +43,18 @@ public List findAllSingleMission(Long memberId) { return missionRepository.findSingleMissionByMemberId(memberId, teams).orElseThrow(NotFoundMissionException::new); } + public List findTeamRepeatMission(Long memberId,Long teamId) { + List teams = new ArrayList<>(); + teams.add(teamId); + return missionRepository.findRepeatMissionByMemberId(memberId,teams).orElseThrow(NotFoundMissionException::new); + } + + public List findTeamSingleMission(Long memberId,Long teamId) { + List teams = new ArrayList<>(); + teams.add(teamId); + return missionRepository.findSingleMissionByMemberId(memberId, teams).orElseThrow(NotFoundMissionException::new); + } + /** * 스케쥴러에서 한시간 단위로 실행 * 현재 시간으로부터 1시간 이내 종료 되는 미션 리턴 diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java index d6d623b1..8f278ce6 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java @@ -13,8 +13,10 @@ public enum MissionArchiveResponseMessage { READ_TEAM_ARCHIVE_SUCCESS("팀원 미션 인증 현황 조회를 완료 했습니다."), HEART_UPDATE_SUCCESS("미션 인증 좋아요를 성공적으로 눌렀습니다."), MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS("미션 인증 성공한 인원 상태 조회를 완료 했습니다."), - ACTIVE_SINGLE_MISSION_SUCCESS("진행 중인 한번 인증 미션 조회를 완료 했습니다."), - ACTIVE_REPEAT_MISSION_SUCCESS("진행 중인 반복 인증 미션 조회를 완료 했습니다."), + ACTIVE_SINGLE_MISSION_SUCCESS("진행 중인 모든 한번 인증 미션 조회를 완료 했습니다."), + ACTIVE_REPEAT_MISSION_SUCCESS("진행 중인 모든 반복 인증 미션 조회를 완료 했습니다."), + ACTIVE_TEAM_SINGLE_MISSION_SUCCESS("진행 중인 팀별 한번 인증 미션 조회를 완료 했습니다."), + ACTIVE_TEAM_REPEAT_MISSION_SUCCESS("진행 중인 팀별 반복 인증 미션 조회를 완료 했습니다."), FINISH_ALL_MISSION_SUCCESS("종료된 미션 조회를 완료하였습니다."), MISSION_ARCHIVE_BY_TEAM("팀별 미션 인증물 사진 조회를 완료했습니다."), GET_MY_TEAM_LIST_SUCCESS("내가 속한 팀을 모두 조회했습니다."); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java index 2c798a35..6a6a2694 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java @@ -13,6 +13,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; 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; @@ -36,7 +37,7 @@ public class MissionGatherController { @GetMapping("/my-once") public ResponseEntity>> getMyActiveSingleMission(@AuthenticationPrincipal User user) { - return ResponseEntity.ok(SuccessResponse.create(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getAllActiveSingleMissions(user.getSocialId()))); + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_TEAM_SINGLE_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getAllActiveSingleMissions(user.getSocialId()))); } /** @@ -45,6 +46,28 @@ public ResponseEntity>> getMyActive * 작성자 : 정승연 */ + @GetMapping("/team-repeat/{teamId}") + public ResponseEntity>> getTeamActiveRepeatMission(@AuthenticationPrincipal User user ,@PathVariable Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_TEAM_REPEAT_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getTeamActiveRepeatMissions( user.getSocialId(),teamId))); + } + + /** + * 팀별 미션 모아보기 - 단일 미션 + * [GET] my-single + * 작성자 : 정승연 + */ + + @GetMapping("/team-once/{teamId}") + public ResponseEntity>> getTeamActiveSingleMission(@AuthenticationPrincipal User user ,@PathVariable Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(ACTIVE_SINGLE_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getTeamActiveSingleMissions(user.getSocialId(),teamId))); + } + + /** + * 팀별 미션 모아보기 - 반복 미션 + * [GET] my-repeat + * 작성자 : 정승연 + */ + @GetMapping("/my-repeat") public ResponseEntity>> getMyActiveRepeatMission(@AuthenticationPrincipal User user) { return ResponseEntity.ok(SuccessResponse.create(ACTIVE_REPEAT_MISSION_SUCCESS.getMessage(), this.missionGatherBoardUseCase.getAllActiveRepeatMissions( user.getSocialId()))); diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index 487a7d8a..6103418b 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -130,6 +130,105 @@ public class MissionGatherControllerTest extends CommonControllerTest { ) .andReturn(); + } + + @Test + public void 팀별_미션_모아보기_단일_미션() throws Exception { + //given + + List output = Lists.newArrayList(GatherSingleMissionRes.builder() + .missionId(1L) + .teamId(1L) + .dueTo("2023-09-03T21:32:33.888") + .teamName("team name") + .missionTitle("mission title") + .build()); + + given(missionGatherBoardUseCase.getTeamActiveSingleMissions(any(),any())).willReturn(output); + + Long teamId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/team-once/{teamId}",teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(ACTIVE_TEAM_SINGLE_MISSION_SUCCESS.getMessage()), + fieldWithPath("data[].missionId").description("미션 아이디"), + fieldWithPath("data[].teamId").description("팀 아이디"), + fieldWithPath("data[].dueTo").description("미션 마감 시각"), + fieldWithPath("data[].teamName").description("팀 이름"), + fieldWithPath("data[].missionTitle").description("미션 제목") + + ) + ) + ) + .andReturn(); + + } + + @Test + public void 팀별_미션_모아보기_반복_미션() throws Exception { + //given + + List output = Lists.newArrayList(GatherRepeatMissionRes.builder() + .missionId(1L) + .teamId(1L) + .teamName("team name") + .missionTitle("mission title") + .doneNum("0") + .totalNum("0") + .build()); + + given(missionGatherBoardUseCase.getTeamActiveRepeatMissions(any(),any())).willReturn(output); + + Long teamId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/team-repeat/{teamId}",teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(ACTIVE_TEAM_REPEAT_MISSION_SUCCESS.getMessage()), + fieldWithPath("data[].missionId").description("미션 아이디"), + fieldWithPath("data[].teamId").description("팀 아이디"), + fieldWithPath("data[].teamName").description("팀 이름"), + fieldWithPath("data[].missionTitle").description("미션 제목"), + fieldWithPath("data[].doneNum").description("완료한 횟수"), + fieldWithPath("data[].totalNum").description("전체 횟수") + + + ) + ) + ) + .andReturn(); + } @Test public void 미션_모아보기_팀별() throws Exception { From b1b3818da61a8953b96b58ac4514134fd4a8d0f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 9 Nov 2023 03:17:03 +0900 Subject: [PATCH 214/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=EB=A7=8C=203=EA=B0=9C=20=EC=A0=9C=ED=95=9C=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/MissionRecommendRes.java | 12 ++++++++++++ .../service/MissionCreateUseCase.java | 19 ++++++++++++++++--- .../repository/MissionCustomRepository.java | 3 +++ .../MissionCustomRepositoryImpl.java | 11 +++++++++++ .../domain/service/MissionQueryService.java | 4 ++++ .../backend/global/response/ErrorCode.java | 2 +- 6 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionRecommendRes.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionRecommendRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionRecommendRes.java new file mode 100644 index 00000000..33663c13 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionRecommendRes.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mission.application.dto.res; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Builder +@Getter +@Setter +public class MissionRecommendRes { + String category; +} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index 850b9dbb..4062d51c 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -5,15 +5,18 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.application.dto.req.MissionReq; import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; +import com.moing.backend.domain.mission.application.dto.res.MissionRecommendRes; import com.moing.backend.domain.mission.application.mapper.MissionMapper; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.mission.domain.service.MissionSaveService; import com.moing.backend.domain.mission.exception.NoAccessCreateMission; import com.moing.backend.domain.mission.exception.NoMoreCreateMission; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.repository.TeamRepository; +import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.global.util.SecurityUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -25,19 +28,21 @@ public class MissionCreateUseCase { private final MissionSaveService missionSaveService; - private final TeamRepository teamRepository; + private final MissionQueryService missionQueryService; + private final TeamGetService teamGetService; private final MemberGetService memberGetService; public MissionCreateRes createMission(String userSocialId, Long teamId, MissionReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); - Team team = teamRepository.findById(teamId).orElseThrow(); + Team team = teamGetService.getTeamByTeamId(teamId); // 소모임 장 확인 if (member.getMemberId().equals(team.getLeaderId())) { Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.ONGOING); // teamRepository 변경 예정 - if (team.getMissions().size() > 3) { + + if (missionQueryService.isAbleCreateRepeatMission(team.getTeamId())) { throw new NoMoreCreateMission(); } mission.setTeam(team); @@ -53,4 +58,12 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR } + public MissionRecommendRes getCategoryByTeam(Long teamId) { + Team team = teamGetService.getTeamByTeamId(teamId); + + return MissionRecommendRes.builder() + .category(team.getCategory().name()) + .build(); + } + } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index c98198f6..45b842f0 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -21,4 +21,7 @@ public interface MissionCustomRepository { Optional> findOngoingRepeatMissions(); + boolean findRepeatMissionsByTeamId(Long teamId); + + } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 9cb1ff84..74fa2095 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -104,4 +104,15 @@ public Optional> findSingleMissionByMemberId(Long m .fetch()); } + public boolean findRepeatMissionsByTeamId(Long teamId) { + return queryFactory + .select(mission) + .from(mission) + .where( + mission.team.teamId.eq(teamId), + mission.type.eq(MissionType.REPEAT), + mission.status.eq(MissionStatus.ONGOING) + ).fetchCount() < 3; + } + } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 08d13f14..3190e252 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -66,4 +66,8 @@ public List findMissionByDueTo() { public List findOngoingRepeatMissions() { return missionRepository.findOngoingRepeatMissions().orElseThrow(NotFoundOngoingMissionException::new); } + + public boolean isAbleCreateRepeatMission(Long teamId) { + return missionRepository.findRepeatMissionsByTeamId(teamId); + } } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 548f26fe..28fe9bd0 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -29,7 +29,7 @@ public enum ErrorCode { NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), NOT_FOUND_MISSION("M0002", "미션을 찾을 수 없습니다."), NOT_FOUND_END_MISSION("M0003", "기한이 지난 미션을 찾을 수 없습니다."), - NO_MORE_CREATE_MISSION("M0004", "반복미션은 3개까지 생성할 수 없습니다."), + NO_MORE_CREATE_MISSION("M0004", "반복미션은 3개까지 생성할 수 있습니다."), NOT_FOUND_MISSION_ARCHIVE("MA0001", "아직 미션을 제출하지 않았습니다."), NO_MORE_ARCHIVE_ERROR("MA0001", "지정한 횟수 이상 미션을 인증할 수 없습니다."), From 1106290869c72568730baab216b5742b1d7f94de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 9 Nov 2023 03:47:48 +0900 Subject: [PATCH 215/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EA=B0=9C=EC=88=98=20=EC=A0=9C=ED=95=9C=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionCreateUseCase.java | 2 +- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index 4062d51c..c5a433b4 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -42,7 +42,7 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.ONGOING); // teamRepository 변경 예정 - if (missionQueryService.isAbleCreateRepeatMission(team.getTeamId())) { + if (mission.getType() == MissionType.REPEAT && missionQueryService.isAbleCreateRepeatMission(team.getTeamId())) { throw new NoMoreCreateMission(); } mission.setTeam(team); diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 74fa2095..0511444d 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -112,7 +112,7 @@ public boolean findRepeatMissionsByTeamId(Long teamId) { mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT), mission.status.eq(MissionStatus.ONGOING) - ).fetchCount() < 3; + ).fetchCount() > 2; } } From 26d4ab70175dbd81a4d90260d6bd751fb1ea7889 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 9 Nov 2023 21:07:33 +0900 Subject: [PATCH 216/619] =?UTF-8?q?feat:=20=EB=AA=A9=ED=91=9C=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20=ED=98=84=EC=9E=AC?= =?UTF-8?q?=20=EC=9C=A0=EC=A0=80=20=EC=95=84=EC=9D=B4=EB=94=94=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/team/application/dto/response/TeamInfo.java | 1 + .../backend/domain/team/application/mapper/TeamMapper.java | 4 ++-- .../domain/team/application/service/GetTeamUserCase.java | 2 +- .../backend/domain/team/presentation/TeamControllerTest.java | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java index 77dc2c8c..b537a398 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java @@ -19,5 +19,6 @@ public class TeamInfo { private Integer numOfMember; //소모임원 수 private Category category; //카테고리 private String introduction; //소개 + private Long currentUserId; //현재 유저 아이디 private List teamMemberInfoList = new ArrayList<>(); //소모임원 정보 } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index be62dc70..ea035595 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -30,8 +30,8 @@ public Team createTeam(CreateTeamRequest createTeamRequest, Member member) { .build(); } - public GetTeamDetailResponse toTeamDetailResponse(Team team, Integer boardNum, List teamMemberInfoList) { - TeamInfo teamInfo = new TeamInfo(team.isDeleted(), team.getDeletionTime(), team.getName(), teamMemberInfoList.size(), team.getCategory(), team.getIntroduction(), teamMemberInfoList); + public GetTeamDetailResponse toTeamDetailResponse(Long memberId, Team team, Integer boardNum, List teamMemberInfoList) { + TeamInfo teamInfo = new TeamInfo(team.isDeleted(), team.getDeletionTime(), team.getName(), teamMemberInfoList.size(), team.getCategory(), team.getIntroduction(), memberId, teamMemberInfoList); return GetTeamDetailResponse.builder() .boardNum(boardNum) .teamInfo(teamInfo) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java index a19b000f..a5b501d0 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java @@ -37,7 +37,7 @@ public GetTeamDetailResponse getTeamDetailResponse(String socialId, Long teamId) Integer boardNum = boardGetService.getUnReadBoardNum(teamId, member.getMemberId()); List teamMemberInfoList = teamMemberGetService.getTeamMemberInfo(teamId); Team team = teamGetService.getTeamByTeamId(teamId); - return teamMapper.toTeamDetailResponse(team, boardNum, teamMemberInfoList); + return teamMapper.toTeamDetailResponse(member.getMemberId(), team, boardNum, teamMemberInfoList); } public GetCurrentStatusResponse getCurrentStatus(Long teamId) { diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 869e763c..386de94b 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -194,6 +194,7 @@ public void get_team_detail() throws Exception { .numOfMember(1) .category(Category.ETC) .introduction("소모임 소개글") + .currentUserId(1L) .teamMemberInfoList(teamMemberInfoList).build(); GetTeamDetailResponse output = GetTeamDetailResponse @@ -235,6 +236,7 @@ public void get_team_detail() throws Exception { fieldWithPath("data.teamInfo.introduction").description("모임 소개"), fieldWithPath("data.teamInfo.isDeleted").description("삭제여부"), fieldWithPath("data.teamInfo.deletionTime").description("삭제 시간 (삭제 안했으면 null)"), + fieldWithPath("data.teamInfo.currentUserId").description("현재 유저 아이디"), fieldWithPath("data.teamInfo.teamMemberInfoList[0].memberId").description("유저 아이디"), fieldWithPath("data.teamInfo.teamMemberInfoList[0].nickName").description("유저 닉네임"), fieldWithPath("data.teamInfo.teamMemberInfoList[0].profileImage").description("유저 프로필 이미지"), From 1359e4aaf57e294239a81d80b220a11526a3c544 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 12 Nov 2023 16:03:44 +0900 Subject: [PATCH 217/619] =?UTF-8?q?refactor:=20=EB=8B=89=EB=84=A4=EC=9E=84?= =?UTF-8?q?=20=EC=A4=91=EB=B3=B5=20=EA=B2=80=EC=82=AC=20API=20endPoint=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Auth-API.adoc | 2 +- .../auth/presentation/AuthController.java | 6 +++--- .../auth/presentation/AuthControllerTest.java | 21 +++++++++---------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/docs/asciidoc/Auth-API.adoc b/src/docs/asciidoc/Auth-API.adoc index 40d5aec1..bfb95656 100644 --- a/src/docs/asciidoc/Auth-API.adoc +++ b/src/docs/asciidoc/Auth-API.adoc @@ -40,7 +40,7 @@ operation::auth-controller-test/reissue_token[snippets='http-request,http-respon [[Auth-닉네임-검사]] == Auth 닉네임 중복검사 요청 -operation::auth-controller-test/check_nickname_중복o[snippets='http-request,path-parameters'] +operation::auth-controller-test/check_nickname_중복o[snippets='http-request'] == Auth 닉네임 중복인 경우 operation::auth-controller-test/check_nickname_중복o[snippets='http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java index 5ecd6ec9..30b82f0f 100644 --- a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java @@ -74,11 +74,11 @@ public ResponseEntity> reissue(@RequestHea /** * 닉네임 중복검사 - * [GET] api/auth/nickname + * [GET] api/auth/checkNickName?nickname={} * 작성자 : 김민수 */ - @GetMapping("/nickname/{nickname}") - public ResponseEntity> checkNickname(@PathVariable String nickname){ + @GetMapping("/checkNickname") + public ResponseEntity> checkNickname(@RequestParam String nickname){ return ResponseEntity.ok(SuccessResponse.create(CHECK_NICKNAME_SUCCESS.getMessage(), checkNicknameService.checkNickname(nickname))); } diff --git a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java index 825d2ff9..ffb90247 100644 --- a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java +++ b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java @@ -21,12 +21,12 @@ import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; import static org.springframework.restdocs.payload.PayloadDocumentation.*; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.restdocs.request.RequestDocumentation.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; @WebMvcTest(AuthController.class) @@ -410,15 +410,14 @@ public void reissue_token() throws Exception { // when ResultActions actions = mockMvc.perform( - get("/api/auth/nickname/{nickname}", "NICKNAME") - .contentType(MediaType.APPLICATION_JSON) + get("/api/auth/checkNickname?nickname=minsu") ); // then actions .andExpect(status().isOk()) .andDo(restDocs.document( - pathParameters( + requestParameters( parameterWithName("nickname").description("중복검사할 닉네임") ), responseFields( @@ -437,15 +436,15 @@ public void reissue_token() throws Exception { // when - ResultActions actions =mockMvc.perform( - get("/api/auth/nickname/{nickname}", "NICKNAME")); - + ResultActions actions = mockMvc.perform( + get("/api/auth/checkNickname?nickname=minsu") + ); // then actions .andExpect(status().isOk()) .andDo(restDocs.document( - pathParameters( + requestParameters( parameterWithName("nickname").description("중복검사할 닉네임") ), responseFields( From 260660aa5ede43e878739cb00d750f8d951cac6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 13 Nov 2023 00:01:51 +0900 Subject: [PATCH 218/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=82=AD=EC=A0=9C=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveDeleteUseCase.java | 76 +++++++++++++++++++ .../MissionArchiveController.java | 17 ++++- .../service/MissionStateUseCase.java | 5 ++ .../MissionStateCustomRepository.java | 3 + .../MissionStateCustomRepositoryImpl.java | 9 +++ .../service/MissionStateDeleteService.java | 4 + .../service/MissionStateQueryService.java | 6 ++ .../MissionArchiveControllerTest.java | 40 ++++++++++ 8 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java new file mode 100644 index 00000000..1ac31cec --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java @@ -0,0 +1,76 @@ +package com.moing.backend.domain.missionArchive.application.service; + +import com.moing.backend.domain.infra.image.application.service.IssuePresignedUrlUseCase; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; +import com.moing.backend.domain.missionArchive.exception.NoAccessMissionArchiveException; +import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; +import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.missionState.domain.entity.MissionState; +import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; +import com.moing.backend.domain.team.domain.entity.Team; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionArchiveDeleteUseCase { + + private final MissionArchiveSaveService missionArchiveSaveService; + private final MissionArchiveQueryService missionArchiveQueryService; + private final MissionArchiveDeleteService missionArchiveDeleteService; + private final MissionHeartQueryService missionHeartQueryService; + + private final MissionQueryService missionQueryService; + + private final MemberGetService memberGetService; + + private final IssuePresignedUrlUseCase getPresignedUrlUseCase; + + private final MissionStateSaveService missionStateSaveService; + private final MissionStateUseCase missionStateUseCase; + private final MissionStateDeleteService missionStateDeleteService; + private final MissionStateQueryService missionStateQueryService; + + + public Long deleteArchive(String userSocialId, Long missionId) { + + Member member = memberGetService.getMemberBySocialId(userSocialId); + Long memberId = member.getMemberId(); + Mission mission = missionQueryService.findMissionById(missionId); + Team team = mission.getTeam(); + + // 사진 제출 했다면, + if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(memberId, missionId)) { + //s3삭제 + + + } + + MissionArchive deleteArchive = missionArchiveQueryService.findMyArchive(memberId, missionId).get(0); + missionArchiveDeleteService.deleteMissionArchive(deleteArchive); + + MissionState missionState = missionStateQueryService.findMissionState(member, mission); + missionStateDeleteService.deleteMissionState(missionState); + return deleteArchive.getId(); + + } +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 6cbcb7e1..77169a15 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MyMissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.service.*; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; import com.moing.backend.domain.missionHeart.application.service.MissionHeartUseCase; import com.moing.backend.global.config.security.dto.User; @@ -27,8 +28,10 @@ public class MissionArchiveController { private final MissionArchiveCreateUseCase missionArchiveCreateUseCase; - private final MissionArchiveUpdateUseCase missionArchiveUpdateUseCase; private final MissionArchiveReadUseCase missionArchiveReadUseCase; + private final MissionArchiveUpdateUseCase missionArchiveUpdateUseCase; + private final MissionArchiveDeleteUseCase missionArchiveDeleteUseCase; + private final RepeatMissionArchiveReadUseCase repeatMissionArchiveReadUseCase; private final MissionHeartUseCase missionHeartUseCase; @@ -60,6 +63,18 @@ public ResponseEntity> updateArchive(@Authent @RequestBody MissionArchiveReq missionArchiveReq) { return ResponseEntity.ok(SuccessResponse.create(UPDATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveUpdateUseCase.updateArchive(user.getSocialId(), missionId,missionArchiveReq))); } + /** + * 미션 인증 취소하기 + * [DELETE] {teamId}/missions/{missionId}/archive + * 작성자 : 정승연 + **/ + + @DeleteMapping() + public ResponseEntity> deleteArchive(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(UPDATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveDeleteUseCase.deleteArchive(user.getSocialId(), missionId))); + } /** * 미션 인증 조회 diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 80f65496..41849b62 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -78,6 +78,11 @@ public void updateMissionState(Member member, Mission mission, MissionArchive mi } + public void deleteMissionState(Member member, Mission mission, MissionArchive missionArchive) { + + + } + } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java index 8493bcdb..6a9e996d 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java @@ -17,5 +17,8 @@ public interface MissionStateCustomRepository { Optional> findFinishMission(); + Optional findMissionStateByMemberAndMission(Member member, Mission mission); + + } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index 3529e333..d6ef72e7 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -1,5 +1,7 @@ package com.moing.backend.domain.missionState.domain.repository; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionState.domain.entity.MissionState; @@ -58,5 +60,12 @@ public Optional> findFinishMission() { ); } + public Optional findMissionStateByMemberAndMission(Member member, Mission mission) { + return Optional.ofNullable(queryFactory + .selectFrom(missionState) + .where(missionState.mission.eq(mission), + missionState.member.eq(member)) + .fetchFirst()); + } } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java index b0674fd5..eb679fb6 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java @@ -19,4 +19,8 @@ public void deleteMissionState(List missionStates) { missionStateRepository.deleteAll(missionStates); } + public void deleteMissionState(MissionState missionStates) { + + missionStateRepository.delete(missionStates); + } } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java index d6c87892..507a9529 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java @@ -1,5 +1,7 @@ package com.moing.backend.domain.missionState.domain.service; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; import com.moing.backend.global.annotation.DomainService; @@ -27,5 +29,9 @@ public List findFinishMission() { return missionStateRepository.findFinishMission().orElseThrow(NotFoundMissionStateException::new); } + public MissionState findMissionState(Member member, Mission mission) { + return missionStateRepository.findMissionStateByMemberAndMission(member, mission).orElseThrow(NotFoundMissionStateException::new); + } + } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 410119f4..cc139084 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -41,6 +41,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { @MockBean private MissionArchiveReadUseCase missionArchiveReadUseCase; @MockBean + private MissionArchiveDeleteUseCase missionArchiveDeleteUseCase; + @MockBean private RepeatMissionArchiveReadUseCase repeatMissionArchiveReadUseCase; @MockBean private MissionHeartUseCase missionHeartUseCase; @@ -181,6 +183,44 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .andReturn(); } +@Test + public void 미션_인증_삭제() throws Exception { + //given + + Long output = 1L; + given(missionArchiveDeleteUseCase.deleteArchive(any(),any())).willReturn(output); + + Long teamId = 1L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/team/{teamId}/missions/{missionId}/archive",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(UPDATE_ARCHIVE_SUCCESS), + fieldWithPath("data").description("삭제한 미션 인증 아이디(무시)") + ) + ) + ) + .andReturn(); + + } @Test public void 나의_미션_인증_조회() throws Exception { From 8239eeb8703fa7b8c6bb82844e2874cd76834223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 13 Nov 2023 00:21:13 +0900 Subject: [PATCH 219/619] =?UTF-8?q?chore=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=82=AD=EC=A0=9C=20Api=20docs=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionArchive-API.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/docs/asciidoc/MissionArchive-API.adoc b/src/docs/asciidoc/MissionArchive-API.adoc index e70060cb..b6bfb4e1 100644 --- a/src/docs/asciidoc/MissionArchive-API.adoc +++ b/src/docs/asciidoc/MissionArchive-API.adoc @@ -12,6 +12,11 @@ operation::mission-archive-controller-test/미션_인증하기[snippets='http-re [[MissionArchive-재인증하기]] == 미션 재인증하기 operation::mission-archive-controller-test/미션_재인증하기[snipipets='http-request,path-parameters,request-fields,http-response,response-fields'] +--- + +[[MissionArchive-미션인증삭제]] +== 미션 인증 삭제 +operation::mission-archive-controller-test/미션_인증_삭제[snipipets='http-request,path-parameters,request-fields,http-response,response-fields'] --- From 33095797f2e4e94b13256c55f0e26750ead352df Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Mon, 13 Nov 2023 13:47:23 +0900 Subject: [PATCH 220/619] chore : update .gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b603f75b..da9e977b 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,6 @@ data.sql #### docs #### !**/src/main/resources/static/docs/ -*.html \ No newline at end of file +*.html + +firebase-key.json From 8acd931c59de6e69dfa061eda9d73eac88260c3e Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 13 Nov 2023 22:50:18 +0900 Subject: [PATCH 221/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EB=95=8C=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=EB=90=9C=20=EA=B2=83=EB=8F=84=20=EC=A1=B0=ED=9A=8C=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/TeamCustomRepositoryImpl.java | 10 ++++------ .../domain/team/domain/service/TeamGetService.java | 2 +- .../com/moing/backend/global/util/StartupRunner.java | 7 +++++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index 8fa7606e..3b170f51 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -36,7 +36,6 @@ public GetTeamResponse findTeamByMemberId(Long memberId) { @Override public Optional findTeamByTeamId(Long teamId) { LocalDateTime threeDaysAgo = LocalDateTime.now().minusDays(3); - return Optional.ofNullable(queryFactory.selectFrom(team) .where(team.teamId.eq(teamId)) .where(team.isDeleted.eq(false) // 강제종료되지 않았거나 @@ -78,7 +77,7 @@ public List findMyPageTeamByMemberId(Long memberId) { private List getTeamBlock(Long memberId) { LocalDateTime threeDaysAgo = LocalDateTime.now().minusDays(3); - + return queryFactory .select(new QTeamBlock(team.teamId, team.approvalTime, @@ -90,10 +89,9 @@ private List getTeamBlock(Long memberId) { .from(teamMember) .innerJoin(teamMember.team, team) .on(teamMember.member.memberId.eq(memberId)) - .where(teamMember.isDeleted.eq(false)) // 탈퇴하지 않았다면 - .where(team.isDeleted.eq(false) // 강제종료되지 않았거나 - .or(team.deletionTime.isNotNull() - .or(team.deletionTime.after(threeDaysAgo)))) // 강제종료된 경우 3일이 지나지 않았다면 + .where(teamMember.isDeleted.eq(false)// 탈퇴하지 않았다면 + .and(team.isDeleted.eq(false) // 강제종료되지 않았거나 + .or(team.deletionTime.after(threeDaysAgo))))// 강제종료된 경우 3일이 지나지 않았다면 .orderBy(team.approvalTime.asc()) .groupBy(team.teamId) .fetch(); diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index e5583318..980bca98 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -28,7 +28,7 @@ public List getTeamIdByMemberId(Long memberId) { } public Team getTeamByTeamId(Long teamId){ - return teamRepository.findTeamByTeamId(teamId).orElseThrow(()->new NotFoundByTeamIdException()); + return teamRepository.findTeamByTeamId(teamId).orElseThrow(NotFoundByTeamIdException::new); } public List getMyPageTeamBlockByMemberId(Long memberId){ diff --git a/src/main/java/com/moing/backend/global/util/StartupRunner.java b/src/main/java/com/moing/backend/global/util/StartupRunner.java index de40dc56..5fa2b867 100644 --- a/src/main/java/com/moing/backend/global/util/StartupRunner.java +++ b/src/main/java/com/moing/backend/global/util/StartupRunner.java @@ -32,5 +32,12 @@ public void run(String... args) throws Exception { Member test03=new Member(LocalDate.now(), "tester3@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester3", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester03"); memberSaveService.saveMember(test03); + + Member test04=new Member(LocalDate.now(), "tester4@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester4", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester04"); + memberSaveService.saveMember(test04); + + Member test05=new Member(LocalDate.now(), "tester5@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester5", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester05"); + memberSaveService.saveMember(test05); + } } From b0194f2f2d112ec121ab43603ebc6f41ed68fcaa Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 13 Nov 2023 23:14:08 +0900 Subject: [PATCH 222/619] =?UTF-8?q?fix:=20=EA=B5=AC=EA=B8=80=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/google/GoogleSignInUserCase.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java index 13c452d9..42bcbd67 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java @@ -29,10 +29,13 @@ public Member getUserData(String accessToken) { .bodyToMono(GoogleUserResponse.class) .block(); - googleTokenUserCase.verifyAccessToken(googleUserResponse.getAud()); +// googleTokenUserCase.verifyAccessToken(googleUserResponse.getAud()); - googleUserResponse.adaptResponse(); - return memberMapper.createGoogleMember(googleUserResponse); + if (googleUserResponse != null) { + googleUserResponse.adaptResponse(); + return memberMapper.createGoogleMember(googleUserResponse); + } + return null; } From 79880c0fc1c7ffacbe080a837e35cf84a02db9bf Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 13 Nov 2023 23:39:05 +0900 Subject: [PATCH 223/619] =?UTF-8?q?fix:=20=EA=B5=AC=EA=B8=80=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=ED=86=A0=ED=81=B0=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/google/GoogleSignInUserCase.java | 11 ++++++----- .../service/google/GoogleTokenUserCase.java | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java index 13c452d9..8db12737 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java @@ -29,11 +29,12 @@ public Member getUserData(String accessToken) { .bodyToMono(GoogleUserResponse.class) .block(); - googleTokenUserCase.verifyAccessToken(googleUserResponse.getAud()); - - googleUserResponse.adaptResponse(); - return memberMapper.createGoogleMember(googleUserResponse); + if (googleUserResponse != null) { + googleTokenUserCase.verifyAccessToken(googleUserResponse.getAud()); + googleUserResponse.adaptResponse(); + return memberMapper.createGoogleMember(googleUserResponse); + } + throw new TokenInvalidException(); } - } diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java index b61cf800..653e7c71 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java @@ -18,7 +18,7 @@ public class GoogleTokenUserCase { public void verifyAccessToken(String aud) { String extractedAppId = Arrays.stream(aud.split("-")) .findFirst() - .orElseThrow(() -> new TokenInvalidException()); + .orElseThrow(TokenInvalidException::new); if (!appId.equals(extractedAppId)) throw new AppIdInvalidException(); } From a6f7150bb1a4a8234b5148a550c0d65781a788be Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 00:19:51 +0900 Subject: [PATCH 224/619] =?UTF-8?q?feat=20:=20cronTab=20=EC=9D=84=20?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=ED=95=9C=20=EB=AF=B8=EC=85=98=20=EB=A7=88?= =?UTF-8?q?=EA=B0=90=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../service/MissionCheckScheduler.java | 4 - .../MissionStateTerminateBatchConfig.java | 96 +++++++++++++++++++ .../service/MissionTerminateConfig.java | 94 ++++++++++++++++++ .../service/MissionTerminationUseCase.java | 1 + .../domain/entity/constant/MissionStatus.java | 3 +- .../repository/MissionCustomRepository.java | 2 + .../MissionCustomRepositoryImpl.java | 11 +++ .../domain/service/MissionQueryService.java | 5 + .../service/MissionStateScheduleUseCase.java | 57 +++++++++-- 10 files changed, 261 insertions(+), 14 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionStateTerminateBatchConfig.java create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminateConfig.java diff --git a/build.gradle b/build.gradle index bd351e8c..2fd7bb34 100644 --- a/build.gradle +++ b/build.gradle @@ -40,6 +40,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-batch' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' @@ -90,6 +91,7 @@ dependencies { implementation platform('software.amazon.awssdk:bom:2.17.230') implementation 'software.amazon.awssdk:s3' + } tasks.named('test') { diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java deleted file mode 100644 index 824407a3..00000000 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.moing.backend.domain.mission.application.service; - -public class MissionCheckScheduler { -} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionStateTerminateBatchConfig.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionStateTerminateBatchConfig.java new file mode 100644 index 00000000..4e4885e2 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionStateTerminateBatchConfig.java @@ -0,0 +1,96 @@ +//package com.moing.backend.domain.mission.application.service; +// +//import com.moing.backend.domain.mission.domain.entity.Mission; +//import com.moing.backend.domain.missionState.domain.entity.MissionState; +//import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; +//import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +//import lombok.RequiredArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.batch.core.Job; +//import org.springframework.batch.core.Step; +//import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +//import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; +//import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +//import org.springframework.batch.core.configuration.annotation.StepScope; +//import org.springframework.batch.item.ItemProcessor; +//import org.springframework.batch.item.database.JpaItemWriter; +//import org.springframework.batch.item.database.JpaPagingItemReader; +//import org.springframework.batch.item.database.builder.JpaItemWriterBuilder; +//import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +// +//import javax.persistence.EntityManagerFactory; +//import java.util.HashMap; +//import java.util.Map; +// +//@Slf4j +//@Configuration +//@EnableBatchProcessing +//@RequiredArgsConstructor +//public class MissionStateTerminateBatchConfig { +// +// private final JobBuilderFactory jobBuilderFactory; +// private final StepBuilderFactory stepBuilderFactory; +// private final EntityManagerFactory entityManagerFactory; +// +// private final TeamScoreLogicUseCase teamScoreLogicUseCase; +// private final MissionStateDeleteService missionStateDeleteService; +// +// @Bean +// public Job missionTerminateJob() { +// return jobBuilderFactory.get("missionTerminateJob") +// .start(missionTerminateStep()) +// .build(); +// } +// +// @Bean +// public Step missionTerminateStep() { +// return stepBuilderFactory.get("missionTerminateStep") +// .chunk(10) +// .reader(missionReader()) +// .processor(missionProcessor()) +// .writer(missionWriter()) +// .reader(missionStateReader()) +// .processor(missionStateProcessor()) +// .writer(missionStateWriter()) +// .build(); +// } +// +// @Bean +// @StepScope +// public JpaPagingItemReader missionStateReader() { +// +// Map parameterValues = new HashMap<>(); +// parameterValues.put("missionId", 10000); +// +// .parameterValues(parameterValues) // 쿼리 파라미터 설정 +// +// return new JpaPagingItemReaderBuilder() +// .name("missionStateReader") +// .entityManagerFactory(entityManagerFactory) +// .queryString("SELECT m FROM MissionState m WHERE m.mission_id = :missionId") +// .pageSize(10) +// .build(); +// } +// +// @Bean +// public ItemProcessor missionStateProcessor() { +// return mission -> { +// teamScoreLogicUseCase.updateTeamScore(mission.getId()); +// return mission; +// }; +// } +// +// +// +// @Bean +// public JpaItemWriter missionStateWriter() { +// return new JpaItemWriterBuilder() +// .entityManagerFactory(entityManagerFactory) +// .build(); +// } +// +// +// +//} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminateConfig.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminateConfig.java new file mode 100644 index 00000000..836a5aff --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminateConfig.java @@ -0,0 +1,94 @@ +//package com.moing.backend.domain.mission.application.service; +// +//import com.moing.backend.domain.mission.domain.entity.Mission; +//import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +//import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +//import com.moing.backend.domain.missionState.application.service.MissionStateScheduleUseCase; +//import com.moing.backend.domain.missionState.domain.entity.MissionState; +//import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; +//import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +//import lombok.RequiredArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.batch.core.Job; +//import org.springframework.batch.core.Step; +//import org.springframework.batch.core.configuration.annotation.*; +//import org.springframework.batch.item.ItemProcessor; +//import org.springframework.batch.item.database.JpaItemWriter; +//import org.springframework.batch.item.database.JpaPagingItemReader; +//import org.springframework.batch.item.database.builder.JpaItemWriterBuilder; +//import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +// +//import javax.persistence.EntityManagerFactory; +//import java.util.HashMap; +//import java.util.Map; +//import java.util.Optional; +// +//import static com.moing.backend.domain.mission.domain.entity.QMission.mission; +// +//@Slf4j +//@Configuration +//@EnableBatchProcessing +//@RequiredArgsConstructor +//public class MissionTerminateBatchConfig { +// +// private final JobBuilderFactory jobBuilderFactory; +// private final StepBuilderFactory stepBuilderFactory; +// private final EntityManagerFactory entityManagerFactory; +// +// private final TeamScoreLogicUseCase teamScoreLogicUseCase; +// private final MissionStateDeleteService missionStateDeleteService; +// private final MissionStateScheduleUseCase missionStateScheduleUseCase; +// +// @Bean +// public Job missionTerminateJob() { +// return jobBuilderFactory.get("missionTerminateJob") +// .start(missionTerminateStep()) +// .build(); +// } +// +// @Bean +// public Step missionTerminateStep() { +// return stepBuilderFactory.get("missionTerminateStep") +// .chunk(10) +// .reader(missionReader()) +// .processor(missionProcessor()) +// .writer(missionWriter()) +// .build(); +// } +// +// @Bean +// @StepScope +// public JpaPagingItemReader missionReader() { +// return new JpaPagingItemReaderBuilder() +// .name("missionReader") +// .entityManagerFactory(entityManagerFactory) +// .queryString("SELECT m FROM Mission m WHERE m.status = 'ONGOING' AND m.type = 'REPEAT'") +// .pageSize(10) +// .build(); +// } +// +// @Bean +// public ItemProcessor missionProcessor() { +// return mission -> { +// teamScoreLogicUseCase.updateTeamScore(mission.getId()); +// return mission; +// }; +// } +// +// +// +// @Bean +// public JpaItemWriter teamScoreWriter() { +// missionStateScheduleUseCase.missionStateReset(); +// return new JpaItemWriterBuilder() +// .entityManagerFactory(entityManagerFactory) +// .build(); +// } +// +// +// +// +// +//} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java index 18866d60..243582d5 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java @@ -33,6 +33,7 @@ public void terminateMission() { // 미션 점수 반영 -> MissionState + // MissionState 조회 해서 미션 점수 현황조회 public void getMissionScoreStatus() { diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java index 07007a45..55f18654 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/constant/MissionStatus.java @@ -9,5 +9,6 @@ public enum MissionStatus { END, ONGOING, SUCCESS, - FAIL + FAIL, + WAIT } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index 45b842f0..4ba36e8a 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -21,6 +21,8 @@ public interface MissionCustomRepository { Optional> findOngoingRepeatMissions(); + Optional> findRepeatMissionByStatus(MissionStatus missionStatus); + boolean findRepeatMissionsByTeamId(Long teamId); diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 0511444d..79691e0e 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -84,6 +84,17 @@ public Optional> findOngoingRepeatMissions() { .fetch()); } + @Override + public Optional> findRepeatMissionByStatus(MissionStatus missionStatus) { + return Optional.ofNullable(queryFactory + .select(mission) + .from(mission) + .where(mission.status.eq(missionStatus), + mission.type.eq(MissionType.REPEAT)) + .fetch()); + } + + @Override public Optional> findSingleMissionByMemberId(Long memberId, List teams) { return Optional.ofNullable(queryFactory diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 3190e252..ef0a716b 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -70,4 +70,9 @@ public List findOngoingRepeatMissions() { public boolean isAbleCreateRepeatMission(Long teamId) { return missionRepository.findRepeatMissionsByTeamId(teamId); } + + public List findMissionByStatus(MissionStatus missionStatus) { + return missionRepository.findRepeatMissionByStatus(missionStatus).orElseThrow(NotFoundMissionException::new + ); + } } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 833f3a4c..15646366 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -9,6 +9,8 @@ import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -18,6 +20,7 @@ @Slf4j @Service @Transactional +@EnableScheduling // 스케줄링 활성화 @RequiredArgsConstructor public class MissionStateScheduleUseCase { @@ -28,7 +31,11 @@ public class MissionStateScheduleUseCase { private final TeamScoreLogicUseCase teamScoreLogicUseCase; - // 스케쥴러에 쓰면 됨. + /** + * 반복미션 마감 + * 일요일 마감 루틴 + */ + @Scheduled(cron = "0 59 23 * * SUN") public void sundayRepeatMissionRoutine() { // 모든 진행중인 반복 미션 모아서 @@ -41,27 +48,59 @@ public void sundayRepeatMissionRoutine() { // 미션 state 에서 지우기 ( 이것도 대용량 ) missionStateReset(ongoingRepeatMissions); } + public void missionStateReset(List missionIds) { List missionStates = missionStateQueryService.findByMissionId(missionIds); missionStateDeleteService.deleteMissionState(missionStates); } - // 한시간마다 실행 - // 미션 단위 - public void singleMissionEndRoutineByMission() { - Mission mission = new Mission(); +// /** +// * 단일 미션 마감 +// * 미션 단위 마감 +// * 한시간 마다 실행 +// */ +// public void singleMissionEndRoutineByMission() { +// +// Mission mission = new Mission(); +// LocalDateTime now = LocalDateTime.now(); +// +// if (mission.getDueTo().isAfter(now)) { +// mission.updateStatus(MissionStatus.END); +// teamScoreLogicUseCase.updateTeamScore(mission.getId()); +// } +// } + + /** + * 단일 미션 마감 + * 해당 시간 미션 마감 + * 한시간 마다 실행 + */ + @Scheduled(cron = "0 0 * * * *") + public void singleMissionEndRoutine() { LocalDateTime now = LocalDateTime.now(); - if (mission.getDueTo().isAfter(now)) { + List missionByDueTo = missionQueryService.findMissionByDueTo(); + + missionByDueTo.stream().forEach(mission -> { mission.updateStatus(MissionStatus.END); - } - } + teamScoreLogicUseCase.updateTeamScore(mission.getId()); + }); - public void singleMissionEndRoutine() { + } + /** + * 미션 시작 + * 월요일 아침 + */ + @Scheduled(cron = "0 0 0 * * MON") + public void RepeatMissionStart() { + List startMission = missionQueryService.findMissionByStatus(MissionStatus.WAIT); + startMission.stream().forEach( + mission -> mission.updateStatus(MissionStatus.ONGOING) + ); } } From bb5dff962d07fa962635e13e217ece5218161035 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 03:09:05 +0900 Subject: [PATCH 225/619] =?UTF-8?q?feat=20:=20=EB=B6=88=EB=8D=98=EC=A7=80?= =?UTF-8?q?=EA=B8=B0=20FCM=20=EC=95=8C=EB=A6=BC=20=EB=B0=9C=EC=86=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/FireThrowUseCase.java | 34 ++++++++++++++++--- .../domain/repository/MemberRepository.java | 2 ++ .../domain/service/MemberGetService.java | 4 +++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java index 36d5175f..c33a2d8b 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -4,18 +4,21 @@ import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; import com.moing.backend.domain.fire.application.mapper.FireMapper; import com.moing.backend.domain.fire.domain.entity.Fire; -import com.moing.backend.domain.fire.domain.repository.FireCustomRepository; import com.moing.backend.domain.fire.domain.service.FireQueryService; import com.moing.backend.domain.fire.domain.service.FireSaveService; import com.moing.backend.domain.fire.exception.NoAuthThrowFireException; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.mission.application.service.MissionCreateUseCase; +import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +import com.moing.backend.global.config.fcm.service.FcmService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; +import static java.lang.Math.random; + @Service @Transactional @RequiredArgsConstructor @@ -25,16 +28,26 @@ public class FireThrowUseCase { public final FireQueryService fireQueryService; private final MemberGetService memberGetService; + private final FcmService fcmService; + public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { - Long throwMemberId = memberGetService.getMemberBySocialId(userId).getMemberId(); + Member throwMember = memberGetService.getMemberBySocialId(userId); + Member receiveMember = memberGetService.getMemberByMemberId(receiveMemberId); - if (!fireQueryService.hasFireCreatedWithinOneHour(throwMemberId, receiveMemberId)) { + if (!fireQueryService.hasFireCreatedWithinOneHour(throwMember.getMemberId(), receiveMemberId)) { throw new NoAuthThrowFireException(); } + String title = "어라… 왜 이렇게 발등이 뜨겁지?🤨"; + + String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), (int) random() * 2); + SingleRequest singleRequest = new SingleRequest(receiveMember.getFcmToken(), title, message); + + fcmService.sendSingleDevice(singleRequest); + return FireMapper.mapToFireThrowRes(fireSaveService.save(Fire.builder() - .throwMemberId(throwMemberId) + .throwMemberId(throwMember.getMemberId()) .receiveMemberId(receiveMemberId) .build())); } @@ -49,4 +62,15 @@ public List getFireReceiveList(String userId,Long teamId, Long m return fireReceiveRes; } + + public String getMessage(String pusher, String receiver, int num) { + + switch (num) { + case 0: return pusher + "님이" + receiver + "님에게 불을 던졌어요! 어서 미션을 인증해볼까요?"; + case 1: return receiver + "님! " + pusher + "님이 던진 불에 타버릴지도 몰라요! 어서 인증하러갈까요?"; + } + return pusher + "님이" + receiver + "님에게 불을 던졌어요! 어서 미션을 인증해볼까요?"; + } + + } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java index 20cb1f23..5d445dfc 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java @@ -11,4 +11,6 @@ public interface MemberRepository extends JpaRepository, MemberCus Optional findByEmail(String email); + Optional findByMemberId(Long id); + } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java index dc88284d..015ca6ea 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java @@ -17,4 +17,8 @@ public class MemberGetService { public Member getMemberBySocialId(String socialId){ return memberRepository.findBySocialId(socialId).orElseThrow(()->new NotFoundBySocialIdException()); } + + public Member getMemberByMemberId(Long memberId) { + return memberRepository.findByMemberId(memberId).orElseThrow(()->new NotFoundBySocialIdException()); + } } From fe62fe2b54eb2e504c2509c0f49ffd951393c231 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 03:14:04 +0900 Subject: [PATCH 226/619] =?UTF-8?q?feat=20:=20=ED=8C=80=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=8B=9C=20TeamScore=20=EC=97=94=ED=8B=B0=ED=8B=B0?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CreateTeamUserCase.java | 5 +++++ .../application/mapper/TeamScoreMapper.java | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/teamScore/application/mapper/TeamScoreMapper.java diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java index 6513c478..262e7a8b 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java @@ -8,6 +8,8 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamSaveService; import com.moing.backend.domain.teamMember.domain.service.TeamMemberSaveService; +import com.moing.backend.domain.teamScore.application.mapper.TeamScoreMapper; +import com.moing.backend.domain.teamScore.domain.service.TeamScoreSaveService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -22,6 +24,8 @@ public class CreateTeamUserCase { private final TeamSaveService teamSaveService; private final TeamMemberSaveService teamMemberSaveService; private final TeamMapper teamMapper; + private final TeamScoreSaveService teamScoreSaveService; + private final TeamScoreMapper teamScoreMapper; public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String socialId){ Member member = memberGetService.getMemberBySocialId(socialId); @@ -31,6 +35,7 @@ public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String //====지워야 함 (테스트 용)===== team.approveTeam(); //====지워야 함 (테스트 용)===== + teamScoreSaveService.save(teamScoreMapper.mapToTeamScore(team)); // 팀스코어 엔티티 생성 return new CreateTeamResponse(team.getTeamId()); } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/mapper/TeamScoreMapper.java b/src/main/java/com/moing/backend/domain/teamScore/application/mapper/TeamScoreMapper.java new file mode 100644 index 00000000..49031bc2 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/application/mapper/TeamScoreMapper.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.teamScore.application.mapper; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.global.annotation.Mapper; +import org.springframework.stereotype.Component; + +@Component +public class TeamScoreMapper { + + public TeamScore mapToTeamScore(Team team) { + return TeamScore.builder() + .score(0L) + .level(1L) + .team(team) + .build(); + } + +} From 80f95adf73ab4b7674a422288bbf4f5161c22189 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 03:18:23 +0900 Subject: [PATCH 227/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EB=AF=B8=EC=85=98=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20WAIT=EC=9C=BC=EB=A1=9C,=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=B2=AB=20=EC=9D=B8=EC=A6=9D=EC=8B=9C=20?= =?UTF-8?q?ONGOING=20=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20=EB=B0=98?= =?UTF-8?q?=EB=B3=B5=20=EB=AF=B8=EC=85=98=EC=9D=80=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A5=B4=EB=A7=81=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionCreateUseCase.java | 2 +- .../application/service/MissionArchiveCreateUseCase.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index c5a433b4..37cf873e 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -39,7 +39,7 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR // 소모임 장 확인 if (member.getMemberId().equals(team.getLeaderId())) { - Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.ONGOING); + Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.WAIT); // teamRepository 변경 예정 if (mission.getType() == MissionType.REPEAT && missionQueryService.isAbleCreateRepeatMission(team.getTeamId())) { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index c66694a3..939ca306 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -52,10 +52,15 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss MissionArchive newArchive = MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission); + // 단일 미션인 경우 미션 인증 시도 시 ongoing 으로 변경 + if (mission.getType() == MissionType.ONCE && mission.getStatus() == MissionStatus.WAIT) { + mission.updateStatus(MissionStatus.ONGOING); + } // 인증 완료한 미션인지 확인 if (isDoneMission(memberId,mission)) { throw new NoMoreMissionArchiveException(); } + // 반복 미션일 경우 if (mission.getType() == MissionType.REPEAT) { // 당일 1회 인증만 가능 From f554cd5a9a7b057e8f2087f435ae17047eb325a4 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 03:20:55 +0900 Subject: [PATCH 228/619] =?UTF-8?q?feat=20:=20=EC=98=88=EC=A0=95=EB=90=9C?= =?UTF-8?q?=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=EC=A0=91=EA=B7=BC=20?= =?UTF-8?q?=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveCreateUseCase.java | 5 +++++ .../exception/NotYetMissionArchiveException.java | 12 ++++++++++++ .../com/moing/backend/global/response/ErrorCode.java | 1 + 3 files changed, 18 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/exception/NotYetMissionArchiveException.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 939ca306..5a1463fd 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -15,6 +15,7 @@ import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; +import com.moing.backend.domain.missionArchive.exception.NotYetMissionArchiveException; import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; @@ -63,6 +64,10 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss // 반복 미션일 경우 if (mission.getType() == MissionType.REPEAT) { + // 예정된 반복미션 접근 제한 + if (mission.getStatus() == MissionStatus.WAIT) { + throw new NotYetMissionArchiveException(); + } // 당일 1회 인증만 가능 if(!missionArchiveQueryService.findDoneTodayArchive(memberId,missionId)) newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/exception/NotYetMissionArchiveException.java b/src/main/java/com/moing/backend/domain/missionArchive/exception/NotYetMissionArchiveException.java new file mode 100644 index 00000000..25c87401 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/exception/NotYetMissionArchiveException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.missionArchive.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotYetMissionArchiveException extends MissionArchiveException { + + public NotYetMissionArchiveException() { + super(ErrorCode.NOT_YET_MISSION_ARCHIVE, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 28fe9bd0..eeb255ca 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -31,6 +31,7 @@ public enum ErrorCode { NOT_FOUND_END_MISSION("M0003", "기한이 지난 미션을 찾을 수 없습니다."), NO_MORE_CREATE_MISSION("M0004", "반복미션은 3개까지 생성할 수 있습니다."), NOT_FOUND_MISSION_ARCHIVE("MA0001", "아직 미션을 제출하지 않았습니다."), + NOT_YET_MISSION_ARCHIVE("MA0001", "아직 미션을 제출할 수 없습니다."), NO_MORE_ARCHIVE_ERROR("MA0001", "지정한 횟수 이상 미션을 인증할 수 없습니다."), //불던지기 관련 에러 코드 From 328d3ece7cf45f25f24a46a48ab5ce11c9f45382 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 03:26:43 +0900 Subject: [PATCH 229/619] =?UTF-8?q?fix=20:=20=EB=82=98=EC=97=90=EA=B2=8C?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=EB=AC=BC=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20=EB=88=84=EB=A5=BC=20=EC=88=98=20=EC=97=86?= =?UTF-8?q?=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionHeartUseCase.java | 4 ++++ .../missionHeart/exception/MissionHeartException.java | 11 +++++++++++ .../exception/NoAccessMissionHeartException.java | 11 +++++++++++ .../com/moing/backend/global/response/ErrorCode.java | 2 ++ 4 files changed, 28 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/exception/MissionHeartException.java create mode 100644 src/main/java/com/moing/backend/domain/missionHeart/exception/NoAccessMissionHeartException.java diff --git a/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java b/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java index 86304259..1b296ce7 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/application/service/MissionHeartUseCase.java @@ -10,6 +10,7 @@ import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartSaveService; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartUpdateService; +import com.moing.backend.domain.missionHeart.exception.NoAccessMissionHeartException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,6 +33,9 @@ public MissionHeartRes pushHeart(String socialId,Long archiveId, String status) MissionArchive archive = missionArchiveQueryService.findByMissionArchiveId(archiveId); MissionHeart missionHeart = MissionHeartMapper.mapToMissionHeart(memberId, archive, MissionHeartStatus.valueOf(status)); + if (memberId.equals(missionHeart.getMissionArchive().getMember().getMemberId())){ + throw new NoAccessMissionHeartException(); + } if(missionHeartQueryService.isAlreadyHeart(memberId, archiveId)) { return MissionHeartMapper.mapToMissionHeartRes( missionHeartUpdateService.update(missionHeart)); diff --git a/src/main/java/com/moing/backend/domain/missionHeart/exception/MissionHeartException.java b/src/main/java/com/moing/backend/domain/missionHeart/exception/MissionHeartException.java new file mode 100644 index 00000000..f085efe1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/exception/MissionHeartException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.missionHeart.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class MissionHeartException extends ApplicationException { + protected MissionHeartException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionHeart/exception/NoAccessMissionHeartException.java b/src/main/java/com/moing/backend/domain/missionHeart/exception/NoAccessMissionHeartException.java new file mode 100644 index 00000000..01fdcde8 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionHeart/exception/NoAccessMissionHeartException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.missionHeart.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NoAccessMissionHeartException extends MissionHeartException { + public NoAccessMissionHeartException() { + super(ErrorCode.NO_ACCESS_HEART_FOR_ME, HttpStatus.NOT_FOUND); + + } +} diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index eeb255ca..71d070ba 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -39,6 +39,8 @@ public enum ErrorCode { NOT_FOUND_FIRE_RECEIVERS("F001","불던지기를 받을 사람을 찾을 수 없습니다"), NOT_AUTH_FIRE_THROW("F002","1시간 이내에 불던지기를 할 수 없습니다"), + NO_ACCESS_HEART_FOR_ME("MH001", "나에게 좋아요를 누를 수 없습니다"), + //팀 관련 에러 코드 NOT_FOUND_BY_TEAM_ID_ERROR("T0001", "해당 teamId인 팀이 존재하지 않습니다."), NOT_AUTH_BY_TEAM_ERROR("T0002","권한이 없습니다."), From 4134040db79d5d0feb73bbefcd17826c46e17f2b Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 03:46:51 +0900 Subject: [PATCH 230/619] =?UTF-8?q?fix=20:=20=EA=B2=BD=ED=97=98=EC=B9=98/?= =?UTF-8?q?=20=EB=AA=A8=EC=9E=89=EB=B6=88=20=EB=A0=88=EB=B2=A8=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=A1=9C=EC=A7=81=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moing/backend/domain/teamScore/domain/entity/TeamScore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index a37f311e..6fd0fb49 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -41,7 +41,7 @@ public void levelUp() { // 0부터 시작하기 때문에 무조건 0에서 걸림. for (int i = 5; i > 0; i--) { - if (steps[i] <= this.level && this.level <= steps[i - 1]) { + if (steps[i-1] <= this.level && this.level <= steps[i]) { if (20 + (i-1) * 15 <= score) { // 여길 들어가질 않음 this.level+=1; this.score -= (20 + (i-1) * 15); From f916eb62093648de038491bd0313bb7508a86264 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 03:53:10 +0900 Subject: [PATCH 231/619] =?UTF-8?q?fix=20:=20=EB=82=98=EC=97=90=EA=B2=8C?= =?UTF-8?q?=20=EB=B6=88=EB=8D=98=EC=A7=80=EA=B8=B0=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/fire/application/service/FireThrowUseCase.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java index c33a2d8b..2c0bd8d0 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -35,6 +35,12 @@ public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { Member throwMember = memberGetService.getMemberBySocialId(userId); Member receiveMember = memberGetService.getMemberByMemberId(receiveMemberId); + // 나에게 던질 수 없음 + if (throwMember.equals(receiveMember)) { + throw new NoAuthThrowFireException(); + } + + // 1시간전 불 던진 기록이 있다면, 던질 수 없음 if (!fireQueryService.hasFireCreatedWithinOneHour(throwMember.getMemberId(), receiveMemberId)) { throw new NoAuthThrowFireException(); } From 5dfbb6ab0497380621862a01fd9320f46ab74d18 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 13:16:07 +0900 Subject: [PATCH 232/619] =?UTF-8?q?feat=20:=20=ED=95=9C=EB=B2=88=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=83=9D=EC=84=B1=EC=8B=9C=20=ED=91=B8?= =?UTF-8?q?=EC=8B=9C=20=EC=95=8C=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionCreateUseCase.java | 12 ++++- .../SendMissionCreateAlarmUseCase.java | 44 +++++++++++++++++++ .../config/fcm/constant/NewMissionTitle.java | 13 ++++++ .../fcm/constant/RemindMissionTitle.java | 4 ++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/constant/NewMissionTitle.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index c5a433b4..63b9a26c 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -17,6 +17,9 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.repository.TeamRepository; import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +import com.moing.backend.global.config.fcm.service.FcmService; import com.moing.backend.global.util.SecurityUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -31,6 +34,7 @@ public class MissionCreateUseCase { private final MissionQueryService missionQueryService; private final TeamGetService teamGetService; private final MemberGetService memberGetService; + private final SendMissionCreateAlarmUseCase sendMissionCreateAlarmUseCase; public MissionCreateRes createMission(String userSocialId, Long teamId, MissionReq missionReq) { @@ -47,6 +51,12 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR } mission.setTeam(team); missionSaveService.save(mission); + + // 단일 미션 최초 1회 알림 + if (mission.getType().equals(MissionType.ONCE)) { + sendMissionCreateAlarmUseCase.sendNewMissionUploadAlarm(member, mission); + } + return MissionMapper.mapToMissionCreateRes(mission); } else{ @@ -54,8 +64,6 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR } - - } public MissionRecommendRes getCategoryByTeam(Long teamId) { diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java new file mode 100644 index 00000000..3edc96e8 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java @@ -0,0 +1,44 @@ +package com.moing.backend.domain.mission.application.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.service.FcmService; +import com.moing.backend.global.response.BaseServiceResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; + +import static com.moing.backend.global.config.fcm.constant.NewMissionTitle.NEW_SINGLE_MISSION_COMING; +import static com.moing.backend.global.config.fcm.constant.NewUploadTitle.UPLOAD_NOTICE_NEW_TITLE; + +@Service +@Transactional +@RequiredArgsConstructor +public class SendMissionCreateAlarmUseCase { + + private final TeamMemberGetService teamMemberGetService; + private final FcmService fcmService; + + public void sendNewMissionUploadAlarm(Member member, Mission mission) { + Team team = mission.getTeam(); + Optional> fcmTokensExceptMe = teamMemberGetService.getFcmTokensExceptMe(team.getTeamId(), member.getMemberId()); + + String title = team.getName() + " " + NEW_SINGLE_MISSION_COMING.getTitle(); + String message = mission.getTitle(); + + Optional> fcmTokens = teamMemberGetService.getFcmTokensExceptMe(team.getTeamId(), member.getMemberId()); + if (fcmTokens.isPresent() && !fcmTokens.get().isEmpty()) { + MultiRequest toMultiRequest = new MultiRequest(fcmTokens.get(), title, message); + fcmService.sendMultipleDevices(toMultiRequest); + + } + } +} + diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/NewMissionTitle.java b/src/main/java/com/moing/backend/global/config/fcm/constant/NewMissionTitle.java new file mode 100644 index 00000000..9bb30c20 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/NewMissionTitle.java @@ -0,0 +1,13 @@ +package com.moing.backend.global.config.fcm.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum NewMissionTitle { + + NEW_SINGLE_MISSION_COMING("의 새로운 미션이 등장했어요! "), + NEW_REPEAT_MISSION_COMING("의 새로운 반복미션이 시작되었어요! "); + private final String title; +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java new file mode 100644 index 00000000..9046e84b --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java @@ -0,0 +1,4 @@ +package com.moing.backend.global.config.fcm.constant; + +public class RemindMissionTitle { +} From 8e99c951ec9d85eb5424ac9be4e4ca98756053a2 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 13:36:49 +0900 Subject: [PATCH 233/619] =?UTF-8?q?fix=20:=20=EB=B6=88=EB=8D=98=EC=A7=80?= =?UTF-8?q?=EA=B8=B0=20=ED=91=B8=EC=8B=9C=20=EC=95=8C=EB=A6=BC=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/FireThrowAlarmUseCase.java | 51 +++++++++++++++++++ .../application/service/FireThrowUseCase.java | 18 +------ .../config/fcm/constant/FireThrowMessage.java | 23 +++++++++ 3 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/constant/FireThrowMessage.java diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java new file mode 100644 index 00000000..54259efb --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -0,0 +1,51 @@ +package com.moing.backend.domain.fire.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +import com.moing.backend.global.config.fcm.service.FcmService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +import static com.moing.backend.global.config.fcm.constant.FireThrowMessage.*; +import static java.lang.Math.random; + +@Service +@Transactional +@RequiredArgsConstructor +public class FireThrowAlarmUseCase { + + private final FcmService fcmService; + + public void sendFireThrowAlarm(Member throwMember, Member receiveMember) { + String title = getTitle(throwMember.getNickName(), receiveMember.getNickName(), (int) random() * 2); + + String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), (int) random() * 2); + SingleRequest singleRequest = new SingleRequest(receiveMember.getFcmToken(), title, message); + + fcmService.sendSingleDevice(singleRequest); + } + + public String getMessage(String pusher, String receiver, int num) { + + switch (num) { + case 0: return pusher + "님이" + receiver + NEW_FIRE_THROW_MESSAGE1.getMessage(); + case 1: return receiver + "님! " + pusher + NEW_FIRE_THROW_MESSAGE2.getMessage(); + } + return pusher + "님이" + receiver + NEW_FIRE_THROW_MESSAGE1.getMessage(); + } + + public String getTitle(String pusher, String receiver, int num) { + + switch (num) { + case 0: + return NEW_FIRE_THROW_TITLE1.getMessage(); + case 1: + return NEW_FIRE_THROW_TITLE2.getMessage(); + } + return NEW_FIRE_THROW_TITLE1.getMessage(); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java index 2c0bd8d0..1f07c6fe 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -28,7 +28,7 @@ public class FireThrowUseCase { public final FireQueryService fireQueryService; private final MemberGetService memberGetService; - private final FcmService fcmService; + private final FireThrowAlarmUseCase fireThrowAlarmUseCase; public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { @@ -45,12 +45,7 @@ public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { throw new NoAuthThrowFireException(); } - String title = "어라… 왜 이렇게 발등이 뜨겁지?🤨"; - - String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), (int) random() * 2); - SingleRequest singleRequest = new SingleRequest(receiveMember.getFcmToken(), title, message); - - fcmService.sendSingleDevice(singleRequest); + fireThrowAlarmUseCase.sendFireThrowAlarm(throwMember, receiveMember); return FireMapper.mapToFireThrowRes(fireSaveService.save(Fire.builder() .throwMemberId(throwMember.getMemberId()) @@ -69,14 +64,5 @@ public List getFireReceiveList(String userId,Long teamId, Long m return fireReceiveRes; } - public String getMessage(String pusher, String receiver, int num) { - - switch (num) { - case 0: return pusher + "님이" + receiver + "님에게 불을 던졌어요! 어서 미션을 인증해볼까요?"; - case 1: return receiver + "님! " + pusher + "님이 던진 불에 타버릴지도 몰라요! 어서 인증하러갈까요?"; - } - return pusher + "님이" + receiver + "님에게 불을 던졌어요! 어서 미션을 인증해볼까요?"; - } - } diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/FireThrowMessage.java b/src/main/java/com/moing/backend/global/config/fcm/constant/FireThrowMessage.java new file mode 100644 index 00000000..dbfb2f79 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/FireThrowMessage.java @@ -0,0 +1,23 @@ +package com.moing.backend.global.config.fcm.constant; + + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum FireThrowMessage { + + NEW_FIRE_THROW_TITLE1("어라… 왜 이렇게 발등이 뜨겁지?\uD83E\uDD28"), + NEW_FIRE_THROW_TITLE2("⚠\uFE0F불조심⚠\uFE0F "), + + + NEW_FIRE_THROW_MESSAGE1("님에게 불을 던졌어요! 어서 미션을 인증해볼까요?"), + NEW_FIRE_THROW_MESSAGE2("님이 던진 불에 타버릴지도 몰라요! 어서 인증하러갈까요?"); + + + + private final String message; + + +} From c7edc266637fc5b5446274c23d22ad3ecb3d786f Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 14:05:09 +0900 Subject: [PATCH 234/619] =?UTF-8?q?feat=20:=20=EC=98=A4=EC=A0=84=208?= =?UTF-8?q?=EC=8B=9C=20=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20(=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=20=EB=85=BC=EC=9D=98=EC=A4=91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/FireThrowAlarmUseCase.java | 8 ++- .../service/MissionRemindAlarmUseCase.java | 62 +++++++++++++++++++ .../fcm/constant/RemindMissionTitle.java | 23 ++++++- 3 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java index 54259efb..83eb1b25 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -8,6 +8,8 @@ import javax.transaction.Transactional; +import java.util.Random; + import static com.moing.backend.global.config.fcm.constant.FireThrowMessage.*; import static java.lang.Math.random; @@ -19,9 +21,11 @@ public class FireThrowAlarmUseCase { private final FcmService fcmService; public void sendFireThrowAlarm(Member throwMember, Member receiveMember) { - String title = getTitle(throwMember.getNickName(), receiveMember.getNickName(), (int) random() * 2); - String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), (int) random() * 2); + Random random = new Random(System.currentTimeMillis()); + String title = getTitle(throwMember.getNickName(), receiveMember.getNickName(), random.nextInt(2)); + + String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), random.nextInt(2)); SingleRequest singleRequest = new SingleRequest(receiveMember.getFcmToken(), title, message); fcmService.sendSingleDevice(singleRequest); diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java new file mode 100644 index 00000000..61fb3d1e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -0,0 +1,62 @@ +package com.moing.backend.domain.mission.application.service; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.service.FcmService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +import java.util.Random; + +import static com.moing.backend.global.config.fcm.constant.RemindMissionTitle.*; +import static java.lang.Math.random; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionRemindAlarmUseCase { + + private final FcmService fcmService; + + public void sendRemindMissionAlarm(Mission mission) { + + Random random = new Random(System.currentTimeMillis()); + + String title = getTitle("receiver",random.nextInt(4)); + String message = getMessage(mission.getTitle(),random.nextInt(4)); + + MultiRequest multiRequest = new MultiRequest(); + } + + public String getTitle(String receiver, int num) { + switch (num) { + case 0: + return receiver + REMIND_MISSION_TITLE1.getMessage(); + case 1: + return receiver + REMIND_MISSION_TITLE2.getMessage(); + case 2: + return receiver + REMIND_MISSION_TITLE3.getMessage(); + case 3: + return receiver + REMIND_MISSION_TITLE4.getMessage(); + } + return receiver + REMIND_MISSION_TITLE4.getMessage(); + + } + public String getMessage(String missionTitle, int num) { + switch (num) { + case 0: + return missionTitle + REMIND_MISSION_MESSAGE1.getMessage(); + case 1: + return missionTitle + REMIND_MISSION_MESSAGE2.getMessage(); + case 2: + return missionTitle + REMIND_MISSION_MESSAGE3.getMessage(); + case 3: + return missionTitle + REMIND_MISSION_MESSAGE4.getMessage(); + } + return missionTitle + REMIND_MISSION_MESSAGE4.getMessage(); + + } + +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java index 9046e84b..d387ca59 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java @@ -1,4 +1,23 @@ package com.moing.backend.global.config.fcm.constant; -public class RemindMissionTitle { -} +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum RemindMissionTitle { + + REMIND_MISSION_TITLE1("님, 오늘도 좋은하루!"), + REMIND_MISSION_TITLE2("님, 잊으신 건 아니죠?\uD83D\uDC40"), + REMIND_MISSION_TITLE3("님, 좋은 아침이에요! ☀\uFE0F"), + REMIND_MISSION_TITLE4("오늘의 열정이 타오르불\uD83D\uDD25"), + + + REMIND_MISSION_MESSAGE1(" 도전과 함께⚡\uFE0F "), + REMIND_MISSION_MESSAGE2(" 인증을 모임원들이 기다리고 있어요!"), + REMIND_MISSION_MESSAGE3(" 수행하고 이번주도 도전해요👊 "), + REMIND_MISSION_MESSAGE4(" 도전하고 성취감 뿜뿜💪 "); + + private final String message; + + } From 35a3abd032f4eb15c6e0fbc2bf638e0721f75aff Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 14 Nov 2023 23:30:40 +0900 Subject: [PATCH 235/619] =?UTF-8?q?feat=20:=20=EC=9D=BC=EC=9A=94=EC=9D=BC?= =?UTF-8?q?=20=EB=B0=A4=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=EB=A7=88?= =?UTF-8?q?=EA=B0=90=20=EB=A3=A8=ED=8B=B4=20=EB=B0=B0=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/RepeatMissionEnd.java | 94 +++++++++++++++++++ .../domain/mission/domain/entity/Mission.java | 4 + .../service/MissionArchiveDeleteUseCase.java | 5 +- .../service/MissionStateUseCase.java | 17 ++++ .../MissionStateCustomRepository.java | 1 + .../MissionStateCustomRepositoryImpl.java | 11 +++ .../service/MissionStateDeleteService.java | 6 ++ 7 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java b/src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java new file mode 100644 index 00000000..811b051f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java @@ -0,0 +1,94 @@ +package com.moing.backend.domain.mission.application.service; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; +import org.springframework.batch.core.configuration.annotation.JobScope; +import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.item.ItemProcessor; +import org.springframework.batch.item.database.JpaItemWriter; +import org.springframework.batch.item.database.JpaPagingItemReader; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.persistence.EntityManagerFactory; + +@Slf4j +@RequiredArgsConstructor +@Configuration +public class RepeatMissionEnd { + + public static final String JOB_NAME = "makeMissionEnd"; + + private final EntityManagerFactory entityManagerFactory; + private final StepBuilderFactory stepBuilderFactory; + private final JobBuilderFactory jobBuilderFactory; + + private final MissionStateUseCase missionStateUseCase; + private final TeamScoreLogicUseCase teamScoreLogicUseCase; + + private final int chunkSize = 10; + + @Bean + public Job payPagingJob() { + return jobBuilderFactory.get(JOB_NAME) + .start(payPagingStep()) + .build(); + } + + @Bean + @JobScope + public Step payPagingStep() { + return stepBuilderFactory.get("makeMissionEndStep") + .chunk(chunkSize) + .reader(payPagingReader()) + .processor(payPagingProcessor()) + .writer(writer()) + .build(); + } + + @Bean + @StepScope + public JpaPagingItemReader payPagingReader() { + + JpaPagingItemReader reader = new JpaPagingItemReader() { + @Override + public int getPage() { + return 0; + } + }; + + reader.setQueryString("SELECT m FROM Mission m WHERE m.status = 'ONGOING' AND m.type = 'REPEAT'"); + reader.setPageSize(chunkSize); + reader.setEntityManagerFactory(entityManagerFactory); + reader.setName("payPagingReader"); + + return reader; + } + + // sundayRepeatMissionRoutine() + @Bean + @StepScope + public ItemProcessor payPagingProcessor() { + return mission -> { + teamScoreLogicUseCase.updateTeamScore(mission.getId()); + missionStateUseCase.deleteAllMissionState(mission.getId()); + mission.makeEnd(); + return mission; + }; + } + + @Bean + @StepScope + public JpaItemWriter writer() { + JpaItemWriter writer = new JpaItemWriter<>(); + writer.setEntityManagerFactory(entityManagerFactory); + return writer; + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index 66177310..df199e4a 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -84,4 +84,8 @@ public void setTeam(Team team) { public void updateStatus(MissionStatus missionStatus) { this.status = missionStatus; } + + public void makeEnd() { + this.status = MissionStatus.END; + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java index 1ac31cec..d4df05e9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java @@ -58,10 +58,8 @@ public Long deleteArchive(String userSocialId, Long missionId) { Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); - // 사진 제출 했다면, + // 사진 제출 했다면, s3 삭제 로직 if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(memberId, missionId)) { - //s3삭제 - } @@ -70,6 +68,7 @@ public Long deleteArchive(String userSocialId, Long missionId) { MissionState missionState = missionStateQueryService.findMissionState(member, mission); missionStateDeleteService.deleteMissionState(missionState); + return deleteArchive.getId(); } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 41849b62..f3405ce6 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -6,6 +6,8 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionState.domain.entity.MissionState; +import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.team.domain.entity.Team; @@ -14,6 +16,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + @Slf4j @Service @Transactional @@ -26,6 +31,7 @@ public class MissionStateUseCase { private final MissionQueryService missionQueryService; private final MissionStateQueryService missionStateQueryService; private final MissionStateSaveService missionStateSaveService; + private final MissionStateDeleteService missionStateDeleteService; private final TeamScoreLogicUseCase teamScoreLogicUseCase; @@ -80,7 +86,18 @@ public void updateMissionState(Member member, Mission mission, MissionArchive mi public void deleteMissionState(Member member, Mission mission, MissionArchive missionArchive) { + MissionState missionState = missionStateQueryService.findMissionState(member, mission); + missionStateDeleteService.deleteMissionState(missionState); + + } + + public void missionStateReset(List missionIds) { + List missionStates = missionStateQueryService.findByMissionId(missionIds); + missionStateDeleteService.deleteMissionState(missionStates); + } + public void deleteAllMissionState(Long missionId) { + missionStateDeleteService.deleteMissionStateByMission(missionId); } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java index 6a9e996d..01166d64 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java @@ -14,6 +14,7 @@ public interface MissionStateCustomRepository { int getCountsByMissionId(Long missionId) ; List findByMissionId(List missionId); + List findByMissionId(Long missionId); Optional> findFinishMission(); diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index d6ef72e7..a8aebddd 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -45,6 +45,17 @@ public List findByMissionId(List missionId) { missionState.mission.id.in(missionId) ).fetch(); + } + @Override + public List findByMissionId(Long missionId) { + + return queryFactory + .select(missionState) + .from(missionState) + .where( + missionState.mission.id.in(missionId) + ).fetch(); + } @Override diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java index eb679fb6..b99aa8b0 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java @@ -23,4 +23,10 @@ public void deleteMissionState(MissionState missionStates) { missionStateRepository.delete(missionStates); } + + public void deleteMissionStateByMission(Long missionId) { + + List missionStates = missionStateRepository.findByMissionId(missionId); + missionStateRepository.deleteAll(missionStates); + } } From 1c7f73e534dda35a5fff5c1458fdefc56cf2968f Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Wed, 15 Nov 2023 21:29:49 +0900 Subject: [PATCH 236/619] docs: Update README.md --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9685d253..ffc9f729 100644 --- a/README.md +++ b/README.md @@ -1 +1,12 @@ -# MOING_server_release \ No newline at end of file +# MOING_server_release +## System Architecture +image + +## Backend CI/CD +image + +## Monitoring +![image](https://github.com/Modagbul/MOING_Server_Release/assets/86006389/c0d135c3-6863-4c32-b6df-0535fcbf9953) + +## DB ERD +![KakaoTalk_Image_2023-11-15-20-38-24 (1)](https://github.com/Modagbul/MOING_Server_Release/assets/86006389/e26f65bb-d717-46a6-9ef2-0b9c9dca4679) From 1e31d175f089a9078e97c8ece1e65a8b112db7dd Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Thu, 16 Nov 2023 17:34:34 +0900 Subject: [PATCH 237/619] docs: Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ffc9f729..5f282781 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MOING_server_release ## System Architecture -image +![image](https://github.com/Modagbul/MOING_Server_Release/assets/86006389/02032a32-da0d-429e-babe-15534476f380) ## Backend CI/CD image From f126420ac6d5a5e335ab3b2283d1ffbe621c6408 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Thu, 16 Nov 2023 22:15:36 +0900 Subject: [PATCH 238/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=B3=B4=EB=93=9C=20=EB=A6=AC=ED=84=B4=EA=B0=92=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80(missionStatus:wait)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/RepeatMissionBoardRes.java | 18 +- .../application/service/RepeatMissionEnd.java | 188 +++++++++--------- .../MissionArchiveCustomRepositoryImpl.java | 10 +- .../MissionBoardControllerTest.java | 8 +- 4 files changed, 120 insertions(+), 104 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java index 3cff40f6..0caa23dc 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java @@ -6,7 +6,7 @@ @Getter @Setter -//@Builder +@Builder public class RepeatMissionBoardRes { private Long missionId; private String title; @@ -16,18 +16,19 @@ public class RepeatMissionBoardRes { private Long done; private int number; private String way; + private String status; - public RepeatMissionBoardRes(Long missionId, String title, Long done,int number,String way) { + public RepeatMissionBoardRes(Long missionId, String title, Long done,int number,String way,String status) { this.missionId = missionId; this.title = title; this.dueTo="False"; this.number = number; this.done = done; this.way = way; + this.status = status; } - @Builder public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long done, int number,String way) { this.missionId = missionId; this.title = title; @@ -36,4 +37,15 @@ public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long do this.number = number; this.way = way; } + + @Builder + public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long done, int number, String way, String status) { + this.missionId = missionId; + this.title = title; + this.dueTo = dueTo; + this.done = done; + this.number = number; + this.way = way; + this.status = status; + } } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java b/src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java index 811b051f..114a2e95 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java @@ -1,94 +1,94 @@ -package com.moing.backend.domain.mission.application.service; - -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; -import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.JobScope; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.database.JpaItemWriter; -import org.springframework.batch.item.database.JpaPagingItemReader; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.persistence.EntityManagerFactory; - -@Slf4j -@RequiredArgsConstructor -@Configuration -public class RepeatMissionEnd { - - public static final String JOB_NAME = "makeMissionEnd"; - - private final EntityManagerFactory entityManagerFactory; - private final StepBuilderFactory stepBuilderFactory; - private final JobBuilderFactory jobBuilderFactory; - - private final MissionStateUseCase missionStateUseCase; - private final TeamScoreLogicUseCase teamScoreLogicUseCase; - - private final int chunkSize = 10; - - @Bean - public Job payPagingJob() { - return jobBuilderFactory.get(JOB_NAME) - .start(payPagingStep()) - .build(); - } - - @Bean - @JobScope - public Step payPagingStep() { - return stepBuilderFactory.get("makeMissionEndStep") - .chunk(chunkSize) - .reader(payPagingReader()) - .processor(payPagingProcessor()) - .writer(writer()) - .build(); - } - - @Bean - @StepScope - public JpaPagingItemReader payPagingReader() { - - JpaPagingItemReader reader = new JpaPagingItemReader() { - @Override - public int getPage() { - return 0; - } - }; - - reader.setQueryString("SELECT m FROM Mission m WHERE m.status = 'ONGOING' AND m.type = 'REPEAT'"); - reader.setPageSize(chunkSize); - reader.setEntityManagerFactory(entityManagerFactory); - reader.setName("payPagingReader"); - - return reader; - } - - // sundayRepeatMissionRoutine() - @Bean - @StepScope - public ItemProcessor payPagingProcessor() { - return mission -> { - teamScoreLogicUseCase.updateTeamScore(mission.getId()); - missionStateUseCase.deleteAllMissionState(mission.getId()); - mission.makeEnd(); - return mission; - }; - } - - @Bean - @StepScope - public JpaItemWriter writer() { - JpaItemWriter writer = new JpaItemWriter<>(); - writer.setEntityManagerFactory(entityManagerFactory); - return writer; - } -} \ No newline at end of file +//package com.moing.backend.domain.mission.application.service; +// +//import com.moing.backend.domain.mission.domain.entity.Mission; +//import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +//import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +//import lombok.RequiredArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.batch.core.Job; +//import org.springframework.batch.core.Step; +//import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; +//import org.springframework.batch.core.configuration.annotation.JobScope; +//import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +//import org.springframework.batch.core.configuration.annotation.StepScope; +//import org.springframework.batch.item.ItemProcessor; +//import org.springframework.batch.item.database.JpaItemWriter; +//import org.springframework.batch.item.database.JpaPagingItemReader; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +// +//import javax.persistence.EntityManagerFactory; +// +//@Slf4j +//@RequiredArgsConstructor +//@Configuration +//public class RepeatMissionEnd { +// +// public static final String JOB_NAME = "makeMissionEnd"; +// +// private final EntityManagerFactory entityManagerFactory; +// private final StepBuilderFactory stepBuilderFactory; +// private final JobBuilderFactory jobBuilderFactory; +// +// private final MissionStateUseCase missionStateUseCase; +// private final TeamScoreLogicUseCase teamScoreLogicUseCase; +// +// private final int chunkSize = 10; +// +// @Bean +// public Job payPagingJob() { +// return jobBuilderFactory.get(JOB_NAME) +// .start(payPagingStep()) +// .build(); +// } +// +// @Bean +// @JobScope +// public Step payPagingStep() { +// return stepBuilderFactory.get("makeMissionEndStep") +// .chunk(chunkSize) +// .reader(payPagingReader()) +// .processor(payPagingProcessor()) +// .writer(writer()) +// .build(); +// } +// +// @Bean +// @StepScope +// public JpaPagingItemReader payPagingReader() { +// +// JpaPagingItemReader reader = new JpaPagingItemReader() { +// @Override +// public int getPage() { +// return 0; +// } +// }; +// +// reader.setQueryString("SELECT m FROM Mission m WHERE m.status = 'ONGOING' AND m.type = 'REPEAT'"); +// reader.setPageSize(chunkSize); +// reader.setEntityManagerFactory(entityManagerFactory); +// reader.setName("payPagingReader"); +// +// return reader; +// } +// +// // sundayRepeatMissionRoutine() +// @Bean +// @StepScope +// public ItemProcessor payPagingProcessor() { +// return mission -> { +// teamScoreLogicUseCase.updateTeamScore(mission.getId()); +// missionStateUseCase.deleteAllMissionState(mission.getId()); +// mission.makeEnd(); +// return mission; +// }; +// } +// +// @Bean +// @StepScope +// public JpaItemWriter writer() { +// JpaItemWriter writer = new JpaItemWriter<>(); +// writer.setEntityManagerFactory(entityManagerFactory); +// return writer; +// } +//} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index efa04b7f..f9781c43 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -43,13 +43,12 @@ public MissionArchiveCustomRepositoryImpl(EntityManager em) { public Optional> findSingleMissionInComplete(Long memberId, Long teamId, MissionStatus status, OrderCondition orderCondition) { OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); - String missionArchiveStatus = "INCOMPLETE"; return Optional.ofNullable(queryFactory .select(Projections.constructor(SingleMissionBoardRes.class, mission.id, mission.dueTo.stringValue(), mission.title, - Expressions.constant(missionArchiveStatus), + mission.status.stringValue(), mission.type.stringValue() )) .from(mission) @@ -64,10 +63,12 @@ public Optional> findSingleMissionInComplete(Long me .or(missionState.mission.status.eq(MissionStatus.ONGOING)) )), mission.type.eq(MissionType.ONCE), + mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), mission.team.teamId.eq(teamId)) .orderBy(orderSpecifiers).fetch()); + } @Override public Optional> findSingleMissionComplete(Long memberId, Long teamId, MissionStatus status, @@ -176,7 +177,8 @@ public Optional> findRepeatMissionArchivesByMemberId mission.title, missionArchive.count.max().coalesce(0L).as("done"), mission.number, - mission.way.stringValue() + mission.way.stringValue(), + mission.status.stringValue() )) .from(mission) .leftJoin(mission.missionArchiveList,missionArchive) @@ -184,7 +186,7 @@ public Optional> findRepeatMissionArchivesByMemberId .where( mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT), - mission.status.eq(MissionStatus.ONGOING) + mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)) ) .groupBy(mission) .fetch()); diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java index 91fae242..5065dcac 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java @@ -42,7 +42,7 @@ public class MissionBoardControllerTest extends CommonControllerTest { .missionId(1L) .dueTo("2023-09-03T21:32:33.888") .title("Mission title") - .status("SKIP/COMPLETE") + .status("WAIT/ONGOING/SKIP/COMPLETE") .missionType("ONCE/REPEAT") .build()); @@ -94,7 +94,8 @@ public class MissionBoardControllerTest extends CommonControllerTest { .dueTo("True/False") .done(1L) .number(3) - .way("TEXT/PHOTO/LINK") + .way("TEXT/PHOTO/LINK") + .status("WAIT/ONGOING/SKIP/COMPLETE") .build()); given(missionArchiveBoardUseCase.getActiveRepeatMissions(any(),any())).willReturn(output); @@ -127,7 +128,8 @@ public class MissionBoardControllerTest extends CommonControllerTest { fieldWithPath("data[].dueTo").description("내일 리셋 상태 리턴, 일요일이면 true[True/False]"), fieldWithPath("data[].number").description("전체 횟수"), fieldWithPath("data[].done").description("인증한 횟수"), - fieldWithPath("data[].way").description("인증 방법") + fieldWithPath("data[].way").description("인증 방법"), + fieldWithPath("data[].status").description("인증 상태") ) ) From ea37fb70672db3a999157c94886ec72c241822fe Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 17 Nov 2023 12:23:08 +0900 Subject: [PATCH 239/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=EB=AC=BC=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=88=98=20=EB=A6=AC=ED=84=B4=20=EB=A1=9C=EC=A7=81=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionHeart/application/mapper/MissionHeartMapper.java | 5 ++++- .../domain/repository/MissionHeartCustomRepositoryImpl.java | 3 ++- .../domain/service/MissionHeartUpdateService.java | 5 +++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java b/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java index 7a049638..e33f3575 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/application/mapper/MissionHeartMapper.java @@ -21,7 +21,10 @@ public static MissionHeartRes mapToMissionHeartRes(MissionHeart missionHeart) { return MissionHeartRes.builder() .missionArchiveId(missionHeart.getMissionArchive().getId()) .missionHeartStatus(missionHeart.getHeartStatus().name()) - .hearts(missionHeart.getMissionArchive().getHeartList().size()) + .hearts((int) missionHeart.getMissionArchive().getHeartList().stream() + .filter(heart -> heart.getHeartStatus().equals( MissionHeartStatus.True)) + .filter(heart -> heart.getId().equals( missionHeart.getId()))// heartStatus가 true인 요소만 필터링 + .count()) .build(); } } diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java index 092f6ece..2dd9ceb1 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/repository/MissionHeartCustomRepositoryImpl.java @@ -1,7 +1,9 @@ package com.moing.backend.domain.missionHeart.domain.repository; +import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; import com.moing.backend.domain.missionHeart.domain.entity.QMissionHeart; +import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -38,5 +40,4 @@ public MissionHeart findByMemberIdAndArchiveId(Long memberId, Long archiveId) { } - } diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java index 7acaee62..5340ea15 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/service/MissionHeartUpdateService.java @@ -19,8 +19,9 @@ public MissionHeart update(MissionHeart missionHeart) { MissionHeart updateHeart = missionHeartRepository.findByMemberIdAndArchiveId(missionHeart.getPushMemberId(), missionHeart.getMissionArchive().getId()); updateHeart.updateHeartStatus(missionHeart.getHeartStatus()); - updateHeart.changeByHeart(missionHeart.getMissionArchive()); - return updateHeart; +// updateHeart.changeByHeart(missionHeart.getMissionArchive()); + + return missionHeartRepository.save(updateHeart); } From 89040f398d249a8e8add38bd3d68c33f983bbd64 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 17 Nov 2023 12:44:21 +0900 Subject: [PATCH 240/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=EB=AC=BC=20=EC=A2=8B=EC=95=84=EC=9A=94=20cou?= =?UTF-8?q?nt=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/mapper/MissionArchiveMapper.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 47e2b5a7..36810af0 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -43,9 +43,10 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc missionHeart -> missionHeart.getPushMemberId().equals(memberId) && missionHeart.getHeartStatus().equals(MissionHeartStatus.True) ))) - .hearts(missionArchive.getHeartList().stream().filter( - missionHeart -> missionHeart.getHeartStatus().equals(MissionHeartStatus.True) - ).count()) + .hearts(missionArchive.getHeartList().stream() + .filter(heart -> heart.getHeartStatus().equals( MissionHeartStatus.True)) + .filter(heart -> heart.getMissionArchive().equals( missionArchive))// heartStatus가 true인 요소만 필터링 + .count()) .build(); } @@ -72,7 +73,10 @@ public static PersonalArchiveRes mapToPersonalArchive(MissionArchive missionArch .heartStatus( String.valueOf(missionArchive.getHeartList().stream().anyMatch( missionHeart -> missionHeart.getPushMemberId().equals(memberId)))) - .hearts(missionArchive.getHeartList().size()) + .hearts((int) missionArchive.getHeartList().stream() + .filter(heart -> heart.getHeartStatus().equals( MissionHeartStatus.True)) + .filter(heart -> heart.getMissionArchive().equals( missionArchive))// heartStatus가 true인 요소만 필터링 + .count()) .build(); } From 8829cf92efcea0a5d92c2e6854165289a8787785 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 17 Nov 2023 22:47:32 +0900 Subject: [PATCH 241/619] =?UTF-8?q?feat:=20s3=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EC=82=AD=EC=A0=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moing/backend/global/config/s3/S3Service.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/moing/backend/global/config/s3/S3Service.java b/src/main/java/com/moing/backend/global/config/s3/S3Service.java index a218a353..253a0de9 100644 --- a/src/main/java/com/moing/backend/global/config/s3/S3Service.java +++ b/src/main/java/com/moing/backend/global/config/s3/S3Service.java @@ -4,6 +4,7 @@ import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.Headers; import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.DeleteObjectRequest; import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; import com.moing.backend.domain.infra.image.application.dto.ImageFileExtension; import com.moing.backend.domain.infra.image.application.dto.ImageUrlDto; @@ -37,6 +38,13 @@ public ImageUrlDto issuePreSignedUrl(ImageFileExtension fileExtension) { return ImageUrlDto.of(url, fileName); } + public void deleteImage(String fileUrl) { + String splitStr = ".com/"; + String fileName = fileUrl.substring(fileUrl.lastIndexOf(splitStr) + splitStr.length()); + + amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName)); + } + private String createFileName(String fileExtension) { return UUID.randomUUID() + "." + fileExtension; } From baacfa12ed024f51b7186a3f4c844cb56fc3c41b Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 17 Nov 2023 22:48:03 +0900 Subject: [PATCH 242/619] =?UTF-8?q?fix:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=ED=9B=84=20=EC=88=98=EC=A0=95=ED=95=98?= =?UTF-8?q?=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/domain/entity/Member.java | 6 ------ .../application/service/ProfileUserCase.java | 14 +++++++++++++- .../application/service/UpdateTeamUserCase.java | 3 +++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index 42508835..5d4fa4b9 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -112,12 +112,6 @@ public Member(String email, String profileImage, Gender gender, LocalDate birthD this.role = role; } - - public void updateMember(String nickName, String fcmToken) { - this.nickName = nickName; - this.fcmToken = fcmToken; - } - public void updateProfile(String profileImage, String nickName, String introduction) { this.profileImage = profileImage; this.nickName = nickName; diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java index fdaa3f4a..dc7e9991 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mypage.application.dto.request.UpdateProfileRequest; import com.moing.backend.domain.mypage.application.dto.response.GetProfileResponse; +import com.moing.backend.global.config.s3.S3Service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -14,6 +15,7 @@ public class ProfileUserCase { private final MemberGetService memberGetService; + private final S3Service s3Service; public GetProfileResponse getProfile(String socialId){ Member member=memberGetService.getMemberBySocialId(socialId); @@ -23,6 +25,7 @@ public GetProfileResponse getProfile(String socialId){ @Transactional public void updateProfile(String socialId, UpdateProfileRequest updateProfileRequest) { Member member = memberGetService.getMemberBySocialId(socialId); + deletePreviousImage(updateProfileRequest, member); member.updateProfile( getUpdatedValue(updateProfileRequest.getProfileImage(), member.getProfileImage()), getUpdatedValue(updateProfileRequest.getNickName(), member.getNickName()), @@ -31,7 +34,16 @@ public void updateProfile(String socialId, UpdateProfileRequest updateProfileReq } private String getUpdatedValue(String newValue, String currentValue) { - return newValue != null ? newValue : currentValue; + if (newValue != null) { + return newValue; + } + return currentValue; + } + + private void deletePreviousImage(UpdateProfileRequest updateProfileRequest, Member member) { + if (updateProfileRequest.getProfileImage() != null) { + s3Service.deleteImage(member.getProfileImage()); + } } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java index 2eea1890..6bce4860 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.team.exception.NotAuthByTeamException; +import com.moing.backend.global.config.s3.S3Service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,11 +21,13 @@ public class UpdateTeamUserCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; private final CheckLeaderUserCase checkLeaderUserCase; + private final S3Service s3Service; public UpdateTeamResponse updateTeam(UpdateTeamRequest updateTeamRequest, String socialId, Long teamId){ Member member = memberGetService.getMemberBySocialId(socialId); Team team=teamGetService.getTeamByTeamId(teamId); if (checkLeaderUserCase.isTeamLeader(member, team)) { + s3Service.deleteImage(team.getProfileImgUrl()); team.updateTeam(updateTeamRequest.getName(), updateTeamRequest.getIntroduction(), updateTeamRequest.getProfileImgUrl()); } else { throw new NotAuthByTeamException(); From a5c5099d49f001d59fd3c9b6ad73adbfda0b5760 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 17 Nov 2023 22:48:22 +0900 Subject: [PATCH 243/619] =?UTF-8?q?fix:=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mypage/application/service/WithdrawUserCase.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java index df959b27..cf693283 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java @@ -8,6 +8,7 @@ import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; import com.moing.backend.domain.mypage.domain.service.FeedbackSaveService; import com.moing.backend.domain.mypage.exception.ExistingTeamException; +import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.global.config.security.jwt.TokenUtil; import lombok.RequiredArgsConstructor; @@ -25,6 +26,7 @@ public class WithdrawUserCase { private final TokenUtil tokenUtil; private final MemberDeleteService memberDeleteService; private final TeamMemberGetService teamMemberGetService; + private final TeamGetService teamGetService; private final Map withdrawProviders; public void withdraw(String socialId, String providerInfo, WithdrawRequest withdrawRequest) throws IOException { @@ -45,7 +47,7 @@ private void withdraw(String providerInfo, String token) throws IOException { } private void checkMemberIsNotPartOfAnyTeam(Member member) { - if (!teamMemberGetService.getNotDeletedTeamMember(member.getMemberId()).isEmpty()) { + if (!teamGetService.getTeamIdByMemberId(member.getMemberId()).isEmpty()) { throw new ExistingTeamException(); } } From 52aba9d6859e1b222fafa81851c8516103161de6 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 18 Nov 2023 11:43:15 +0900 Subject: [PATCH 244/619] =?UTF-8?q?refactor:=20=EC=95=A0=ED=94=8C=20?= =?UTF-8?q?=ED=82=A4=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20confiuration=EC=9C=BC=EB=A1=9C=20=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- .../service/apple/AppleWithdrawUserCase.java | 26 ++---------- .../global/config/sns/AppleConfig.java | 42 +++++++++++++++++++ 3 files changed, 47 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/moing/backend/global/config/sns/AppleConfig.java diff --git a/.gitignore b/.gitignore index 9b5677c4..e1cf4c91 100644 --- a/.gitignore +++ b/.gitignore @@ -49,4 +49,5 @@ data.sql #### docs #### !**/src/main/resources/static/docs/ *.html -firebase-key.json \ No newline at end of file +firebase-key.json +apple-key.p8 \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java index 910519a3..8d7a2a0e 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java @@ -3,21 +3,14 @@ import com.moing.backend.domain.auth.application.service.WithdrawProvider; import com.moing.backend.domain.auth.application.service.apple.utils.AppleClient; import com.moing.backend.domain.auth.application.service.apple.utils.AppleToken; +import com.moing.backend.global.config.sns.AppleConfig; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import lombok.RequiredArgsConstructor; -import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Service; -import org.springframework.util.FileCopyUtils; import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.security.Key; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Date; @@ -37,10 +30,8 @@ public class AppleWithdrawUserCase implements WithdrawProvider { @Value("${oauth2.apple.clientId}") private String clientId; - @Value("${oauth2.apple.keyPath}") - private String keyPath; - private final AppleClient appleClient; + private final AppleConfig appleConfig; public void withdraw(String token) throws IOException { AppleToken.Response response = generateAuthToken(token); @@ -78,18 +69,7 @@ public String createClientSecret() throws IOException { .setExpiration(expirationDate) .setAudience("https://appleid.apple.com") .setSubject(clientId) - .signWith(getPrivateKey(), SignatureAlgorithm.ES256) + .signWith(appleConfig.applePrivateKey(), SignatureAlgorithm.ES256) .compact(); } - - private Key getPrivateKey() throws IOException { - ClassPathResource resource = new ClassPathResource(keyPath); - String privateKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); - - Reader pemReader = new StringReader(privateKey); - PEMParser pemParser = new PEMParser(pemReader); - JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); - PrivateKeyInfo object = (PrivateKeyInfo) pemParser.readObject(); - return converter.getPrivateKey(object); - } } diff --git a/src/main/java/com/moing/backend/global/config/sns/AppleConfig.java b/src/main/java/com/moing/backend/global/config/sns/AppleConfig.java new file mode 100644 index 00000000..c1ad050b --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/sns/AppleConfig.java @@ -0,0 +1,42 @@ +package com.moing.backend.global.config.sns; + +import com.moing.backend.global.config.fcm.exception.InitializeException; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.util.FileCopyUtils; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.security.PrivateKey; + +@Configuration +public class AppleConfig { + + + @Value("${oauth2.apple.keyPath}") + private String keyPath; + + @Bean + public PrivateKey applePrivateKey(){ + try{ + ClassPathResource resource = new ClassPathResource(keyPath); + String privateKeyString = new String(FileCopyUtils.copyToByteArray(resource.getInputStream())); + Reader reader = new StringReader(privateKeyString); + PEMParser pemParser = new PEMParser(reader); + JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); + PrivateKeyInfo object = (PrivateKeyInfo) pemParser.readObject(); + return converter.getPrivateKey(object); + } catch (FileNotFoundException e) { + throw new IllegalStateException("파일을 찾을 수 없습니다." + e.getMessage()); + } catch (IOException e) { + throw new InitializeException(); + } + } +} \ No newline at end of file From eca7797aa24ac56921230a6ad2ca0945c236662f Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 18 Nov 2023 16:29:02 +0900 Subject: [PATCH 245/619] =?UTF-8?q?refactor:=20member=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20=EC=86=8C=ED=94=84=ED=8A=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/member/domain/entity/Member.java | 18 +++++++++++++++--- .../teamMember/domain/entity/TeamMember.java | 4 +++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index 5d4fa4b9..ca87d769 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -17,6 +17,7 @@ import javax.persistence.*; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; @@ -32,7 +33,7 @@ public class Member extends BaseTimeEntity { @Column(name = "member_id") private Long memberId; - @Column(nullable = false, unique = true) + @Column(nullable = false) private String socialId; @Enumerated(EnumType.STRING) @@ -44,7 +45,7 @@ public class Member extends BaseTimeEntity { private RegistrationStatus registrationStatus; @Convert(converter = AesConverter.class) - @Column(nullable = false, unique = true) + @Column(nullable = false) private String email; private String profileImage; @@ -56,7 +57,6 @@ public class Member extends BaseTimeEntity { private LocalDate birthDate; @Convert(converter = AesConverter.class) - @Column(unique=true) private String nickName; @Column(nullable = false) @@ -79,6 +79,10 @@ public class Member extends BaseTimeEntity { @Column(nullable = false) private boolean isFirePush; + private boolean isDeleted; + + private LocalDateTime lastSignInTime; + @OneToMany(mappedBy = "member") private List teamMembers = new ArrayList<>(); //최대 3개이므로 양방향 @@ -140,6 +144,10 @@ public void updateFcmToken(String fcmToken) { this.fcmToken = fcmToken; } + public void updateLastSignInTime(LocalDateTime time){ + this.lastSignInTime=time; + } + public Member(LocalDate birthDate, String email, String fcmToken, Gender gender, String introduction, String nickName, String profileImage, SocialProvider provider, RegistrationStatus registrationStatus, Role role, String socialId) { this.birthDate = birthDate; this.email = email; @@ -154,4 +162,8 @@ public Member(LocalDate birthDate, String email, String fcmToken, Gender gender, this.socialId = socialId; } + public void deleteMember(){ + this.isDeleted=true; + } + } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java index 9769d51f..5cf9ffea 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java @@ -39,7 +39,9 @@ public void updateTeam(Team team) { public void updateMember(Member member) { this.member = member; - member.getTeamMembers().add(this); + if (member != null) { + member.getTeamMembers().add(this); + } } public void deleteMember(Team team) { From 6d39adc787efc80007130a86922b1dff131d3012 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 18 Nov 2023 16:29:25 +0900 Subject: [PATCH 246/619] =?UTF-8?q?fix:=20member=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20=EC=82=AD=EC=A0=9C=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EC=9D=80=20member=EC=A1=B0=ED=9A=8C=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MemberCustomRepository.java | 4 ++++ .../MemberCustomRepositoryImpl.java | 19 +++++++++++++++++++ .../domain/repository/MemberRepository.java | 4 ---- .../domain/service/MemberGetService.java | 2 +- .../domain/service/MemberSaveService.java | 4 +++- .../application/service/WithdrawUserCase.java | 5 ++--- 6 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java index c1b27c23..03f785ca 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java @@ -6,4 +6,8 @@ public interface MemberCustomRepository { boolean checkNickname(String nickname); + + Optional findNotDeletedBySocialId(String socialId); + + Optional findNotDeletedByEmail(String email); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java index 2126f3b1..0149fdcc 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java @@ -22,6 +22,25 @@ public boolean checkNickname(String nickname) { .selectOne() .from(member) .where(member.nickName.eq(nickname)) + .where(member.isDeleted.eq(false)) .fetchFirst() != null; } + + @Override + public Optional findNotDeletedBySocialId(String socialId) { + return Optional.ofNullable(queryFactory + .selectFrom(member) + .where(member.socialId.eq(socialId)) + .where(member.isDeleted.eq(false)) + .fetchOne()); + } + + @Override + public Optional findNotDeletedByEmail(String email) { + return Optional.ofNullable(queryFactory + .selectFrom(member) + .where(member.email.eq(email)) + .where(member.isDeleted.eq(false)) + .fetchOne()); + } } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java index 20cb1f23..694e75df 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java @@ -7,8 +7,4 @@ public interface MemberRepository extends JpaRepository, MemberCustomRepository { - Optional findBySocialId(String socialId); - - Optional findByEmail(String email); - } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java index dc88284d..31dc3a07 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java @@ -15,6 +15,6 @@ public class MemberGetService { private final MemberRepository memberRepository; public Member getMemberBySocialId(String socialId){ - return memberRepository.findBySocialId(socialId).orElseThrow(()->new NotFoundBySocialIdException()); + return memberRepository.findNotDeletedBySocialId(socialId).orElseThrow(()->new NotFoundBySocialIdException()); } } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java index ca6480f0..2332f2f7 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java @@ -6,6 +6,7 @@ import lombok.AllArgsConstructor; import javax.transaction.Transactional; +import java.time.LocalDateTime; import java.util.Optional; @DomainService @@ -16,11 +17,12 @@ public class MemberSaveService { private final MemberRepository memberRepository; public Member saveMember(Member member) { - OptionalfindMember=memberRepository.findByEmail(member.getEmail()); + OptionalfindMember=memberRepository.findNotDeletedByEmail(member.getEmail()); if(findMember.isEmpty()){ return memberRepository.save(member); } else { findMember.get().updateFcmToken(member.getFcmToken()); + findMember.get().updateLastSignInTime(LocalDateTime.now()); return findMember.get(); } } diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java index cf693283..02ee59dc 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java @@ -9,6 +9,7 @@ import com.moing.backend.domain.mypage.domain.service.FeedbackSaveService; import com.moing.backend.domain.mypage.exception.ExistingTeamException; import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.global.config.security.jwt.TokenUtil; import lombok.RequiredArgsConstructor; @@ -24,8 +25,6 @@ public class WithdrawUserCase { private final MemberGetService memberGetService; private final FeedbackSaveService feedbackSaveService; private final TokenUtil tokenUtil; - private final MemberDeleteService memberDeleteService; - private final TeamMemberGetService teamMemberGetService; private final TeamGetService teamGetService; private final Map withdrawProviders; @@ -33,7 +32,7 @@ public void withdraw(String socialId, String providerInfo, WithdrawRequest withd Member member = memberGetService.getMemberBySocialId(socialId); checkMemberIsNotPartOfAnyTeam(member); withdraw(providerInfo, withdrawRequest.getSocialToken()); - memberDeleteService.deleteMember(member); + member.deleteMember(); feedbackSaveService.saveFeedback(member, withdrawRequest); tokenUtil.expireRefreshToken(socialId); } From cfc0748e915a53b6ae1f8a38147a16174b455f38 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 18 Nov 2023 16:33:14 +0900 Subject: [PATCH 247/619] =?UTF-8?q?fix:=20member=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20=EC=82=AD=EC=A0=9C=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EC=9D=80=20member=20=EC=A1=B0=ED=9A=8C=ED=95=98?= =?UTF-8?q?=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/domain/repository/MemberCustomRepository.java | 1 + .../domain/repository/MemberCustomRepositoryImpl.java | 9 +++++++++ .../domain/member/domain/service/MemberGetService.java | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java index 03f785ca..3f8ab192 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java @@ -10,4 +10,5 @@ public interface MemberCustomRepository { Optional findNotDeletedBySocialId(String socialId); Optional findNotDeletedByEmail(String email); + Optional findNotDeletedByMemberId(Long id); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java index 0149fdcc..9c841321 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java @@ -43,4 +43,13 @@ public Optional findNotDeletedByEmail(String email) { .where(member.isDeleted.eq(false)) .fetchOne()); } + + @Override + public Optional findNotDeletedByMemberId(Long id) { + return Optional.ofNullable(queryFactory + .selectFrom(member) + .where(member.memberId.eq(id)) + .where(member.isDeleted.eq(false)) + .fetchOne()); + } } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java index 33dab9ef..8c78c8b8 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java @@ -19,6 +19,6 @@ public Member getMemberBySocialId(String socialId){ } public Member getMemberByMemberId(Long memberId) { - return memberRepository.findByMemberId(memberId).orElseThrow(()->new NotFoundBySocialIdException()); + return memberRepository.findNotDeletedByMemberId(memberId).orElseThrow(()->new NotFoundBySocialIdException()); } } From 6835ee9cbdb5b57687d6e457f338f3254dae50ee Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 18 Nov 2023 17:27:15 +0900 Subject: [PATCH 248/619] =?UTF-8?q?hotfix:=20eq(null)=20is=20not=20allowed?= =?UTF-8?q?.=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/service/apple/AppleTokenUserCase.java | 4 ++-- .../domain/member/domain/service/MemberSaveService.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java index 20d9218d..0955c6c6 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java @@ -38,11 +38,11 @@ public Jws sigVerificationAndGetJws(String unverifiedToken) { Keys.PubKey pubKey = keys.getKeys().stream() .filter((key) -> key.getKid().equals(kid)) .findAny() - .orElseThrow(() -> new TokenInvalidException()); + .orElseThrow(TokenInvalidException::new); return getOIDCTokenJws(unverifiedToken, pubKey.getN(), pubKey.getE()); } catch (Exception e) { - throw new InternalServerErrorException("Token verification failed"); + throw new TokenInvalidException(); } } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java index 2332f2f7..3aeff0eb 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java @@ -17,7 +17,7 @@ public class MemberSaveService { private final MemberRepository memberRepository; public Member saveMember(Member member) { - OptionalfindMember=memberRepository.findNotDeletedByEmail(member.getEmail()); + OptionalfindMember=memberRepository.findNotDeletedBySocialId(member.getSocialId()); if(findMember.isEmpty()){ return memberRepository.save(member); } else { From 8cb6d1a58a8e7cdc9dbd114c4bfcf427be16d869 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 18 Nov 2023 17:50:37 +0900 Subject: [PATCH 249/619] =?UTF-8?q?fix:=20email=20nullable=20true=EB=A1=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moing/backend/domain/member/domain/entity/Member.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index ca87d769..2c8b2310 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -45,7 +45,6 @@ public class Member extends BaseTimeEntity { private RegistrationStatus registrationStatus; @Convert(converter = AesConverter.class) - @Column(nullable = false) private String email; private String profileImage; From 4f74feb9a9b31e71dfc40c316b0c6db5359eec7a Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 20 Nov 2023 22:01:11 +0900 Subject: [PATCH 250/619] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=20=EC=8B=9C=20slack=20Alarm=EB=B3=B4=EB=82=B4?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../exception/GlobalExceptionHandler.java | 8 ++- .../backend/global/util/SlackService.java | 65 +++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/global/util/SlackService.java diff --git a/build.gradle b/build.gradle index 2fd7bb34..74cdd0b3 100644 --- a/build.gradle +++ b/build.gradle @@ -91,6 +91,8 @@ dependencies { implementation platform('software.amazon.awssdk:bom:2.17.230') implementation 'software.amazon.awssdk:s3' + //slack + implementation 'com.slack.api:slack-api-client:1.30.0' } diff --git a/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java b/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java index 7a5b3529..04298e10 100644 --- a/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java @@ -2,6 +2,8 @@ import com.moing.backend.global.response.ErrorCode; import com.moing.backend.global.response.ErrorResponse; +import com.moing.backend.global.util.SlackService; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -12,15 +14,18 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.context.support.DefaultMessageSourceResolvable; +import javax.servlet.http.HttpServletRequest; import java.util.function.Consumer; import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; @RestControllerAdvice @Slf4j +@RequiredArgsConstructor public class GlobalExceptionHandler { private static final String LOG_FORMAT = "Class : {}, Code : {}, Message : {}"; + private final SlackService slackService; @ExceptionHandler(ApplicationException.class) public ResponseEntity handleApplicationException(ApplicationException ex) { @@ -51,7 +56,8 @@ public ResponseEntity httpRequestNotSupportedExceptionHandler(Htt } @ExceptionHandler(Exception.class) - public ResponseEntity internalServerErrorHandler(Exception ex) { + public ResponseEntity internalServerErrorHandler(Exception ex, HttpServletRequest request) { + slackService.sendSlackAlertErrorLog(ex, request); return handleException(ex, ErrorCode.INTERNAL_SERVER_ERROR, ErrorCode.INTERNAL_SERVER_ERROR.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR, log::error); } diff --git a/src/main/java/com/moing/backend/global/util/SlackService.java b/src/main/java/com/moing/backend/global/util/SlackService.java new file mode 100644 index 00000000..97a14dd4 --- /dev/null +++ b/src/main/java/com/moing/backend/global/util/SlackService.java @@ -0,0 +1,65 @@ +package com.moing.backend.global.util; + +import com.slack.api.Slack; +import com.slack.api.model.Attachment; +import com.slack.api.model.Field; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; + +import static com.slack.api.webhook.WebhookPayloads.payload; + +@Service +@Slf4j +public class SlackService { + + @Value("${webhook.slack.error_url}") + private String errorWebhookUrl; + + private final Slack slackClient = Slack.getInstance(); + + // 슬랙 에러 알림 보내는 메서드 + public void sendSlackAlertErrorLog(Exception e, HttpServletRequest request) { + try { + slackClient.send(errorWebhookUrl, payload(p -> p + .text("[500 에러가 발생했습니다.]") + .attachments( + List.of(generateSlackAttachment(e, request)) + ) + )); + } catch (IOException slackError) { + log.debug("Slack 통신과의 예외 발생"); + } + } + + // attachment 생성 메서드 + private Attachment generateSlackAttachment(Exception e, HttpServletRequest request) { + String requestTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(LocalDateTime.now()); + String xffHeader = request.getHeader("X-FORWARDED-FOR"); + return Attachment.builder() + .color("ff0000") + .title(requestTime + " 발생 에러 로그") + .fields(List.of( + generateSlackField("Request IP", xffHeader == null ? request.getRemoteAddr() : xffHeader), + generateSlackField("Request URL", request.getRequestURL() + " " + request.getMethod()), + generateSlackField("Error Message", e.getMessage()) + ) + ) + .build(); + } + + private Field generateSlackField(String title, String value) { + return Field.builder() + .title(title) + .value(value) + .valueShortEnough(false) + .build(); + } + +} From ae99b7b7c24ce08c206327e8ec8178b84f251f5c Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 20 Nov 2023 22:15:45 +0900 Subject: [PATCH 251/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=8B=9C=20slack=20Alarm=20=EB=B3=B4?= =?UTF-8?q?=EB=82=B4=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CreateTeamUserCase.java | 3 ++ .../backend/global/util/SlackService.java | 44 +++++++++++++++---- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java index 262e7a8b..1b6238a1 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java @@ -10,6 +10,7 @@ import com.moing.backend.domain.teamMember.domain.service.TeamMemberSaveService; import com.moing.backend.domain.teamScore.application.mapper.TeamScoreMapper; import com.moing.backend.domain.teamScore.domain.service.TeamScoreSaveService; +import com.moing.backend.global.util.SlackService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -26,6 +27,7 @@ public class CreateTeamUserCase { private final TeamMapper teamMapper; private final TeamScoreSaveService teamScoreSaveService; private final TeamScoreMapper teamScoreMapper; + private final SlackService slackService; public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String socialId){ Member member = memberGetService.getMemberBySocialId(socialId); @@ -36,6 +38,7 @@ public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String team.approveTeam(); //====지워야 함 (테스트 용)===== teamScoreSaveService.save(teamScoreMapper.mapToTeamScore(team)); // 팀스코어 엔티티 생성 + slackService.sendSlackTeamCreatedMessage(team.getName(), team.getLeaderId()); return new CreateTeamResponse(team.getTeamId()); } } diff --git a/src/main/java/com/moing/backend/global/util/SlackService.java b/src/main/java/com/moing/backend/global/util/SlackService.java index 97a14dd4..813a52b7 100644 --- a/src/main/java/com/moing/backend/global/util/SlackService.java +++ b/src/main/java/com/moing/backend/global/util/SlackService.java @@ -5,6 +5,7 @@ import com.slack.api.model.Field; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; @@ -22,24 +23,51 @@ public class SlackService { @Value("${webhook.slack.error_url}") private String errorWebhookUrl; + @Value("${webhook.slack.team_alarm_url}") + private String teamAlarmWebhookUrl; + private final Slack slackClient = Slack.getInstance(); - // 슬랙 에러 알림 보내는 메서드 - public void sendSlackAlertErrorLog(Exception e, HttpServletRequest request) { + // 공통 슬랙 메시지 전송 메서드 + @Async + public void sendSlackMessage(String webhookUrl, String message, List attachments) { try { - slackClient.send(errorWebhookUrl, payload(p -> p - .text("[500 에러가 발생했습니다.]") - .attachments( - List.of(generateSlackAttachment(e, request)) - ) + slackClient.send(webhookUrl, payload(p -> p + .text(message) + .attachments(attachments) )); } catch (IOException slackError) { log.debug("Slack 통신과의 예외 발생"); } } + // 슬랙 에러 알림 메서드 + public void sendSlackAlertErrorLog(Exception e, HttpServletRequest request) { + String message = "[500 에러가 발생했습니다.]"; + List attachments = List.of(generateSlackErrorAttachment(e, request)); + sendSlackMessage(errorWebhookUrl, message, attachments); + } + + // 슬랙 소모임 생성 알림 메서드 + public void sendSlackTeamCreatedMessage(String teamName, Long leaderId) { + String message = String.format("새로운 소모임 '%s'이(가) 생성되었습니다!", teamName); + List attachments = List.of(generateSlackTeamAttachment(teamName, leaderId)); + sendSlackMessage(teamAlarmWebhookUrl, message, attachments); + } + + private Attachment generateSlackTeamAttachment(String teamName, Long leaderId) { + return Attachment.builder() + .color("36a64f") + .title("소모임 생성 알림") + .fields(List.of( + generateSlackField("소모임 이름", teamName), + generateSlackField("생성자 아이디", String.valueOf(leaderId)) + )) + .build(); + } + // attachment 생성 메서드 - private Attachment generateSlackAttachment(Exception e, HttpServletRequest request) { + private Attachment generateSlackErrorAttachment(Exception e, HttpServletRequest request) { String requestTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(LocalDateTime.now()); String xffHeader = request.getHeader("X-FORWARDED-FOR"); return Attachment.builder() From fd711b639e587bf4cf4fb3cd3cda40d828502b0e Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 20 Nov 2023 22:37:24 +0900 Subject: [PATCH 252/619] =?UTF-8?q?fix:=20test=EC=8B=9C=20=EB=B9=88?= =?UTF-8?q?=EC=9D=84=20=EC=B0=BE=EC=9D=84=20=EC=88=98=20=EC=97=86=EB=8A=94?= =?UTF-8?q?=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/moing/backend/global/util/SlackService.java | 3 ++- .../java/com/moing/backend/config/CommonControllerTest.java | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/global/util/SlackService.java b/src/main/java/com/moing/backend/global/util/SlackService.java index 813a52b7..17a7054b 100644 --- a/src/main/java/com/moing/backend/global/util/SlackService.java +++ b/src/main/java/com/moing/backend/global/util/SlackService.java @@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; @@ -16,7 +17,7 @@ import static com.slack.api.webhook.WebhookPayloads.payload; -@Service +@Component @Slf4j public class SlackService { diff --git a/src/test/java/com/moing/backend/config/CommonControllerTest.java b/src/test/java/com/moing/backend/config/CommonControllerTest.java index 00cfcd09..893b51c5 100644 --- a/src/test/java/com/moing/backend/config/CommonControllerTest.java +++ b/src/test/java/com/moing/backend/config/CommonControllerTest.java @@ -8,6 +8,7 @@ import com.moing.backend.global.config.security.filter.JwtAuthenticationEntryPoint; import com.moing.backend.global.config.security.jwt.TokenUtil; import com.moing.backend.global.config.security.util.AuthenticationUtil; +import com.moing.backend.global.util.SlackService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -32,6 +33,7 @@ @MockBean(JpaMetamodelMappingContext.class) @ExtendWith({RestDocumentationExtension.class, SpringExtension.class}) public class CommonControllerTest { + @Autowired protected RestDocumentationResultHandler restDocs; @@ -56,6 +58,9 @@ public class CommonControllerTest { @MockBean public MemberGetService memberQueryService; + @MockBean + private SlackService slackService; + @BeforeEach public void setUp(final WebApplicationContext context, final RestDocumentationContextProvider provider) throws Exception { From 7475c9ca14789b0ede05fd2c143c8c88f327dd76 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 21 Nov 2023 23:58:43 +0900 Subject: [PATCH 253/619] =?UTF-8?q?feat:=20=EC=8A=AC=EB=9E=99=20=EC=9B=B9?= =?UTF-8?q?=ED=9B=85=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/global/config/slack/util/WebhookUtil.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/com/moing/backend/global/config/slack/util/WebhookUtil.java diff --git a/src/main/java/com/moing/backend/global/config/slack/util/WebhookUtil.java b/src/main/java/com/moing/backend/global/config/slack/util/WebhookUtil.java new file mode 100644 index 00000000..7c613543 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/slack/util/WebhookUtil.java @@ -0,0 +1,10 @@ +package com.moing.backend.global.config.slack.util; + +import javax.servlet.http.HttpServletRequest; + +public interface WebhookUtil { + + void sendSlackAlertErrorLog(HttpServletRequest request, Exception e); + + void sendSlackTeamCreatedMessage(String teamName, Long leaderId); +} From 1f749c3d1af1f139917c1daf6e3814c6bb9e8ed6 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 22 Nov 2023 00:02:21 +0900 Subject: [PATCH 254/619] =?UTF-8?q?refactor:=20OCP=20=EC=9B=90=EC=B9=99=20?= =?UTF-8?q?=EC=A4=80=EC=88=98=EB=A5=BC=20=EC=9C=84=ED=95=B4=20SlackService?= =?UTF-8?q?=EB=A5=BC=20WebhookUtil=20=EB=B0=8F=20=EA=B7=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=B2=B4=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/slack/SlackConfig.java | 14 +++++++++++ .../slack/util/SlackAdapter.java} | 25 ++++++++----------- 2 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/moing/backend/global/config/slack/SlackConfig.java rename src/main/java/com/moing/backend/global/{util/SlackService.java => config/slack/util/SlackAdapter.java} (84%) diff --git a/src/main/java/com/moing/backend/global/config/slack/SlackConfig.java b/src/main/java/com/moing/backend/global/config/slack/SlackConfig.java new file mode 100644 index 00000000..9f3dbe0d --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/slack/SlackConfig.java @@ -0,0 +1,14 @@ +package com.moing.backend.global.config.slack; + +import com.slack.api.Slack; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SlackConfig { + + @Bean + public Slack slackClient() { + return Slack.getInstance(); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/util/SlackService.java b/src/main/java/com/moing/backend/global/config/slack/util/SlackAdapter.java similarity index 84% rename from src/main/java/com/moing/backend/global/util/SlackService.java rename to src/main/java/com/moing/backend/global/config/slack/util/SlackAdapter.java index 17a7054b..2ce8f901 100644 --- a/src/main/java/com/moing/backend/global/util/SlackService.java +++ b/src/main/java/com/moing/backend/global/config/slack/util/SlackAdapter.java @@ -1,13 +1,12 @@ -package com.moing.backend.global.util; +package com.moing.backend.global.config.slack.util; import com.slack.api.Slack; import com.slack.api.model.Attachment; import com.slack.api.model.Field; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @@ -17,9 +16,10 @@ import static com.slack.api.webhook.WebhookPayloads.payload; -@Component +@RequiredArgsConstructor @Slf4j -public class SlackService { +@Component +public class SlackAdapter implements WebhookUtil { @Value("${webhook.slack.error_url}") private String errorWebhookUrl; @@ -29,8 +29,6 @@ public class SlackService { private final Slack slackClient = Slack.getInstance(); - // 공통 슬랙 메시지 전송 메서드 - @Async public void sendSlackMessage(String webhookUrl, String message, List attachments) { try { slackClient.send(webhookUrl, payload(p -> p @@ -42,16 +40,16 @@ public void sendSlackMessage(String webhookUrl, String message, List } } - // 슬랙 에러 알림 메서드 - public void sendSlackAlertErrorLog(Exception e, HttpServletRequest request) { + @Override + public void sendSlackAlertErrorLog(HttpServletRequest request, Exception e) { String message = "[500 에러가 발생했습니다.]"; List attachments = List.of(generateSlackErrorAttachment(e, request)); sendSlackMessage(errorWebhookUrl, message, attachments); } - // 슬랙 소모임 생성 알림 메서드 + @Override public void sendSlackTeamCreatedMessage(String teamName, Long leaderId) { - String message = String.format("새로운 소모임 '%s'이(가) 생성되었습니다!", teamName); + String message = String.format("[새로운 소모임 '%s'이(가) 생성되었습니다.]", teamName); List attachments = List.of(generateSlackTeamAttachment(teamName, leaderId)); sendSlackMessage(teamAlarmWebhookUrl, message, attachments); } @@ -76,7 +74,7 @@ private Attachment generateSlackErrorAttachment(Exception e, HttpServletRequest .title(requestTime + " 발생 에러 로그") .fields(List.of( generateSlackField("Request IP", xffHeader == null ? request.getRemoteAddr() : xffHeader), - generateSlackField("Request URL", request.getRequestURL() + " " + request.getMethod()), + generateSlackField("Request URL", request.getMethod() + " " + request.getRequestURL()), generateSlackField("Error Message", e.getMessage()) ) ) @@ -90,5 +88,4 @@ private Field generateSlackField(String title, String value) { .valueShortEnough(false) .build(); } - -} +} \ No newline at end of file From df76af0da795e439ec99ad35e510634215f556eb Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 22 Nov 2023 00:05:02 +0900 Subject: [PATCH 255/619] =?UTF-8?q?feat:=20=ED=8C=80=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=B2=98=EB=A6=AC=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/slack/team/TeamCreateHandler.java | 22 +++++++++++++++++++ .../slack/team/dto/TeamCreateEvent.java | 13 +++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java create mode 100644 src/main/java/com/moing/backend/global/config/slack/team/dto/TeamCreateEvent.java diff --git a/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java b/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java new file mode 100644 index 00000000..0985a3bc --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java @@ -0,0 +1,22 @@ +package com.moing.backend.global.config.slack.team; + +import com.moing.backend.global.config.slack.team.dto.TeamCreateEvent; +import com.moing.backend.global.config.slack.util.WebhookUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +@RequiredArgsConstructor +@Component +public class TeamCreateHandler { + + private final WebhookUtil webhookUtil; + + @Async("asyncTaskExecutor") + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onTeamCreateEvent(TeamCreateEvent event) { + webhookUtil.sendSlackTeamCreatedMessage(event.getTeamName(), event.getLeaderId()); + } +} diff --git a/src/main/java/com/moing/backend/global/config/slack/team/dto/TeamCreateEvent.java b/src/main/java/com/moing/backend/global/config/slack/team/dto/TeamCreateEvent.java new file mode 100644 index 00000000..7a896a62 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/slack/team/dto/TeamCreateEvent.java @@ -0,0 +1,13 @@ +package com.moing.backend.global.config.slack.team.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class TeamCreateEvent { + + private final String teamName; + private final Long leaderId; + +} From 26a099db1e942c474a8a9c0623d7340ae2ad31f3 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 22 Nov 2023 00:10:15 +0900 Subject: [PATCH 256/619] =?UTF-8?q?refactor:=20=ED=8C=80=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=8B=9C=20eventPublisher=EB=A1=9C=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=ED=95=B4=20slackService=20=EC=9D=98=EC=A1=B4=EC=84=B1?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/application/service/CreateTeamUserCase.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java index 1b6238a1..12a9b6b4 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java @@ -10,8 +10,9 @@ import com.moing.backend.domain.teamMember.domain.service.TeamMemberSaveService; import com.moing.backend.domain.teamScore.application.mapper.TeamScoreMapper; import com.moing.backend.domain.teamScore.domain.service.TeamScoreSaveService; -import com.moing.backend.global.util.SlackService; +import com.moing.backend.global.config.slack.team.dto.TeamCreateEvent; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.transaction.Transactional; @@ -27,7 +28,7 @@ public class CreateTeamUserCase { private final TeamMapper teamMapper; private final TeamScoreSaveService teamScoreSaveService; private final TeamScoreMapper teamScoreMapper; - private final SlackService slackService; + private final ApplicationEventPublisher eventPublisher; public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String socialId){ Member member = memberGetService.getMemberBySocialId(socialId); @@ -38,7 +39,7 @@ public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String team.approveTeam(); //====지워야 함 (테스트 용)===== teamScoreSaveService.save(teamScoreMapper.mapToTeamScore(team)); // 팀스코어 엔티티 생성 - slackService.sendSlackTeamCreatedMessage(team.getName(), team.getLeaderId()); + eventPublisher.publishEvent(new TeamCreateEvent(team.getName(), team.getLeaderId())); return new CreateTeamResponse(team.getTeamId()); } } From b0b093a0842871601d72b6ac78e5c488e69969dc Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 22 Nov 2023 00:10:30 +0900 Subject: [PATCH 257/619] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/ExceptionEventHandler.java | 21 +++++++++++++++++++ .../slack/exception/dto/ExceptionEvent.java | 14 +++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java create mode 100644 src/main/java/com/moing/backend/global/config/slack/exception/dto/ExceptionEvent.java diff --git a/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java b/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java new file mode 100644 index 00000000..7466ba76 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java @@ -0,0 +1,21 @@ +package com.moing.backend.global.config.slack.exception; + +import com.moing.backend.global.config.slack.exception.dto.ExceptionEvent; +import com.moing.backend.global.config.slack.util.WebhookUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +public class ExceptionEventHandler { + + private final WebhookUtil webhookUtil; + + @Async("asyncTaskExecutor") + @EventListener + public void onExceptionEvent(ExceptionEvent event) { + webhookUtil.sendSlackAlertErrorLog(event.getRequest(), event.getException()); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/config/slack/exception/dto/ExceptionEvent.java b/src/main/java/com/moing/backend/global/config/slack/exception/dto/ExceptionEvent.java new file mode 100644 index 00000000..b044d749 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/slack/exception/dto/ExceptionEvent.java @@ -0,0 +1,14 @@ +package com.moing.backend.global.config.slack.exception.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import javax.servlet.http.HttpServletRequest; + +@Getter +@AllArgsConstructor +public class ExceptionEvent { + + private final HttpServletRequest request; + private final Exception exception; +} From 27495f240e6d43b6f95c7ab391b6c019baf15a54 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 22 Nov 2023 00:10:47 +0900 Subject: [PATCH 258/619] =?UTF-8?q?refactor:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=20=EC=8B=9C=20eventPublisher=EB=A1=9C=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=ED=95=B4=20slackService=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/global/exception/GlobalExceptionHandler.java | 9 +++++---- .../com/moing/backend/config/CommonControllerTest.java | 4 ---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java b/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java index 04298e10..d48461eb 100644 --- a/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/moing/backend/global/exception/GlobalExceptionHandler.java @@ -1,10 +1,12 @@ package com.moing.backend.global.exception; +import com.moing.backend.global.config.slack.exception.dto.ExceptionEvent; import com.moing.backend.global.response.ErrorCode; import com.moing.backend.global.response.ErrorResponse; -import com.moing.backend.global.util.SlackService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; @@ -12,7 +14,6 @@ import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.context.support.DefaultMessageSourceResolvable; import javax.servlet.http.HttpServletRequest; import java.util.function.Consumer; @@ -25,7 +26,7 @@ public class GlobalExceptionHandler { private static final String LOG_FORMAT = "Class : {}, Code : {}, Message : {}"; - private final SlackService slackService; + private final ApplicationEventPublisher eventPublisher; @ExceptionHandler(ApplicationException.class) public ResponseEntity handleApplicationException(ApplicationException ex) { @@ -57,7 +58,7 @@ public ResponseEntity httpRequestNotSupportedExceptionHandler(Htt @ExceptionHandler(Exception.class) public ResponseEntity internalServerErrorHandler(Exception ex, HttpServletRequest request) { - slackService.sendSlackAlertErrorLog(ex, request); + eventPublisher.publishEvent(new ExceptionEvent(request, ex)); return handleException(ex, ErrorCode.INTERNAL_SERVER_ERROR, ErrorCode.INTERNAL_SERVER_ERROR.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR, log::error); } diff --git a/src/test/java/com/moing/backend/config/CommonControllerTest.java b/src/test/java/com/moing/backend/config/CommonControllerTest.java index 893b51c5..50f698fa 100644 --- a/src/test/java/com/moing/backend/config/CommonControllerTest.java +++ b/src/test/java/com/moing/backend/config/CommonControllerTest.java @@ -8,7 +8,6 @@ import com.moing.backend.global.config.security.filter.JwtAuthenticationEntryPoint; import com.moing.backend.global.config.security.jwt.TokenUtil; import com.moing.backend.global.config.security.util.AuthenticationUtil; -import com.moing.backend.global.util.SlackService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -58,9 +57,6 @@ public class CommonControllerTest { @MockBean public MemberGetService memberQueryService; - @MockBean - private SlackService slackService; - @BeforeEach public void setUp(final WebApplicationContext context, final RestDocumentationContextProvider provider) throws Exception { From 0bc7ac2b89c05d5af2317ce66dd8b702920c2bb5 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 22 Nov 2023 22:38:45 +0900 Subject: [PATCH 259/619] =?UTF-8?q?refactor:=20UserCase=20->=20UseCase?= =?UTF-8?q?=EB=A1=9C=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...serCase.java => CheckNicknameUseCase.java} | 2 +- ...thUserCase.java => MemberAuthUseCase.java} | 3 +-- ...UserCase.java => ReissueTokenUseCase.java} | 3 +-- ...SignInUserCase.java => SignInUseCase.java} | 4 +-- ...SignUpUserCase.java => SignUpUseCase.java} | 2 +- .../auth/presentation/AuthController.java | 26 ++++++------------- ...dUserCase.java => CreateBoardUseCase.java} | 18 ++++++------- ...dUserCase.java => DeleteBoardUseCase.java} | 2 +- ...oardUserCase.java => GetBoardUseCase.java} | 8 +++--- ...erCase.java => SendBoardAlarmUseCase.java} | 2 +- ...dUserCase.java => UpdateBoardUseCase.java} | 2 +- .../board/presentation/BoardController.java | 26 +++++++++---------- ...se.java => CreateBoardCommentUseCase.java} | 2 +- ...se.java => DeleteBoardCommentUseCase.java} | 2 +- ...rCase.java => GetBoardCommentUseCase.java} | 2 +- .../presentattion/BoardCommentController.java | 18 ++++++------- ...rCase.java => CreateBoardReadUseCase.java} | 2 +- .../{AlarmUserCase.java => AlarmUseCase.java} | 2 +- ...ageUserCase.java => GetMyPageUseCase.java} | 2 +- ...ofileUserCase.java => ProfileUseCase.java} | 2 +- ...gnOutUserCase.java => SignOutUseCase.java} | 4 +-- ...drawUserCase.java => WithdrawUseCase.java} | 6 +---- .../mypage/presentation/MyPageController.java | 20 +++++++------- ...rUserCase.java => CheckLeaderUseCase.java} | 2 +- ...amUserCase.java => CreateTeamUseCase.java} | 2 +- ...mUserCase.java => DisbandTeamUseCase.java} | 8 +++--- ...tTeamUserCase.java => GetTeamUseCase.java} | 2 +- ...amUserCase.java => ReviewTeamUseCase.java} | 2 +- ...amUserCase.java => SignInTeamUseCase.java} | 3 +-- ...amUserCase.java => UpdateTeamUseCase.java} | 6 ++--- ...UserCase.java => WithdrawTeamUseCase.java} | 4 +-- 31 files changed, 83 insertions(+), 106 deletions(-) rename src/main/java/com/moing/backend/domain/auth/application/service/{CheckNicknameUserCase.java => CheckNicknameUseCase.java} (94%) rename src/main/java/com/moing/backend/domain/auth/application/service/{MemberAuthUserCase.java => MemberAuthUseCase.java} (94%) rename src/main/java/com/moing/backend/domain/auth/application/service/{ReissueTokenUserCase.java => ReissueTokenUseCase.java} (96%) rename src/main/java/com/moing/backend/domain/auth/application/service/{SignInUserCase.java => SignInUseCase.java} (97%) rename src/main/java/com/moing/backend/domain/auth/application/service/{SignUpUserCase.java => SignUpUseCase.java} (98%) rename src/main/java/com/moing/backend/domain/board/application/service/{CreateBoardUserCase.java => CreateBoardUseCase.java} (74%) rename src/main/java/com/moing/backend/domain/board/application/service/{DeleteBoardUserCase.java => DeleteBoardUseCase.java} (96%) rename src/main/java/com/moing/backend/domain/board/application/service/{GetBoardUserCase.java => GetBoardUseCase.java} (88%) rename src/main/java/com/moing/backend/domain/board/application/service/{SendBoardAlarmUserCase.java => SendBoardAlarmUseCase.java} (97%) rename src/main/java/com/moing/backend/domain/board/application/service/{UpdateBoardUserCase.java => UpdateBoardUseCase.java} (97%) rename src/main/java/com/moing/backend/domain/boardComment/application/service/{CreateBoardCommentUserCase.java => CreateBoardCommentUseCase.java} (97%) rename src/main/java/com/moing/backend/domain/boardComment/application/service/{DeleteBoardCommentUserCase.java => DeleteBoardCommentUseCase.java} (97%) rename src/main/java/com/moing/backend/domain/boardComment/application/service/{GetBoardCommentUserCase.java => GetBoardCommentUseCase.java} (96%) rename src/main/java/com/moing/backend/domain/boardRead/application/service/{CreateBoardReadUserCase.java => CreateBoardReadUseCase.java} (96%) rename src/main/java/com/moing/backend/domain/mypage/application/service/{AlarmUserCase.java => AlarmUseCase.java} (98%) rename src/main/java/com/moing/backend/domain/mypage/application/service/{GetMyPageUserCase.java => GetMyPageUseCase.java} (98%) rename src/main/java/com/moing/backend/domain/mypage/application/service/{ProfileUserCase.java => ProfileUseCase.java} (98%) rename src/main/java/com/moing/backend/domain/mypage/application/service/{SignOutUserCase.java => SignOutUseCase.java} (76%) rename src/main/java/com/moing/backend/domain/mypage/application/service/{WithdrawUserCase.java => WithdrawUseCase.java} (86%) rename src/main/java/com/moing/backend/domain/team/application/service/{CheckLeaderUserCase.java => CheckLeaderUseCase.java} (93%) rename src/main/java/com/moing/backend/domain/team/application/service/{CreateTeamUserCase.java => CreateTeamUseCase.java} (98%) rename src/main/java/com/moing/backend/domain/team/application/service/{DisbandTeamUserCase.java => DisbandTeamUseCase.java} (78%) rename src/main/java/com/moing/backend/domain/team/application/service/{GetTeamUserCase.java => GetTeamUseCase.java} (98%) rename src/main/java/com/moing/backend/domain/team/application/service/{ReviewTeamUserCase.java => ReviewTeamUseCase.java} (96%) rename src/main/java/com/moing/backend/domain/team/application/service/{SignInTeamUserCase.java => SignInTeamUseCase.java} (91%) rename src/main/java/com/moing/backend/domain/team/application/service/{UpdateTeamUserCase.java => UpdateTeamUseCase.java} (90%) rename src/main/java/com/moing/backend/domain/team/application/service/{WithdrawTeamUserCase.java => WithdrawTeamUseCase.java} (87%) diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUseCase.java similarity index 94% rename from src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUseCase.java index 73b80f8c..89c292b6 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUseCase.java @@ -10,7 +10,7 @@ @Service @Transactional @RequiredArgsConstructor -public class CheckNicknameUserCase { +public class CheckNicknameUseCase { private final MemberCheckService memberCheckService; public CheckNicknameResponse checkNickname(String nickname){ diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUseCase.java similarity index 94% rename from src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUseCase.java index 9413d73d..12a85a5b 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUseCase.java @@ -7,12 +7,11 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; -import java.util.Optional; @Service @Transactional @RequiredArgsConstructor -public class MemberAuthUserCase { +public class MemberAuthUseCase { private final MemberSaveService memberSaveService; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUseCase.java similarity index 96% rename from src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUseCase.java index 5167d875..b4517a44 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUseCase.java @@ -12,14 +12,13 @@ @Service @Transactional @RequiredArgsConstructor -public class ReissueTokenUserCase { +public class ReissueTokenUseCase { private final TokenUtil tokenUtil; public ReissueTokenResponse reissueToken(String token) { // refresh 토큰이 유효한지 확인 if (token != null && tokenUtil.verifyToken(token)) { - // 토큰 새로 받아오기 TokenInfoResponse newToken = tokenUtil.tokenReissue(token); diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUseCase.java similarity index 97% rename from src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/SignInUseCase.java index 205bfbd1..818395b2 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/SignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignInUseCase.java @@ -17,9 +17,9 @@ @Service @Transactional @RequiredArgsConstructor -public class SignInUserCase { +public class SignInUseCase { - private final MemberAuthUserCase internalAuthService; + private final MemberAuthUseCase internalAuthService; private final TokenUtil tokenUtil; private final Map signInProviders; private final MemberGetService memberGetService; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUseCase.java similarity index 98% rename from src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/SignUpUseCase.java index 195ce705..f1e3d24d 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/SignUpUseCase.java @@ -18,7 +18,7 @@ @Service @Transactional @RequiredArgsConstructor -public class SignUpUserCase { +public class SignUpUseCase { private final TokenUtil tokenUtil; private final MemberGetService memberQueryService; diff --git a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java index 30b82f0f..4f459e26 100644 --- a/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java +++ b/src/main/java/com/moing/backend/domain/auth/presentation/AuthController.java @@ -6,25 +6,17 @@ import com.moing.backend.domain.auth.application.dto.response.CheckNicknameResponse; import com.moing.backend.domain.auth.application.dto.response.ReissueTokenResponse; import com.moing.backend.domain.auth.application.dto.response.SignInResponse; -import com.moing.backend.domain.auth.application.service.CheckNicknameUserCase; -import com.moing.backend.domain.auth.application.service.ReissueTokenUserCase; -import com.moing.backend.domain.auth.application.service.SignInUserCase; -import com.moing.backend.domain.auth.application.service.SignUpUserCase; +import com.moing.backend.domain.auth.application.service.CheckNicknameUseCase; +import com.moing.backend.domain.auth.application.service.ReissueTokenUseCase; +import com.moing.backend.domain.auth.application.service.SignInUseCase; +import com.moing.backend.domain.auth.application.service.SignUpUseCase; import com.moing.backend.global.response.SuccessResponse; -import com.moing.backend.global.response.TokenInfoResponse; import lombok.AllArgsConstructor; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; -import java.net.URI; -import java.net.URISyntaxException; - import static com.moing.backend.domain.auth.presentation.constant.AuthResponseMessage.*; @RestController @@ -32,12 +24,10 @@ @RequestMapping("/api/auth") public class AuthController { - private final SignInUserCase authService; - - private final SignUpUserCase signUpService; - - private final ReissueTokenUserCase reissueTokenService; - private final CheckNicknameUserCase checkNicknameService; + private final SignInUseCase authService; + private final SignUpUseCase signUpService; + private final ReissueTokenUseCase reissueTokenService; + private final CheckNicknameUseCase checkNicknameService; /** * 소셜 로그인 (애플/ 카카오/구글) diff --git a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java similarity index 74% rename from src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java rename to src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java index c6e401c0..59d989f9 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java @@ -5,8 +5,8 @@ import com.moing.backend.domain.board.application.mapper.BoardMapper; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardSaveService; -import com.moing.backend.domain.boardRead.application.service.CreateBoardReadUserCase; -import com.moing.backend.domain.team.application.service.CheckLeaderUserCase; +import com.moing.backend.domain.boardRead.application.service.CreateBoardReadUseCase; +import com.moing.backend.domain.team.application.service.CheckLeaderUseCase; import com.moing.backend.global.response.BaseServiceResponse; import com.moing.backend.global.util.BaseService; import lombok.RequiredArgsConstructor; @@ -17,15 +17,15 @@ @Service @Transactional @RequiredArgsConstructor -public class CreateBoardUserCase { +public class CreateBoardUseCase { private final BoardSaveService boardSaveService; - private final CheckLeaderUserCase checkLeaderUserCase; + private final CheckLeaderUseCase checkLeaderUseCase; private final BoardMapper boardMapper; - private final CreateBoardReadUserCase createBoardReadUserCase; + private final CreateBoardReadUseCase createBoardReadUseCase; private final BaseService baseService; - private final SendBoardAlarmUserCase sendBoardAlarmUserCase; + private final SendBoardAlarmUseCase sendBoardAlarmUseCase; /** * 게시글 생성 @@ -33,14 +33,14 @@ public class CreateBoardUserCase { public CreateBoardResponse createBoard(String socialId, Long teamId, CreateBoardRequest createBoardRequest) { //1, 게시글 생성, 저장 BaseServiceResponse data=baseService.getCommonData(socialId, teamId); - boolean isLeader = checkLeaderUserCase.isTeamLeader(data.getMember(), data.getTeam()); //작성자 리더 여부 + boolean isLeader = checkLeaderUseCase.isTeamLeader(data.getMember(), data.getTeam()); //작성자 리더 여부 Board board=boardSaveService.saveBoard(boardMapper.toBoard(data.getMember(), data.getTeamMember(), data.getTeam(), createBoardRequest, isLeader)); //2. 읽음 처리 - 생성한 사람은 무조건 읽음 - createBoardReadUserCase.createBoardRead(data.getTeam(), data.getMember(), board); + createBoardReadUseCase.createBoardRead(data.getTeam(), data.getMember(), board); //3. 알림 보내기 - 공지인 경우 - sendBoardAlarmUserCase.sendNewUploadAlarm(data, board); + sendBoardAlarmUseCase.sendNewUploadAlarm(data, board); return new CreateBoardResponse(board.getBoardId()); } } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUseCase.java similarity index 96% rename from src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java rename to src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUseCase.java index 0274a771..46549472 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUseCase.java @@ -12,7 +12,7 @@ @Service @Transactional @RequiredArgsConstructor -public class DeleteBoardUserCase { +public class DeleteBoardUseCase { private final BaseBoardService baseBoardService; private final BoardDeleteService boardDeleteService; diff --git a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java similarity index 88% rename from src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java rename to src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java index e72be8e8..6fe4e3cb 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java @@ -4,7 +4,7 @@ import com.moing.backend.domain.board.application.dto.response.GetBoardDetailResponse; import com.moing.backend.domain.board.application.mapper.BoardMapper; import com.moing.backend.domain.board.domain.service.BoardGetService; -import com.moing.backend.domain.boardRead.application.service.CreateBoardReadUserCase; +import com.moing.backend.domain.boardRead.application.service.CreateBoardReadUseCase; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.global.response.BaseBoardServiceResponse; @@ -17,13 +17,13 @@ @Service @Transactional @RequiredArgsConstructor -public class GetBoardUserCase { +public class GetBoardUseCase { private final BaseBoardService baseBoardService; private final BoardMapper boardMapper; private final MemberGetService memberGetService; - private final CreateBoardReadUserCase createBoardReadUserCase; + private final CreateBoardReadUseCase createBoardReadUseCase; private final BoardGetService boardGetService; @@ -34,7 +34,7 @@ public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long // 1. 게시글 조회 BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); // 2. 읽음 처리 - createBoardReadUserCase.createBoardRead(data.getTeam(), data.getMember(), data.getBoard()); + createBoardReadUseCase.createBoardRead(data.getTeam(), data.getMember(), data.getBoard()); return boardMapper.toBoardDetail(data.getBoard(), data.getTeamMember() == data.getBoard().getTeamMember()); } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java similarity index 97% rename from src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUserCase.java rename to src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index 94efba16..221c28d8 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -19,7 +19,7 @@ @Service @RequiredArgsConstructor @Transactional -public class SendBoardAlarmUserCase { +public class SendBoardAlarmUseCase { private final TeamMemberGetService teamMemberGetService; private final FcmService fcmService; diff --git a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUseCase.java similarity index 97% rename from src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java rename to src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUseCase.java index 21e20b91..32e2bc02 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUserCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUseCase.java @@ -13,7 +13,7 @@ @Service @Transactional @RequiredArgsConstructor -public class UpdateBoardUserCase { +public class UpdateBoardUseCase { private final BaseBoardService baseBoardService; diff --git a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java index 26443cca..739935e4 100644 --- a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java +++ b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java @@ -6,10 +6,10 @@ import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; import com.moing.backend.domain.board.application.dto.response.GetBoardDetailResponse; import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; -import com.moing.backend.domain.board.application.service.CreateBoardUserCase; -import com.moing.backend.domain.board.application.service.DeleteBoardUserCase; -import com.moing.backend.domain.board.application.service.GetBoardUserCase; -import com.moing.backend.domain.board.application.service.UpdateBoardUserCase; +import com.moing.backend.domain.board.application.service.CreateBoardUseCase; +import com.moing.backend.domain.board.application.service.DeleteBoardUseCase; +import com.moing.backend.domain.board.application.service.GetBoardUseCase; +import com.moing.backend.domain.board.application.service.UpdateBoardUseCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -26,10 +26,10 @@ @RequestMapping("/api/{teamId}/board") public class BoardController { - private final CreateBoardUserCase createBoardUserCase; - private final UpdateBoardUserCase updateBoardUserCase; - private final GetBoardUserCase getBoardUserCase; - private final DeleteBoardUserCase deleteBoardUserCase; + private final CreateBoardUseCase createBoardUseCase; + private final UpdateBoardUseCase updateBoardUseCase; + private final GetBoardUseCase getBoardUseCase; + private final DeleteBoardUseCase deleteBoardUseCase; /** * 게시글 생성 @@ -40,7 +40,7 @@ public class BoardController { public ResponseEntity> createBoard(@AuthenticationPrincipal User user, @PathVariable Long teamId, @Valid @RequestBody CreateBoardRequest createBoardRequest) { - return ResponseEntity.ok(SuccessResponse.create(CREATE_BOARD_SUCCESS.getMessage(), this.createBoardUserCase.createBoard(user.getSocialId(), teamId, createBoardRequest))); + return ResponseEntity.ok(SuccessResponse.create(CREATE_BOARD_SUCCESS.getMessage(), this.createBoardUseCase.createBoard(user.getSocialId(), teamId, createBoardRequest))); } /** @@ -53,7 +53,7 @@ public ResponseEntity> updateBoard(@Authent @PathVariable Long teamId, @PathVariable Long boardId, @Valid @RequestBody UpdateBoardRequest updateBoardRequest) { - return ResponseEntity.ok(SuccessResponse.create(UPDATE_BOARD_SUCCESS.getMessage(), this.updateBoardUserCase.updateBoard(user.getSocialId(), teamId, boardId, updateBoardRequest))); + return ResponseEntity.ok(SuccessResponse.create(UPDATE_BOARD_SUCCESS.getMessage(), this.updateBoardUseCase.updateBoard(user.getSocialId(), teamId, boardId, updateBoardRequest))); } /** @@ -65,7 +65,7 @@ public ResponseEntity> updateBoard(@Authent public ResponseEntity deleteBoard(@AuthenticationPrincipal User user, @PathVariable Long teamId, @PathVariable Long boardId) { - this.deleteBoardUserCase.deleteBoard(user.getSocialId(), teamId, boardId); + this.deleteBoardUseCase.deleteBoard(user.getSocialId(), teamId, boardId); return ResponseEntity.ok(SuccessResponse.create(DELETE_BOARD_SUCCESS.getMessage())); } @@ -78,7 +78,7 @@ public ResponseEntity deleteBoard(@AuthenticationPrincipal User public ResponseEntity> getBoardDetail(@AuthenticationPrincipal User user, @PathVariable Long teamId, @PathVariable Long boardId) { - return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_DETAIL_SUCCESS.getMessage(), this.getBoardUserCase.getBoardDetail(user.getSocialId(), teamId, boardId))); + return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_DETAIL_SUCCESS.getMessage(), this.getBoardUseCase.getBoardDetail(user.getSocialId(), teamId, boardId))); } /** @@ -89,6 +89,6 @@ public ResponseEntity> getBoardDetail(@A @GetMapping public ResponseEntity> getBoardAll(@AuthenticationPrincipal User user, @PathVariable Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_ALL_SUCCESS.getMessage(), this.getBoardUserCase.getAllBoard(user.getSocialId(), teamId))); + return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_ALL_SUCCESS.getMessage(), this.getBoardUseCase.getAllBoard(user.getSocialId(), teamId))); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java similarity index 97% rename from src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java rename to src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java index 23e1d12b..6245acfe 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java @@ -15,7 +15,7 @@ @Service @RequiredArgsConstructor @Transactional -public class CreateBoardCommentUserCase { +public class CreateBoardCommentUseCase { private final BoardCommentSaveService boardCommentSaveService; private final BoardCommentMapper boardCommentMapper; diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java similarity index 97% rename from src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java rename to src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java index 2f0285c3..7f06ffb2 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java @@ -14,7 +14,7 @@ @Service @Transactional @RequiredArgsConstructor -public class DeleteBoardCommentUserCase { +public class DeleteBoardCommentUseCase { private final BoardCommentGetService boardCommentGetService; private final BoardCommentDeleteService boardCommentDeleteService; diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java similarity index 96% rename from src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java rename to src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java index 544c5174..fda15898 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java @@ -12,7 +12,7 @@ @Service @Transactional @RequiredArgsConstructor -public class GetBoardCommentUserCase { +public class GetBoardCommentUseCase { private final BoardCommentGetService boardCommentGetService; private final BaseBoardService baseBoardService; diff --git a/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java b/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java index 1ba471ca..506d9250 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java +++ b/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java @@ -3,9 +3,9 @@ import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; import com.moing.backend.domain.boardComment.application.dto.response.CreateBoardCommentResponse; import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; -import com.moing.backend.domain.boardComment.application.service.CreateBoardCommentUserCase; -import com.moing.backend.domain.boardComment.application.service.DeleteBoardCommentUserCase; -import com.moing.backend.domain.boardComment.application.service.GetBoardCommentUserCase; +import com.moing.backend.domain.boardComment.application.service.CreateBoardCommentUseCase; +import com.moing.backend.domain.boardComment.application.service.DeleteBoardCommentUseCase; +import com.moing.backend.domain.boardComment.application.service.GetBoardCommentUseCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -24,9 +24,9 @@ @RequestMapping("/api/{teamId}/{boardId}/comment") public class BoardCommentController { - private final CreateBoardCommentUserCase createBoardCommentUserCase; - private final DeleteBoardCommentUserCase deleteBoardCommentUserCase; - private final GetBoardCommentUserCase getBoardCommentUserCase; + private final CreateBoardCommentUseCase createBoardCommentUseCase; + private final DeleteBoardCommentUseCase deleteBoardCommentUseCase; + private final GetBoardCommentUseCase getBoardCommentUseCase; /** * 댓글 생성 @@ -38,7 +38,7 @@ public ResponseEntity> createBoardCo @PathVariable Long teamId, @PathVariable Long boardId, @Valid @RequestBody CreateBoardCommentRequest createBoardCommentRequest) { - return ResponseEntity.ok(SuccessResponse.create(CREATE_BOARD_COMMENT_SUCCESS.getMessage(), this.createBoardCommentUserCase.createBoardComment(user.getSocialId(), teamId, boardId, createBoardCommentRequest))); + return ResponseEntity.ok(SuccessResponse.create(CREATE_BOARD_COMMENT_SUCCESS.getMessage(), this.createBoardCommentUseCase.createBoardComment(user.getSocialId(), teamId, boardId, createBoardCommentRequest))); } /** @@ -51,7 +51,7 @@ public ResponseEntity deleteBoardComment(@AuthenticationPrincip @PathVariable Long teamId, @PathVariable Long boardId, @PathVariable Long commentId) { - this.deleteBoardCommentUserCase.deleteBoardComment(user.getSocialId(), teamId, boardId, commentId); + this.deleteBoardCommentUseCase.deleteBoardComment(user.getSocialId(), teamId, boardId, commentId); return ResponseEntity.ok(SuccessResponse.create(DELETE_BOARD_COMMENT_SUCCESS.getMessage())); } @@ -65,6 +65,6 @@ public ResponseEntity deleteBoardComment(@AuthenticationPrincip public ResponseEntity> getBoardCommentAll(@AuthenticationPrincipal User user, @PathVariable Long teamId, @PathVariable Long boardId) { - return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_ALL_SUCCESS.getMessage(), this.getBoardCommentUserCase.getBoardCommentAll(user.getSocialId(), teamId, boardId))); + return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_ALL_SUCCESS.getMessage(), this.getBoardCommentUseCase.getBoardCommentAll(user.getSocialId(), teamId, boardId))); } } diff --git a/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java b/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUseCase.java similarity index 96% rename from src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java rename to src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUseCase.java index 9c55a2fc..d1146dd9 100644 --- a/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUserCase.java +++ b/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUseCase.java @@ -14,7 +14,7 @@ @Service @Transactional @RequiredArgsConstructor -public class CreateBoardReadUserCase { +public class CreateBoardReadUseCase { private final BoardReadMapper boardReadMapper; private final BoardReadSaveService boardReadSaveService; diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java similarity index 98% rename from src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java rename to src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java index 1d9c7a6e..2ad0e803 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java @@ -12,7 +12,7 @@ @Service @Transactional @RequiredArgsConstructor -public class AlarmUserCase { +public class AlarmUseCase { private final MemberGetService memberGetService; diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java similarity index 98% rename from src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUserCase.java rename to src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java index 818d1843..544aa3fc 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java @@ -17,7 +17,7 @@ @Service @Transactional @RequiredArgsConstructor -public class GetMyPageUserCase { +public class GetMyPageUseCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java similarity index 98% rename from src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java rename to src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java index dc7e9991..fc7c88ca 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java @@ -12,7 +12,7 @@ @Service @RequiredArgsConstructor -public class ProfileUserCase { +public class ProfileUseCase { private final MemberGetService memberGetService; private final S3Service s3Service; diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java similarity index 76% rename from src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java rename to src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java index 441a6db7..26180396 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java @@ -1,15 +1,13 @@ package com.moing.backend.domain.mypage.application.service; -import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.config.security.jwt.TokenUtil; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor -public class SignOutUserCase { +public class SignOutUseCase { private final TokenUtil tokenUtil; private final MemberGetService memberGetService; diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUseCase.java similarity index 86% rename from src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java rename to src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUseCase.java index 02ee59dc..02e1b99e 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUseCase.java @@ -1,16 +1,12 @@ package com.moing.backend.domain.mypage.application.service; -import com.moing.backend.domain.auth.application.service.SignInProvider; import com.moing.backend.domain.auth.application.service.WithdrawProvider; import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberDeleteService; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mypage.application.dto.request.WithdrawRequest; import com.moing.backend.domain.mypage.domain.service.FeedbackSaveService; import com.moing.backend.domain.mypage.exception.ExistingTeamException; import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.global.config.security.jwt.TokenUtil; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,7 +16,7 @@ @Service @RequiredArgsConstructor -public class WithdrawUserCase { +public class WithdrawUseCase { private final MemberGetService memberGetService; private final FeedbackSaveService feedbackSaveService; diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java index deb82e9b..afbfea24 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java @@ -24,11 +24,11 @@ @RequestMapping("/api/mypage") public class MyPageController { - private final SignOutUserCase signOutService; - private final WithdrawUserCase withdrawService; - private final ProfileUserCase profileUserCase; - private final AlarmUserCase alarmUserCase; - private final GetMyPageUserCase getMyPageUserCase; + private final SignOutUseCase signOutService; + private final WithdrawUseCase withdrawService; + private final ProfileUseCase profileUseCase; + private final AlarmUseCase alarmUseCase; + private final GetMyPageUseCase getMyPageUseCase; /** * 로그아웃 @@ -61,7 +61,7 @@ public ResponseEntity withdraw(@AuthenticationPrincipal User us */ @GetMapping public ResponseEntity> getMyPage(@AuthenticationPrincipal User user){ - return ResponseEntity.ok(SuccessResponse.create(GET_MYPAGE_SUCCESS.getMessage(), this.getMyPageUserCase.getMyPageResponse(user.getSocialId()))); + return ResponseEntity.ok(SuccessResponse.create(GET_MYPAGE_SUCCESS.getMessage(), this.getMyPageUseCase.getMyPageResponse(user.getSocialId()))); } /** @@ -71,7 +71,7 @@ public ResponseEntity> getMyPage(@Authenticat */ @GetMapping("/profile") public ResponseEntity> getProfile(@AuthenticationPrincipal User user){ - return ResponseEntity.ok(SuccessResponse.create(GET_PROFILE_SUCCESS.getMessage(), this.profileUserCase.getProfile(user.getSocialId()))); + return ResponseEntity.ok(SuccessResponse.create(GET_PROFILE_SUCCESS.getMessage(), this.profileUseCase.getProfile(user.getSocialId()))); } /** @@ -82,7 +82,7 @@ public ResponseEntity> getProfile(@Authentic @PutMapping("/profile") public ResponseEntity updatePorfile(@AuthenticationPrincipal User user, @RequestBody UpdateProfileRequest updateProfileRequest){ - this.profileUserCase.updateProfile(user.getSocialId(), updateProfileRequest); + this.profileUseCase.updateProfile(user.getSocialId(), updateProfileRequest); return ResponseEntity.ok(SuccessResponse.create(UPDATE_PROFILE_SUCCESS.getMessage())); } @@ -93,7 +93,7 @@ public ResponseEntity updatePorfile(@AuthenticationPrincipal Us */ @GetMapping("/alarm") public ResponseEntity> getAlarm(@AuthenticationPrincipal User user) { - return ResponseEntity.ok(SuccessResponse.create(GET_ALARM_SUCCESS.getMessage(), this.alarmUserCase.getAlarm(user.getSocialId()))); + return ResponseEntity.ok(SuccessResponse.create(GET_ALARM_SUCCESS.getMessage(), this.alarmUseCase.getAlarm(user.getSocialId()))); } /** @@ -104,7 +104,7 @@ public ResponseEntity> getAlarm(@Authenticatio public ResponseEntity> updateAlarm(@AuthenticationPrincipal User user, @RequestParam(name = "type") String type, @RequestParam(name = "status") String status) { - return ResponseEntity.ok(SuccessResponse.create(UPDATE_PROFILE_SUCCESS.getMessage(), this.alarmUserCase.updateAlarm(user.getSocialId(), type, status))); + return ResponseEntity.ok(SuccessResponse.create(UPDATE_PROFILE_SUCCESS.getMessage(), this.alarmUseCase.updateAlarm(user.getSocialId(), type, status))); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUseCase.java similarity index 93% rename from src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java rename to src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUseCase.java index b397a9e9..f703245f 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUseCase.java @@ -11,7 +11,7 @@ @Service @Transactional @RequiredArgsConstructor -public class CheckLeaderUserCase { +public class CheckLeaderUseCase { public boolean isTeamLeader(Member member, Team team) { return Objects.equals(member.getMemberId(), team.getLeaderId()); } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java similarity index 98% rename from src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java rename to src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java index 12a9b6b4..027838c4 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java @@ -20,7 +20,7 @@ @Service @Transactional @RequiredArgsConstructor -public class CreateTeamUserCase { +public class CreateTeamUseCase { private final MemberGetService memberGetService; private final TeamSaveService teamSaveService; diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java similarity index 78% rename from src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java rename to src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java index 82fdae48..4abde79f 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java @@ -2,9 +2,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; -import com.moing.backend.domain.team.application.mapper.TeamMapper; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.team.exception.NotAuthByTeamException; @@ -16,17 +14,17 @@ @Service @Transactional @RequiredArgsConstructor -public class DisbandTeamUserCase { +public class DisbandTeamUseCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; - private final CheckLeaderUserCase checkLeaderUserCase; + private final CheckLeaderUseCase checkLeaderUseCase; public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); - if (checkLeaderUserCase.isTeamLeader(member, team)) { + if (checkLeaderUseCase.isTeamLeader(member, team)) { team.deleteTeam(); } else { throw new NotAuthByTeamException(); diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java similarity index 98% rename from src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java rename to src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java index a5b501d0..9af285f2 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java @@ -20,7 +20,7 @@ @Service @Transactional @RequiredArgsConstructor -public class GetTeamUserCase { +public class GetTeamUseCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; private final BoardGetService boardGetService; diff --git a/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java similarity index 96% rename from src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUserCase.java rename to src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java index 3c7c477e..9647aedf 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java @@ -13,7 +13,7 @@ @Service @RequiredArgsConstructor @Transactional -public class ReviewTeamUserCase { +public class ReviewTeamUseCase { private final TeamGetService teamGetService; private final TeamMapper teamMapper; diff --git a/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java similarity index 91% rename from src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUserCase.java rename to src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java index 8515ef61..093a098a 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java @@ -5,7 +5,6 @@ import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.domain.teamMember.domain.service.TeamMemberSaveService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,7 +14,7 @@ @Service @Transactional @RequiredArgsConstructor -public class SignInTeamUserCase { +public class SignInTeamUseCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; diff --git a/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java similarity index 90% rename from src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java rename to src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java index 6bce4860..91976f63 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java @@ -16,17 +16,17 @@ @Service @Transactional @RequiredArgsConstructor -public class UpdateTeamUserCase { +public class UpdateTeamUseCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; - private final CheckLeaderUserCase checkLeaderUserCase; + private final CheckLeaderUseCase checkLeaderUseCase; private final S3Service s3Service; public UpdateTeamResponse updateTeam(UpdateTeamRequest updateTeamRequest, String socialId, Long teamId){ Member member = memberGetService.getMemberBySocialId(socialId); Team team=teamGetService.getTeamByTeamId(teamId); - if (checkLeaderUserCase.isTeamLeader(member, team)) { + if (checkLeaderUseCase.isTeamLeader(member, team)) { s3Service.deleteImage(team.getProfileImgUrl()); team.updateTeam(updateTeamRequest.getName(), updateTeamRequest.getIntroduction(), updateTeamRequest.getProfileImgUrl()); } else { diff --git a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUseCase.java similarity index 87% rename from src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java rename to src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUseCase.java index 3e3a162d..e4e007eb 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUserCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUseCase.java @@ -2,9 +2,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; -import com.moing.backend.domain.team.application.mapper.TeamMapper; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; @@ -17,7 +15,7 @@ @Service @Transactional @RequiredArgsConstructor -public class WithdrawTeamUserCase { +public class WithdrawTeamUseCase { private final TeamMemberGetService teamMemberGetService; private final MemberGetService memberGetService; From 268e3d50be7f6f27356591abf11d16de3b8f41aa Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 22 Nov 2023 22:41:05 +0900 Subject: [PATCH 260/619] =?UTF-8?q?refactor:=20UserCase=20->=20UseCase?= =?UTF-8?q?=EB=A1=9C=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/presentation/AuthControllerTest.java | 18 +++++------ .../presentation/BoardControllerTest.java | 24 +++++++-------- .../BoardCommentControllerTest.java | 16 +++++----- .../presentation/MypageControllerTest.java | 18 +++++------ .../team/presentation/TeamControllerTest.java | 30 +++++++++---------- 5 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java index ffb90247..c7fe00a3 100644 --- a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java +++ b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java @@ -6,10 +6,10 @@ import com.moing.backend.domain.auth.application.dto.response.CheckNicknameResponse; import com.moing.backend.domain.auth.application.dto.response.ReissueTokenResponse; import com.moing.backend.domain.auth.application.dto.response.SignInResponse; -import com.moing.backend.domain.auth.application.service.CheckNicknameUserCase; -import com.moing.backend.domain.auth.application.service.ReissueTokenUserCase; -import com.moing.backend.domain.auth.application.service.SignInUserCase; -import com.moing.backend.domain.auth.application.service.SignUpUserCase; +import com.moing.backend.domain.auth.application.service.CheckNicknameUseCase; +import com.moing.backend.domain.auth.application.service.ReissueTokenUseCase; +import com.moing.backend.domain.auth.application.service.SignInUseCase; +import com.moing.backend.domain.auth.application.service.SignUpUseCase; import com.moing.backend.domain.member.domain.constant.Gender; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -33,16 +33,16 @@ class AuthControllerTest extends CommonControllerTest { @MockBean - private SignInUserCase authService; + private SignInUseCase authService; @MockBean - private SignUpUserCase signUpUserCase; + private SignUpUseCase signUpUserCase; @MockBean - private ReissueTokenUserCase reissueTokenUserCase; + private ReissueTokenUseCase reissueTokenUseCase; @MockBean - private CheckNicknameUserCase checkNicknameService; + private CheckNicknameUseCase checkNicknameService; @Test public void Kakao_소셜_로그인_회원가입_전() throws Exception { @@ -375,7 +375,7 @@ public void reissue_token() throws Exception { .refreshToken("SERVER_REFRESH_TOKEN") .build(); - given(reissueTokenUserCase.reissueToken(any())).willReturn(output); + given(reissueTokenUseCase.reissueToken(any())).willReturn(output); //when ResultActions actions = mockMvc.perform( diff --git a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java index 000a3f04..f93c223f 100644 --- a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java @@ -4,10 +4,10 @@ import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; import com.moing.backend.domain.board.application.dto.response.*; -import com.moing.backend.domain.board.application.service.CreateBoardUserCase; -import com.moing.backend.domain.board.application.service.DeleteBoardUserCase; -import com.moing.backend.domain.board.application.service.GetBoardUserCase; -import com.moing.backend.domain.board.application.service.UpdateBoardUserCase; +import com.moing.backend.domain.board.application.service.CreateBoardUseCase; +import com.moing.backend.domain.board.application.service.DeleteBoardUseCase; +import com.moing.backend.domain.board.application.service.GetBoardUseCase; +import com.moing.backend.domain.board.application.service.UpdateBoardUseCase; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -30,13 +30,13 @@ @WebMvcTest(BoardController.class) public class BoardControllerTest extends CommonControllerTest { @MockBean - private CreateBoardUserCase createBoardUserCase; + private CreateBoardUseCase createBoardUseCase; @MockBean - private UpdateBoardUserCase updateBoardUserCase; + private UpdateBoardUseCase updateBoardUseCase; @MockBean - private GetBoardUserCase getBoardUserCase; + private GetBoardUseCase getBoardUseCase; @MockBean - private DeleteBoardUserCase deleteBoardUserCase; + private DeleteBoardUseCase deleteBoardUseCase; @Test public void create_board() throws Exception { @@ -55,7 +55,7 @@ public void create_board() throws Exception { .boardId(1L) .build(); - given(createBoardUserCase.createBoard(any(), any(), any())).willReturn(output); + given(createBoardUseCase.createBoard(any(), any(), any())).willReturn(output); //when @@ -109,7 +109,7 @@ public void update_board() throws Exception { .boardId(1L) .build(); - given(updateBoardUserCase.updateBoard(any(), any(), any(), any())).willReturn(output); + given(updateBoardUseCase.updateBoard(any(), any(), any(), any())).willReturn(output); //when @@ -218,7 +218,7 @@ public void get_board_all() throws Exception { GetAllBoardResponse output = new GetAllBoardResponse(noticeBlocks.size(), noticeBlocks, notNoticeBlocks.size(), notNoticeBlocks); - given(getBoardUserCase.getAllBoard(any(), any())).willReturn(output); + given(getBoardUseCase.getAllBoard(any(), any())).willReturn(output); //when @@ -287,7 +287,7 @@ public void get_board_detail() throws Exception { .isNotice(false) .build(); - given(getBoardUserCase.getBoardDetail(any(), any(), any())).willReturn(output); + given(getBoardUseCase.getBoardDetail(any(), any(), any())).willReturn(output); //when diff --git a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java index 846fd443..3175bc6f 100644 --- a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java +++ b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java @@ -5,9 +5,9 @@ import com.moing.backend.domain.boardComment.application.dto.response.CommentBlocks; import com.moing.backend.domain.boardComment.application.dto.response.CreateBoardCommentResponse; import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; -import com.moing.backend.domain.boardComment.application.service.CreateBoardCommentUserCase; -import com.moing.backend.domain.boardComment.application.service.DeleteBoardCommentUserCase; -import com.moing.backend.domain.boardComment.application.service.GetBoardCommentUserCase; +import com.moing.backend.domain.boardComment.application.service.CreateBoardCommentUseCase; +import com.moing.backend.domain.boardComment.application.service.DeleteBoardCommentUseCase; +import com.moing.backend.domain.boardComment.application.service.GetBoardCommentUseCase; import com.moing.backend.domain.boardComment.presentattion.BoardCommentController; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -32,11 +32,11 @@ public class BoardCommentControllerTest extends CommonControllerTest { @MockBean - private CreateBoardCommentUserCase createBoardCommentUserCase; + private CreateBoardCommentUseCase createBoardCommentUseCase; @MockBean - private DeleteBoardCommentUserCase deleteBoardCommentUserCase; + private DeleteBoardCommentUseCase deleteBoardCommentUseCase; @MockBean - private GetBoardCommentUserCase getBoardCommentUserCase; + private GetBoardCommentUseCase getBoardCommentUseCase; @Test public void create_board_comment() throws Exception { @@ -54,7 +54,7 @@ public void create_board_comment() throws Exception { .boardCommentId(1L) .build(); - given(createBoardCommentUserCase.createBoardComment(any(), any(), any(), any())).willReturn(output); + given(createBoardCommentUseCase.createBoardComment(any(), any(), any(), any())).willReturn(output); //when @@ -148,7 +148,7 @@ public void get_board_comment_all() throws Exception { GetBoardCommentResponse output = new GetBoardCommentResponse(commentBlocks); - given(getBoardCommentUserCase.getBoardCommentAll(any(), any(), any())).willReturn(output); + given(getBoardCommentUseCase.getBoardCommentAll(any(), any(), any())).willReturn(output); //when diff --git a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java index 0e811495..c2932b6a 100644 --- a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java @@ -31,19 +31,19 @@ @WebMvcTest(MyPageController.class) public class MypageControllerTest extends CommonControllerTest { @MockBean - private SignOutUserCase signOutService; + private SignOutUseCase signOutService; @MockBean - private WithdrawUserCase withdrawService; + private WithdrawUseCase withdrawService; @MockBean - private ProfileUserCase profileUserCase; + private ProfileUseCase profileUseCase; @MockBean - private AlarmUserCase alarmUserCase; + private AlarmUseCase alarmUseCase; @MockBean - private GetMyPageUserCase getMyPageUserCase; + private GetMyPageUseCase getMyPageUseCase; @Test public void sign_out() throws Exception { @@ -136,7 +136,7 @@ public void get_mypage() throws Exception{ .getMyPageTeamBlocks(getMyPageTeamBlocks) .build(); - given(getMyPageUserCase.getMyPageResponse(any())).willReturn(output); + given(getMyPageUseCase.getMyPageResponse(any())).willReturn(output); //when ResultActions actions = mockMvc.perform( @@ -178,7 +178,7 @@ public void get_profile() throws Exception { .nickName("NICKNAME") .build(); - given(profileUserCase.getProfile(any())).willReturn(output); + given(profileUseCase.getProfile(any())).willReturn(output); //when ResultActions actions = mockMvc.perform( @@ -258,7 +258,7 @@ public void get_alarm() throws Exception { .isRemindPush(true) .build(); - given(alarmUserCase.getAlarm(any())).willReturn(output); + given(alarmUseCase.getAlarm(any())).willReturn(output); //when ResultActions actions = mockMvc.perform( @@ -296,7 +296,7 @@ public void update_alarm() throws Exception { .isRemindPush(true) .build(); - given(alarmUserCase.updateAlarm(any(),any(),any())).willReturn(output); + given(alarmUseCase.updateAlarm(any(),any(),any())).willReturn(output); //when ResultActions actions = mockMvc.perform( diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 386de94b..7ff3399b 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -31,19 +31,19 @@ @WebMvcTest(TeamController.class) public class TeamControllerTest extends CommonControllerTest { @MockBean - private CreateTeamUserCase createTeamService; + private CreateTeamUseCase createTeamService; @MockBean - private GetTeamUserCase getTeamUserCase; + private GetTeamUseCase getTeamUseCase; @MockBean - private DisbandTeamUserCase disbandTeamUserCase; + private DisbandTeamUseCase disbandTeamUseCase; @MockBean - private WithdrawTeamUserCase withdrawTeamUserCase; + private WithdrawTeamUseCase withdrawTeamUseCase; @MockBean - private SignInTeamUserCase signInTeamUserCase; + private SignInTeamUseCase signInTeamUseCase; @MockBean - private UpdateTeamUserCase updateTeamUserCase; + private UpdateTeamUseCase updateTeamUseCase; @MockBean - private ReviewTeamUserCase reviewTeamUserCase; + private ReviewTeamUseCase reviewTeamUseCase; @Test public void create_team() throws Exception { @@ -134,7 +134,7 @@ public void get_team() throws Exception { .teamBlocks(teamBlocks) .build(); - given(getTeamUserCase.getTeam(any())).willReturn(output); + given(getTeamUseCase.getTeam(any())).willReturn(output); //when @@ -204,7 +204,7 @@ public void get_team_detail() throws Exception { .build(); - given(getTeamUserCase.getTeamDetailResponse(any(),any())).willReturn(output); + given(getTeamUseCase.getTeamDetailResponse(any(),any())).willReturn(output); //when @@ -261,7 +261,7 @@ public void review_team() throws Exception { .levelOfFire(3) .build(); - given(reviewTeamUserCase.reviewTeam(any(), any())).willReturn(output); + given(reviewTeamUseCase.reviewTeam(any(), any())).willReturn(output); //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. @@ -303,7 +303,7 @@ public void disband_team() throws Exception { .teamId(teamId) .build(); - given(disbandTeamUserCase.disbandTeam(any(), any())).willReturn(output); + given(disbandTeamUseCase.disbandTeam(any(), any())).willReturn(output); //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. @@ -339,7 +339,7 @@ public void withdraw_team() throws Exception { .teamId(teamId) .build(); - given(withdrawTeamUserCase.withdrawTeam(any(), any())).willReturn(output); + given(withdrawTeamUseCase.withdrawTeam(any(), any())).willReturn(output); //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. @@ -376,7 +376,7 @@ public void signIn_team() throws Exception { .teamId(teamId) .build(); - given(signInTeamUserCase.signInTeam(any(), any())).willReturn(output); + given(signInTeamUseCase.signInTeam(any(), any())).willReturn(output); //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. @@ -425,7 +425,7 @@ public void update_team() throws Exception { .teamId(1L) .build(); - given(updateTeamUserCase.updateTeam(any(), any(), any())).willReturn(output); + given(updateTeamUseCase.updateTeam(any(), any(), any())).willReturn(output); //when @@ -474,7 +474,7 @@ public void get_current_status() throws Exception { .profileImgUrl("프로필 이미지") .build(); - given(getTeamUserCase.getCurrentStatus(any())).willReturn(output); + given(getTeamUseCase.getCurrentStatus(any())).willReturn(output); //when From 101c1339dc38418567c171f24bdbec4545d8b242 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 22 Nov 2023 22:43:54 +0900 Subject: [PATCH 261/619] =?UTF-8?q?feat:=20fcm=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=B3=B4=EB=82=B4=EA=B8=B0=20eventPublisher=EB=A1=9C=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=ED=95=A0=20=EC=88=98=20=EC=9E=88=EA=B2=8C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fcm/constant/ApproveTeamMessage.java | 22 ++++++++++++++ .../global/config/fcm/dto/event/FcmEvent.java | 16 ++++++++++ .../config/fcm/util/FcmMessageUtil.java | 29 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 src/main/java/com/moing/backend/global/config/fcm/constant/ApproveTeamMessage.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/dto/event/FcmEvent.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/ApproveTeamMessage.java b/src/main/java/com/moing/backend/global/config/fcm/constant/ApproveTeamMessage.java new file mode 100644 index 00000000..f5a6a3d8 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/ApproveTeamMessage.java @@ -0,0 +1,22 @@ +package com.moing.backend.global.config.fcm.constant; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum ApproveTeamMessage { + + APPROVE_TEAM_MESSAGE("%s님, [%s] 모임이 타오를 준비를 마쳤어요!", "지금 바로 우리 모임원들을 초대해볼까요? 🔥"), + + REJECT_TEAM_MESSAGE("%s님, [%s] 모임 신청이 반려됐어요.", "신청서를 점검한 뒤 다시 한번 모임을 신청해주세요!"); + + private final String title; + private final String body; + + public String title(String memberName, String teamName) { + return String.format(title, memberName, teamName); + } + + public String body() { + return body; + } +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/event/FcmEvent.java b/src/main/java/com/moing/backend/global/config/fcm/dto/event/FcmEvent.java new file mode 100644 index 00000000..d5c29fa4 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/event/FcmEvent.java @@ -0,0 +1,16 @@ +package com.moing.backend.global.config.fcm.dto.event; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class FcmEvent { + + private String title; + private String body; + private List tokens; + +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java new file mode 100644 index 00000000..ebc7771f --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java @@ -0,0 +1,29 @@ +package com.moing.backend.global.config.fcm.util; + +import com.moing.backend.global.config.fcm.dto.event.FcmEvent; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +import com.moing.backend.global.config.fcm.service.FcmService; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +@Component +@RequiredArgsConstructor +public class FcmMessageUtil { + + private final FcmService fcmService; + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onFcmMessageEvent(FcmEvent event) { + if (event.getTokens().size() == 1) { + fcmService.sendSingleDevice(new SingleRequest(event.getTitle(), event.getBody(), event.getTokens().get(0))); + } else { + fcmService.sendMultipleDevices(new MultiRequest(event.getTokens(), event.getTitle(), event.getBody())); + } + } +} + From 60806ead762490739b6debe0f0fa73c6c0071cae Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 22 Nov 2023 22:47:11 +0900 Subject: [PATCH 262/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=8A=B9=EC=9D=B8,=20=EB=B0=98=EB=A0=A4=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/GetLeaderInfoResponse.java | 18 ++++++++ .../service/ApproveTeamUseCase.java | 35 +++++++++++++++ .../service/RejectTeamUseCase.java | 35 +++++++++++++++ .../service/SendTeamAlarmUserCase.java | 43 ------------------- .../domain/service/TeamUpdateService.java | 20 +++++++++ .../team/presentation/TeamController.java | 30 ++++++------- .../constant/TeamResponseMessage.java | 4 +- 7 files changed, 125 insertions(+), 60 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/GetLeaderInfoResponse.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java delete mode 100644 src/main/java/com/moing/backend/domain/team/application/service/SendTeamAlarmUserCase.java create mode 100644 src/main/java/com/moing/backend/domain/team/domain/service/TeamUpdateService.java diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetLeaderInfoResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetLeaderInfoResponse.java new file mode 100644 index 00000000..0b04008d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetLeaderInfoResponse.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.team.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class GetLeaderInfoResponse { + + private Long teamId; + private String teamName; + private Long leaderId; + private String leaderName; + private String leaderFcmToken; + +} diff --git a/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java new file mode 100644 index 00000000..d84958ec --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java @@ -0,0 +1,35 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.team.application.dto.response.GetLeaderInfoResponse; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.team.domain.service.TeamUpdateService; +import com.moing.backend.global.config.fcm.dto.event.FcmEvent; +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.Collections; +import java.util.List; + +import static com.moing.backend.global.config.fcm.constant.ApproveTeamMessage.APPROVE_TEAM_MESSAGE; + +@Service +@RequiredArgsConstructor +@Transactional +public class ApproveTeamUseCase { + + private final TeamUpdateService teamUpdateService; + private final TeamGetService teamGetService; + private final ApplicationEventPublisher eventPublisher; + + public void approveTeams(List teamIds){ + teamUpdateService.updateTeamStatus(true, teamIds); + List leaderInfos=teamGetService.getLeaderInfoResponses(teamIds); + for(GetLeaderInfoResponse info: leaderInfos){ + String title=APPROVE_TEAM_MESSAGE.title(info.getLeaderName(), info.getTeamName()); + String body= APPROVE_TEAM_MESSAGE.body(); + eventPublisher.publishEvent(new FcmEvent(title, body, Collections.singletonList(info.getLeaderFcmToken()))); + } + } +} diff --git a/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java new file mode 100644 index 00000000..7b80720a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java @@ -0,0 +1,35 @@ +package com.moing.backend.domain.team.application.service; + +import com.moing.backend.domain.team.application.dto.response.GetLeaderInfoResponse; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.team.domain.service.TeamUpdateService; +import com.moing.backend.global.config.fcm.dto.event.FcmEvent; +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.Collections; +import java.util.List; + +import static com.moing.backend.global.config.fcm.constant.ApproveTeamMessage.REJECT_TEAM_MESSAGE; + +@Service +@RequiredArgsConstructor +@Transactional +public class RejectTeamUseCase { + + private final TeamUpdateService teamUpdateService; + private final TeamGetService teamGetService; + private final ApplicationEventPublisher eventPublisher; + + public void rejectTeams(List teamIds) { + teamUpdateService.updateTeamStatus(false, teamIds); + List leaderInfos = teamGetService.getLeaderInfoResponses(teamIds); + for (GetLeaderInfoResponse info : leaderInfos) { + String title = REJECT_TEAM_MESSAGE.title(info.getLeaderName(), info.getTeamName()); + String body = REJECT_TEAM_MESSAGE.body(); + eventPublisher.publishEvent(new FcmEvent(title, body, Collections.singletonList(info.getLeaderFcmToken()))); + } + } +} diff --git a/src/main/java/com/moing/backend/domain/team/application/service/SendTeamAlarmUserCase.java b/src/main/java/com/moing/backend/domain/team/application/service/SendTeamAlarmUserCase.java deleted file mode 100644 index e5ef6690..00000000 --- a/src/main/java/com/moing/backend/domain/team/application/service/SendTeamAlarmUserCase.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.moing.backend.domain.team.application.service; - -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; -import com.moing.backend.global.config.fcm.dto.request.MultiRequest; -import com.moing.backend.global.config.fcm.service.FcmService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; -import java.util.List; -import java.util.Optional; - -import static com.moing.backend.global.config.fcm.constant.NewUploadTitle.UPLOAD_NOTICE_NEW_TITLE; - -@Service -@Transactional -@RequiredArgsConstructor -public class SendTeamAlarmUserCase { - private final TeamMemberGetService teamMemberGetService; - private final FcmService fcmService; - - public void sendApprovalAlarm(Long teamId) { - //TODO: 승인, 반려 문구 constant로 - String title = "소모임 승인 안내"; - String message = "소모임이 승인되었습니다."; - sendAlarm(teamId, title, message); - } - - public void sendRejectionAlarm(Long teamId) { - String title = "소모임 반려 안내"; - String message = "소모임이 반려되었습니다."; - sendAlarm(teamId, title, message); - } - - private void sendAlarm(Long teamId, String title, String message) { - Optional> fcmTokens = teamMemberGetService.getFcmTokens(teamId); - if(fcmTokens.isPresent() && !fcmTokens.get().isEmpty()) { - MultiRequest toMultiRequest = new MultiRequest(fcmTokens.get(), title, message); - fcmService.sendMultipleDevices(toMultiRequest); - } - } -} - diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamUpdateService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamUpdateService.java new file mode 100644 index 00000000..a5603e61 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamUpdateService.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.team.domain.service; + +import com.moing.backend.domain.team.domain.repository.TeamRepository; +import com.moing.backend.global.annotation.DomainService; +import com.moing.backend.global.config.fcm.dto.event.FcmEvent; +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; + +import java.util.List; + +@DomainService +@RequiredArgsConstructor +public class TeamUpdateService { + + private final TeamRepository teamRepository; + private final ApplicationEventPublisher eventPublisher; + public void updateTeamStatus(boolean isApproved, List teamIds){ + teamRepository.updateTeamStatus(isApproved, teamIds); + } +} diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index 137cc77b..8e74802a 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -19,13 +19,13 @@ @AllArgsConstructor @RequestMapping("/api/team") public class TeamController { - private final CreateTeamUserCase createTeamService; - private final GetTeamUserCase getTeamUserCase; - private final SignInTeamUserCase signInTeamUserCase; - private final DisbandTeamUserCase disbandTeamUserCase; - private final WithdrawTeamUserCase withdrawTeamUserCase; - private final UpdateTeamUserCase updateTeamUserCase; - private final ReviewTeamUserCase reviewTeamUserCase; + private final CreateTeamUseCase createTeamService; + private final GetTeamUseCase getTeamUseCase; + private final SignInTeamUseCase signInTeamUseCase; + private final DisbandTeamUseCase disbandTeamUseCase; + private final WithdrawTeamUseCase withdrawTeamUseCase; + private final UpdateTeamUseCase updateTeamUseCase; + private final ReviewTeamUseCase reviewTeamUseCase; /** * 소모임 생성 (only 개설만) @@ -45,7 +45,7 @@ public ResponseEntity> createTeam(@Authentic */ @GetMapping public ResponseEntity> getTeam(@AuthenticationPrincipal User user) { - return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_SUCCESS.getMessage(), this.getTeamUserCase.getTeam(user.getSocialId()))); + return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_SUCCESS.getMessage(), this.getTeamUseCase.getTeam(user.getSocialId()))); } /** @@ -56,7 +56,7 @@ public ResponseEntity> getTeam(@AuthenticationP @GetMapping("/board/{teamId}") public ResponseEntity> getTeamDetail(@AuthenticationPrincipal User user, @PathVariable Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_DETAIL_SUCCESS.getMessage(), this.getTeamUserCase.getTeamDetailResponse(user.getSocialId(), teamId))); + return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_DETAIL_SUCCESS.getMessage(), this.getTeamUseCase.getTeamDetailResponse(user.getSocialId(), teamId))); } /** @@ -68,7 +68,7 @@ public ResponseEntity> getTeamDetail(@Aut @PostMapping("/{teamId}") public ResponseEntity> signInTeam(@AuthenticationPrincipal User user, @PathVariable Long teamId){ - return ResponseEntity.ok(SuccessResponse.create(SIGNIN_TEAM_SUCCESS.getMessage(),this.signInTeamUserCase.signInTeam(user.getSocialId(), teamId))); + return ResponseEntity.ok(SuccessResponse.create(SIGNIN_TEAM_SUCCESS.getMessage(),this.signInTeamUseCase.signInTeam(user.getSocialId(), teamId))); } /** @@ -79,7 +79,7 @@ public ResponseEntity> signInTeam(@Authentic @DeleteMapping("/{teamId}/disband") public ResponseEntity> disbandTeam(@AuthenticationPrincipal User user, @PathVariable Long teamId){ - return ResponseEntity.ok(SuccessResponse.create(DISBAND_TEAM_SUCCESS.getMessage(), this.disbandTeamUserCase.disbandTeam(user.getSocialId(), teamId))); + return ResponseEntity.ok(SuccessResponse.create(DISBAND_TEAM_SUCCESS.getMessage(), this.disbandTeamUseCase.disbandTeam(user.getSocialId(), teamId))); } /** @@ -90,7 +90,7 @@ public ResponseEntity> disbandTeam(@Authenti @DeleteMapping("/{teamId}/withdraw") public ResponseEntity> withdrawTeam(@AuthenticationPrincipal User user, @PathVariable Long teamId){ - return ResponseEntity.ok(SuccessResponse.create(WITHDRAW_TEAM_SUCCESS.getMessage(), this.withdrawTeamUserCase.withdrawTeam(user.getSocialId(),teamId))); + return ResponseEntity.ok(SuccessResponse.create(WITHDRAW_TEAM_SUCCESS.getMessage(), this.withdrawTeamUseCase.withdrawTeam(user.getSocialId(),teamId))); } /** @@ -101,7 +101,7 @@ public ResponseEntity> withdrawTeam(@Authent @GetMapping("/{teamId}/review") public ResponseEntity> reviewTeam(@AuthenticationPrincipal User user, @PathVariable Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(REVIEW_TEAM_SUCCESS.getMessage(), this.reviewTeamUserCase.reviewTeam(user.getSocialId(), teamId))); + return ResponseEntity.ok(SuccessResponse.create(REVIEW_TEAM_SUCCESS.getMessage(), this.reviewTeamUseCase.reviewTeam(user.getSocialId(), teamId))); } @@ -114,7 +114,7 @@ public ResponseEntity> reviewTeam(@Authentic public ResponseEntity> updateTeam(@Valid @RequestBody UpdateTeamRequest updateTeamRequest, @AuthenticationPrincipal User user, @PathVariable Long teamId){ - return ResponseEntity.ok(SuccessResponse.create(UPDATE_TEAM_SUCCESS.getMessage(), this.updateTeamUserCase.updateTeam(updateTeamRequest, user.getSocialId(), teamId))); + return ResponseEntity.ok(SuccessResponse.create(UPDATE_TEAM_SUCCESS.getMessage(), this.updateTeamUseCase.updateTeam(updateTeamRequest, user.getSocialId(), teamId))); } /** @@ -124,7 +124,7 @@ public ResponseEntity> updateTeam(@Valid @Re @GetMapping("/{teamId}") public ResponseEntity> getCurrentStatus(@AuthenticationPrincipal User user, @PathVariable Long teamId) { - return ResponseEntity.ok(SuccessResponse.create(GET_CURRENT_STATUS_SUCCESS.getMessage(), this.getTeamUserCase.getCurrentStatus(teamId))); + return ResponseEntity.ok(SuccessResponse.create(GET_CURRENT_STATUS_SUCCESS.getMessage(), this.getTeamUseCase.getCurrentStatus(teamId))); } } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index d400e9f4..095156f0 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -15,7 +15,7 @@ public enum TeamResponseMessage { DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."), UPDATE_TEAM_SUCCESS("[소모임장 권한] 소모임을 수정했습니다"), WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"), - SEND_APPROVAL_ALARM_SUCCESS("소모임 승인 알림을 보냈습니다."), - SEND_REJECTION_ALARM_SUCCESS("소모임 반려 알림을 보냈습니다."); + SEND_APPROVAL_ALARM_SUCCESS("소모임들이 승인되었습니다.."), + SEND_REJECTION_ALARM_SUCCESS("소모임들이 반려되었습니다."); private final String message; } From 6346bd451644b608d974bfa136a42ae3cc62dfb3 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Wed, 22 Nov 2023 23:43:40 +0900 Subject: [PATCH 263/619] =?UTF-8?q?=08deploy:=20=EB=8F=84=EC=BB=A4=20?= =?UTF-8?q?=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=88=20=ED=83=80=EC=9E=84?= =?UTF-8?q?=EC=A1=B4=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Dockerfile b/Dockerfile index 24f680a7..25848cbe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,9 @@ FROM openjdk:11-jdk + +# 타임존 설정 +ENV TZ=Asia/Seoul +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + ARG CACHEBREAKER=1 ARG JAR_FILE=./build/libs/backend-0.0.1-SNAPSHOT.jar COPY ${JAR_FILE} app.jar @@ -8,3 +13,4 @@ COPY ./build/docs/asciidoc/*.html /static/docs/ # 애플리케이션 실행 시 -cp 옵션을 사용하여 /static/docs 디렉토리를 클래스패스에 추가 ENTRYPOINT ["java","-cp",".:/static/docs","-jar","/app.jar"] + From 203b633387646f8db5ce9817bdb696b51becda37 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Wed, 22 Nov 2023 23:52:03 +0900 Subject: [PATCH 264/619] =?UTF-8?q?deploy:=20=EB=8F=84=EC=BB=A4=20?= =?UTF-8?q?=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=88=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=83=80=EC=9E=84=EC=A1=B4=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy.sh b/deploy.sh index 59c6402d..39ee49ca 100644 --- a/deploy.sh +++ b/deploy.sh @@ -18,7 +18,7 @@ if [ -z "$EXIST_BLUE" ] && [ -z "$EXIST_GREEN" ]; then docker rm ${DOCKER_APP_NAME}-blue fi - docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 ${DOCKER_USERNAME}/moing:blue + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing:blue BEFORE_COMPOSE_COLOR="green" AFTER_COMPOSE_COLOR="blue" elif [ -z "$EXIST_BLUE" ]; then @@ -29,7 +29,7 @@ elif [ -z "$EXIST_BLUE" ]; then docker rm ${DOCKER_APP_NAME}-blue fi - docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 ${DOCKER_USERNAME}/moing:blue + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing:blue BEFORE_COMPOSE_COLOR="green" AFTER_COMPOSE_COLOR="blue" else @@ -40,7 +40,7 @@ else docker rm ${DOCKER_APP_NAME}-green fi - docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 ${DOCKER_USERNAME}/moing:green + docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing:green BEFORE_COMPOSE_COLOR="blue" AFTER_COMPOSE_COLOR="green" fi From a46e1c09360c21f98a00bbc0ab31de51ec855881 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Thu, 23 Nov 2023 00:46:45 +0900 Subject: [PATCH 265/619] =?UTF-8?q?=08hotfix:=20redis=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EB=B0=80=EB=A6=AC=EC=B4=88=EC=97=90=EC=84=9C=20=EC=B4=88?= =?UTF-8?q?=EB=A1=9C=20=EB=8B=A8=EC=9C=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/moing/backend/global/config/redis/RedisUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/global/config/redis/RedisUtil.java b/src/main/java/com/moing/backend/global/config/redis/RedisUtil.java index 978fd649..71bb8ee9 100644 --- a/src/main/java/com/moing/backend/global/config/redis/RedisUtil.java +++ b/src/main/java/com/moing/backend/global/config/redis/RedisUtil.java @@ -21,7 +21,7 @@ public RedisUtil(final RedisTemplate redisTemplate) { public void save(String refreshToken, String socialId) { //동일한 key 값으로 저장하면 value값 updat됨 - redisTemplate.opsForValue().set(socialId, refreshToken, refreshTokenValidityTime, TimeUnit.SECONDS); + redisTemplate.opsForValue().set(socialId, refreshToken, refreshTokenValidityTime/1000, TimeUnit.SECONDS); } public void deleteById(String socialId) { From fb08c5e7cb2585ac1d0bd876432825ba9e2f27fe Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 26 Nov 2023 14:35:36 +0900 Subject: [PATCH 266/619] =?UTF-8?q?feat:=20=EC=83=88=EB=A1=9C=EC=9A=B4=20?= =?UTF-8?q?=EC=86=8C=EB=AA=A8=EC=9E=84=20=EC=A1=B0=ED=9A=8C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/GetNewTeamResponse.java | 22 ++++++ .../service/CreateTeamUseCase.java | 3 - .../application/service/GetTeamUseCase.java | 11 +-- .../repository/TeamCustomRepository.java | 8 ++- .../repository/TeamCustomRepositoryImpl.java | 67 ++++++++++++++++++- .../team/domain/service/TeamGetService.java | 17 +++++ .../presentation/AdminTeamController.java | 47 ++++++++----- .../constant/TeamResponseMessage.java | 3 +- 8 files changed, 150 insertions(+), 28 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/GetNewTeamResponse.java diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetNewTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetNewTeamResponse.java new file mode 100644 index 00000000..56f85a4b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetNewTeamResponse.java @@ -0,0 +1,22 @@ +package com.moing.backend.domain.team.application.dto.response; + +import com.moing.backend.domain.team.domain.constant.Category; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; + +@Getter +@Builder +@AllArgsConstructor +public class GetNewTeamResponse { + + private String teamName; + private Category category; + private String promise; + private String introduction; + private String profileImgUrl; + private LocalDateTime createdDate; + +} diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java index 027838c4..13d19c39 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java @@ -35,9 +35,6 @@ public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String Team team=teamMapper.createTeam(createTeamRequest, member); teamSaveService.saveTeam(team); teamMemberSaveService.addTeamMember(team, member); - //====지워야 함 (테스트 용)===== - team.approveTeam(); - //====지워야 함 (테스트 용)===== teamScoreSaveService.save(teamScoreMapper.mapToTeamScore(team)); // 팀스코어 엔티티 생성 eventPublisher.publishEvent(new TeamCreateEvent(team.getName(), team.getLeaderId())); return new CreateTeamResponse(team.getTeamId()); diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java index 9af285f2..9f4ee340 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java @@ -3,15 +3,14 @@ import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.team.application.dto.response.GetCurrentStatusResponse; -import com.moing.backend.domain.team.application.dto.response.GetTeamDetailResponse; -import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; -import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; +import com.moing.backend.domain.team.application.dto.response.*; import com.moing.backend.domain.team.application.mapper.TeamMapper; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import javax.transaction.Transactional; @@ -44,4 +43,8 @@ public GetCurrentStatusResponse getCurrentStatus(Long teamId) { Team team=teamGetService.getTeamByTeamId(teamId); return teamMapper.toCurrentStatusResponse(team); } + + public Page getNewTeam(String dateSort, Pageable pageable) { + return teamGetService.getNewTeams(dateSort, pageable); + } } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index 7df50396..bed05135 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -2,9 +2,12 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; -import com.moing.backend.domain.team.application.dto.response.GetTeamDetailResponse; +import com.moing.backend.domain.team.application.dto.response.GetLeaderInfoResponse; +import com.moing.backend.domain.team.application.dto.response.GetNewTeamResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import java.util.List; import java.util.Optional; @@ -15,4 +18,7 @@ public interface TeamCustomRepository { List findTeamIdByMemberId(Long memberId); List findMyPageTeamByMemberId(Long memberId); List findTeamNameByTeamId(List teamId); + void updateTeamStatus(boolean isApproved, List teamIds); + List findLeaderInfoByTeamIds(List teamIds); + Page findNewTeam(String dateSort, Pageable pageable); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index 3b170f51..001ea28d 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -2,28 +2,33 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; -import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; -import com.moing.backend.domain.team.application.dto.response.QTeamBlock; -import com.moing.backend.domain.team.application.dto.response.TeamBlock; +import com.moing.backend.domain.team.application.dto.response.*; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.moing.backend.domain.team.domain.entity.Team; +import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.support.PageableExecutionUtils; import javax.persistence.EntityManager; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; +import static com.moing.backend.domain.member.domain.entity.QMember.member; import static com.moing.backend.domain.team.domain.entity.QTeam.team; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; public class TeamCustomRepositoryImpl implements TeamCustomRepository { private final JPAQueryFactory queryFactory; + private final EntityManager em; public TeamCustomRepositoryImpl(EntityManager em) { this.queryFactory = new JPAQueryFactory(em); + this.em = em; } @Override @@ -108,5 +113,61 @@ public List findTeamNameByTeamId(List teamId) { .fetch(); } + @Override + public void updateTeamStatus(boolean isApproved, List teamIds) { + ApprovalStatus approvalStatus = ApprovalStatus.REJECTION; + if (isApproved) { + approvalStatus = ApprovalStatus.APPROVAL; + } + queryFactory + .update(team) + .set(team.approvalStatus, approvalStatus) + .where(team.teamId.in(teamIds)) + .execute(); + em.flush(); + em.clear(); + } + + @Override + public List findLeaderInfoByTeamIds(List teamIds) { + return queryFactory + .select(Projections.constructor(GetLeaderInfoResponse.class, + team.teamId, + team.name, + member.memberId, + member.nickName, + member.fcmToken)) + .from(team) + .join(member).on(team.leaderId.eq(member.memberId)) + .where(team.teamId.in(teamIds)) + .fetch(); + } + + @Override + public Page findNewTeam(String dateSort, Pageable pageable) { + OrderSpecifier orderBy = team.createdDate.asc(); + if ("desc".equals(dateSort)) { + orderBy = team.createdDate.desc(); + } + + List teams = queryFactory + .select(Projections.constructor(GetNewTeamResponse.class, + team.name, team.category, team.promise, team.introduction, team.profileImgUrl, team.createdDate)) + .from(team) + .where(team.approvalStatus.eq(ApprovalStatus.NO_CONFIRMATION)) + .orderBy(orderBy) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + Long count = queryFactory + .select(team.count()) + .from(team) + .where(team.approvalStatus.eq(ApprovalStatus.NO_CONFIRMATION)) + .fetchOne(); + + return PageableExecutionUtils.getPage(teams, pageable, () -> count); + } + } diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index 980bca98..2885b416 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -3,12 +3,18 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; +import com.moing.backend.domain.team.application.dto.response.GetLeaderInfoResponse; +import com.moing.backend.domain.team.application.dto.response.GetNewTeamResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.repository.TeamRepository; import com.moing.backend.domain.team.exception.NotFoundByTeamIdException; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import java.util.List; @@ -38,4 +44,15 @@ public List getMyPageTeamBlockByMemberId(Long memberId){ public List getTeamNameByTeamId(List teamId) { return teamRepository.findTeamNameByTeamId(teamId); } + + public List getLeaderInfoResponses(List teamIds){ + return teamRepository.findLeaderInfoByTeamIds(teamIds); + } + + public Page getNewTeams(String dateSort, Pageable pageable) { + int page = (pageable.getPageNumber() == 0) ? 0 : (pageable.getPageNumber() - 1); + pageable = PageRequest.of(page, pageable.getPageSize(), Sort.by("no").descending()); + return teamRepository.findNewTeam(dateSort, pageable); + } + } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java index 5ffa70f9..79b9421a 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java @@ -1,13 +1,17 @@ package com.moing.backend.domain.team.presentation; -import com.moing.backend.domain.team.application.service.SendTeamAlarmUserCase; +import com.moing.backend.domain.team.application.dto.response.GetNewTeamResponse; +import com.moing.backend.domain.team.application.service.ApproveTeamUseCase; +import com.moing.backend.domain.team.application.service.GetTeamUseCase; +import com.moing.backend.domain.team.application.service.RejectTeamUseCase; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; import static com.moing.backend.domain.team.presentation.constant.TeamResponseMessage.*; @@ -17,29 +21,40 @@ public class AdminTeamController { - private final SendTeamAlarmUserCase sendTeamAlarmUserCase; + private final ApproveTeamUseCase approveTeamUseCase; + private final RejectTeamUseCase rejectTeamUseCase; + private final GetTeamUseCase getTeamUseCase; /** - * 소모임 승인 알림 보내기 - * [POST] api/admin/team/approval/{teamId} + * 소모임 승인 + * [POST] api/admin/team/approval??teamIds=1,2,3 * 작성자 : 김민수 */ - @PostMapping("/approval/{teamId}") - public ResponseEntity sendApproveAlarm(@PathVariable Long teamId) { - this.sendTeamAlarmUserCase.sendApprovalAlarm(teamId); + @PostMapping("/approval") + public ResponseEntity sendApproveAlarm(@RequestParam List teamIds) { + this.approveTeamUseCase.approveTeams(teamIds); return ResponseEntity.ok(SuccessResponse.create(SEND_APPROVAL_ALARM_SUCCESS.getMessage())); } /** - * 소모임 반려 알림 보내기 - * [POST] api/admin/team/rejection/{teamId} + * 소모임 반려 + * [POST] api/admin/team/rejection?teamIds=1,2,3 * 작성자: 김민수 */ - @PostMapping("/rejection/{teamId}") - public ResponseEntity sendRejectionAlarm(@PathVariable Long teamId){ - this.sendTeamAlarmUserCase.sendRejectionAlarm(teamId); + @PostMapping("/rejection") + public ResponseEntity sendRejectionAlarm(@RequestParam List teamIds) { + this.rejectTeamUseCase.rejectTeams(teamIds); return ResponseEntity.ok(SuccessResponse.create(SEND_REJECTION_ALARM_SUCCESS.getMessage())); } + /** + * 소모임 전체 조회 + */ + @GetMapping + public ResponseEntity>> getNewTeam(@RequestParam(value = "dateSort", defaultValue = "asc") String dateSort, + Pageable pageable) { + return ResponseEntity.ok(SuccessResponse.create(GET_NEW_TEAM_SUCCESS.getMessage(), this.getTeamUseCase.getNewTeam(dateSort, pageable))); + } + } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 095156f0..6107598d 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -16,6 +16,7 @@ public enum TeamResponseMessage { UPDATE_TEAM_SUCCESS("[소모임장 권한] 소모임을 수정했습니다"), WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"), SEND_APPROVAL_ALARM_SUCCESS("소모임들이 승인되었습니다.."), - SEND_REJECTION_ALARM_SUCCESS("소모임들이 반려되었습니다."); + SEND_REJECTION_ALARM_SUCCESS("소모임들이 반려되었습니다."), + GET_NEW_TEAM_SUCCESS("새로운 소모임들을 조회했습니다."); private final String message; } From ddaf3ae602cfa13a3676d29e10a5e7325a842d8f Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 26 Nov 2023 14:53:46 +0900 Subject: [PATCH 267/619] =?UTF-8?q?fix:=20=EC=8A=B9=EC=9D=B8=EB=90=98?= =?UTF-8?q?=EC=97=88=EC=9D=84=20=EB=95=8C=EB=A7=8C=20=ED=98=84=EC=9E=AC=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=EC=9C=BC=EB=A1=9C=20approvalTime=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/TeamCustomRepositoryImpl.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index 001ea28d..964489fa 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -8,6 +8,7 @@ import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; +import com.querydsl.jpa.impl.JPAUpdateClause; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.support.PageableExecutionUtils; @@ -115,15 +116,21 @@ public List findTeamNameByTeamId(List teamId) { @Override public void updateTeamStatus(boolean isApproved, List teamIds) { - ApprovalStatus approvalStatus = ApprovalStatus.REJECTION; + ApprovalStatus approvalStatus = isApproved ? ApprovalStatus.APPROVAL : ApprovalStatus.REJECTION; + + JPAUpdateClause updateClause = queryFactory + .update(team) + .set(team.approvalStatus, approvalStatus); + + // 승인되었을 때만 현재 시간으로 approvalTime 설정 if (isApproved) { - approvalStatus = ApprovalStatus.APPROVAL; + updateClause.set(team.approvalTime, LocalDateTime.now()); } - queryFactory - .update(team) - .set(team.approvalStatus, approvalStatus) + + updateClause .where(team.teamId.in(teamIds)) .execute(); + em.flush(); em.clear(); } From 83ea384ac42590b36fd7a6b76abc4401c1ccc133 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 26 Nov 2023 15:07:17 +0900 Subject: [PATCH 268/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20=EC=8A=B9=EC=9D=B8=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=20=EC=B6=94=EA=B0=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/team/domain/repository/TeamCustomRepositoryImpl.java | 1 + .../domain/team/presentation/constant/TeamResponseMessage.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index 964489fa..699ec33b 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -95,6 +95,7 @@ private List getTeamBlock(Long memberId) { .from(teamMember) .innerJoin(teamMember.team, team) .on(teamMember.member.memberId.eq(memberId)) + .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) // 승인 되었고 .where(teamMember.isDeleted.eq(false)// 탈퇴하지 않았다면 .and(team.isDeleted.eq(false) // 강제종료되지 않았거나 .or(team.deletionTime.after(threeDaysAgo))))// 강제종료된 경우 3일이 지나지 않았다면 diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 6107598d..55dca2b6 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -15,7 +15,7 @@ public enum TeamResponseMessage { DISBAND_TEAM_SUCCESS("[소모임장 권한] 소모임을 강제 종료했습니다."), UPDATE_TEAM_SUCCESS("[소모임장 권한] 소모임을 수정했습니다"), WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"), - SEND_APPROVAL_ALARM_SUCCESS("소모임들이 승인되었습니다.."), + SEND_APPROVAL_ALARM_SUCCESS("소모임들이 승인되었습니다."), SEND_REJECTION_ALARM_SUCCESS("소모임들이 반려되었습니다."), GET_NEW_TEAM_SUCCESS("새로운 소모임들을 조회했습니다."); private final String message; From 5902eb5741a081b6a0fd416ced22ec906518c458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 26 Nov 2023 15:34:28 +0900 Subject: [PATCH 269/619] =?UTF-8?q?fix=20:=20=ED=95=9C=EB=B2=88=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20wait=20=EB=A6=AC=ED=84=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 79691e0e..9455fe5a 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -108,7 +108,7 @@ public Optional> findSingleMissionByMemberId(Long m .from(mission) .where( mission.team.teamId.in(teams), - mission.status.eq(MissionStatus.ONGOING), + mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), mission.type.eq(MissionType.ONCE) ) From 5ab75be69a883ea58aa7efa0af650cfc80442882 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 26 Nov 2023 17:05:26 +0900 Subject: [PATCH 270/619] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mypage/presentation/MyPageController.java | 9 +++++++++ .../presentation/constant/MypageResponseMessage.java | 1 + 2 files changed, 10 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java index afbfea24..bea13408 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java @@ -30,6 +30,15 @@ public class MyPageController { private final AlarmUseCase alarmUseCase; private final GetMyPageUseCase getMyPageUseCase; + /** + * 사용자 회원가입 여부 + * [GET] api/mypage/test + * 작성자: 김민수 + */ + @GetMapping("/test") + public ResponseEntity test(@AuthenticationPrincipal User user){ + return ResponseEntity.ok(SuccessResponse.create(TEST_SIGNUP_SUCCESS.getMessage())); + } /** * 로그아웃 * [POST] api/mypage/signOut diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java b/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java index 085033a7..d7aa915d 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/constant/MypageResponseMessage.java @@ -6,6 +6,7 @@ @Getter @RequiredArgsConstructor public enum MypageResponseMessage { + TEST_SIGNUP_SUCCESS("회원가입이 되었습니다."), SIGN_OUT_SUCCESS("로그아웃을 했습니다"), WITHDRAWAL_SUCCESS("회원탈퇴를 했습니다"), GET_MYPAGE_SUCCESS("마이페이지를 조회했습니다"), From 99aa605bed23b41824c23fdceffc15154f7980f2 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 26 Nov 2023 17:20:54 +0900 Subject: [PATCH 271/619] =?UTF-8?q?fix:=20=EC=9E=84=EC=8B=9C=EB=A1=9C=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=98=EB=A9=B4=20=EC=8A=B9=EC=9D=B8?= =?UTF-8?q?=EB=90=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/team/application/service/CreateTeamUseCase.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java index 13d19c39..027838c4 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java @@ -35,6 +35,9 @@ public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String Team team=teamMapper.createTeam(createTeamRequest, member); teamSaveService.saveTeam(team); teamMemberSaveService.addTeamMember(team, member); + //====지워야 함 (테스트 용)===== + team.approveTeam(); + //====지워야 함 (테스트 용)===== teamScoreSaveService.save(teamScoreMapper.mapToTeamScore(team)); // 팀스코어 엔티티 생성 eventPublisher.publishEvent(new TeamCreateEvent(team.getName(), team.getLeaderId())); return new CreateTeamResponse(team.getTeamId()); From 90109d8ad0fa1d4a1aa6b146f570397070d1f578 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 26 Nov 2023 19:00:11 +0900 Subject: [PATCH 272/619] =?UTF-8?q?fix:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=82=AD=EC=A0=9C=20=EC=97=AC=EB=B6=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/CommentBlocks.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java index 8a24f5f9..beb1c057 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java @@ -24,8 +24,10 @@ public class CommentBlocks { private Boolean writerIsDeleted; - public void deleteMember(){ - this.writerNickName="(알 수 없음)"; - this.writerProfileImage="undef"; + public void deleteMember() { + if (Boolean.TRUE.equals(writerIsDeleted)) { + this.writerNickName = "(알 수 없음)"; + this.writerProfileImage = "undef"; + } } } From 3c03f17238e8587184a1f341d44a0c1192a84e0a Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 26 Nov 2023 20:58:06 +0900 Subject: [PATCH 273/619] =?UTF-8?q?fix:=20fcmService=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/dto/res/SingleMissionBoardRes.java | 1 - .../team/application/service/ApproveTeamUseCase.java | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java index d26f76b2..8f4a5e9d 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java @@ -4,7 +4,6 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; -import org.checkerframework.checker.units.qual.A; @Getter @Setter diff --git a/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java index d84958ec..c58ba97c 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java @@ -3,7 +3,10 @@ import com.moing.backend.domain.team.application.dto.response.GetLeaderInfoResponse; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.team.domain.service.TeamUpdateService; +import com.moing.backend.global.config.fcm.FcmConfig; import com.moing.backend.global.config.fcm.dto.event.FcmEvent; +import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +import com.moing.backend.global.config.fcm.service.FcmService; import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; @@ -21,7 +24,7 @@ public class ApproveTeamUseCase { private final TeamUpdateService teamUpdateService; private final TeamGetService teamGetService; - private final ApplicationEventPublisher eventPublisher; + private final FcmService fcmService; public void approveTeams(List teamIds){ teamUpdateService.updateTeamStatus(true, teamIds); @@ -29,7 +32,7 @@ public void approveTeams(List teamIds){ for(GetLeaderInfoResponse info: leaderInfos){ String title=APPROVE_TEAM_MESSAGE.title(info.getLeaderName(), info.getTeamName()); String body= APPROVE_TEAM_MESSAGE.body(); - eventPublisher.publishEvent(new FcmEvent(title, body, Collections.singletonList(info.getLeaderFcmToken()))); + fcmService.sendSingleDevice(new SingleRequest(info.getLeaderFcmToken(), title, body)); } } } From 49b1fab27b8663273f76098c50021c53ff4daf6e Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 26 Nov 2023 21:34:45 +0900 Subject: [PATCH 274/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=EC=99=80=20=EC=9D=B4=EB=A6=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Team-API.adoc | 4 ++ .../dto/response/GetTeamCountResponse.java | 15 +++++++ .../application/dto/response/TeamBlock.java | 1 + .../application/service/GetTeamUseCase.java | 5 +++ .../repository/TeamCustomRepository.java | 2 + .../repository/TeamCustomRepositoryImpl.java | 16 +++++++ .../team/domain/service/TeamGetService.java | 7 +++ .../team/presentation/TeamController.java | 10 +++++ .../constant/TeamResponseMessage.java | 3 +- .../team/presentation/TeamControllerTest.java | 43 +++++++++++++++++++ 10 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java diff --git a/src/docs/asciidoc/Team-API.adoc b/src/docs/asciidoc/Team-API.adoc index b6e71d0d..a7add657 100644 --- a/src/docs/asciidoc/Team-API.adoc +++ b/src/docs/asciidoc/Team-API.adoc @@ -60,3 +60,7 @@ operation::team-controller-test/disband_team[snippets='http-request,path-paramet [[Team-소모임-탈퇴]] == Team 소모임원 강제종료 operation::team-controller-test/withdraw_team[snippets='http-request,path-parameters,http-response,response-fields'] + +[[Team-소모임-개수_이름-조회]] +== Team 소모임 개수 이름 조회 +operation::team-controller-test/get_team_count[snippets='http-request,path-parameters,http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java new file mode 100644 index 00000000..7cae31ee --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java @@ -0,0 +1,15 @@ +package com.moing.backend.domain.team.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class GetTeamCountResponse { + + private String teamName; + private Long numOfTeam; + +} diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java index c4988a47..7c2e1803 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java @@ -18,6 +18,7 @@ @Builder @NoArgsConstructor public class TeamBlock { + private Long teamId; private Long duration; //걸린시간(단위:날짜) private Integer levelOfFire; //불꽃 레벨 diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java index 9f4ee340..74700bc0 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java @@ -47,4 +47,9 @@ public GetCurrentStatusResponse getCurrentStatus(Long teamId) { public Page getNewTeam(String dateSort, Pageable pageable) { return teamGetService.getNewTeams(dateSort, pageable); } + + public GetTeamCountResponse getTeamCount(String socialId, Long teamId) { + Member member = memberGetService.getMemberBySocialId(socialId); + return teamGetService.getTeamCountAndName(teamId, member.getMemberId()); + } } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index bed05135..df7083d4 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.team.application.dto.response.GetLeaderInfoResponse; import com.moing.backend.domain.team.application.dto.response.GetNewTeamResponse; +import com.moing.backend.domain.team.application.dto.response.GetTeamCountResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import org.springframework.data.domain.Page; @@ -21,4 +22,5 @@ public interface TeamCustomRepository { void updateTeamStatus(boolean isApproved, List teamIds); List findLeaderInfoByTeamIds(List teamIds); Page findNewTeam(String dateSort, Pageable pageable); + Long findTeamCount(Long memberId); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index 699ec33b..f94c031c 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -177,5 +177,21 @@ public Page findNewTeam(String dateSort, Pageable pageable) return PageableExecutionUtils.getPage(teams, pageable, () -> count); } + @Override + public Long findTeamCount(Long memberId) { + LocalDateTime threeDaysAgo = LocalDateTime.now().minusDays(3); + return queryFactory + .select(team.count()) // 팀의 개수를 세기 위해 수정 + .from(teamMember) + .innerJoin(teamMember.team, team) + .on(teamMember.member.memberId.eq(memberId)) + .where(team.approvalStatus.eq(ApprovalStatus.APPROVAL)) // 승인 되었고 + .where(teamMember.isDeleted.eq(false) // 탈퇴하지 않았다면 + .and(team.isDeleted.eq(false) // 강제종료되지 않았거나 + .or(team.deletionTime.after(threeDaysAgo)))) // 강제종료된 경우 3일이 지나지 않았다면 + .fetchOne(); // 단일 결과 (개수) 반환 + + } + } diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index 2885b416..6afe5733 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.team.application.dto.response.GetLeaderInfoResponse; import com.moing.backend.domain.team.application.dto.response.GetNewTeamResponse; +import com.moing.backend.domain.team.application.dto.response.GetTeamCountResponse; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.repository.TeamRepository; @@ -55,4 +56,10 @@ public Page getNewTeams(String dateSort, Pageable pageable) return teamRepository.findNewTeam(dateSort, pageable); } + public GetTeamCountResponse getTeamCountAndName(Long teamId, Long memberId) { + String teamName = getTeamByTeamId(teamId).getName(); + Long numOfTeam = teamRepository.findTeamCount(memberId); + return new GetTeamCountResponse(teamName, numOfTeam); + } + } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index 8e74802a..8e24226f 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -127,4 +127,14 @@ public ResponseEntity> getCurrentStatu return ResponseEntity.ok(SuccessResponse.create(GET_CURRENT_STATUS_SUCCESS.getMessage(), this.getTeamUseCase.getCurrentStatus(teamId))); } + /** + * 소모임 닉네임과 소모임 개수 조회 + * [GET] api/team/{teamId}/count + */ + @GetMapping("/{teamId}/count") + public ResponseEntity> getTeamCount(@AuthenticationPrincipal User user, + @PathVariable Long teamId){ + return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_COUNT_SUCCESS.getMessage(), this.getTeamUseCase.getTeamCount(user.getSocialId(),teamId))); + } + } diff --git a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java index 55dca2b6..c0a1215e 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/constant/TeamResponseMessage.java @@ -17,6 +17,7 @@ public enum TeamResponseMessage { WITHDRAW_TEAM_SUCCESS("[소모임원 권한] 소모임을 탈퇴하였습니다"), SEND_APPROVAL_ALARM_SUCCESS("소모임들이 승인되었습니다."), SEND_REJECTION_ALARM_SUCCESS("소모임들이 반려되었습니다."), - GET_NEW_TEAM_SUCCESS("새로운 소모임들을 조회했습니다."); + GET_NEW_TEAM_SUCCESS("새로운 소모임들을 조회했습니다."), + GET_TEAM_COUNT_SUCCESS("소모임의 개수와 닉네임을 조회했습니다."); private final String message; } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 7ff3399b..56513f5a 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -507,4 +507,47 @@ public void get_current_status() throws Exception { ); } + @Test + public void get_team_count() throws Exception { + + // given + Long teamId = 1L; + + GetTeamCountResponse output = GetTeamCountResponse.builder() + .teamName("소모임 이름") + .numOfTeam(2L) + .build(); + + given(getTeamUseCase.getTeamCount(any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/{teamId}/count", teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("소모임을 수정했습니다."), + fieldWithPath("data.teamName").description("소모임 이름"), + fieldWithPath("data.numOfTeam").description("지금까지 가입한 소모임 개수") + ) + ) + ); + } + } From a58bae4966f202348936d4c210b4fae192842f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 28 Nov 2023 13:17:18 +0900 Subject: [PATCH 275/619] =?UTF-8?q?fix=20:=20=EB=B6=88=EB=8D=98=EC=A7=80?= =?UTF-8?q?=EA=B8=B0=20URL=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/FireThrowAlarmUseCase.java | 6 ++-- .../application/service/FireThrowUseCase.java | 17 +++++++++-- .../repository/FireCustomRepository.java | 3 +- .../repository/FireCustomRepositoryImpl.java | 28 +++++++++++++++++-- .../fire/domain/service/FireQueryService.java | 5 ++-- .../fire/presentation/FireController.java | 6 ++-- .../representation/FireControllerTest.java | 4 +-- 7 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java index 83eb1b25..ffddb4b7 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -23,9 +23,11 @@ public class FireThrowAlarmUseCase { public void sendFireThrowAlarm(Member throwMember, Member receiveMember) { Random random = new Random(System.currentTimeMillis()); - String title = getTitle(throwMember.getNickName(), receiveMember.getNickName(), random.nextInt(2)); + int randomNum = random.nextInt(2); + + String title = getTitle(throwMember.getNickName(), receiveMember.getNickName(), randomNum); + String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), randomNum); - String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), random.nextInt(2)); SingleRequest singleRequest = new SingleRequest(receiveMember.getFcmToken(), title, message); fcmService.sendSingleDevice(singleRequest); diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java index 1f07c6fe..117ccb0b 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -9,6 +9,7 @@ import com.moing.backend.domain.fire.exception.NoAuthThrowFireException; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.global.config.fcm.dto.request.SingleRequest; import com.moing.backend.global.config.fcm.service.FcmService; import lombok.RequiredArgsConstructor; @@ -30,6 +31,8 @@ public class FireThrowUseCase { private final FireThrowAlarmUseCase fireThrowAlarmUseCase; + private final MissionArchiveQueryService missionArchiveQueryService; + public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { Member throwMember = memberGetService.getMemberBySocialId(userId); @@ -54,15 +57,25 @@ public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { } public List getFireReceiveList(String userId,Long teamId, Long missionId) { - Long memberId = memberGetService.getMemberBySocialId(userId).getMemberId(); + Member member = memberGetService.getMemberBySocialId(userId); + Long memberId = member.getMemberId(); - List fireReceiveRes = FireMapper.mapToFireReceiversList(fireQueryService.getNotYetMissionMember(teamId, missionId)); + List fireReceiveRes = fireQueryService.getNotYetMissionMember(teamId, missionId,memberId); fireReceiveRes.forEach( res -> res.updateFireStatus(fireQueryService.hasFireCreatedWithinOneHour(memberId,res.getReceiveMemberId()) )); + if (!missionArchiveQueryService.isDone(memberId, missionId)) { + fireReceiveRes.add(0,FireReceiveRes.builder() + .receiveMemberId(memberId) + .nickname(member.getNickName()) + .fireStatus("False") + .build()); + } + return fireReceiveRes; } + } diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java index 4e2d2b10..12470073 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.fire.domain.repository; +import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.domain.entity.Fire; import com.moing.backend.domain.member.domain.entity.Member; import org.springframework.data.jpa.repository.JpaRepository; @@ -11,6 +12,6 @@ public interface FireCustomRepository { boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMemberId); - Optional> getFireReceivers(Long teamId, Long missionId); + Optional> getFireReceivers(Long teamId, Long missionId, Long memberId); } diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 8e90d441..fa5ab01e 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -1,8 +1,11 @@ package com.moing.backend.domain.fire.domain.repository; +import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.domain.entity.Fire; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -46,9 +49,27 @@ public boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMembe } - public Optional> getFireReceivers(Long teamId, Long missionId) { + public Optional> getFireReceivers(Long teamId, Long missionId, Long memberId) { + + LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1); // 현재 시간에서 1시간을 뺀 시간 + + BooleanExpression oneHourStatus = JPAExpressions + .select() + .from(fire) + .where( + fire.throwMemberId.eq(memberId), + fire.receiveMemberId.eq(teamMember.member.memberId), + fire.createdDate.after(oneHourAgo) // createdDate가 oneHourAgo 이후인 데이터 + ) + .exists(); + + return Optional.ofNullable(queryFactory - .select(teamMember.member) + .select(Projections.constructor(FireReceiveRes.class, + teamMember.member.memberId, + teamMember.member.nickName, + oneHourStatus + )) .from(teamMember) .where( teamMember.team.teamId.eq(teamId), @@ -57,7 +78,8 @@ public Optional> getFireReceivers(Long teamId, Long missionId) { .select(missionArchive.member.memberId) .from(missionArchive,mission) .where(missionArchive.mission.id.eq(missionId), - mission.id.eq(missionId)) + mission.id.eq(missionId), + missionArchive.member.memberId.notIn(memberId)) .groupBy(missionArchive.member.memberId, missionArchive.mission.id, missionArchive.count, mission.number) .having( diff --git a/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java b/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java index abb94e44..2bcaef0c 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.fire.domain.service; +import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.domain.entity.Fire; import com.moing.backend.domain.fire.domain.repository.FireCustomRepository; import com.moing.backend.domain.fire.domain.repository.FireRepository; @@ -21,8 +22,8 @@ public boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMembe return fireRepository.hasFireCreatedWithinOneHour(throwMemberId,receiveMemberId); } - public List getNotYetMissionMember(Long teamId, Long missionId) { - return fireRepository.getFireReceivers(teamId, missionId).orElseThrow(NotFoundFireReceiversException::new); + public List getNotYetMissionMember(Long teamId, Long missionId, Long memberId) { + return fireRepository.getFireReceivers(teamId, missionId,memberId).orElseThrow(NotFoundFireReceiversException::new); } } diff --git a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java index a9210481..f302d0f2 100644 --- a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java +++ b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java @@ -19,7 +19,7 @@ @RestController @AllArgsConstructor -@RequestMapping("/api/{teamId}/missions/{missionId}/fire") +@RequestMapping("/api/team/{teamId}/missions/{missionId}/fire") public class FireController { private final FireThrowUseCase fireThrowUseCase; @@ -30,7 +30,7 @@ public class FireController { * 작성자 : 정승연 */ - @PostMapping("{receiveMemberId}") + @PostMapping("/{receiveMemberId}") public ResponseEntity> throwFire (@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("receiveMemberId") Long receiveMemberId) { return ResponseEntity.ok(SuccessResponse.create(THROW_FIRE_SUCCESS.getMessage(), this.fireThrowUseCase.createFireThrow(user.getSocialId(),receiveMemberId))); @@ -42,7 +42,7 @@ public ResponseEntity> throwFire (@AuthenticationP * 작성자 : 정승연 */ - @GetMapping("") + @GetMapping() public ResponseEntity>> throwFireList (@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId) { return ResponseEntity.ok(SuccessResponse.create(GET_RECEIVERS_SUCCESS.getMessage(), this.fireThrowUseCase.getFireReceiveList(user.getSocialId(),teamId,missionId))); diff --git a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java index 767f6e4c..8aa1e1b0 100644 --- a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java +++ b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java @@ -51,7 +51,7 @@ public class FireControllerTest extends CommonControllerTest { Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/{teamId}/missions/{missionId}/fire",teamId,missionId) + get("/api/team/{teamId}/missions/{missionId}/fire",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) @@ -99,7 +99,7 @@ public class FireControllerTest extends CommonControllerTest { Long receiveMemberId = 2L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - post("/api/{teamId}/missions/{missionId}/fire/{receiveMemberId}",teamId,missionId,receiveMemberId) + post("/api/team/{teamId}/missions/{missionId}/fire/{receiveMemberId}",teamId,missionId,receiveMemberId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) ); From 2c5b71b52111052837d742ee19e1726cf320efe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 29 Nov 2023 18:07:41 +0900 Subject: [PATCH 276/619] =?UTF-8?q?fix=20:=20=EC=99=84=EB=A3=8C=EB=90=9C?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98=20=EC=A4=91=20=EC=84=B1=EA=B3=B5/?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8=20=EA=B8=B0=EC=A4=80=20=EB=B3=B4=EC=99=84=20?= =?UTF-8?q?(=EA=B0=9C=EC=9D=B8=EB=B3=84)=20::=20coalesce(FAIL)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index f9781c43..9aba3d60 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -206,7 +206,7 @@ public Optional> findFinishMissionsByStatus(Long mem mission.id, mission.dueTo.stringValue(), mission.title, - missionArchive.status.stringValue().coalesce("INCOMPLETE").as("status"), + missionArchive.status.stringValue().coalesce("FAIL").as("status"), mission.type.stringValue(), mission.way.stringValue() )) @@ -215,7 +215,7 @@ public Optional> findFinishMissionsByStatus(Long mem .on(missionArchive.member.memberId.eq(memberId)) .where( mission.team.teamId.eq(teamId), - mission.status.eq(MissionStatus.SUCCESS).or(mission.status.eq(MissionStatus.FAIL)) + mission.status.eq(MissionStatus.SUCCESS).or(mission.status.eq(MissionStatus.END)) ) .fetch() ); From 629d6ca627c2e11ac4ebd8fa56517d0959ef42b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 29 Nov 2023 18:57:31 +0900 Subject: [PATCH 277/619] =?UTF-8?q?fix=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20WAIT=20=EC=83=81=ED=83=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=84=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 9455fe5a..d90ab4e8 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -65,7 +65,7 @@ public Optional> findRepeatMissionByMemberId(Long m @Override public Optional> findMissionByDueTo() { - LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1); + LocalDateTime oneHourAgo = LocalDateTime.now(); return Optional.ofNullable(queryFactory .selectFrom(mission) From 1198e968f4f8fc4df6246f8a15e5b207d190f8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 29 Nov 2023 18:58:12 +0900 Subject: [PATCH 278/619] =?UTF-8?q?fix=20:=20=EB=B6=88=EB=8D=98=EC=A7=80?= =?UTF-8?q?=EA=B8=B0=20=EB=AA=A9=EB=A1=9D=EC=97=90=EC=84=9C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=ED=95=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=A0=9C=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/FireReceiveRes.java | 7 ++++ .../application/service/FireThrowUseCase.java | 14 +++---- .../repository/FireCustomRepositoryImpl.java | 39 +++++++++++-------- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java index 7b59d0a9..87ac3456 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java +++ b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java @@ -1,16 +1,23 @@ package com.moing.backend.domain.fire.application.dto.res; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @Builder @Getter +@AllArgsConstructor public class FireReceiveRes { private Long receiveMemberId; private String nickname; private String fireStatus; + public FireReceiveRes(Long receiveMemberId, String nickname) { + this.receiveMemberId = receiveMemberId; + this.nickname = nickname; + } + public void updateFireStatus(boolean status) { if (status) this.fireStatus = "True"; diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java index 117ccb0b..2c3faca8 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -65,13 +65,13 @@ public List getFireReceiveList(String userId,Long teamId, Long m res -> res.updateFireStatus(fireQueryService.hasFireCreatedWithinOneHour(memberId,res.getReceiveMemberId()) )); - if (!missionArchiveQueryService.isDone(memberId, missionId)) { - fireReceiveRes.add(0,FireReceiveRes.builder() - .receiveMemberId(memberId) - .nickname(member.getNickName()) - .fireStatus("False") - .build()); - } +// if (!missionArchiveQueryService.isDone(memberId, missionId)) { +// fireReceiveRes.add(0,FireReceiveRes.builder() +// .receiveMemberId(memberId) +// .nickname(member.getNickName()) +// .fireStatus("False") +// .build()); +// } return fireReceiveRes; } diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index fa5ab01e..29abcb5a 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -7,6 +7,7 @@ import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -51,6 +52,20 @@ public boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMembe public Optional> getFireReceivers(Long teamId, Long missionId, Long memberId) { + JPQLQuery missionDonePeople = select(missionArchive.member.memberId) + .from(missionArchive, mission) + .where(missionArchive.mission.id.eq(missionId), + mission.id.eq(missionId) + ) + .groupBy(missionArchive.member.memberId, + missionArchive.mission.id, + missionArchive.count, + mission.number) + .having( + missionArchive.mission.id.eq(missionId), + missionArchive.count.max().goe(mission.number) + ); + LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1); // 현재 시간에서 1시간을 뺀 시간 BooleanExpression oneHourStatus = JPAExpressions @@ -58,35 +73,25 @@ public Optional> getFireReceivers(Long teamId, Long mission .from(fire) .where( fire.throwMemberId.eq(memberId), - fire.receiveMemberId.eq(teamMember.member.memberId), + fire.receiveMemberId.notIn(missionDonePeople), fire.createdDate.after(oneHourAgo) // createdDate가 oneHourAgo 이후인 데이터 ) + .exists(); return Optional.ofNullable(queryFactory .select(Projections.constructor(FireReceiveRes.class, teamMember.member.memberId, - teamMember.member.nickName, - oneHourStatus + teamMember.member.nickName +// oneHourStatus.stringValue() +// teamMember.member.nickName )) .from(teamMember) .where( teamMember.team.teamId.eq(teamId), - teamMember.member.memberId.notIn( - JPAExpressions - .select(missionArchive.member.memberId) - .from(missionArchive,mission) - .where(missionArchive.mission.id.eq(missionId), - mission.id.eq(missionId), - missionArchive.member.memberId.notIn(memberId)) - .groupBy(missionArchive.member.memberId, missionArchive.mission.id, - missionArchive.count, mission.number) - .having( - missionArchive.mission.id.eq(missionId), - missionArchive.count.max().goe(mission.number) - ) - ) + teamMember.member.memberId.ne(memberId), + teamMember.member.memberId.notIn(missionDonePeople) ) .fetch()); From 4008c8ff64633e9bdb33fca55dbe5d9f7b54626d Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 30 Nov 2023 00:19:01 +0900 Subject: [PATCH 279/619] =?UTF-8?q?fix:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=9E=91=EC=84=B1=EC=9E=90=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/mapper/BoardCommentMapper.java | 6 +++++- .../application/service/CreateBoardCommentUseCase.java | 5 ++++- .../boardComment/domain/entity/BoardComment.java | 10 ++++++++++ .../repository/BoardCommentCustomRepositoryImpl.java | 6 +++--- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java b/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java index 03169f2d..f191d0e5 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -10,9 +11,12 @@ @Component @RequiredArgsConstructor public class BoardCommentMapper { - public BoardComment toBoardComment(TeamMember teamMember, Board board, CreateBoardCommentRequest createBoardCommentRequest){ + public BoardComment toBoardComment(Member member, TeamMember teamMember, Board board, CreateBoardCommentRequest createBoardCommentRequest, boolean isLeader){ BoardComment boardComment= BoardComment.builder() .content(createBoardCommentRequest.getContent()) + .writerNickName(member.getNickName()) + .writerProfileImage(member.getProfileImage()) + .isLeader(isLeader) .build(); boardComment.updateBoard(board); boardComment.updateTeamMember(teamMember); diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java index 6245acfe..c4e707f4 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.boardComment.application.mapper.BoardCommentMapper; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.service.BoardCommentSaveService; +import com.moing.backend.domain.team.application.service.CheckLeaderUseCase; import com.moing.backend.global.response.BaseBoardServiceResponse; import com.moing.backend.global.util.BaseBoardService; import lombok.RequiredArgsConstructor; @@ -20,6 +21,7 @@ public class CreateBoardCommentUseCase { private final BoardCommentSaveService boardCommentSaveService; private final BoardCommentMapper boardCommentMapper; private final BaseBoardService baseBoardService; + private final CheckLeaderUseCase checkLeaderUseCase; /** * 게시글 댓글 생성 @@ -27,7 +29,8 @@ public class CreateBoardCommentUseCase { public CreateBoardCommentResponse createBoardComment(String socialId, Long teamId, Long boardId, CreateBoardCommentRequest createBoardCommentRequest) { // 1. 게시글 댓글 생성 BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); - BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(data.getTeamMember(), data.getBoard(), createBoardCommentRequest)); + boolean isLeader = checkLeaderUseCase.isTeamLeader(data.getMember(), data.getTeam()); + BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(data.getMember(), data.getTeamMember(), data.getBoard(), createBoardCommentRequest, isLeader)); // 2. 게시글 댓글 개수 증가 data.getBoard().incrComNum(); return new CreateBoardCommentResponse(boardComment.getBoardCommentId()); diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java index 35381e68..2de67841 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.entity.BaseTimeEntity; +import com.moing.backend.global.util.AesConverter; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -31,6 +32,15 @@ public class BoardComment extends BaseTimeEntity { @JoinColumn(name = "board_id") private Board board; + //반정규화 -> 작성자에 대한 정보 + @Convert(converter = AesConverter.class) + @Column(nullable = false) + private String writerNickName; /*작성자 닉네임*/ + + private boolean isLeader; /*작성자 소모임장유무*/ + + private String writerProfileImage; /*작성자 프로필 사진*/ + /** * 연관관계 매핑 */ diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index f31d6e11..9b3ec7e4 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -29,9 +29,9 @@ public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember team .select(Projections.constructor(CommentBlocks.class, boardComment.boardCommentId, boardComment.content, - boardComment.board.writerNickName, - boardComment.board.isLeader, - boardComment.board.writerProfileImage, + boardComment.writerNickName, + boardComment.isLeader, + boardComment.writerProfileImage, ExpressionUtils.as(JPAExpressions .selectOne() .from(QTeamMember.teamMember) From 72f885ddd7e4eeaff3dd763d2b2e25edede5909a Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 30 Nov 2023 01:21:53 +0900 Subject: [PATCH 280/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=20=EC=A1=B0=ED=9A=8C=20api=EC=97=90=20?= =?UTF-8?q?=EC=86=8C=EB=AA=A8=EC=9E=84=EC=9E=A5=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/GetTeamCountResponse.java | 11 +++++++++++ .../domain/repository/TeamCustomRepository.java | 2 +- .../repository/TeamCustomRepositoryImpl.java | 14 ++++++++++++-- .../domain/team/domain/service/TeamGetService.java | 5 ++--- .../team/presentation/TeamControllerTest.java | 4 +++- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java index 7cae31ee..ff627afc 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.team.application.dto.response; +import com.querydsl.core.annotations.QueryProjection; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -11,5 +12,15 @@ public class GetTeamCountResponse { private String teamName; private Long numOfTeam; + private String leaderName; + public void updateCount(Long count){ + this.numOfTeam=count; + } + + @QueryProjection + public GetTeamCountResponse(String teamName, String leaderName){ + this.teamName=teamName; + this.leaderName=leaderName; + } } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index df7083d4..a65e5c0a 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -22,5 +22,5 @@ public interface TeamCustomRepository { void updateTeamStatus(boolean isApproved, List teamIds); List findLeaderInfoByTeamIds(List teamIds); Page findNewTeam(String dateSort, Pageable pageable); - Long findTeamCount(Long memberId); + GetTeamCountResponse findTeamCount(Long memberId, Long teamId); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index f94c031c..f5c764c8 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -178,9 +178,9 @@ public Page findNewTeam(String dateSort, Pageable pageable) } @Override - public Long findTeamCount(Long memberId) { + public GetTeamCountResponse findTeamCount(Long memberId, Long teamId) { LocalDateTime threeDaysAgo = LocalDateTime.now().minusDays(3); - return queryFactory + long count=queryFactory .select(team.count()) // 팀의 개수를 세기 위해 수정 .from(teamMember) .innerJoin(teamMember.team, team) @@ -191,6 +191,16 @@ public Long findTeamCount(Long memberId) { .or(team.deletionTime.after(threeDaysAgo)))) // 강제종료된 경우 3일이 지나지 않았다면 .fetchOne(); // 단일 결과 (개수) 반환 + GetTeamCountResponse response=queryFactory + .select(new QGetTeamCountResponse(team.name, member.nickName)) + .from(team) + .join(member).on(team.leaderId.eq(member.memberId)) + .where(team.teamId.eq(teamId)) + .fetchOne(); + + response.updateCount(count); + + return response; } diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index 6afe5733..9498ce8d 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -57,9 +57,8 @@ public Page getNewTeams(String dateSort, Pageable pageable) } public GetTeamCountResponse getTeamCountAndName(Long teamId, Long memberId) { - String teamName = getTeamByTeamId(teamId).getName(); - Long numOfTeam = teamRepository.findTeamCount(memberId); - return new GetTeamCountResponse(teamName, numOfTeam); + + return teamRepository.findTeamCount(memberId, teamId); } } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 56513f5a..4d0f0f82 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -516,6 +516,7 @@ public void get_team_count() throws Exception { GetTeamCountResponse output = GetTeamCountResponse.builder() .teamName("소모임 이름") .numOfTeam(2L) + .leaderName("소모임장 이름") .build(); given(getTeamUseCase.getTeamCount(any(), any())).willReturn(output); @@ -544,7 +545,8 @@ public void get_team_count() throws Exception { fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("소모임을 수정했습니다."), fieldWithPath("data.teamName").description("소모임 이름"), - fieldWithPath("data.numOfTeam").description("지금까지 가입한 소모임 개수") + fieldWithPath("data.numOfTeam").description("지금까지 가입한 소모임 개수"), + fieldWithPath("data.leaderName").description("소모임장 이름") ) ) ); From 275bcd8ba849c9f2dc31b267835c094d2bd80305 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 30 Nov 2023 01:30:51 +0900 Subject: [PATCH 281/619] =?UTF-8?q?fix:=20team=20review=20api=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=86=8C=EB=AA=A8=EC=9E=84=EC=9E=A5=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/ReviewTeamResponse.java | 2 ++ .../domain/team/application/mapper/TeamMapper.java | 3 ++- .../team/application/service/ReviewTeamUseCase.java | 9 +++++++-- .../domain/team/presentation/TeamControllerTest.java | 4 +++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java index f3b86539..bca79fe1 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java @@ -10,10 +10,12 @@ @AllArgsConstructor @NoArgsConstructor public class ReviewTeamResponse { + private Long teamId; private String teamName; private Integer numOfMember; private Long duration; //걸린시간(단위:날짜) private Long numOfMission; private Integer levelOfFire; //불꽃 레벨 + private Boolean isLeader; } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index ea035595..d6239590 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -38,7 +38,7 @@ public GetTeamDetailResponse toTeamDetailResponse(Long memberId, Team team, Inte .build(); } - public ReviewTeamResponse toReviewTeamResponse(Long numOfMission, Team team){ + public ReviewTeamResponse toReviewTeamResponse(Long numOfMission, Team team, boolean isLeader){ return ReviewTeamResponse .builder() .teamId(team.getTeamId()) @@ -47,6 +47,7 @@ public ReviewTeamResponse toReviewTeamResponse(Long numOfMission, Team team){ .levelOfFire(team.getLevelOfFire()) .duration(calculateDuration(team.getApprovalTime())) .numOfMission(numOfMission) + .isLeader(isLeader) .build(); } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java index 9647aedf..f8ee2fae 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java @@ -1,5 +1,7 @@ package com.moing.backend.domain.team.application.service; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.team.application.dto.response.ReviewTeamResponse; import com.moing.backend.domain.team.application.mapper.TeamMapper; @@ -18,10 +20,13 @@ public class ReviewTeamUseCase { private final TeamGetService teamGetService; private final TeamMapper teamMapper; private final MissionQueryService missionQueryService; - + private final CheckLeaderUseCase checkLeaderUseCase; + private final MemberGetService memberGetService; public ReviewTeamResponse reviewTeam(String socialId, Long teamId){ Team team=teamGetService.getTeamByTeamId(teamId); - return teamMapper.toReviewTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()),team); + Member member=memberGetService.getMemberBySocialId(socialId); + boolean isLeader=checkLeaderUseCase.isTeamLeader(member, team); + return teamMapper.toReviewTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()),team, isLeader); } } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 4d0f0f82..c997a72c 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -259,6 +259,7 @@ public void review_team() throws Exception { .duration(30L) .numOfMission(90L) .levelOfFire(3) + .isLeader(false) .build(); given(reviewTeamUseCase.reviewTeam(any(), any())).willReturn(output); @@ -289,7 +290,8 @@ public void review_team() throws Exception { fieldWithPath("data.numOfMember").description("모임원 명 수"), fieldWithPath("data.duration").description("소모임과 함께한 시간"), fieldWithPath("data.levelOfFire").description("소모임 불꽃 레벨"), - fieldWithPath("data.numOfMission").description("미션 총 개수") + fieldWithPath("data.numOfMission").description("미션 총 개수"), + fieldWithPath("data.isLeader").description("소모임장 여부") ) ) ); From e76f9e002250982f9af2688085005186ef646475 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 30 Nov 2023 01:49:03 +0900 Subject: [PATCH 282/619] =?UTF-8?q?fix:=20=EA=B3=B5=EC=A7=80=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EB=AC=B8=EA=B5=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendBoardAlarmUseCase.java | 15 ++++++------- .../fcm/constant/NewNoticeUploadMessage.java | 22 +++++++++++++++++++ .../global/config/fcm/service/FcmService.java | 4 ++++ 3 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/moing/backend/global/config/fcm/constant/NewNoticeUploadMessage.java diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index 221c28d8..9a66df10 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -4,17 +4,17 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; -import com.moing.backend.global.config.fcm.dto.request.MultiRequest; -import com.moing.backend.global.config.fcm.service.FcmService; +import com.moing.backend.global.config.fcm.dto.event.FcmEvent; import com.moing.backend.global.response.BaseServiceResponse; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.transaction.Transactional; import java.util.List; import java.util.Optional; -import static com.moing.backend.global.config.fcm.constant.NewUploadTitle.UPLOAD_NOTICE_NEW_TITLE; +import static com.moing.backend.global.config.fcm.constant.NewNoticeUploadMessage.NEW_NOTICE_UPLOAD_MESSAGE; @Service @RequiredArgsConstructor @@ -22,19 +22,18 @@ public class SendBoardAlarmUseCase { private final TeamMemberGetService teamMemberGetService; - private final FcmService fcmService; + private final ApplicationEventPublisher eventPublisher; public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board board) { Member member = baseServiceResponse.getMember(); Team team = baseServiceResponse.getTeam(); if (board.isNotice() && member.isNewUploadPush()) { - String title = team.getName() + " " + UPLOAD_NOTICE_NEW_TITLE.getTitle(); - String message = board.getTitle(); + String title = NEW_NOTICE_UPLOAD_MESSAGE.title(team.getName()); + String body = NEW_NOTICE_UPLOAD_MESSAGE.body(board.getTitle()); Optional> fcmTokens = teamMemberGetService.getFcmTokensExceptMe(team.getTeamId(), member.getMemberId()); if (fcmTokens.isPresent() && !fcmTokens.get().isEmpty()) { - MultiRequest toMultiRequest = new MultiRequest(fcmTokens.get(), title, message); - fcmService.sendMultipleDevices(toMultiRequest); + eventPublisher.publishEvent(new FcmEvent(title, body, fcmTokens.get())); } } } diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/NewNoticeUploadMessage.java b/src/main/java/com/moing/backend/global/config/fcm/constant/NewNoticeUploadMessage.java new file mode 100644 index 00000000..f404ac6e --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/NewNoticeUploadMessage.java @@ -0,0 +1,22 @@ +package com.moing.backend.global.config.fcm.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum NewNoticeUploadMessage { + + NEW_NOTICE_UPLOAD_MESSAGE("%s에 새로 올라온 공지를 확인하세요!", "%s"); + + private final String title; + private final String body; + + public String title(String teamName) { + return String.format(title, teamName); + } + + public String body(String noticeTitle) { + return String.format(title, noticeTitle); + } +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java index 74cdb54d..30276df5 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java +++ b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java @@ -8,6 +8,8 @@ import com.moing.backend.global.config.fcm.exception.NotificationException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Service; import javax.transaction.Transactional; @@ -23,6 +25,7 @@ public class FcmService { private final FirebaseMessaging firebaseMessaging; + @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { Notification notification = Notification.builder() @@ -67,6 +70,7 @@ public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { } + @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) public MultiResponse sendMultipleDevices(MultiRequest toMultiRequest) { Notification notification = Notification.builder() From 2b4cc24d344ccbcb5732971d1e92dfd0ad7d7ac7 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 30 Nov 2023 02:13:32 +0900 Subject: [PATCH 283/619] =?UTF-8?q?hotfix:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mypage/application/service/ProfileUseCase.java | 7 +++++-- .../java/com/moing/backend/global/config/s3/S3Service.java | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java index fc7c88ca..979f060a 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.util.concurrent.CompletableFuture; @Service @RequiredArgsConstructor @@ -41,8 +42,10 @@ private String getUpdatedValue(String newValue, String currentValue) { } private void deletePreviousImage(UpdateProfileRequest updateProfileRequest, Member member) { - if (updateProfileRequest.getProfileImage() != null) { - s3Service.deleteImage(member.getProfileImage()); + if (updateProfileRequest.getProfileImage() != null && member.getProfileImage() != null) { + CompletableFuture.runAsync(() -> { + s3Service.deleteImage(member.getProfileImage()); + }); } } diff --git a/src/main/java/com/moing/backend/global/config/s3/S3Service.java b/src/main/java/com/moing/backend/global/config/s3/S3Service.java index 253a0de9..5f39dfdc 100644 --- a/src/main/java/com/moing/backend/global/config/s3/S3Service.java +++ b/src/main/java/com/moing/backend/global/config/s3/S3Service.java @@ -42,10 +42,12 @@ public void deleteImage(String fileUrl) { String splitStr = ".com/"; String fileName = fileUrl.substring(fileUrl.lastIndexOf(splitStr) + splitStr.length()); - amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName)); + if (amazonS3.doesObjectExist(bucket, fileName)) { + amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName)); + } } - private String createFileName(String fileExtension) { + private String createFileName(String fileExtension) { return UUID.randomUUID() + "." + fileExtension; } From 17d65771f329c33b568b036baba7aa5a51ca63aa Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 30 Nov 2023 02:32:55 +0900 Subject: [PATCH 284/619] =?UTF-8?q?fix:=20=EC=82=AD=EC=A0=9C=20=EC=A0=84?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EB=95=8C=20=EC=9C=A0=EC=A0=80?= =?UTF-8?q?=20=EB=8B=89=EB=84=A4=EC=9E=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/application/dto/response/ReviewTeamResponse.java | 1 + .../backend/domain/team/application/mapper/TeamMapper.java | 3 ++- .../domain/team/application/service/ReviewTeamUseCase.java | 2 +- .../backend/domain/team/presentation/TeamControllerTest.java | 4 +++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java index bca79fe1..f259913a 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/ReviewTeamResponse.java @@ -18,4 +18,5 @@ public class ReviewTeamResponse { private Long numOfMission; private Integer levelOfFire; //불꽃 레벨 private Boolean isLeader; + private String memberName; } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index d6239590..081a39a2 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -38,7 +38,7 @@ public GetTeamDetailResponse toTeamDetailResponse(Long memberId, Team team, Inte .build(); } - public ReviewTeamResponse toReviewTeamResponse(Long numOfMission, Team team, boolean isLeader){ + public ReviewTeamResponse toReviewTeamResponse(Long numOfMission, Team team, boolean isLeader, String memberName){ return ReviewTeamResponse .builder() .teamId(team.getTeamId()) @@ -48,6 +48,7 @@ public ReviewTeamResponse toReviewTeamResponse(Long numOfMission, Team team, boo .duration(calculateDuration(team.getApprovalTime())) .numOfMission(numOfMission) .isLeader(isLeader) + .memberName(memberName) .build(); } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java index f8ee2fae..7176ca7a 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java @@ -27,6 +27,6 @@ public ReviewTeamResponse reviewTeam(String socialId, Long teamId){ Team team=teamGetService.getTeamByTeamId(teamId); Member member=memberGetService.getMemberBySocialId(socialId); boolean isLeader=checkLeaderUseCase.isTeamLeader(member, team); - return teamMapper.toReviewTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()),team, isLeader); + return teamMapper.toReviewTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()),team, isLeader, member.getNickName()); } } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index c997a72c..fd30a521 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -260,6 +260,7 @@ public void review_team() throws Exception { .numOfMission(90L) .levelOfFire(3) .isLeader(false) + .memberName("유저 닉네임") .build(); given(reviewTeamUseCase.reviewTeam(any(), any())).willReturn(output); @@ -291,7 +292,8 @@ public void review_team() throws Exception { fieldWithPath("data.duration").description("소모임과 함께한 시간"), fieldWithPath("data.levelOfFire").description("소모임 불꽃 레벨"), fieldWithPath("data.numOfMission").description("미션 총 개수"), - fieldWithPath("data.isLeader").description("소모임장 여부") + fieldWithPath("data.isLeader").description("소모임장 여부"), + fieldWithPath("data.memberName").description("유저 닉네임") ) ) ); From 3d882eb10ad86e277cab884e682466a61925d2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:06:39 +0900 Subject: [PATCH 285/619] =?UTF-8?q?fix=20:=20=EB=AA=A8=EC=9E=84=EC=95=84?= =?UTF-8?q?=20=EC=A0=9C=EB=B0=9C=20=EC=82=AC=EB=9D=BC=EC=A7=80=EC=A7=80?= =?UTF-8?q?=EB=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index d90ab4e8..296ca6a8 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -70,7 +70,7 @@ public Optional> findMissionByDueTo() { return Optional.ofNullable(queryFactory .selectFrom(mission) .where( - mission.dueTo.after(oneHourAgo) + mission.dueTo.eq(oneHourAgo) ).fetch()); } From 61b69c30dfa59d618274ff3a2f0d40d5cc8fe4b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 30 Nov 2023 22:17:41 +0900 Subject: [PATCH 286/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=EC=95=84?= =?UTF-8?q?=20=EC=A0=9C=EB=B0=9C=20..=20=EC=82=AC=EB=9D=BC=EC=A7=80?= =?UTF-8?q?=EC=A7=80=EB=A7=88=20..?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionCustomRepositoryImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 296ca6a8..2dee0bc5 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -65,12 +65,14 @@ public Optional> findRepeatMissionByMemberId(Long m @Override public Optional> findMissionByDueTo() { - LocalDateTime oneHourAgo = LocalDateTime.now(); + LocalDateTime now = LocalDateTime.now(); return Optional.ofNullable(queryFactory .selectFrom(mission) .where( - mission.dueTo.eq(oneHourAgo) + mission.dueTo.before(now), + mission.status.eq(MissionStatus.WAIT).or(mission.status.eq(MissionStatus.ONGOING)), + mission.type.eq(MissionType.ONCE) ).fetch()); } From aa82eea8c7c783c5ee15affb9b729ea121491a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 30 Nov 2023 22:22:11 +0900 Subject: [PATCH 287/619] =?UTF-8?q?fix=20:=20=EB=B6=88=EB=8D=98=EC=A7=80?= =?UTF-8?q?=EA=B8=B0=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EB=A6=AC?= =?UTF-8?q?=ED=84=B4=EA=B0=92=20=EC=B6=94=EA=B0=80(=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fire/application/dto/res/FireReceiveRes.java | 4 +++- .../repository/FireCustomRepositoryImpl.java | 3 ++- .../service/MissionStateScheduleUseCase.java | 14 +++++++++++--- .../fire/representation/FireControllerTest.java | 4 +++- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java index 87ac3456..337d90ac 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java +++ b/src/main/java/com/moing/backend/domain/fire/application/dto/res/FireReceiveRes.java @@ -12,10 +12,12 @@ public class FireReceiveRes { private Long receiveMemberId; private String nickname; private String fireStatus; + private String profileImg; - public FireReceiveRes(Long receiveMemberId, String nickname) { + public FireReceiveRes(Long receiveMemberId, String nickname,String profileImg) { this.receiveMemberId = receiveMemberId; this.nickname = nickname; + this.profileImg = profileImg; } public void updateFireStatus(boolean status) { diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 29abcb5a..9b51a0a0 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -83,7 +83,8 @@ public Optional> getFireReceivers(Long teamId, Long mission return Optional.ofNullable(queryFactory .select(Projections.constructor(FireReceiveRes.class, teamMember.member.memberId, - teamMember.member.nickName + teamMember.member.nickName, + teamMember.member.profileImage // oneHourStatus.stringValue() // teamMember.member.nickName )) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 15646366..57d5b21c 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionState.application.service; +import com.moing.backend.domain.mission.application.service.MissionRemindAlarmUseCase; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.service.MissionQueryService; @@ -25,10 +26,12 @@ public class MissionStateScheduleUseCase { private final MissionStateUseCase missionStateUseCase; + private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; private final MissionQueryService missionQueryService; private final MissionStateQueryService missionStateQueryService; private final MissionStateDeleteService missionStateDeleteService; + private final TeamScoreLogicUseCase teamScoreLogicUseCase; /** @@ -76,11 +79,9 @@ public void missionStateReset(List missionIds) { * 해당 시간 미션 마감 * 한시간 마다 실행 */ - @Scheduled(cron = "0 0 * * * *") + @Scheduled(cron = "0 1 * * * *") public void singleMissionEndRoutine() { - LocalDateTime now = LocalDateTime.now(); - List missionByDueTo = missionQueryService.findMissionByDueTo(); missionByDueTo.stream().forEach(mission -> { @@ -103,4 +104,11 @@ public void RepeatMissionStart() { mission -> mission.updateStatus(MissionStatus.ONGOING) ); } + + +// @Scheduled(cron = "8 0 0 * * *") +// public void MissionRemindAlarm() { +// +// missionRemindAlarmUseCase.sendRemindMissionAlarm(); +// } } diff --git a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java index 8aa1e1b0..5a2b61a5 100644 --- a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java +++ b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java @@ -43,6 +43,7 @@ public class FireControllerTest extends CommonControllerTest { .receiveMemberId(1L) .nickname("receiver 닉네임") .fireStatus("True/False") + .profileImg("https://oawijowijfi") .build()); given(fireThrowUseCase.getFireReceiveList(any(),any(),any())).willReturn(output); @@ -74,7 +75,8 @@ public class FireControllerTest extends CommonControllerTest { fieldWithPath("message").description(GET_RECEIVERS_SUCCESS.getMessage()), fieldWithPath("data[].receiveMemberId").description("미션 아이디"), fieldWithPath("data[].nickname").description("불 받을 사람 "), - fieldWithPath("data[].fireStatus").description("불 던질 수 있는 상태 리턴, 1시간 내 불 던진 내역에 따라 true[True/False]") + fieldWithPath("data[].fireStatus").description("불 던질 수 있는 상태 리턴, 1시간 내 불 던진 내역에 따라 true[True/False]"), + fieldWithPath("data[].profileImg").description("프로필 이미지") ) ) From 25a00739130c29baa8f423d251d0e63c1f0e9327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 30 Nov 2023 22:45:28 +0900 Subject: [PATCH 288/619] =?UTF-8?q?fix=20:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=20=EB=A9=94=EC=9D=B8=20=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=EB=AC=BC=20=EC=82=AC=EC=A7=84=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 9aba3d60..82837681 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; @@ -226,7 +227,8 @@ public Optional> findTop5ArchivesByTeam(List List queryResults = queryFactory .select(missionArchive.mission.team.teamId, missionArchive.archive) .from(missionArchive) - .where(missionArchive.mission.team.teamId.in(teamIds)) + .where(missionArchive.member.memberId.in(teamIds), + missionArchive.mission.way.eq(MissionWay.PHOTO)) .orderBy(missionArchive.createdDate.desc()) .limit(14) .fetch(); From e045478698e196ff1700e98559e27854475c5ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 1 Dec 2023 04:03:32 +0900 Subject: [PATCH 289/619] =?UTF-8?q?fix=20:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=20=EB=A9=94=EC=9D=B8=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=82=AC=EC=A7=84=20=EC=A1=B0=ED=9A=8C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionArchiveCustomRepositoryImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 82837681..7f8d8f95 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -227,8 +227,9 @@ public Optional> findTop5ArchivesByTeam(List List queryResults = queryFactory .select(missionArchive.mission.team.teamId, missionArchive.archive) .from(missionArchive) - .where(missionArchive.member.memberId.in(teamIds), - missionArchive.mission.way.eq(MissionWay.PHOTO)) + .where(missionArchive.mission.team.teamId.in(teamIds), + missionArchive.mission.way.eq(MissionWay.PHOTO), + missionArchive.status.eq(MissionArchiveStatus.COMPLETE)) .orderBy(missionArchive.createdDate.desc()) .limit(14) .fetch(); From 0603dc6b02c170d9dc07a39f62803fd63c5c6870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 1 Dec 2023 04:03:32 +0900 Subject: [PATCH 290/619] =?UTF-8?q?fix=20:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=20=EB=A9=94=EC=9D=B8=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=82=AC=EC=A7=84=20=EC=A1=B0=ED=9A=8C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionArchiveCustomRepositoryImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 82837681..7f8d8f95 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -227,8 +227,9 @@ public Optional> findTop5ArchivesByTeam(List List queryResults = queryFactory .select(missionArchive.mission.team.teamId, missionArchive.archive) .from(missionArchive) - .where(missionArchive.member.memberId.in(teamIds), - missionArchive.mission.way.eq(MissionWay.PHOTO)) + .where(missionArchive.mission.team.teamId.in(teamIds), + missionArchive.mission.way.eq(MissionWay.PHOTO), + missionArchive.status.eq(MissionArchiveStatus.COMPLETE)) .orderBy(missionArchive.createdDate.desc()) .limit(14) .fetch(); From 9116b5ba6568d3251a3816c024933ee581a8faa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:28:37 +0900 Subject: [PATCH 291/619] =?UTF-8?q?fix=20:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=20=EB=A9=94=EC=9D=B8=ED=8E=98=EC=9D=B4=EC=A7=80=20=ED=8C=80=20?= =?UTF-8?q?=EC=8A=A4=EC=BD=94=EC=96=B4=20team=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moing/backend/domain/team/domain/entity/Team.java | 4 ++++ .../teamScore/application/service/TeamScoreLogicUseCase.java | 1 + .../backend/domain/teamScore/domain/entity/TeamScore.java | 2 ++ 3 files changed, 7 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java index a028794e..099196e4 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -91,4 +91,8 @@ public void addTeamMember(){ public void deleteTeamMember(){ numOfMember--; } + + public void updateLevelOfFire() { + levelOfFire++; + } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index c48f0333..eebc5a56 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -44,6 +44,7 @@ public Long updateTeamScore(Long missionId) { teamScore.updateScore(getScoreByMission(mission)); teamScore.levelUp(); + team.updateLevelOfFire(); teamScoreSaveService.save(teamScore); return teamScore.getScore(); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index 6fd0fb49..8a6b4565 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -7,6 +7,7 @@ import lombok.RequiredArgsConstructor; import javax.persistence.*; +import javax.transaction.Transactional; @Entity @Getter @@ -36,6 +37,7 @@ public void updateScore(Long score) { this.score += score; } + @Transactional public void levelUp() { final int[] steps = {1, 2, 10, 25, 45, 100}; // 0부터 시작하기 때문에 무조건 0에서 걸림. From a7e46dd1b797f0f233e891c34d848eb4bcca911f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 1 Dec 2023 20:14:09 +0900 Subject: [PATCH 292/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EB=8B=B9=EC=9D=BC=20=EC=9D=B8=EC=A6=9D=20=EC=A0=9C?= =?UTF-8?q?=ED=95=9C=20=EA=B4=80=EB=A0=A8=20=EB=A1=9C=EA=B7=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionCustomRepositoryImpl.java | 10 ++++++++-- .../repository/MissionArchiveCustomRepositoryImpl.java | 4 ---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 2dee0bc5..ed8e04a2 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -5,7 +5,9 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.missionState.domain.entity.QMissionState; import com.querydsl.core.types.Projections; +import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -16,6 +18,7 @@ import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; +import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; public class MissionCustomRepositoryImpl implements MissionCustomRepository{ @@ -99,6 +102,7 @@ public Optional> findRepeatMissionByStatus(MissionStatus missionSt @Override public Optional> findSingleMissionByMemberId(Long memberId, List teams) { + return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherSingleMissionRes.class, mission.id, @@ -108,12 +112,14 @@ public Optional> findSingleMissionByMemberId(Long m mission.dueTo.stringValue() )) .from(mission) + .leftJoin(missionState).on(mission.id.eq(missionState.mission.id)) .where( mission.team.teamId.in(teams), mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), - mission.type.eq(MissionType.ONCE) - + mission.type.eq(MissionType.ONCE), + missionState.id.isNull() // missionState에 해당하는 행이 없는 경우만 필터링 ) + .orderBy(mission.dueTo.desc()) .fetch()); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 7f8d8f95..293ec640 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -264,10 +264,6 @@ public Boolean findMyArchivesToday(Long memberId, Long missionId) { LocalDateTime startOfToday = today.withHour(0).withMinute(0).withSecond(0).withNano(0); LocalDateTime endOfToday = today.withHour(23).withMinute(59).withSecond(59).withNano(999999999); - log.info("today"+ today); - log.info("startToday"+startOfToday); - log.info("endToday"+endOfToday); - long count = queryFactory .selectFrom(missionArchive) .where( From 74fefa405290f3d77669315456d759897fd68721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 1 Dec 2023 20:36:48 +0900 Subject: [PATCH 293/619] =?UTF-8?q?fix=20:=20=EB=B6=88=EA=BD=83=20?= =?UTF-8?q?=EC=A0=90=EC=88=98=EA=B0=80=20=EC=9A=B0=EC=88=98=EC=88=98=20?= =?UTF-8?q?=EC=98=AC=EB=9D=BC=EA=B0=80=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/TeamScoreLogicUseCase.java | 7 +++++-- .../backend/domain/teamScore/domain/entity/TeamScore.java | 6 ++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index eebc5a56..5ffadc2b 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.team.domain.service.TeamSaveService; import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; import com.moing.backend.domain.teamScore.domain.entity.TeamScore; import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; @@ -26,6 +27,7 @@ public class TeamScoreLogicUseCase { private final TeamScoreQueryService teamScoreQueryService; private final TeamScoreSaveService teamScoreSaveService; private final MissionStateQueryService missionStateQueryService; + private final TeamSaveService teamSaveService; public TeamScoreRes getTeamScoreInfo(Long teamId) { @@ -45,7 +47,10 @@ public Long updateTeamScore(Long missionId) { teamScore.updateScore(getScoreByMission(mission)); teamScore.levelUp(); team.updateLevelOfFire(); + teamScoreSaveService.save(teamScore); + teamSaveService.saveTeam(team); + return teamScore.getScore(); } @@ -66,8 +71,6 @@ public Long getScoreByMission(Mission mission) { } public Long donePeople(Mission mission) { - - log.info("done people-> {}", missionStateQueryService.stateCountByMissionId(mission.getId())); return Long.valueOf(missionStateQueryService.stateCountByMissionId(mission.getId())); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index 8a6b4565..efa1b47b 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -37,16 +37,14 @@ public void updateScore(Long score) { this.score += score; } - @Transactional public void levelUp() { final int[] steps = {1, 2, 10, 25, 45, 100}; -// 0부터 시작하기 때문에 무조건 0에서 걸림. for (int i = 5; i > 0; i--) { if (steps[i-1] <= this.level && this.level <= steps[i]) { - if (20 + (i-1) * 15 <= score) { // 여길 들어가질 않음 + if (20 + ((i-1) * 15) <= score) { this.level+=1; - this.score -= (20 + (i-1) * 15); + this.score -= (20 + ((i-1) * 15)); return; } } From 4c8e2d44e7b635925852a0a05e427eb013e89784 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 3 Dec 2023 21:16:32 +0900 Subject: [PATCH 294/619] =?UTF-8?q?hotfix:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=82=AC=EC=A7=84=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mypage/application/service/ProfileUseCase.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java index 979f060a..7b1ec83b 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java @@ -26,7 +26,9 @@ public GetProfileResponse getProfile(String socialId){ @Transactional public void updateProfile(String socialId, UpdateProfileRequest updateProfileRequest) { Member member = memberGetService.getMemberBySocialId(socialId); - deletePreviousImage(updateProfileRequest, member); + if(updateProfileRequest.getProfileImage()!=null){ + s3Service.deleteImage(member.getProfileImage()); + } member.updateProfile( getUpdatedValue(updateProfileRequest.getProfileImage(), member.getProfileImage()), getUpdatedValue(updateProfileRequest.getNickName(), member.getNickName()), @@ -41,12 +43,4 @@ private String getUpdatedValue(String newValue, String currentValue) { return currentValue; } - private void deletePreviousImage(UpdateProfileRequest updateProfileRequest, Member member) { - if (updateProfileRequest.getProfileImage() != null && member.getProfileImage() != null) { - CompletableFuture.runAsync(() -> { - s3Service.deleteImage(member.getProfileImage()); - }); - } - } - } From ccffea9f891964c623881feaaef173f08f48c969 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 3 Dec 2023 21:30:05 +0900 Subject: [PATCH 295/619] =?UTF-8?q?hotfix:=20=ED=94=84=EB=A1=9C=ED=95=84?= =?UTF-8?q?=20=EC=82=AC=EC=A7=84=20=EC=88=98=EC=A0=95=20null=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mypage/application/service/ProfileUseCase.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java index 7b1ec83b..e2371ca4 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java @@ -9,7 +9,6 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; -import java.util.concurrent.CompletableFuture; @Service @RequiredArgsConstructor @@ -26,7 +25,7 @@ public GetProfileResponse getProfile(String socialId){ @Transactional public void updateProfile(String socialId, UpdateProfileRequest updateProfileRequest) { Member member = memberGetService.getMemberBySocialId(socialId); - if(updateProfileRequest.getProfileImage()!=null){ + if (updateProfileRequest.getProfileImage() != null && member.getProfileImage() != null) { s3Service.deleteImage(member.getProfileImage()); } member.updateProfile( From 2f975707c23a92b3bcfb9091102d18aad09e3226 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 3 Dec 2023 22:53:57 +0900 Subject: [PATCH 296/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=20=EB=B3=B4=EB=82=BC=20=EB=95=8C=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=20=EB=8B=89=EB=84=A4=EC=9E=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/application/dto/response/GetTeamCountResponse.java | 5 +++++ .../domain/team/application/service/GetTeamUseCase.java | 4 +++- .../backend/domain/team/presentation/TeamControllerTest.java | 4 +++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java index ff627afc..e6ad022b 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java @@ -13,11 +13,16 @@ public class GetTeamCountResponse { private String teamName; private Long numOfTeam; private String leaderName; + private String memberName; public void updateCount(Long count){ this.numOfTeam=count; } + public void updateMemberName(String nickName){ + this.memberName=memberName; + } + @QueryProjection public GetTeamCountResponse(String teamName, String leaderName){ this.teamName=teamName; diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java index 74700bc0..d81edcba 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java @@ -50,6 +50,8 @@ public Page getNewTeam(String dateSort, Pageable pageable) { public GetTeamCountResponse getTeamCount(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); - return teamGetService.getTeamCountAndName(teamId, member.getMemberId()); + GetTeamCountResponse response= teamGetService.getTeamCountAndName(teamId, member.getMemberId()); + response.updateMemberName(member.getNickName()); + return response; } } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index fd30a521..7306ffe0 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -521,6 +521,7 @@ public void get_team_count() throws Exception { .teamName("소모임 이름") .numOfTeam(2L) .leaderName("소모임장 이름") + .memberName("멤버 이름") .build(); given(getTeamUseCase.getTeamCount(any(), any())).willReturn(output); @@ -550,7 +551,8 @@ public void get_team_count() throws Exception { fieldWithPath("message").description("소모임을 수정했습니다."), fieldWithPath("data.teamName").description("소모임 이름"), fieldWithPath("data.numOfTeam").description("지금까지 가입한 소모임 개수"), - fieldWithPath("data.leaderName").description("소모임장 이름") + fieldWithPath("data.leaderName").description("소모임장 이름"), + fieldWithPath("data.memberName").description("유저 닉네임") ) ) ); From ff100d4ff9b3b264960772fc32314f2aad929310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 3 Dec 2023 23:20:24 +0900 Subject: [PATCH 297/619] =?UTF-8?q?fix=20:=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=EC=9D=B8=EC=9B=90=20=EB=AF=B8=EC=85=98=20=EC=99=84=EB=A3=8C=20?= =?UTF-8?q?=EC=A0=84=EC=97=90=20=EC=99=84=EB=A3=8C=EB=90=98=EB=8D=98=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionState/application/service/MissionStateUseCase.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index f3405ce6..43e90c1e 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -42,9 +42,7 @@ public boolean isAbleToEnd(Long missionId) { Long total = totalPeople(mission); Long done = donePeople(mission); - log.info("done/total -> "+ done+ total); - - return done == total-1; + return done.equals(total); } public boolean isAbleToScoreUp(Long missionId) { From d1819349e090fe4be7f95e044837df5c3fff2212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 3 Dec 2023 23:20:53 +0900 Subject: [PATCH 298/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=99=84=EB=A3=8C=20=ED=9B=84=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0=EC=97=90=20=EB=9C=A8?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=95=84=EC=95=BC=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionCustomRepositoryImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index ed8e04a2..1a6987e7 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -54,7 +54,10 @@ public Optional> findRepeatMissionByMemberId(Long m )) .from(mission) .leftJoin(missionArchive) - .on(missionArchive.mission.eq(mission), missionArchive.member.memberId.eq(memberId)) + .on(missionArchive.mission.eq(mission), + missionArchive.member.memberId.eq(memberId) +// ,missionArchive.count.max().loe(missionArchive.mission.number) + ) .where( mission.team.teamId.in(teams), mission.status.eq(MissionStatus.ONGOING), @@ -117,7 +120,7 @@ public Optional> findSingleMissionByMemberId(Long m mission.team.teamId.in(teams), mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), mission.type.eq(MissionType.ONCE), - missionState.id.isNull() // missionState에 해당하는 행이 없는 경우만 필터링 + missionState.id.isNull() ) .orderBy(mission.dueTo.desc()) .fetch()); From 570d2b2e92e25766dce53f23dbefe6e49569c8d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 3 Dec 2023 23:44:14 +0900 Subject: [PATCH 299/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=82=AD=EC=A0=9C=20response=20message?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/constant/MissionArchiveResponseMessage.java | 1 + .../domain/service/MissionArchiveDeleteService.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java index 8f278ce6..4be74d90 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java @@ -9,6 +9,7 @@ public enum MissionArchiveResponseMessage { CREATE_ARCHIVE_SUCCESS("미션 인증을 완료 했습니다."), UPDATE_ARCHIVE_SUCCESS("미션 재인증을 완료 했습니다."), + DELETE_ARCHIVE_SUCCESS("미션 인증 삭제를 완료 했습니다."), READ_MY_ARCHIVE_SUCCESS("나의 미션 인증 현황 조회를 완료 했습니다."), READ_TEAM_ARCHIVE_SUCCESS("팀원 미션 인증 현황 조회를 완료 했습니다."), HEART_UPDATE_SUCCESS("미션 인증 좋아요를 성공적으로 눌렀습니다."), diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java index a616fe10..3bb8f5c1 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java @@ -11,7 +11,7 @@ @RequiredArgsConstructor public class MissionArchiveDeleteService { - private MissionArchiveRepository missionArchiveRepository; + private final MissionArchiveRepository missionArchiveRepository; public void deleteMissionArchive(MissionArchive missionArchive) { missionArchiveRepository.delete(missionArchive); From 094d67b008861d74b5ded3dd8a0df2dee9d9dc77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 4 Dec 2023 00:36:01 +0900 Subject: [PATCH 300/619] =?UTF-8?q?feat=20:=20=EA=B2=8C=EC=8B=9C=EA=B8=80/?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=8B=A0=EA=B3=A0=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/mapper/ReportMapper.java | 18 +++++++++++ .../service/ReportCreateUseCase.java | 24 +++++++++++++++ .../domain/report/domain/entity/Report.java | 30 +++++++++++++++++++ .../domain/entity/constant/ReportType.java | 5 ++++ .../domain/repository/ReportRepository.java | 8 +++++ .../domain/service/ReportSaveService.java | 17 +++++++++++ .../report/presentation/ReportController.java | 30 +++++++++++++++++++ .../constant/ReportResponseMessage.java | 16 ++++++++++ 8 files changed, 148 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/report/application/mapper/ReportMapper.java create mode 100644 src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/report/domain/entity/Report.java create mode 100644 src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java create mode 100644 src/main/java/com/moing/backend/domain/report/domain/repository/ReportRepository.java create mode 100644 src/main/java/com/moing/backend/domain/report/domain/service/ReportSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/report/presentation/ReportController.java create mode 100644 src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java diff --git a/src/main/java/com/moing/backend/domain/report/application/mapper/ReportMapper.java b/src/main/java/com/moing/backend/domain/report/application/mapper/ReportMapper.java new file mode 100644 index 00000000..2190cec0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/application/mapper/ReportMapper.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.report.application.mapper; + +import com.moing.backend.domain.report.domain.entity.Report; +import com.moing.backend.domain.report.domain.entity.constant.ReportType; +import com.moing.backend.global.annotation.Mapper; + +@Mapper +public class ReportMapper { + + public static Report mapToReport(Long memberId, Long targetId, String reportType) { + return Report.builder() + .reportMemberId(memberId) + .reportType(ReportType.valueOf(reportType)) + .targetId(targetId) + .build(); + } + +} diff --git a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java new file mode 100644 index 00000000..73a2d2fa --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.report.application.service; + +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.report.application.mapper.ReportMapper; +import com.moing.backend.domain.report.domain.entity.Report; +import com.moing.backend.domain.report.domain.service.ReportSaveService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class ReportCreateUseCase { + + private final ReportSaveService reportSaveService; + private final MemberGetService memberGetService; + + public Long createReport(String socialId, Long targetId, String reportType) { + Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); + Report save = reportSaveService.save(ReportMapper.mapToReport(memberId, targetId, reportType)); + return save.getTargetId(); + } +} diff --git a/src/main/java/com/moing/backend/domain/report/domain/entity/Report.java b/src/main/java/com/moing/backend/domain/report/domain/entity/Report.java new file mode 100644 index 00000000..505d0a2c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/domain/entity/Report.java @@ -0,0 +1,30 @@ +package com.moing.backend.domain.report.domain.entity; + + +import com.moing.backend.domain.report.domain.entity.constant.ReportType; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Builder +public class Report extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "report_id") + private Long id; + + @Enumerated(EnumType.STRING) + private ReportType reportType; + + private Long reportMemberId; + private Long targetId; +} diff --git a/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java b/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java new file mode 100644 index 00000000..2c844a0c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.report.domain.entity.constant; + +public enum ReportType { + MISSION,BOARD +} diff --git a/src/main/java/com/moing/backend/domain/report/domain/repository/ReportRepository.java b/src/main/java/com/moing/backend/domain/report/domain/repository/ReportRepository.java new file mode 100644 index 00000000..50c5b296 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/domain/repository/ReportRepository.java @@ -0,0 +1,8 @@ +package com.moing.backend.domain.report.domain.repository; + +import com.moing.backend.domain.report.domain.entity.Report; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReportRepository extends JpaRepository { + +} diff --git a/src/main/java/com/moing/backend/domain/report/domain/service/ReportSaveService.java b/src/main/java/com/moing/backend/domain/report/domain/service/ReportSaveService.java new file mode 100644 index 00000000..00c3fce6 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/domain/service/ReportSaveService.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.report.domain.service; + +import com.moing.backend.domain.report.domain.entity.Report; +import com.moing.backend.domain.report.domain.repository.ReportRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class ReportSaveService { + + private final ReportRepository reportRepository; + + public Report save(Report report) { + return reportRepository.save(report); + } +} diff --git a/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java b/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java new file mode 100644 index 00000000..b0332b5e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java @@ -0,0 +1,30 @@ +package com.moing.backend.domain.report.presentation; + +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.report.application.service.ReportCreateUseCase; +import com.moing.backend.domain.report.domain.entity.Report; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.CREATE_ARCHIVE_SUCCESS; +import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.CREATE_REPORT_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/report") +public class ReportController { + + private final ReportCreateUseCase reportCreateUseCase; + + @PostMapping("/{reportType}/{targetId}") + public ResponseEntity> createReport(@AuthenticationPrincipal User user, + @PathVariable("reportType") String reportType, + @PathVariable("targetId") Long targetId) { + return ResponseEntity.ok(SuccessResponse.create(CREATE_REPORT_SUCCESS.getMessage(), this.reportCreateUseCase.createReport(user.getSocialId(), targetId,reportType))); + } +} diff --git a/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java b/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java new file mode 100644 index 00000000..60f5aa47 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.report.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum ReportResponseMessage { + + CREATE_REPORT_SUCCESS("게시글 신고를 완료 했습니다."); + + private final String message; + + +} + From 4dd4083a23c61c0c10a5a3846a72b89bdf62c006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 4 Dec 2023 00:46:23 +0900 Subject: [PATCH 301/619] =?UTF-8?q?feat=20:=20=EC=8B=A0=EA=B3=A0=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20api=20=EB=AC=B8=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Report-API.adoc | 10 +++ src/docs/asciidoc/api.adoc | 2 + .../presentation/ReportControllerTest.java | 71 +++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 src/docs/asciidoc/Report-API.adoc create mode 100644 src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java diff --git a/src/docs/asciidoc/Report-API.adoc b/src/docs/asciidoc/Report-API.adoc new file mode 100644 index 00000000..c8ea808e --- /dev/null +++ b/src/docs/asciidoc/Report-API.adoc @@ -0,0 +1,10 @@ + + +[[Report-API]] += Report API + +[[Report-신고하기]] +=== 신고하기 +operation::report-controller-test/신고하기[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 5d102566..d43dec6c 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -32,3 +32,5 @@ include::BoardComment_API.adoc[] include::TeamScore-API.adoc[] +include::Report-API.adoc[] + diff --git a/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java b/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java new file mode 100644 index 00000000..d7fe241f --- /dev/null +++ b/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java @@ -0,0 +1,71 @@ +package com.moing.backend.domain.report.presentation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.report.application.service.ReportCreateUseCase; +import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; +import com.moing.backend.domain.teamScore.presentation.TeamScoreController; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.CREATE_REPORT_SUCCESS; +import static com.moing.backend.domain.teamScore.presentation.constant.TeamScoreResponseMessage.GET_TEAMSCORE_SUCCESS; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; + +@WebMvcTest(ReportController.class) +public class ReportControllerTest extends CommonControllerTest { + + @MockBean + private ReportCreateUseCase reportCreateUseCase; + + @Test + public void 신고하기() throws Exception { + //given + + Long targetId = 1L; + + given(reportCreateUseCase.createReport(any(),any(),any())).willReturn(targetId); + + + String reportType = "MISSION"; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + post("/api/report/{reportType}/{targetId}", reportType, targetId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(CREATE_REPORT_SUCCESS.getMessage()), + fieldWithPath("data").description("신고한 게시글 번호") + + ) + ) + ) + .andReturn(); + + } + +} \ No newline at end of file From 8999b9ec5740edd9e5adf64fdb930ba934f2d72e Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 4 Dec 2023 06:30:57 +0900 Subject: [PATCH 302/619] =?UTF-8?q?fix:=20=EA=B3=B5=EC=A7=80=20=EB=B3=B8?= =?UTF-8?q?=EB=AC=B8=20=EC=95=8C=EB=A6=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/fcm/constant/NewNoticeUploadMessage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/NewNoticeUploadMessage.java b/src/main/java/com/moing/backend/global/config/fcm/constant/NewNoticeUploadMessage.java index f404ac6e..76f6b270 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/constant/NewNoticeUploadMessage.java +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/NewNoticeUploadMessage.java @@ -17,6 +17,6 @@ public String title(String teamName) { } public String body(String noticeTitle) { - return String.format(title, noticeTitle); + return String.format(body, noticeTitle); } } From e2a2acf8289d175cdcfe9e1b520418442e67bb43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 4 Dec 2023 10:56:57 +0900 Subject: [PATCH 303/619] =?UTF-8?q?fix=20:=20MissionReadRes=EC=97=90=20isL?= =?UTF-8?q?eader=20=ED=95=AD=EB=AA=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/MissionReadRes.java | 4 ++++ .../service/MissionReadUseCase.java | 4 +--- .../repository/MissionCustomRepository.java | 3 +++ .../MissionCustomRepositoryImpl.java | 24 +++++++++++++++++++ .../domain/service/MissionQueryService.java | 4 ++++ .../service/MissionStateScheduleUseCase.java | 1 + 6 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionReadRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionReadRes.java index 14b85380..22aeac19 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionReadRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionReadRes.java @@ -1,10 +1,12 @@ package com.moing.backend.domain.mission.application.dto.res; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @Getter @Builder +@AllArgsConstructor public class MissionReadRes { private String title; @@ -16,4 +18,6 @@ public class MissionReadRes { private String type; private String way; + private Boolean isLeader; + } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java index 7092685a..6ed68694 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java @@ -27,9 +27,7 @@ public class MissionReadUseCase { public MissionReadRes getMission(String userSocialId, Long missionId) { Member member = memberGetService.getMemberBySocialId(userSocialId); - - Mission mission = missionQueryService.findMissionById(missionId); - return MissionMapper.mapToMissionReadRes(mission); + return missionQueryService.findMissionByIds(member.getMemberId(),missionId); } public String getTeamCategory(Long teamId) { diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index 4ba36e8a..e0610615 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; +import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import org.springframework.stereotype.Repository; @@ -25,5 +26,7 @@ public interface MissionCustomRepository { boolean findRepeatMissionsByTeamId(Long teamId); + Optional findByIds(Long memberId, Long missionId); + } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 1a6987e7..d9cd3327 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -2,11 +2,13 @@ import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; +import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionState.domain.entity.QMissionState; import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -137,4 +139,26 @@ public boolean findRepeatMissionsByTeamId(Long teamId) { ).fetchCount() > 2; } + @Override + public Optional findByIds(Long memberId, Long missionId) { + + + BooleanExpression isLeader = mission.team.leaderId.eq(memberId); + + return Optional.ofNullable(queryFactory + .select(Projections.constructor(MissionReadRes.class, + mission.title, + mission.dueTo.stringValue(), + mission.rule, + mission.content, + mission.type.stringValue(), + mission.way.stringValue(), + isLeader)) + .from(mission) + .where(mission.id.eq(missionId)) + .fetchOne() + ); + } + + } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index ef0a716b..136f5c43 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; +import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.exception.*; @@ -28,6 +29,9 @@ public class MissionQueryService { public Mission findMissionById(Long missionId) { return missionRepository.findById(missionId).orElseThrow(NotFoundMissionException::new); } + public MissionReadRes findMissionByIds(Long memberId, Long missionId) { + return missionRepository.findByIds(memberId,missionId).orElseThrow(NotFoundMissionException::new); + } public Long findMissionsCountByTeam(Long teamId) { return missionRepository.findMissionsCountByTeam(teamId); diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 57d5b21c..8cfa4b54 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -109,6 +109,7 @@ public void RepeatMissionStart() { // @Scheduled(cron = "8 0 0 * * *") // public void MissionRemindAlarm() { // +// // missionRemindAlarmUseCase.sendRemindMissionAlarm(); // } } From 5ab163a2c85001349e186906ddc160c6709f4880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:25:04 +0900 Subject: [PATCH 304/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=20&=20API=20=EB=AC=B8=EC=84=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Mission-API.adoc | 6 ++ .../application/dto/res/MissionCreateRes.java | 2 + .../application/mapper/MissionMapper.java | 1 + .../service/MissionUpdateUseCase.java | 21 +++++- .../presentation/MissionController.java | 15 ++++ .../constant/MissionResponseMessage.java | 1 + .../representation/MissionControllerTest.java | 71 ++++++++++++++++++- 7 files changed, 113 insertions(+), 4 deletions(-) diff --git a/src/docs/asciidoc/Mission-API.adoc b/src/docs/asciidoc/Mission-API.adoc index 8a63b7e7..3cdf3e8d 100644 --- a/src/docs/asciidoc/Mission-API.adoc +++ b/src/docs/asciidoc/Mission-API.adoc @@ -34,3 +34,9 @@ operation::mission-controller-test/미션_추천[snippets='http-request,path-par --- +[[Mission-종료]] +=== Mission 종료 +operation::mission-controller-test/미션_종료[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java index 59338e38..39d07123 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionCreateRes.java @@ -20,4 +20,6 @@ public class MissionCreateRes { private String status; private String way; + private Boolean isLeader; + } diff --git a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java index 756ac7e5..01da4b6b 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java +++ b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java @@ -47,6 +47,7 @@ public static MissionCreateRes mapToMissionCreateRes(Mission mission) { .type(mission.getType().name()) .status(mission.getStatus().name()) .number(mission.getNumber()) + .isLeader(Boolean.TRUE) .build(); } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index fefc9c0c..0e41b413 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -4,11 +4,14 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.application.dto.req.MissionReq; import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; +import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; import com.moing.backend.domain.mission.application.mapper.MissionMapper; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.mission.domain.service.MissionSaveService; +import com.moing.backend.domain.mission.exception.NoAccessCreateMission; import com.moing.backend.global.util.SecurityUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -23,7 +26,7 @@ public class MissionUpdateUseCase { private final MissionQueryService missionQueryService; private final MemberGetService memberGetService; - public MissionCreateRes updateMission(String userSocialId,Long missionId, MissionReq missionReq) { + public MissionCreateRes updateMission(String userSocialId, Long missionId, MissionReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); @@ -36,4 +39,20 @@ public MissionCreateRes updateMission(String userSocialId,Long missionId, Missio } + public MissionReadRes updateMissionStatus(String userSocialId, Long missionId) { + + + Member member = memberGetService.getMemberBySocialId(userSocialId); + + Mission findMission = missionQueryService.findMissionById(missionId); + + if (findMission.getTeam().getLeaderId().equals(member.getMemberId())) { + findMission.updateStatus(MissionStatus.END); + } else { + throw new NoAccessCreateMission(); + } + + return MissionMapper.mapToMissionReadRes(findMission); + + } } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 12362a25..531e7ef5 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -64,6 +64,16 @@ public ResponseEntity> updateMission(@Authenti return ResponseEntity.ok(SuccessResponse.create(UPDATE_MISSION_SUCCESS.getMessage(), this.missionUpdateUseCase.updateMission(user.getSocialId(),missionId, missionReq))); } + /** + * 미션 종료 + * [PUT] {teamId}/missions/{missionId}/end + * 작성자 : 정승연 + */ + @PutMapping("/{missionId}/end") + public ResponseEntity> endMission(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId,@PathVariable Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(END_MISSION_SUCCESS.getMessage(), this.missionUpdateUseCase.updateMissionStatus(user.getSocialId(),missionId))); + } + /** * 미션 삭제 * [DELETE] {teamId}/missions/{missionId} @@ -86,4 +96,9 @@ public ResponseEntity> recommendMission(@AuthenticationP } + + + + + } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java b/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java index 757a41d4..1adb30cf 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java @@ -9,6 +9,7 @@ public enum MissionResponseMessage { CREATE_MISSION_SUCCESS("미션 생성을 완료 했습니다"), READ_MISSION_SUCCESS("미션 조회를 완료 했습니다"), UPDATE_MISSION_SUCCESS("미션 수정을 완료 했습니다"), + END_MISSION_SUCCESS("미션 종료를 완료 했습니다"), DELETE_MISSION_SUCCESS("미션 삭제를 완료 했습니다"), RECOMMEND_MISSION_SUCCESS("미션 추천을 위한 팀 카테고리를 조회 했습니다"); diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index 095fc040..e1736dfd 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -80,6 +80,7 @@ public class MissionControllerTest extends CommonControllerTest { .type("ONCE/REPEAT") .status("END/ONGOING/SUCCESS/FAIL") .way("TEXT/PHOTO/LINK") + .isLeader(Boolean.FALSE) .build(); given(missionCreateUseCase.createMission(any(),any(),any())).willReturn(output); @@ -124,7 +125,8 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.number").description("미션 반복 횟수"), fieldWithPath("data.type").description("미션 유형(단일/반복)"), fieldWithPath("data.way").description("미션 진행 방법(사진/글/링크)"), - fieldWithPath("data.status").description("미션 진행 상태") + fieldWithPath("data.status").description("미션 진행 상태"), + fieldWithPath("data.isLeader").description("소모임장 여부") ) ) ) @@ -157,6 +159,7 @@ public class MissionControllerTest extends CommonControllerTest { .type("ONCE") .status("END") .way("TEXT") + .isLeader(Boolean.FALSE) .build(); given(missionUpdateUseCase.updateMission(any(),any(),any())).willReturn(output); @@ -203,7 +206,8 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.number").description("미션 반복 횟수"), fieldWithPath("data.type").description("미션 유형(ONCE/REPEAT)"), fieldWithPath("data.way").description("미션 진행 방법(TEXT/PHOTO/LINK)"), - fieldWithPath("data.status").description("미션 진행 상태(END/ONGOING/SUCCESS/FAIL)") + fieldWithPath("data.status").description("미션 진행 상태(END/ONGOING/SUCCESS/FAIL)"), + fieldWithPath("data.isLeader").description("소모임장 여부") ) ) @@ -224,6 +228,7 @@ public class MissionControllerTest extends CommonControllerTest { .content("content") .type("ONCE") .way("TEXT") + .isLeader(Boolean.FALSE) .build(); given(missionReadUseCase.getMission(any(),any())).willReturn(output); @@ -258,7 +263,9 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.rule").description("미션 규칙"), fieldWithPath("data.content").description("미션 내용"), fieldWithPath("data.way").description("미션 진행 방법(TEXT/PHOTO/LINK)"), - fieldWithPath("data.type").description("미션 유형(ONCE/REPEAT)") + fieldWithPath("data.type").description("미션 유형(ONCE/REPEAT)"), + fieldWithPath("data.isLeader").description("소모임장인지 여부") + ) ) @@ -342,4 +349,62 @@ public class MissionControllerTest extends CommonControllerTest { .andReturn(); } + + @Test + public void 미션_종료() throws Exception { + //given + + + MissionReadRes output = MissionReadRes.builder() + .title("title") + .dueTo("2023-12-31 23:39:22.333") + .rule("rule") + .content("content") + .type("ONCE") + .way("TEXT") + .isLeader(Boolean.FALSE) + .build(); + + given(missionUpdateUseCase.updateMissionStatus(any(),any())).willReturn(output); + + Long teamId = 2L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + put("/api/team/{teamId}/missions/{missionId}/end",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("로그인을 했습니다"), + fieldWithPath("data.title").description("미션 제목"), + fieldWithPath("data.dueTo").description("미션 마감 날짜"), + fieldWithPath("data.rule").description("미션 규칙"), + fieldWithPath("data.content").description("미션 내용"), + fieldWithPath("data.way").description("미션 진행 방법(TEXT/PHOTO/LINK)"), + fieldWithPath("data.type").description("미션 유형(ONCE/REPEAT)"), + fieldWithPath("data.isLeader").description("소모임장 여부") + + ) + ) + ) + .andReturn(); + + } + } From a443ba066ac10deaa21da16ec624df2dac53f94e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:27:28 +0900 Subject: [PATCH 305/619] =?UTF-8?q?chore=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moing/backend/domain/mission/domain/entity/Mission.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index df199e4a..66177310 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -84,8 +84,4 @@ public void setTeam(Team team) { public void updateStatus(MissionStatus missionStatus) { this.status = missionStatus; } - - public void makeEnd() { - this.status = MissionStatus.END; - } } From bf32f938ebc5c79d9604cbed21e5d806a7872d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 4 Dec 2023 12:58:28 +0900 Subject: [PATCH 306/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=82=AD=EC=A0=9C(=EB=B0=98=EB=B3=B5?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EA=B2=BD=EC=9A=B0=20=EA=B3=A0=EB=A0=A4?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EC=88=98=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveDeleteUseCase.java | 4 ++-- .../MissionArchiveCustomRepository.java | 1 + .../MissionArchiveCustomRepositoryImpl.java | 17 +++++++++++++++++ .../service/MissionArchiveQueryService.java | 12 +++++++++++- .../presentation/MissionArchiveController.java | 7 ++++--- .../MissionArchiveControllerTest.java | 10 ++++++---- 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java index d4df05e9..ddf6df7a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java @@ -51,7 +51,7 @@ public class MissionArchiveDeleteUseCase { private final MissionStateQueryService missionStateQueryService; - public Long deleteArchive(String userSocialId, Long missionId) { + public Long deleteArchive(String userSocialId, Long missionId,Long count) { Member member = memberGetService.getMemberBySocialId(userSocialId); Long memberId = member.getMemberId(); @@ -63,7 +63,7 @@ public Long deleteArchive(String userSocialId, Long missionId) { } - MissionArchive deleteArchive = missionArchiveQueryService.findMyArchive(memberId, missionId).get(0); + MissionArchive deleteArchive = missionArchiveQueryService.findOneMyArchive(memberId, missionId,count).get(0); missionArchiveDeleteService.deleteMissionArchive(deleteArchive); MissionState missionState = missionStateQueryService.findMissionState(member, mission); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 1818b2ed..d46cea25 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -16,6 +16,7 @@ public interface MissionArchiveCustomRepository { Optional> findSingleMissionInComplete(Long memberId, Long teamId, MissionStatus status,OrderCondition orderCondition); Optional> findSingleMissionComplete(Long memberId, Long teamId, MissionStatus status,OrderCondition orderCondition); Optional> findMyArchives(Long memberId,Long missionId); + Optional> findOneMyArchives(Long memberId,Long missionId,Long count); Optional> findOthersArchives(Long memberId, Long missionId) ; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 293ec640..4a87d55b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -109,6 +109,23 @@ private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { } @Override + public Optional> findOneMyArchives(Long memberId,Long missionId,Long count) { + + return Optional.ofNullable(queryFactory + .select(missionArchive) + .from(missionArchive) + .where( + missionArchive.mission.id.eq(missionId), + missionArchive.member.memberId.eq(memberId), + missionArchive.count.eq(count) + ) + .orderBy(missionArchive.createdDate.desc()) + .fetch() + + ); + } + + @Override public Optional> findMyArchives(Long memberId,Long missionId) { return Optional.ofNullable(queryFactory diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 04f924c3..9e081919 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -41,9 +41,19 @@ public MissionArchive findArchive(Long memberId, Long missionId) { public List findMyArchive(Long memberId, Long missionId) { Optional> optional = missionArchiveRepository.findMyArchives(memberId, missionId); + + if (optional.isPresent() && optional.get().size() == 0) { + return new ArrayList<>(); + } else { + return optional.get(); + } + } + public List findOneMyArchive(Long memberId, Long missionId, Long count) { + + Optional> optional = missionArchiveRepository.findMyArchives(memberId, missionId); + if (optional.isPresent() && optional.get().size() == 0) { return new ArrayList<>(); -// throw new NotFoundMissionArchiveException(); } else { return optional.get(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 77169a15..bd242267 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -69,11 +69,12 @@ public ResponseEntity> updateArchive(@Authent * 작성자 : 정승연 **/ - @DeleteMapping() + @DeleteMapping("/{count}") public ResponseEntity> deleteArchive(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(UPDATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveDeleteUseCase.deleteArchive(user.getSocialId(), missionId))); + @PathVariable("missionId") Long missionId, + @PathVariable("count") Long count) { + return ResponseEntity.ok(SuccessResponse.create(DELETE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveDeleteUseCase.deleteArchive(user.getSocialId(), missionId,count))); } /** diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index cc139084..bef311b4 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -188,13 +188,14 @@ public class MissionArchiveControllerTest extends CommonControllerTest { //given Long output = 1L; - given(missionArchiveDeleteUseCase.deleteArchive(any(),any())).willReturn(output); + Long count =1L; + given(missionArchiveDeleteUseCase.deleteArchive(any(),any(),any())).willReturn(output); Long teamId = 1L; Long missionId = 1L; //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - delete("/api/team/{teamId}/missions/{missionId}/archive",teamId,missionId) + delete("/api/team/{teamId}/missions/{missionId}/archive/{count}",teamId,missionId,count) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) ); @@ -209,11 +210,12 @@ public class MissionArchiveControllerTest extends CommonControllerTest { ), pathParameters( parameterWithName("teamId").description("팀 아이디"), - parameterWithName("missionId").description("미션 아이디") + parameterWithName("missionId").description("미션 아이디"), + parameterWithName("count").description("반복미션 횟수(단일 미션일 경우 1, 반복미션일 경우 n") ), responseFields( fieldWithPath("isSuccess").description("true"), - fieldWithPath("message").description(UPDATE_ARCHIVE_SUCCESS), + fieldWithPath("message").description(DELETE_ARCHIVE_SUCCESS), fieldWithPath("data").description("삭제한 미션 인증 아이디(무시)") ) ) From 8dc654d12420f67740b6221ad19d560af0626c07 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 4 Dec 2023 19:14:32 +0900 Subject: [PATCH 307/619] =?UTF-8?q?fix:=20=ED=8C=80=20=ED=83=88=ED=87=B4?= =?UTF-8?q?=ED=95=9C=20=ED=9A=8C=EC=9B=90=EC=97=90=EA=B2=8C=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=95=88=EA=B0=80=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/TeamMemberCustomRepository.java | 1 - .../repository/TeamMemberCustomRepositoryImpl.java | 14 ++------------ .../domain/service/TeamMemberGetService.java | 4 ---- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index ff212d46..89b22d3b 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -10,7 +10,6 @@ public interface TeamMemberCustomRepository { List findMemberIdsByTeamId(Long teamId); Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId); - Optional> findFcmTokensByTeamId(Long teamId); List findTeamMemberInfoByTeamId(Long teamId); List findTeamMemberByMemberId(Long memberId); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index b692fcee..7942c58f 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -37,18 +37,8 @@ public Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long .from(teamMember) .where(teamMember.team.teamId.eq(teamId) .and(teamMember.member.isNewUploadPush.eq(true)) - .and(teamMember.member.memberId.ne(memberId))) - .fetch(); - - return result.isEmpty() ? Optional.empty() : Optional.of(result); - } - - @Override - public Optional> findFcmTokensByTeamId(Long teamId) { - List result = queryFactory.select(teamMember.member.fcmToken) - .from(teamMember) - .where(teamMember.team.teamId.eq(teamId) - .and(teamMember.member.isNewUploadPush.eq(true))) + .and(teamMember.member.memberId.ne(memberId)) + .and(teamMember.isDeleted.eq(false))) .fetch(); return result.isEmpty() ? Optional.empty() : Optional.of(result); diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index 138d8d0f..2b9dfee2 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -29,10 +29,6 @@ public Optional> getFcmTokensExceptMe(Long teamId, Long memberId) { return teamMemberRepository.findFcmTokensByTeamIdAndMemberId(teamId, memberId); } - public Optional> getFcmTokens(Long teamId) { - return teamMemberRepository.findFcmTokensByTeamId(teamId); - } - public List getTeamMemberInfo(Long teamId){ return teamMemberRepository.findTeamMemberInfoByTeamId(teamId); } From 1c16c6af617d37ac0ec2a47189ee288e04be0cb8 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 4 Dec 2023 19:18:20 +0900 Subject: [PATCH 308/619] =?UTF-8?q?refactor:=20fcmService=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendMissionCreateAlarmUseCase.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java index 3edc96e8..b0a82df3 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java @@ -5,13 +5,16 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.config.fcm.dto.event.FcmEvent; import com.moing.backend.global.config.fcm.dto.request.MultiRequest; import com.moing.backend.global.config.fcm.service.FcmService; import com.moing.backend.global.response.BaseServiceResponse; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.util.EventListener; import java.util.List; import java.util.Optional; @@ -24,20 +27,16 @@ public class SendMissionCreateAlarmUseCase { private final TeamMemberGetService teamMemberGetService; - private final FcmService fcmService; + private final ApplicationEventPublisher eventPublisher; public void sendNewMissionUploadAlarm(Member member, Mission mission) { Team team = mission.getTeam(); - Optional> fcmTokensExceptMe = teamMemberGetService.getFcmTokensExceptMe(team.getTeamId(), member.getMemberId()); - String title = team.getName() + " " + NEW_SINGLE_MISSION_COMING.getTitle(); String message = mission.getTitle(); Optional> fcmTokens = teamMemberGetService.getFcmTokensExceptMe(team.getTeamId(), member.getMemberId()); if (fcmTokens.isPresent() && !fcmTokens.get().isEmpty()) { - MultiRequest toMultiRequest = new MultiRequest(fcmTokens.get(), title, message); - fcmService.sendMultipleDevices(toMultiRequest); - + eventPublisher.publishEvent(new FcmEvent(title, message, fcmTokens.get())); } } } From 7ac6681f275101461b613682cf09018f39b96242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 4 Dec 2023 21:44:15 +0900 Subject: [PATCH 309/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0=20=EC=A0=95=EB=A0=AC=20?= =?UTF-8?q?=EA=B8=B0=EC=A4=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 1a6987e7..f8834e6f 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -64,6 +64,7 @@ public Optional> findRepeatMissionByMemberId(Long m mission.type.eq(MissionType.REPEAT) ) .groupBy(mission.id) + .orderBy(missionArchive.count().desc()) .fetch()); } @@ -122,7 +123,7 @@ public Optional> findSingleMissionByMemberId(Long m mission.type.eq(MissionType.ONCE), missionState.id.isNull() ) - .orderBy(mission.dueTo.desc()) + .orderBy(mission.dueTo.asc()) .fetch()); } From d0e9c8e22c7560d4d92c7ee15e38228e9b6b9f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 4 Dec 2023 21:49:38 +0900 Subject: [PATCH 310/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=9D=B8=EC=A6=9D=EB=AC=BC=20=EA=B8=80?= =?UTF-8?q?=EC=9E=90=EC=88=98=201000=EC=9E=90=20=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/missionArchive/domain/entity/MissionArchive.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index eece71b9..4841d57a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -39,7 +39,7 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 @Enumerated(value = EnumType.STRING) private MissionArchiveStatus status; - @Column(nullable = false) + @Column(nullable = false, length = 1000) private String archive; //링크, 글, 사진 뭐든 가능 private Long count; // 횟수 From d05098658639887e3f53ed61fdc8c868449a831e Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 4 Dec 2023 22:56:33 +0900 Subject: [PATCH 311/619] =?UTF-8?q?hotfix:=20nickName=20=EC=A0=84=EC=86=A1?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/application/dto/response/GetTeamCountResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java index e6ad022b..b4bd207a 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamCountResponse.java @@ -20,7 +20,7 @@ public void updateCount(Long count){ } public void updateMemberName(String nickName){ - this.memberName=memberName; + this.memberName=nickName; } @QueryProjection From 8be42be46538c54edd5cb98d9808964bb593175a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:56:41 +0900 Subject: [PATCH 312/619] =?UTF-8?q?fix=20:=20=EC=9D=B8=EC=A6=9D=EB=AC=BC?= =?UTF-8?q?=20=EA=B8=80=EC=9E=90=EC=88=98=20=EC=A0=9C=ED=95=9C=201000?= =?UTF-8?q?=EC=9E=90=20->=204000byte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/missionArchive/domain/entity/MissionArchive.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index 4841d57a..670adbec 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -39,7 +39,7 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 @Enumerated(value = EnumType.STRING) private MissionArchiveStatus status; - @Column(nullable = false, length = 1000) + @Column(nullable = false, length = 4000) private String archive; //링크, 글, 사진 뭐든 가능 private Long count; // 횟수 From 79c81952888b8221bdcb87150761b447fbdfc587 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 01:01:13 +0900 Subject: [PATCH 313/619] =?UTF-8?q?refactor:=20=ED=8C=8C=EC=9D=BC=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{AppleSignInUserCase.java => AppleSignInUseCase.java} | 6 +++--- .../{AppleTokenUserCase.java => AppleTokenUseCase.java} | 2 +- ...AppleWithdrawUserCase.java => AppleWithdrawUseCase.java} | 2 +- .../auth/application/service/apple/utils/AppleClient.java | 2 +- .../{GoogleSignInUserCase.java => GoogleSignInUseCase.java} | 6 +++--- .../{GoogleTokenUserCase.java => GoogleTokenUseCase.java} | 2 +- ...ogleWithdrawUserCase.java => GoogleWithdrawUseCase.java} | 2 +- .../auth/application/service/google/utils/GoogleClient.java | 2 +- .../{KakaoSignInUserCase.java => KakaoSignInUseCase.java} | 6 +++--- .../{KakaoTokenUserCase.java => KakaoTokenUseCase.java} | 2 +- ...KakaoWithdrawUserCase.java => KakaoWithdrawUseCase.java} | 2 +- .../auth/application/service/kakao/utils/KakaoClient.java | 2 +- .../moing/backend/global/{util => utils}/AesConverter.java | 2 +- .../com/moing/backend/global/{util => utils}/AesUtil.java | 2 +- .../backend/global/{util => utils}/BaseBoardService.java | 2 +- .../moing/backend/global/{util => utils}/BaseService.java | 2 +- .../backend/global/{util => utils}/FeignClientConfig.java | 2 +- .../moing/backend/global/{util => utils}/SecurityUtils.java | 2 +- .../moing/backend/global/{util => utils}/StartupRunner.java | 3 +-- 19 files changed, 25 insertions(+), 26 deletions(-) rename src/main/java/com/moing/backend/domain/auth/application/service/apple/{AppleSignInUserCase.java => AppleSignInUseCase.java} (78%) rename src/main/java/com/moing/backend/domain/auth/application/service/apple/{AppleTokenUserCase.java => AppleTokenUseCase.java} (99%) rename src/main/java/com/moing/backend/domain/auth/application/service/apple/{AppleWithdrawUserCase.java => AppleWithdrawUseCase.java} (97%) rename src/main/java/com/moing/backend/domain/auth/application/service/google/{GoogleSignInUserCase.java => GoogleSignInUseCase.java} (89%) rename src/main/java/com/moing/backend/domain/auth/application/service/google/{GoogleTokenUserCase.java => GoogleTokenUseCase.java} (95%) rename src/main/java/com/moing/backend/domain/auth/application/service/google/{GoogleWithdrawUserCase.java => GoogleWithdrawUseCase.java} (89%) rename src/main/java/com/moing/backend/domain/auth/application/service/kakao/{KakaoSignInUserCase.java => KakaoSignInUseCase.java} (89%) rename src/main/java/com/moing/backend/domain/auth/application/service/kakao/{KakaoTokenUserCase.java => KakaoTokenUseCase.java} (97%) rename src/main/java/com/moing/backend/domain/auth/application/service/kakao/{KakaoWithdrawUserCase.java => KakaoWithdrawUseCase.java} (89%) rename src/main/java/com/moing/backend/global/{util => utils}/AesConverter.java (96%) rename src/main/java/com/moing/backend/global/{util => utils}/AesUtil.java (98%) rename src/main/java/com/moing/backend/global/{util => utils}/BaseBoardService.java (97%) rename src/main/java/com/moing/backend/global/{util => utils}/BaseService.java (96%) rename src/main/java/com/moing/backend/global/{util => utils}/FeignClientConfig.java (73%) rename src/main/java/com/moing/backend/global/{util => utils}/SecurityUtils.java (95%) rename src/main/java/com/moing/backend/global/{util => utils}/StartupRunner.java (95%) diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUseCase.java similarity index 78% rename from src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUseCase.java index 05b1f179..6f498fb6 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUseCase.java @@ -10,14 +10,14 @@ @Service("appleSignIn") @AllArgsConstructor -public class AppleSignInUserCase implements SignInProvider { +public class AppleSignInUseCase implements SignInProvider { - private final AppleTokenUserCase appleTokenUserCase; + private final AppleTokenUseCase appleTokenUseCase; private final MemberMapper memberMapper; public Member getUserData(String identityToken) { - Jws oidcTokenJws = appleTokenUserCase.sigVerificationAndGetJws(identityToken); + Jws oidcTokenJws = appleTokenUseCase.sigVerificationAndGetJws(identityToken); String socialId = oidcTokenJws.getBody().getSubject(); String email = (String) oidcTokenJws.getBody().get("email"); diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUseCase.java similarity index 99% rename from src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUseCase.java index 0955c6c6..4a5db82e 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleTokenUseCase.java @@ -19,7 +19,7 @@ @Component @RequiredArgsConstructor -public class AppleTokenUserCase { +public class AppleTokenUseCase { @Value("${oauth2.apple.clientId}") private String appId; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUseCase.java similarity index 97% rename from src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUseCase.java index 8d7a2a0e..12ff5133 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleWithdrawUseCase.java @@ -19,7 +19,7 @@ @Service("appleWithdraw") @RequiredArgsConstructor -public class AppleWithdrawUserCase implements WithdrawProvider { +public class AppleWithdrawUseCase implements WithdrawProvider { @Value("${oauth2.apple.keyId}") private String keyId; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleClient.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleClient.java index de75629d..68686358 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleClient.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/utils/AppleClient.java @@ -1,6 +1,6 @@ package com.moing.backend.domain.auth.application.service.apple.utils; -import com.moing.backend.global.util.FeignClientConfig; +import com.moing.backend.global.utils.FeignClientConfig; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUseCase.java similarity index 89% rename from src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUseCase.java index 8db12737..5873460a 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUseCase.java @@ -14,11 +14,11 @@ @Service("googleSignIn") @RequiredArgsConstructor -public class GoogleSignInUserCase implements SignInProvider { +public class GoogleSignInUseCase implements SignInProvider { private final MemberMapper memberMapper; private final WebClient webClient; - private final GoogleTokenUserCase googleTokenUserCase; + private final GoogleTokenUseCase googleTokenUseCase; public Member getUserData(String accessToken) { GoogleUserResponse googleUserResponse = webClient.get() @@ -30,7 +30,7 @@ public Member getUserData(String accessToken) { .block(); if (googleUserResponse != null) { - googleTokenUserCase.verifyAccessToken(googleUserResponse.getAud()); + googleTokenUseCase.verifyAccessToken(googleUserResponse.getAud()); googleUserResponse.adaptResponse(); return memberMapper.createGoogleMember(googleUserResponse); } diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUseCase.java similarity index 95% rename from src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUseCase.java index 653e7c71..39bfb01b 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleTokenUseCase.java @@ -10,7 +10,7 @@ @Component @RequiredArgsConstructor -public class GoogleTokenUserCase { +public class GoogleTokenUseCase { @Value("${oauth2.google.appId}") private String appId; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleWithdrawUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleWithdrawUseCase.java similarity index 89% rename from src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleWithdrawUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleWithdrawUseCase.java index 7fddb5b9..c28d4bf9 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleWithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleWithdrawUseCase.java @@ -9,7 +9,7 @@ @Service("googleWithdraw") @RequiredArgsConstructor -public class GoogleWithdrawUserCase implements WithdrawProvider { +public class GoogleWithdrawUseCase implements WithdrawProvider { private final GoogleClient googleClient; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/utils/GoogleClient.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/utils/GoogleClient.java index dd83003c..af6653ee 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/google/utils/GoogleClient.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/utils/GoogleClient.java @@ -1,6 +1,6 @@ package com.moing.backend.domain.auth.application.service.google.utils; -import com.moing.backend.global.util.FeignClientConfig; +import com.moing.backend.global.utils.FeignClientConfig; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUseCase.java similarity index 89% rename from src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUseCase.java index ef939b37..9fbf06e5 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUseCase.java @@ -14,15 +14,15 @@ @Service("kakaoSignIn") @RequiredArgsConstructor -public class KakaoSignInUserCase implements SignInProvider { +public class KakaoSignInUseCase implements SignInProvider { private final WebClient webClient; private final MemberMapper memberMapper; - private final KakaoTokenUserCase kakaoTokenUserCase; + private final KakaoTokenUseCase kakaoTokenUseCase; public Member getUserData(String accessToken) { - kakaoTokenUserCase.verifyAccessToken(accessToken); + kakaoTokenUseCase.verifyAccessToken(accessToken); KakaoUserResponse kakaoUserResponse = webClient.get() diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUseCase.java similarity index 97% rename from src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUseCase.java index 8f6d3766..802c0828 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoTokenUseCase.java @@ -13,7 +13,7 @@ @Component @RequiredArgsConstructor -public class KakaoTokenUserCase { +public class KakaoTokenUseCase { @Value("${oauth2.kakao.appId}") private String appId; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoWithdrawUserCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoWithdrawUseCase.java similarity index 89% rename from src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoWithdrawUserCase.java rename to src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoWithdrawUseCase.java index f4525ba7..f8e70689 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoWithdrawUserCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoWithdrawUseCase.java @@ -9,7 +9,7 @@ @Service("kakaoWithdraw") @RequiredArgsConstructor -public class KakaoWithdrawUserCase implements WithdrawProvider { +public class KakaoWithdrawUseCase implements WithdrawProvider { private final KakaoClient kakaoClient; diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoClient.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoClient.java index a02b0d21..3de222fe 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoClient.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/utils/KakaoClient.java @@ -1,6 +1,6 @@ package com.moing.backend.domain.auth.application.service.kakao.utils; -import com.moing.backend.global.util.FeignClientConfig; +import com.moing.backend.global.utils.FeignClientConfig; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestHeader; diff --git a/src/main/java/com/moing/backend/global/util/AesConverter.java b/src/main/java/com/moing/backend/global/utils/AesConverter.java similarity index 96% rename from src/main/java/com/moing/backend/global/util/AesConverter.java rename to src/main/java/com/moing/backend/global/utils/AesConverter.java index fc7da8b7..f3208b2a 100644 --- a/src/main/java/com/moing/backend/global/util/AesConverter.java +++ b/src/main/java/com/moing/backend/global/utils/AesConverter.java @@ -1,4 +1,4 @@ -package com.moing.backend.global.util; +package com.moing.backend.global.utils; import javax.persistence.AttributeConverter; import javax.persistence.Converter; diff --git a/src/main/java/com/moing/backend/global/util/AesUtil.java b/src/main/java/com/moing/backend/global/utils/AesUtil.java similarity index 98% rename from src/main/java/com/moing/backend/global/util/AesUtil.java rename to src/main/java/com/moing/backend/global/utils/AesUtil.java index 7ada8b89..b66586d6 100644 --- a/src/main/java/com/moing/backend/global/util/AesUtil.java +++ b/src/main/java/com/moing/backend/global/utils/AesUtil.java @@ -1,4 +1,4 @@ -package com.moing.backend.global.util; +package com.moing.backend.global.utils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/moing/backend/global/util/BaseBoardService.java b/src/main/java/com/moing/backend/global/utils/BaseBoardService.java similarity index 97% rename from src/main/java/com/moing/backend/global/util/BaseBoardService.java rename to src/main/java/com/moing/backend/global/utils/BaseBoardService.java index c502c37c..f99ffac8 100644 --- a/src/main/java/com/moing/backend/global/util/BaseBoardService.java +++ b/src/main/java/com/moing/backend/global/utils/BaseBoardService.java @@ -1,4 +1,4 @@ -package com.moing.backend.global.util; +package com.moing.backend.global.utils; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardGetService; diff --git a/src/main/java/com/moing/backend/global/util/BaseService.java b/src/main/java/com/moing/backend/global/utils/BaseService.java similarity index 96% rename from src/main/java/com/moing/backend/global/util/BaseService.java rename to src/main/java/com/moing/backend/global/utils/BaseService.java index 0926e321..f6fd8513 100644 --- a/src/main/java/com/moing/backend/global/util/BaseService.java +++ b/src/main/java/com/moing/backend/global/utils/BaseService.java @@ -1,4 +1,4 @@ -package com.moing.backend.global.util; +package com.moing.backend.global.utils; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; diff --git a/src/main/java/com/moing/backend/global/util/FeignClientConfig.java b/src/main/java/com/moing/backend/global/utils/FeignClientConfig.java similarity index 73% rename from src/main/java/com/moing/backend/global/util/FeignClientConfig.java rename to src/main/java/com/moing/backend/global/utils/FeignClientConfig.java index a9b6bd75..2c7f1f20 100644 --- a/src/main/java/com/moing/backend/global/util/FeignClientConfig.java +++ b/src/main/java/com/moing/backend/global/utils/FeignClientConfig.java @@ -1,4 +1,4 @@ -package com.moing.backend.global.util; +package com.moing.backend.global.utils; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/moing/backend/global/util/SecurityUtils.java b/src/main/java/com/moing/backend/global/utils/SecurityUtils.java similarity index 95% rename from src/main/java/com/moing/backend/global/util/SecurityUtils.java rename to src/main/java/com/moing/backend/global/utils/SecurityUtils.java index 8c9620ad..0c901985 100644 --- a/src/main/java/com/moing/backend/global/util/SecurityUtils.java +++ b/src/main/java/com/moing/backend/global/utils/SecurityUtils.java @@ -1,4 +1,4 @@ -package com.moing.backend.global.util; +package com.moing.backend.global.utils; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.global.config.security.oauth.CustomUserDetails; diff --git a/src/main/java/com/moing/backend/global/util/StartupRunner.java b/src/main/java/com/moing/backend/global/utils/StartupRunner.java similarity index 95% rename from src/main/java/com/moing/backend/global/util/StartupRunner.java rename to src/main/java/com/moing/backend/global/utils/StartupRunner.java index 5fa2b867..52205ec2 100644 --- a/src/main/java/com/moing/backend/global/util/StartupRunner.java +++ b/src/main/java/com/moing/backend/global/utils/StartupRunner.java @@ -1,11 +1,10 @@ -package com.moing.backend.global.util; +package com.moing.backend.global.utils; import com.moing.backend.domain.member.domain.constant.Gender; import com.moing.backend.domain.member.domain.constant.RegistrationStatus; import com.moing.backend.domain.member.domain.constant.Role; import com.moing.backend.domain.member.domain.constant.SocialProvider; import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.member.domain.service.MemberSaveService; import lombok.RequiredArgsConstructor; import org.springframework.boot.CommandLineRunner; From a5430697331d968107d443334a1384a018295eda Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 01:07:03 +0900 Subject: [PATCH 314/619] =?UTF-8?q?refactor:=20=ED=8C=8C=EC=9D=BC=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/board/application/service/UpdateBoardUseCase.java | 2 +- .../com/moing/backend/domain/board/domain/entity/Board.java | 2 +- .../application/service/CreateBoardCommentUseCase.java | 2 +- .../application/service/DeleteBoardCommentUseCase.java | 2 +- .../application/service/GetBoardCommentUseCase.java | 2 +- .../backend/domain/boardComment/domain/entity/BoardComment.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUseCase.java index 32e2bc02..d95582e3 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/UpdateBoardUseCase.java @@ -4,7 +4,7 @@ import com.moing.backend.domain.board.application.dto.response.UpdateBoardResponse; import com.moing.backend.domain.board.exception.NotAuthByBoardException; import com.moing.backend.global.response.BaseBoardServiceResponse; -import com.moing.backend.global.util.BaseBoardService; +import com.moing.backend.global.utils.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java index 829bfe53..bc8690ed 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java +++ b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java @@ -6,7 +6,7 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.entity.BaseTimeEntity; -import com.moing.backend.global.util.AesConverter; +import com.moing.backend.global.utils.AesConverter; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java index c4e707f4..60ef6b4f 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java @@ -7,7 +7,7 @@ import com.moing.backend.domain.boardComment.domain.service.BoardCommentSaveService; import com.moing.backend.domain.team.application.service.CheckLeaderUseCase; import com.moing.backend.global.response.BaseBoardServiceResponse; -import com.moing.backend.global.util.BaseBoardService; +import com.moing.backend.global.utils.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java index 7f06ffb2..0937123d 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java @@ -5,7 +5,7 @@ import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; import com.moing.backend.domain.boardComment.exception.NotAuthByBoardCommentException; import com.moing.backend.global.response.BaseBoardServiceResponse; -import com.moing.backend.global.util.BaseBoardService; +import com.moing.backend.global.utils.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java index fda15898..a3163427 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java @@ -3,7 +3,7 @@ import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; import com.moing.backend.global.response.BaseBoardServiceResponse; -import com.moing.backend.global.util.BaseBoardService; +import com.moing.backend.global.utils.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java index 2de67841..4fe54475 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java @@ -3,7 +3,7 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.entity.BaseTimeEntity; -import com.moing.backend.global.util.AesConverter; +import com.moing.backend.global.utils.AesConverter; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; From d60ecf6c98a3bc3f0eb209f55922f6691d2a4604 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 01:07:19 +0900 Subject: [PATCH 315/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=ED=83=88=ED=87=B4=20=EC=8B=9C=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/board/application/mapper/BoardMapper.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java index 4dc06d79..dbc36017 100644 --- a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java +++ b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java @@ -34,12 +34,13 @@ public Board toBoard(Member member, TeamMember teamMember, Team team, CreateBoar return board; } - public GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter) { + public GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter, boolean writerIsDeleted) { + String nickName = writerIsDeleted ? "(알 수 없음)" : board.getWriterNickName(); return GetBoardDetailResponse.builder() .boardId(board.getBoardId()) .title(board.getTitle()) .content(board.getContent()) - .writerNickName(board.getWriterNickName()) + .writerNickName(nickName) .writerIsLeader(board.isLeader()) .writerProfileImage(board.getWriterProfileImage()) .createdDate(getFormattedDate(board.getCreatedDate())) From 8bb4f01869644af5fcc217ca1bc2413f822f398e Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 01:09:44 +0900 Subject: [PATCH 316/619] =?UTF-8?q?feat:=20AlarmHistory=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../history/domain/entity/AlarmHistory.java | 45 +++++++++++++++++++ .../history/domain/entity/AlarmType.java | 12 +++++ .../history/domain/entity/PagePath.java | 21 +++++++++ 3 files changed, 78 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/history/domain/entity/AlarmHistory.java create mode 100644 src/main/java/com/moing/backend/domain/history/domain/entity/AlarmType.java create mode 100644 src/main/java/com/moing/backend/domain/history/domain/entity/PagePath.java diff --git a/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmHistory.java b/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmHistory.java new file mode 100644 index 00000000..06ed3f76 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmHistory.java @@ -0,0 +1,45 @@ +package com.moing.backend.domain.history.domain.entity; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Builder +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class AlarmHistory extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "alarm_history_id") + private Long id; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private AlarmType type; + + @Column(nullable = false) + private String path; + + private String idInfo; + + private Long receiverId; + + @Column(nullable = false) + private String title; + + @Column(nullable = false) + private String body; + + @Column(nullable = false) + private String name; + + private boolean isRead; +} diff --git a/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmType.java b/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmType.java new file mode 100644 index 00000000..fbf7fd58 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmType.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.history.domain.entity; + +import lombok.Getter; + +@Getter +public enum AlarmType { + NEW_UPLOAD, + FIRE, + REMIND, + APPROVE_TEAM, + REJECT_TEAM +} diff --git a/src/main/java/com/moing/backend/domain/history/domain/entity/PagePath.java b/src/main/java/com/moing/backend/domain/history/domain/entity/PagePath.java new file mode 100644 index 00000000..e597bc2a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/domain/entity/PagePath.java @@ -0,0 +1,21 @@ +package com.moing.backend.domain.history.domain.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum PagePath { + + NOTICE_PATH("/post/detail"), + + MISSION_PATH("/missions/prove"), + + MISSION_ALL_PTAH("/missions"), + + HOME_PATH("/home"); + + + private final String value; + +} From 58f7ad94ae08c363d25c15c1b8dc093215c17bf8 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 01:11:42 +0900 Subject: [PATCH 317/619] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EB=B3=B4=EB=82=BC=20=EB=95=8C=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 ++ .../service/CreateBoardUseCase.java | 8 ++- .../service/DeleteBoardUseCase.java | 2 +- .../application/service/GetBoardUseCase.java | 4 +- .../service/SendBoardAlarmUseCase.java | 53 +++++++++++++++++-- .../dto/response/MemberIdAndToken.java | 17 ++++++ .../mapper/AlarmHistoryMapper.java | 27 ++++++++++ .../service/AlarmHistorySaveService.java | 22 ++++++++ .../TeamMemberCustomRepository.java | 2 + .../TeamMemberCustomRepositoryImpl.java | 19 ++++++- .../domain/service/TeamMemberGetService.java | 5 ++ 11 files changed, 153 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/history/application/dto/response/MemberIdAndToken.java create mode 100644 src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java create mode 100644 src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistorySaveService.java diff --git a/build.gradle b/build.gradle index 74cdd0b3..e9a7af8c 100644 --- a/build.gradle +++ b/build.gradle @@ -94,6 +94,9 @@ dependencies { //slack implementation 'com.slack.api:slack-api-client:1.30.0' + //json + implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.3' + } tasks.named('test') { diff --git a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java index 59d989f9..953eab1e 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java @@ -6,9 +6,14 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardSaveService; import com.moing.backend.domain.boardRead.application.service.CreateBoardReadUseCase; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.domain.entity.AlarmHistory; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.entity.PagePath; +import com.moing.backend.domain.history.domain.service.AlarmHistorySaveService; import com.moing.backend.domain.team.application.service.CheckLeaderUseCase; import com.moing.backend.global.response.BaseServiceResponse; -import com.moing.backend.global.util.BaseService; +import com.moing.backend.global.utils.BaseService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -41,6 +46,7 @@ public CreateBoardResponse createBoard(String socialId, Long teamId, CreateBoard //3. 알림 보내기 - 공지인 경우 sendBoardAlarmUseCase.sendNewUploadAlarm(data, board); + return new CreateBoardResponse(board.getBoardId()); } } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUseCase.java index 46549472..f601362f 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/DeleteBoardUseCase.java @@ -3,7 +3,7 @@ import com.moing.backend.domain.board.domain.service.BoardDeleteService; import com.moing.backend.domain.board.exception.NotAuthByBoardException; import com.moing.backend.global.response.BaseBoardServiceResponse; -import com.moing.backend.global.util.BaseBoardService; +import com.moing.backend.global.utils.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java index 6fe4e3cb..83d0104c 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java @@ -8,7 +8,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.global.response.BaseBoardServiceResponse; -import com.moing.backend.global.util.BaseBoardService; +import com.moing.backend.global.utils.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -35,7 +35,7 @@ public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); // 2. 읽음 처리 createBoardReadUseCase.createBoardRead(data.getTeam(), data.getMember(), data.getBoard()); - return boardMapper.toBoardDetail(data.getBoard(), data.getTeamMember() == data.getBoard().getTeamMember()); + return boardMapper.toBoardDetail(data.getBoard(), data.getTeamMember() == data.getBoard().getTeamMember(), data.getBoard().getTeamMember().isDeleted()); } /** diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index 9a66df10..7bdd77ba 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -1,18 +1,27 @@ package com.moing.backend.domain.board.application.service; import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.domain.entity.AlarmHistory; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.entity.PagePath; +import com.moing.backend.domain.history.domain.service.AlarmHistorySaveService; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.global.config.fcm.dto.event.FcmEvent; import com.moing.backend.global.response.BaseServiceResponse; import lombok.RequiredArgsConstructor; +import net.minidev.json.JSONObject; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import static com.moing.backend.global.config.fcm.constant.NewNoticeUploadMessage.NEW_NOTICE_UPLOAD_MESSAGE; @@ -23,6 +32,8 @@ public class SendBoardAlarmUseCase { private final TeamMemberGetService teamMemberGetService; private final ApplicationEventPublisher eventPublisher; + private final AlarmHistorySaveService alarmHistorySaveService; + private final AlarmHistoryMapper alarmHistoryMapper; public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board board) { Member member = baseServiceResponse.getMember(); @@ -31,11 +42,47 @@ public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board bo if (board.isNotice() && member.isNewUploadPush()) { String title = NEW_NOTICE_UPLOAD_MESSAGE.title(team.getName()); String body = NEW_NOTICE_UPLOAD_MESSAGE.body(board.getTitle()); - Optional> fcmTokens = teamMemberGetService.getFcmTokensExceptMe(team.getTeamId(), member.getMemberId()); - if (fcmTokens.isPresent() && !fcmTokens.get().isEmpty()) { - eventPublisher.publishEvent(new FcmEvent(title, body, fcmTokens.get())); + Optional> memberIdAndTokens = teamMemberGetService.getMemberInfoExceptMe(team.getTeamId(), member.getMemberId()); + if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { + //알림 보내기 + List fcmTokens = getFcmTokens(memberIdAndTokens); + eventPublisher.publishEvent(new FcmEvent(title, body, fcmTokens)); + //알림 저장하기 + List memberIds = getMemberIds(memberIdAndTokens); + String idInfo = createIdInfo(team.getTeamId(), board.getBoardId()); + saveAlarmHistory(idInfo, memberIds, title, body, team.getName()); } } } + + private List getFcmTokens(Optional> memberIdAndTokens) { + return memberIdAndTokens.map(list -> list.stream() + .map(MemberIdAndToken::getFcmToken) + .collect(Collectors.toList())) + .orElse(Collections.emptyList()); + } + + private List getMemberIds(Optional> memberIdAndTokens) { + return memberIdAndTokens.map(list -> list.stream() + .map(MemberIdAndToken::getMemberId) + .collect(Collectors.toList())) + .orElse(Collections.emptyList()); + } + + private void saveAlarmHistory(String idInfo, List memberIds, String title, String body, String teamName) { + List alarmHistories = memberIds.stream() + .map(memberId -> alarmHistoryMapper.toAlarmHistory(AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue(), idInfo, memberId, title, body, teamName)) + .collect(Collectors.toList()); + + alarmHistorySaveService.saveAlarmHistory(alarmHistories); // 여기서 saveAll은 일괄 삽입을 처리하는 메서드입니다. + } + + private String createIdInfo(Long teamId, Long boardId) { + JSONObject jo = new JSONObject(); + jo.put("teamId", teamId); + jo.put("boardId", boardId); + return jo.toJSONString(); + } + } diff --git a/src/main/java/com/moing/backend/domain/history/application/dto/response/MemberIdAndToken.java b/src/main/java/com/moing/backend/domain/history/application/dto/response/MemberIdAndToken.java new file mode 100644 index 00000000..06361d3b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/application/dto/response/MemberIdAndToken.java @@ -0,0 +1,17 @@ +package com.moing.backend.domain.history.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.util.List; + +@Getter +@Builder +@AllArgsConstructor +public class MemberIdAndToken { + + private String fcmToken; + private Long memberId; + +} diff --git a/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java b/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java new file mode 100644 index 00000000..13ee5fa9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.history.application.mapper; + +import com.moing.backend.domain.history.domain.entity.AlarmHistory; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.member.domain.entity.Member; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import javax.persistence.*; + +@Component +@RequiredArgsConstructor +public class AlarmHistoryMapper { + + public AlarmHistory toAlarmHistory(AlarmType type, String path, String idInfo, Long receiverId, String title, String body, String name){ + return AlarmHistory.builder() + .type(type) + .path(path) + .idInfo(idInfo) + .receiverId(receiverId) + .title(title) + .body(body) + .name(name) + .isRead(false) + .build(); + } +} diff --git a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistorySaveService.java b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistorySaveService.java new file mode 100644 index 00000000..4efef5d0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistorySaveService.java @@ -0,0 +1,22 @@ +package com.moing.backend.domain.history.domain.service; + +import com.moing.backend.domain.history.domain.entity.AlarmHistory; +import com.moing.backend.domain.history.domain.repository.AlarmHistoryRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; +import java.util.List; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class AlarmHistorySaveService { + + private final AlarmHistoryRepository alarmHistoryRepository; + + public void saveAlarmHistory(List alarmHistories){ + alarmHistoryRepository.saveAll(alarmHistories); + } + +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index 89b22d3b..a9f0bdfa 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.teamMember.domain.repository; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; @@ -9,6 +10,7 @@ public interface TeamMemberCustomRepository { List findMemberIdsByTeamId(Long teamId); + Optional> findIdAndTokensByTeamIdAndMemberId(Long teamId, Long memberId); Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId); List findTeamMemberInfoByTeamId(Long teamId); List findTeamMemberByMemberId(Long memberId); diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index 7942c58f..435b0ac2 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -1,10 +1,10 @@ package com.moing.backend.domain.teamMember.domain.repository; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.team.application.dto.response.QTeamMemberInfo; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; -import com.moing.backend.domain.team.domain.constant.ApprovalStatus; -import com.moing.backend.domain.team.domain.entity.QTeam; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -31,6 +31,21 @@ public List findMemberIdsByTeamId(Long teamId) { .fetch(); } + @Override + public Optional> findIdAndTokensByTeamIdAndMemberId(Long teamId, Long memberId) { + List result = queryFactory.select(Projections.constructor(MemberIdAndToken.class, + teamMember.member.memberId, + teamMember.member.fcmToken)) + .from(teamMember) + .where(teamMember.team.teamId.eq(teamId) + .and(teamMember.member.isNewUploadPush.eq(true)) + .and(teamMember.member.memberId.ne(memberId)) + .and(teamMember.isDeleted.eq(false))) + .fetch(); + + return result.isEmpty() ? Optional.empty() : Optional.of(result); + } + @Override public Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId) { List result = queryFactory.select(teamMember.member.fcmToken) diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index 2b9dfee2..8b76cd09 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.teamMember.domain.service; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; import com.moing.backend.domain.team.domain.entity.Team; @@ -36,4 +37,8 @@ public List getTeamMemberInfo(Long teamId){ public List getNotDeletedTeamMember(Long memberId){ return teamMemberRepository.findTeamMemberByMemberId(memberId); } + + public Optional> getMemberInfoExceptMe(Long teamId, Long memberId) { + return teamMemberRepository.findIdAndTokensByTeamIdAndMemberId(teamId, memberId); + } } From 7f39ce1d14637c3035aec5438be85e2400450fe3 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 01:12:11 +0900 Subject: [PATCH 318/619] =?UTF-8?q?feat:=20=EC=95=8C=EB=A6=BC=20=ED=9E=88?= =?UTF-8?q?=EC=8A=A4=ED=86=A0=EB=A6=AC=20=EB=AA=A8=EB=91=90=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/GetAlarmHistoryResponse.java | 60 +++++++++++++++++++ .../service/GetAlarmHistoryUseCase.java | 26 ++++++++ .../AlarmHistoryCustomRepository.java | 10 ++++ .../AlarmHistoryCustomRepositoryImpl.java | 36 +++++++++++ .../repository/AlarmHistoryRepository.java | 7 +++ .../service/AlarmHistoryGetService.java | 21 +++++++ .../presentation/AlarmHistoryController.java | 38 ++++++++++++ .../constant/AlarmHistoryResponseMessage.java | 12 ++++ .../domain/member/domain/entity/Member.java | 2 +- 9 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java create mode 100644 src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java create mode 100644 src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java create mode 100644 src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java create mode 100644 src/main/java/com/moing/backend/domain/history/presentation/constant/AlarmHistoryResponseMessage.java diff --git a/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java b/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java new file mode 100644 index 00000000..8bebbdd9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java @@ -0,0 +1,60 @@ +package com.moing.backend.domain.history.application.dto.response; + +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.querydsl.core.annotations.QueryProjection; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +@Getter +@AllArgsConstructor +public class GetAlarmHistoryResponse { + + private Long alarmHistoryId; + + private AlarmType type; + + private String path; + + private String idInfo; + + private String title; + + private String body; + + private String name; + + private boolean isRead; + + private String createdDate; + + @QueryProjection + public GetAlarmHistoryResponse(Long alarmHistoryId, AlarmType type, String path, String idInfo, String title, String body, String name, boolean isRead, LocalDateTime createdDate) { + this.alarmHistoryId = alarmHistoryId; + this.type = type; + this.path = path; + this.idInfo = idInfo; + this.title = title; + this.body = body; + this.name = name; + this.isRead = isRead; + this.createdDate = formatCreatedDate(createdDate); + } + + public String formatCreatedDate(LocalDateTime createdDate) { + LocalDateTime currentDateTime = LocalDateTime.now(); + + LocalDateTime midnightOfCreatedDate = createdDate.toLocalDate().atStartOfDay(); + + if (currentDateTime.isAfter(midnightOfCreatedDate.plusDays(1))) { + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("M월 d일"); + return midnightOfCreatedDate.plusDays(1).format(dateFormatter); + } else { + DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("a h:mm"); + return currentDateTime.format(timeFormatter); + } + } + +} diff --git a/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java new file mode 100644 index 00000000..f509595f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java @@ -0,0 +1,26 @@ +package com.moing.backend.domain.history.application.service; + +import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; +import com.moing.backend.domain.history.domain.service.AlarmHistoryGetService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class GetAlarmHistoryUseCase { + + private final MemberGetService memberGetService; + private final AlarmHistoryGetService alarmHistoryGetService; + + /** + * 알림 히스토리 조회 + */ + public List getAllAlarmHistories(String socialId) { + Member member = memberGetService.getMemberBySocialId(socialId); + return alarmHistoryGetService.getAlarmHistories(member.getMemberId()); + } +} diff --git a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepository.java b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepository.java new file mode 100644 index 00000000..625ca22c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepository.java @@ -0,0 +1,10 @@ +package com.moing.backend.domain.history.domain.repository; + +import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; + +import java.util.List; + +public interface AlarmHistoryCustomRepository { + + List findAlarmHistoriesByMemberId(Long memberId); +} diff --git a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java new file mode 100644 index 00000000..6a5fd6db --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java @@ -0,0 +1,36 @@ +package com.moing.backend.domain.history.domain.repository; + +import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; +import com.moing.backend.domain.history.application.dto.response.QGetAlarmHistoryResponse; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.util.List; + +import static com.moing.backend.domain.history.domain.entity.QAlarmHistory.alarmHistory; + +public class AlarmHistoryCustomRepositoryImpl implements AlarmHistoryCustomRepository { + + private final JPAQueryFactory queryFactory; + + public AlarmHistoryCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + @Override + public List findAlarmHistoriesByMemberId(Long memberId) { + return queryFactory.select(new QGetAlarmHistoryResponse(alarmHistory.id, + alarmHistory.type, + alarmHistory.path, + alarmHistory.idInfo, + alarmHistory.title, + alarmHistory.body, + alarmHistory.name, + alarmHistory.isRead, + alarmHistory.createdDate)) + .from(alarmHistory) + .where(alarmHistory.receiverId.eq(memberId)) + .orderBy(alarmHistory.createdDate.desc()) + .fetch(); + } +} diff --git a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java new file mode 100644 index 00000000..9a7ddfd8 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.history.domain.repository; + +import com.moing.backend.domain.history.domain.entity.AlarmHistory; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AlarmHistoryRepository extends JpaRepository, AlarmHistoryCustomRepository { +} diff --git a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java new file mode 100644 index 00000000..75493087 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java @@ -0,0 +1,21 @@ +package com.moing.backend.domain.history.domain.service; + +import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; +import com.moing.backend.domain.history.domain.repository.AlarmHistoryRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; +import java.util.List; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class AlarmHistoryGetService { + + private final AlarmHistoryRepository alarmHistoryRepository; + + public List getAlarmHistories(Long memberId){ + return alarmHistoryRepository.findAlarmHistoriesByMemberId(memberId); + } +} diff --git a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java new file mode 100644 index 00000000..75fda705 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java @@ -0,0 +1,38 @@ +package com.moing.backend.domain.history.presentation; + +import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; +import com.moing.backend.domain.history.application.service.GetAlarmHistoryUseCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.GET_ALL_ALARM_HISTORY; + + +@RestController +@AllArgsConstructor +@RequestMapping("/api/history/alarm") +public class AlarmHistoryController { + + private final GetAlarmHistoryUseCase getAlarmHistoryUseCase; + + /** + * 알림 전체 조회 + * [GET] api/history/alarm + * 작성자 : 김민수 + */ + @GetMapping + public ResponseEntity>> getAllAlarmHistories(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(GET_ALL_ALARM_HISTORY.getMessage(), getAlarmHistoryUseCase.getAllAlarmHistories(user.getSocialId()))); + } + + //TODO: 알림 한개씩 읽기 + +} diff --git a/src/main/java/com/moing/backend/domain/history/presentation/constant/AlarmHistoryResponseMessage.java b/src/main/java/com/moing/backend/domain/history/presentation/constant/AlarmHistoryResponseMessage.java new file mode 100644 index 00000000..ef6b52ab --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/presentation/constant/AlarmHistoryResponseMessage.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.history.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum AlarmHistoryResponseMessage { + GET_ALL_ALARM_HISTORY("알림 히스토리를 모두 조회했습니다."), + READ_ALARM_HISTORY("알림 히스토리 한 개를 조회했습니다."); + private final String message; +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index 2c8b2310..b2c6b0f0 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -7,7 +7,7 @@ import com.moing.backend.domain.member.domain.constant.SocialProvider; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.entity.BaseTimeEntity; -import com.moing.backend.global.util.AesConverter; +import com.moing.backend.global.utils.AesConverter; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; From 79d755b254d23542c357a2b26d916695873bb0f5 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 01:44:03 +0900 Subject: [PATCH 319/619] =?UTF-8?q?fix:=20constructor=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/application/service/SendBoardAlarmUseCase.java | 5 ++++- .../history/application/dto/response/MemberIdAndToken.java | 2 ++ .../domain/repository/TeamMemberCustomRepositoryImpl.java | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index 7bdd77ba..5421ed26 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -39,15 +39,18 @@ public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board bo Member member = baseServiceResponse.getMember(); Team team = baseServiceResponse.getTeam(); - if (board.isNotice() && member.isNewUploadPush()) { + if (board.isNotice()) { + System.out.println("공지인 경우"); String title = NEW_NOTICE_UPLOAD_MESSAGE.title(team.getName()); String body = NEW_NOTICE_UPLOAD_MESSAGE.body(board.getTitle()); Optional> memberIdAndTokens = teamMemberGetService.getMemberInfoExceptMe(team.getTeamId(), member.getMemberId()); if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { //알림 보내기 + System.out.println("###알림 보내기###"); List fcmTokens = getFcmTokens(memberIdAndTokens); eventPublisher.publishEvent(new FcmEvent(title, body, fcmTokens)); //알림 저장하기 + System.out.println("###알림 저장###"); List memberIds = getMemberIds(memberIdAndTokens); String idInfo = createIdInfo(team.getTeamId(), board.getBoardId()); saveAlarmHistory(idInfo, memberIds, title, body, team.getName()); diff --git a/src/main/java/com/moing/backend/domain/history/application/dto/response/MemberIdAndToken.java b/src/main/java/com/moing/backend/domain/history/application/dto/response/MemberIdAndToken.java index 06361d3b..e8d303b0 100644 --- a/src/main/java/com/moing/backend/domain/history/application/dto/response/MemberIdAndToken.java +++ b/src/main/java/com/moing/backend/domain/history/application/dto/response/MemberIdAndToken.java @@ -3,12 +3,14 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import java.util.List; @Getter @Builder @AllArgsConstructor +@NoArgsConstructor public class MemberIdAndToken { private String fcmToken; diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index 435b0ac2..db8e8ce5 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -34,8 +34,8 @@ public List findMemberIdsByTeamId(Long teamId) { @Override public Optional> findIdAndTokensByTeamIdAndMemberId(Long teamId, Long memberId) { List result = queryFactory.select(Projections.constructor(MemberIdAndToken.class, - teamMember.member.memberId, - teamMember.member.fcmToken)) + teamMember.member.fcmToken, + teamMember.member.memberId)) .from(teamMember) .where(teamMember.team.teamId.eq(teamId) .and(teamMember.member.isNewUploadPush.eq(true)) From aa1993258240a9f1feaf69c9840ecf0dd14fcbf5 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 02:05:06 +0900 Subject: [PATCH 320/619] =?UTF-8?q?feat:=20adco=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/AlarmHistory-API.adoc | 24 +++++ src/docs/asciidoc/api.adoc | 2 + .../dto/response/GetAlarmHistoryResponse.java | 4 +- .../AlarmHistoryControllerTest.java | 89 +++++++++++++++++++ 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/docs/asciidoc/AlarmHistory-API.adoc create mode 100644 src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java diff --git a/src/docs/asciidoc/AlarmHistory-API.adoc b/src/docs/asciidoc/AlarmHistory-API.adoc new file mode 100644 index 00000000..077c244c --- /dev/null +++ b/src/docs/asciidoc/AlarmHistory-API.adoc @@ -0,0 +1,24 @@ +[[AlarmHistory-알림-모아보기]] +== AlarmHistory 알림 모아보기 +operation::alarm-history-controller-test/get_all_alarm_history[snippets='http-request,http-response,response-fields'] + +== Type Category +|=== +| Category | Description + +| `NEW_UPLOAD` +| 신규 업로드 알림 + +| `FIRE` +| 불던지기 알림 + +| `REMIND` +| 리마인드 알림 + +| `APPROVE_TEAM` +| 소모임 승인 + +| `REJECT_TEAM` +| 소모임 반려 + +|=== diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 5d102566..d0758df3 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -14,6 +14,8 @@ include::Auth-API.adoc[] include::Mypage-API.adoc[] +include::AlarmHistory-API.adoc[] + include::Team-API.adoc[] include::Mission-API.adoc[] diff --git a/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java b/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java index 8bebbdd9..75560e49 100644 --- a/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java +++ b/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.history.domain.entity.AlarmType; import com.querydsl.core.annotations.QueryProjection; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import java.time.LocalDateTime; @@ -10,6 +11,7 @@ @Getter @AllArgsConstructor +@Builder public class GetAlarmHistoryResponse { private Long alarmHistoryId; @@ -26,7 +28,7 @@ public class GetAlarmHistoryResponse { private String name; - private boolean isRead; + private Boolean isRead; private String createdDate; diff --git a/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java b/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java new file mode 100644 index 00000000..eaf2daee --- /dev/null +++ b/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java @@ -0,0 +1,89 @@ +package com.moing.backend.domain.history.presentation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; +import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; +import com.moing.backend.domain.history.application.service.GetAlarmHistoryUseCase; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.List; + +import static com.moing.backend.domain.fire.presentation.constant.FireResponseMessage.GET_RECEIVERS_SUCCESS; +import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.GET_ALL_ALARM_HISTORY; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; + +@WebMvcTest(AlarmHistoryController.class) +class AlarmHistoryControllerTest extends CommonControllerTest { + + @MockBean + private GetAlarmHistoryUseCase getAlarmHistoryUseCase; + + @Test + public void get_all_alarm_history() throws Exception { + //given + List output = Lists.newArrayList(GetAlarmHistoryResponse.builder() + .alarmHistoryId(1L) + .type(AlarmType.NEW_UPLOAD) + .path("/post/detail") + .idInfo("{\"teamId\":74,\"boardId\":96}") + .title("갓생살자에 새로 올라온 공지를 확인하세요!") + .body("모임 장소 공지") + .name("모닥모닥불") + .isRead(false) + .createdDate("오후 06:39") + .build()); + + given(getAlarmHistoryUseCase.getAllAlarmHistories(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform( + get("/api/history/alarm") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(GET_ALL_ALARM_HISTORY.getMessage()), + fieldWithPath("data[].alarmHistoryId").description("알림 히스토리 아이디"), + fieldWithPath("data[].type").description("알림 아이콘 구분"), + fieldWithPath("data[].path").description("알림 이동 페이지 path"), + fieldWithPath("data[].idInfo").description("알림 페이지 이동할 때 필요한 data (JSON String)"), + fieldWithPath("data[].title").description("알림의 제목 (가장 bold 처리 된거)"), + fieldWithPath("data[].body").description("알림의 본문 (제목 밑)"), + fieldWithPath("data[].name").description("미션 리마인드 제외하고는 팀 이름 (제목 위)"), + fieldWithPath("data[].createdDate").description("작성 시간"), + fieldWithPath("data[].isRead").description("읽음여부") + + ) + ) + ) + .andReturn(); + + } +} \ No newline at end of file From 10295efaebab7d53344c28491f20980e07f47419 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 02:09:23 +0900 Subject: [PATCH 321/619] =?UTF-8?q?refactor:=20print=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/application/service/SendBoardAlarmUseCase.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index 5421ed26..bb5dfb46 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -40,17 +40,14 @@ public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board bo Team team = baseServiceResponse.getTeam(); if (board.isNotice()) { - System.out.println("공지인 경우"); String title = NEW_NOTICE_UPLOAD_MESSAGE.title(team.getName()); String body = NEW_NOTICE_UPLOAD_MESSAGE.body(board.getTitle()); Optional> memberIdAndTokens = teamMemberGetService.getMemberInfoExceptMe(team.getTeamId(), member.getMemberId()); if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { //알림 보내기 - System.out.println("###알림 보내기###"); List fcmTokens = getFcmTokens(memberIdAndTokens); eventPublisher.publishEvent(new FcmEvent(title, body, fcmTokens)); //알림 저장하기 - System.out.println("###알림 저장###"); List memberIds = getMemberIds(memberIdAndTokens); String idInfo = createIdInfo(team.getTeamId(), board.getBoardId()); saveAlarmHistory(idInfo, memberIds, title, body, team.getName()); From d9bdff13164a4755b8b87e44eab1775e1daf47af Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 02:18:39 +0900 Subject: [PATCH 322/619] =?UTF-8?q?refactor:=20adoc=20=EC=98=A4=ED=83=80?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/AlarmHistory-API.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/asciidoc/AlarmHistory-API.adoc b/src/docs/asciidoc/AlarmHistory-API.adoc index 077c244c..1e8c4ccb 100644 --- a/src/docs/asciidoc/AlarmHistory-API.adoc +++ b/src/docs/asciidoc/AlarmHistory-API.adoc @@ -1,5 +1,5 @@ [[AlarmHistory-알림-모아보기]] -== AlarmHistory 알림 모아보기 += AlarmHistory 알림 모아보기 operation::alarm-history-controller-test/get_all_alarm_history[snippets='http-request,http-response,response-fields'] == Type Category From b10a89110646583f25df33c69d07dbeddc90a16d Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 22:44:16 +0900 Subject: [PATCH 323/619] =?UTF-8?q?fix:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=ED=95=98=EB=A9=B4=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=204=EC=9D=BC=20=EC=A0=84=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moing/backend/domain/team/domain/entity/Team.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java index 099196e4..5086ada7 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -81,7 +81,9 @@ public void updateTeam(String name, String introduction, String profileImgUrl) { public void deleteTeam() { this.isDeleted=true; - this.deletionTime = LocalDateTime.now(ZoneId.of("Asia/Seoul")).withNano(0); + //TODO 테스트 용으로 현재 시간이 아닌 4일 전으로 +// this.deletionTime = LocalDateTime.now().withNano(0); + this.deletionTime=LocalDateTime.now().minusDays(4).withNano(0); } public void addTeamMember(){ From b42e367faca7a611a64a5df119941ab535d13779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 6 Dec 2023 23:04:51 +0900 Subject: [PATCH 324/619] =?UTF-8?q?fix=20:=20=EA=B8=80=EC=9E=90=EC=88=98?= =?UTF-8?q?=20=EC=A0=9C=ED=95=9C=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20=EA=B3=BC=EC=97=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionArchive/application/dto/req/MissionArchiveReq.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java index e0c82411..6bc71af4 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java @@ -2,12 +2,15 @@ import lombok.*; +import javax.validation.constraints.Size; + @Builder @NoArgsConstructor @Getter public class MissionArchiveReq { private String status; + @Size(min = 1, max = 4000) private String archive; //사진일 경우 파일명, 이외에는 text,link @Builder From ea5f269188db4401d0030230e85e65ea193bea46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 6 Dec 2023 23:07:07 +0900 Subject: [PATCH 325/619] =?UTF-8?q?fix=20:=20MissionArchiveController=20@V?= =?UTF-8?q?alid=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveController.java | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 77169a15..04c6ba67 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.presentation; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; @@ -8,6 +9,7 @@ import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.service.*; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveScheduleQueryService; import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; import com.moing.backend.domain.missionHeart.application.service.MissionHeartUseCase; import com.moing.backend.global.config.security.dto.User; @@ -17,6 +19,7 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; +import javax.validation.Valid; import java.util.List; import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; @@ -46,8 +49,8 @@ public class MissionArchiveController { public ResponseEntity> createArchive(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId, - @RequestBody MissionArchiveReq missionArchiveReq) { - return ResponseEntity.ok(SuccessResponse.create(CREATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveCreateUseCase.createArchive(user.getSocialId(), missionId,missionArchiveReq))); + @Valid @RequestBody MissionArchiveReq missionArchiveReq) { + return ResponseEntity.ok(SuccessResponse.create(CREATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveCreateUseCase.createArchive(user.getSocialId(), missionId, missionArchiveReq))); } /** @@ -61,8 +64,9 @@ public ResponseEntity> updateArchive(@Authent @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId, @RequestBody MissionArchiveReq missionArchiveReq) { - return ResponseEntity.ok(SuccessResponse.create(UPDATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveUpdateUseCase.updateArchive(user.getSocialId(), missionId,missionArchiveReq))); + return ResponseEntity.ok(SuccessResponse.create(UPDATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveUpdateUseCase.updateArchive(user.getSocialId(), missionId, missionArchiveReq))); } + /** * 미션 인증 취소하기 * [DELETE] {teamId}/missions/{missionId}/archive @@ -71,8 +75,8 @@ public ResponseEntity> updateArchive(@Authent @DeleteMapping() public ResponseEntity> deleteArchive(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId) { + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { return ResponseEntity.ok(SuccessResponse.create(UPDATE_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveDeleteUseCase.deleteArchive(user.getSocialId(), missionId))); } @@ -98,7 +102,7 @@ public ResponseEntity> getMyArchive(@Authen public ResponseEntity>> getOtherPeopleArchives(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable("missionId") Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getPersonalArchive(user.getSocialId(),missionId))); + return ResponseEntity.ok(SuccessResponse.create(READ_TEAM_ARCHIVE_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getPersonalArchive(user.getSocialId(), missionId))); } @@ -114,7 +118,7 @@ public ResponseEntity> pushHeart(@Authenticatio @PathVariable("missionId") Long missionId, @PathVariable("archiveId") Long archiveId, @PathVariable("missionHeartStatus") String missionHeartStatus) { - return ResponseEntity.ok(SuccessResponse.create(CREATE_ARCHIVE_SUCCESS.getMessage(), this.missionHeartUseCase.pushHeart(user.getSocialId(),archiveId,missionHeartStatus))); + return ResponseEntity.ok(SuccessResponse.create(CREATE_ARCHIVE_SUCCESS.getMessage(), this.missionHeartUseCase.pushHeart(user.getSocialId(), archiveId, missionHeartStatus))); } /** @@ -131,7 +135,6 @@ public ResponseEntity> getMissionDoneSt } - /** * 반복미션 - 나의 성공 횟수 조회 * [GET] {teamId}/missions/{missionId}/archive/my-status @@ -140,14 +143,10 @@ public ResponseEntity> getMissionDoneSt @GetMapping("/my-status") public ResponseEntity> getMyMissionDoneStatus(@AuthenticationPrincipal User user, - @PathVariable("teamId") Long teamId, - @PathVariable("missionId") Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage(), this.repeatMissionArchiveReadUseCase.getMyMissionDoneStatus(user.getSocialId(),missionId))); + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage(), this.repeatMissionArchiveReadUseCase.getMyMissionDoneStatus(user.getSocialId(), missionId))); } - - - - } \ No newline at end of file From 576f32d7f423adb50a7fabf96dd908b3d39fb828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 6 Dec 2023 23:36:02 +0900 Subject: [PATCH 326/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=B0=9C=EC=86=A1=20=EA=B5=AC=ED=98=84=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionRemindAlarmUseCase.java | 32 +++++++++++-------- .../domain/mission/domain/entity/Mission.java | 4 +++ .../dto/res/MissionArchiveRes.java | 2 ++ .../domain/entity/MissionArchive.java | 2 +- .../MissionArchiveCustomRepository.java | 4 +++ .../MissionArchiveCustomRepositoryImpl.java | 27 ++++++++++++++++ .../repository/MissionArchiveRepository.java | 2 ++ .../MissionArchiveScheduleQueryService.java | 25 +++++++++++++++ .../domain/entity/MissionState.java | 2 +- .../fcm/constant/RemindMissionTitle.java | 14 ++++---- ...issionArchiveCustomRepositoryImplTest.java | 29 +++++++++++++++++ 11 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java create mode 100644 src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index 61fb3d1e..1e651bdd 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -22,40 +22,44 @@ public class MissionRemindAlarmUseCase { public void sendRemindMissionAlarm(Mission mission) { + + Random random = new Random(System.currentTimeMillis()); - String title = getTitle("receiver",random.nextInt(4)); - String message = getMessage(mission.getTitle(),random.nextInt(4)); + + + String title = getTitle(random.nextInt(4)); + String message = getMessage(random.nextInt(4)); MultiRequest multiRequest = new MultiRequest(); } - public String getTitle(String receiver, int num) { + public String getTitle(int num) { switch (num) { case 0: - return receiver + REMIND_MISSION_TITLE1.getMessage(); + return REMIND_MISSION_TITLE1.getMessage(); case 1: - return receiver + REMIND_MISSION_TITLE2.getMessage(); + return REMIND_MISSION_TITLE2.getMessage(); case 2: - return receiver + REMIND_MISSION_TITLE3.getMessage(); + return REMIND_MISSION_TITLE3.getMessage(); case 3: - return receiver + REMIND_MISSION_TITLE4.getMessage(); + return REMIND_MISSION_TITLE4.getMessage(); } - return receiver + REMIND_MISSION_TITLE4.getMessage(); + return REMIND_MISSION_TITLE4.getMessage(); } - public String getMessage(String missionTitle, int num) { + public String getMessage(int num) { switch (num) { case 0: - return missionTitle + REMIND_MISSION_MESSAGE1.getMessage(); + return REMIND_MISSION_MESSAGE1.getMessage(); case 1: - return missionTitle + REMIND_MISSION_MESSAGE2.getMessage(); + return REMIND_MISSION_MESSAGE2.getMessage(); case 2: - return missionTitle + REMIND_MISSION_MESSAGE3.getMessage(); + return REMIND_MISSION_MESSAGE3.getMessage(); case 3: - return missionTitle + REMIND_MISSION_MESSAGE4.getMessage(); + return REMIND_MISSION_MESSAGE4.getMessage(); } - return missionTitle + REMIND_MISSION_MESSAGE4.getMessage(); + return REMIND_MISSION_MESSAGE4.getMessage(); } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index df199e4a..44384433 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; @@ -49,6 +50,9 @@ public class Mission extends BaseTimeEntity { @OneToMany(mappedBy = "mission") List missionArchiveList = new ArrayList<>(); + + @OneToMany(mappedBy = "mission") + List missionStateList = new ArrayList<>(); @Builder public Mission(String title, LocalDateTime dueTo, String rule, String content, int number, Team team, MissionType type, MissionStatus status, MissionWay way) { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index b154c6ce..31c9b26f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -19,6 +19,8 @@ public class MissionArchiveRes { private String heartStatus; private Long hearts; + private boolean isAbleToEdit; + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index 670adbec..abf8cae3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -39,7 +39,7 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 @Enumerated(value = EnumType.STRING) private MissionArchiveStatus status; - @Column(nullable = false, length = 4000) + @Column(nullable = false, length = 5000) private String archive; //링크, 글, 사진 뭐든 가능 private Long count; // 횟수 diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 1818b2ed..0a393d16 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.domain.repository; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; @@ -30,4 +31,7 @@ public interface MissionArchiveCustomRepository { Boolean findMyArchivesToday(Long memberId,Long missionId); + Optional> findPeopleRemainMission(); + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 293ec640..db04e918 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.domain.repository; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; @@ -22,6 +23,7 @@ import org.springframework.data.jpa.repository.Query; import javax.persistence.EntityManager; +import javax.swing.text.html.Option; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -30,7 +32,11 @@ import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; +import static com.moing.backend.domain.team.domain.entity.QTeam.team; +import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; import static javax.swing.Spring.constant; +import static org.springframework.data.jpa.domain.Specification.where; + @Slf4j public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { @@ -277,5 +283,26 @@ public Boolean findMyArchivesToday(Long memberId, Long missionId) { } + public Optional> findPeopleRemainMission() { + return Optional.ofNullable(queryFactory + .select(teamMember.member.nickName).distinct() + .from(teamMember) + .join(teamMember.team, team) + .join(team.missions, mission) + .join(mission.missionStateList,missionState) + .where(missionState.isNull()) + .fetch()); +// .where( +// // active 한 미션 필터링 +// (((mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT))).and(mission.type.eq(MissionType.ONCE))) +// .or((mission.status.eq(MissionStatus.ONGOING)).and(mission.type.eq(MissionType.REPEAT)))), +// // 인증하지 않은값 +// missionState.id.isNull() + + +// ).fetch()); + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java index 804a5b01..4b6065b5 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -7,10 +7,12 @@ import org.hibernate.annotations.Parameter; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; +@Repository public interface MissionArchiveRepository extends JpaRepository,MissionArchiveCustomRepository { @Query("select m from MissionArchive as m where m.member =:memberId" ) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java new file mode 100644 index 00000000..e2f8585c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java @@ -0,0 +1,25 @@ +package com.moing.backend.domain.missionArchive.domain.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionArchiveScheduleQueryService { + + + private final MissionArchiveRepository missionArchiveRepository; + + public List getRemainMissionPeople() { + return missionArchiveRepository.findPeopleRemainMission().orElseThrow(); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java index 788b602c..22a550b8 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java @@ -23,7 +23,7 @@ public class MissionState extends BaseTimeEntity { @Column(name = "missionState_id") private Long id; - @OneToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY) private Mission mission; @OneToOne private Member member; diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java index d387ca59..662d90e9 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java @@ -7,16 +7,16 @@ @RequiredArgsConstructor public enum RemindMissionTitle { - REMIND_MISSION_TITLE1("님, 오늘도 좋은하루!"), - REMIND_MISSION_TITLE2("님, 잊으신 건 아니죠?\uD83D\uDC40"), - REMIND_MISSION_TITLE3("님, 좋은 아침이에요! ☀\uFE0F"), + REMIND_MISSION_TITLE1("오늘도 좋은 하루 보내세요!"), + REMIND_MISSION_TITLE2("혹시 ... 잊으신 건 아니죠?\uD83D\uDC40"), + REMIND_MISSION_TITLE3("좋은 아침이에요! ☀\uFE0F"), REMIND_MISSION_TITLE4("오늘의 열정이 타오르불\uD83D\uDD25"), - REMIND_MISSION_MESSAGE1(" 도전과 함께⚡\uFE0F "), - REMIND_MISSION_MESSAGE2(" 인증을 모임원들이 기다리고 있어요!"), - REMIND_MISSION_MESSAGE3(" 수행하고 이번주도 도전해요👊 "), - REMIND_MISSION_MESSAGE4(" 도전하고 성취감 뿜뿜💪 "); + REMIND_MISSION_MESSAGE1(" 자기계발 미션 도전과 함께⚡\uFE0F "), + REMIND_MISSION_MESSAGE2(" 미션 인증을 모임원들이 기다리고 있어요!"), + REMIND_MISSION_MESSAGE3(" 미션 인증하고 이번주도 도전해요👊 "), + REMIND_MISSION_MESSAGE4(" 미션 도전하고 성취감 뿜뿜💪 "); private final String message; diff --git a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java new file mode 100644 index 00000000..dc94f7fc --- /dev/null +++ b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java @@ -0,0 +1,29 @@ +package com.moing.backend.domain.missionArchive.domain.repository; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import javax.persistence.EntityManager; +import java.util.List; +import java.util.Optional; + +import static com.moing.backend.domain.mission.domain.entity.QMission.mission; +import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; +@SpringBootTest +class MissionArchiveCustomRepositoryImplTest { + + @Autowired + EntityManager em; + + @Autowired + private MissionArchiveRepository missionArchiveRepository; + + @Test + void findPeopleRemainMission() { + + System.out.println("!!!"+ missionArchiveRepository.findPeopleRemainMission()); + + } +} \ No newline at end of file From 327b597096ae02b904d9a7f6adfa2819812b8f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 6 Dec 2023 23:37:34 +0900 Subject: [PATCH 327/619] =?UTF-8?q?chore=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20serivce=20import=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionArchive/presentation/MissionArchiveController.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 1bf57b83..5864ffdd 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -1,15 +1,11 @@ package com.moing.backend.domain.missionArchive.presentation; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.MyMissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.service.*; -import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; -import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveScheduleQueryService; import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; import com.moing.backend.domain.missionHeart.application.service.MissionHeartUseCase; import com.moing.backend.global.config.security.dto.User; From 87102c68867c73f8733faa6ea3cd94520d7a196b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 6 Dec 2023 23:37:34 +0900 Subject: [PATCH 328/619] =?UTF-8?q?chore=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20method=20import=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionArchive/presentation/MissionArchiveController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 77169a15..da56c1ab 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -1,13 +1,13 @@ package com.moing.backend.domain.missionArchive.presentation; -import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; + import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; import com.moing.backend.domain.missionArchive.application.dto.res.MyMissionArchiveRes; import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; import com.moing.backend.domain.missionArchive.application.service.*; -import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; + import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; import com.moing.backend.domain.missionHeart.application.service.MissionHeartUseCase; import com.moing.backend.global.config.security.dto.User; From c96ae8f505f6eca87460b678424ca02dea3a60f9 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 23:41:03 +0900 Subject: [PATCH 329/619] =?UTF-8?q?feat:=20=EC=95=8C=EB=A6=BC=20=EB=8B=A8?= =?UTF-8?q?=EA=B1=B4=20=EC=A1=B0=ED=9A=8C=20(=EC=9D=BD=EC=9D=8C=EC=B2=98?= =?UTF-8?q?=EB=A6=AC)=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ReadAlarmHistoryUseCase.java | 30 +++++++++++++++++++ .../history/domain/entity/AlarmHistory.java | 4 +++ .../AlarmHistoryCustomRepositoryImpl.java | 4 +++ .../repository/AlarmHistoryRepository.java | 4 +++ .../service/AlarmHistoryGetService.java | 6 ++++ .../exception/AlarmHistoryException.java | 11 +++++++ .../NotFoundAlarmHistoryException.java | 11 +++++++ .../presentation/AlarmHistoryController.java | 27 +++++++++++++---- .../backend/global/response/ErrorCode.java | 5 +++- 9 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/history/application/service/ReadAlarmHistoryUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/history/exception/AlarmHistoryException.java create mode 100644 src/main/java/com/moing/backend/domain/history/exception/NotFoundAlarmHistoryException.java diff --git a/src/main/java/com/moing/backend/domain/history/application/service/ReadAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/ReadAlarmHistoryUseCase.java new file mode 100644 index 00000000..58c56347 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/application/service/ReadAlarmHistoryUseCase.java @@ -0,0 +1,30 @@ +package com.moing.backend.domain.history.application.service; + +import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; +import com.moing.backend.domain.history.domain.entity.AlarmHistory; +import com.moing.backend.domain.history.domain.service.AlarmHistoryGetService; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class ReadAlarmHistoryUseCase { + + private final MemberGetService memberGetService; + private final AlarmHistoryGetService alarmHistoryGetService; + + /** + * 알림 히스토리 읽기 + */ + @Transactional + public void readAlarmHistory(String socialId, Long alarmHistoryId) { + Member member = memberGetService.getMemberBySocialId(socialId); + AlarmHistory alarmHistory=alarmHistoryGetService.getAlarmHistory(alarmHistoryId, member.getMemberId()); + alarmHistory.readAlarmHistory(); + } +} diff --git a/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmHistory.java b/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmHistory.java index 06ed3f76..723b23b6 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmHistory.java +++ b/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmHistory.java @@ -42,4 +42,8 @@ public class AlarmHistory extends BaseTimeEntity { private String name; private boolean isRead; + + public void readAlarmHistory(){ + this.isRead=true; + } } diff --git a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java index 6a5fd6db..38f36379 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java @@ -2,12 +2,16 @@ import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; import com.moing.backend.domain.history.application.dto.response.QGetAlarmHistoryResponse; +import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.querydsl.jpa.impl.JPAQueryFactory; +import com.querydsl.jpa.impl.JPAUpdateClause; import javax.persistence.EntityManager; +import java.time.LocalDateTime; import java.util.List; import static com.moing.backend.domain.history.domain.entity.QAlarmHistory.alarmHistory; +import static com.moing.backend.domain.team.domain.entity.QTeam.team; public class AlarmHistoryCustomRepositoryImpl implements AlarmHistoryCustomRepository { diff --git a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java index 9a7ddfd8..a076f7aa 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java +++ b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java @@ -3,5 +3,9 @@ import com.moing.backend.domain.history.domain.entity.AlarmHistory; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface AlarmHistoryRepository extends JpaRepository, AlarmHistoryCustomRepository { + + Optional findAlarmHistoryByIdAndReceiverId(Long id, Long receiverId); } diff --git a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java index 75493087..08481283 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java +++ b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java @@ -1,7 +1,9 @@ package com.moing.backend.domain.history.domain.service; import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; +import com.moing.backend.domain.history.domain.entity.AlarmHistory; import com.moing.backend.domain.history.domain.repository.AlarmHistoryRepository; +import com.moing.backend.domain.history.exception.NotFoundAlarmHistoryException; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; @@ -18,4 +20,8 @@ public class AlarmHistoryGetService { public List getAlarmHistories(Long memberId){ return alarmHistoryRepository.findAlarmHistoriesByMemberId(memberId); } + + public AlarmHistory getAlarmHistory(Long alarmHistoryId, Long memberId){ + return alarmHistoryRepository.findAlarmHistoryByIdAndReceiverId(alarmHistoryId, alarmHistoryId).orElseThrow(NotFoundAlarmHistoryException::new); + } } diff --git a/src/main/java/com/moing/backend/domain/history/exception/AlarmHistoryException.java b/src/main/java/com/moing/backend/domain/history/exception/AlarmHistoryException.java new file mode 100644 index 00000000..2d9ee9a8 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/exception/AlarmHistoryException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.history.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class AlarmHistoryException extends ApplicationException { + protected AlarmHistoryException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} diff --git a/src/main/java/com/moing/backend/domain/history/exception/NotFoundAlarmHistoryException.java b/src/main/java/com/moing/backend/domain/history/exception/NotFoundAlarmHistoryException.java new file mode 100644 index 00000000..ab77af9f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/exception/NotFoundAlarmHistoryException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.history.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundAlarmHistoryException extends AlarmHistoryException { + public NotFoundAlarmHistoryException() { + super(ErrorCode.NOT_FOUND_BY_ALARM_HISOTRY_ID_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java index 75fda705..5e0392e9 100644 --- a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java +++ b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java @@ -2,18 +2,18 @@ import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; import com.moing.backend.domain.history.application.service.GetAlarmHistoryUseCase; +import com.moing.backend.domain.history.application.service.ReadAlarmHistoryUseCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.GET_ALL_ALARM_HISTORY; +import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.READ_ALARM_HISTORY; @RestController @@ -22,7 +22,7 @@ public class AlarmHistoryController { private final GetAlarmHistoryUseCase getAlarmHistoryUseCase; - + private final ReadAlarmHistoryUseCase readAlarmHistoryUseCase; /** * 알림 전체 조회 * [GET] api/history/alarm @@ -33,6 +33,23 @@ public ResponseEntity>> getAllAlar return ResponseEntity.ok(SuccessResponse.create(GET_ALL_ALARM_HISTORY.getMessage(), getAlarmHistoryUseCase.getAllAlarmHistories(user.getSocialId()))); } - //TODO: 알림 한개씩 읽기 + /** + * 알림 한개 조회 + * [POST] api/history/alarm/read?alarmHistoryId=1 + */ + @PostMapping("/read") + public ResponseEntity readAlarmHistory(@AuthenticationPrincipal User user, + @RequestParam Long alarmHistoryId) { + readAlarmHistoryUseCase.readAlarmHistory(user.getSocialId(), alarmHistoryId); + return ResponseEntity.ok(SuccessResponse.create(READ_ALARM_HISTORY.getMessage())); + } + /** + * 안 읽은 알림 개수 조회 + * [GET] api/history/alarm/count + */ + @GetMapping("/count") + public ResponseEntity> getAlarmHistoryCount(@AuthenticationPrincipal User user){ + return ResponseEntity.ok(SuccessResponse.create()) + } } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 71d070ba..2bfa13ad 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -57,7 +57,10 @@ public enum ErrorCode { //게시글 댓글 관련 에러 코드 NOT_FOUND_BY_BOARD_COMMENT_ID_ERROR("BC0001","해당 boardCommentId인 댓글이 존재하지 않습니다."), - NOT_AUTH_BY_BOARD_COMMENT_ID_ERROR("BC0002","권한이 없습니다."); + NOT_AUTH_BY_BOARD_COMMENT_ID_ERROR("BC0002","권한이 없습니다."), + + //알림 관련 에러 코드 + NOT_FOUND_BY_ALARM_HISOTRY_ID_ERROR("AH0001","해당 alarmHistoryId인 알림이 존재하지 않습니다."); private String errorCode; private String message; From 348801efc2e0b143e2a5af8b80aa7a5f8bb211a7 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 6 Dec 2023 23:49:10 +0900 Subject: [PATCH 330/619] =?UTF-8?q?feat:=20=EB=8B=A8=EA=B1=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20(=EC=9D=BD=EC=9D=8C=20=EC=B2=98=EB=A6=AC)=20adoc=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/AlarmHistory-API.adoc | 9 ++++- .../presentation/AlarmHistoryController.java | 5 +-- .../AlarmHistoryControllerTest.java | 40 ++++++++++++++++--- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/docs/asciidoc/AlarmHistory-API.adoc b/src/docs/asciidoc/AlarmHistory-API.adoc index 1e8c4ccb..0b380894 100644 --- a/src/docs/asciidoc/AlarmHistory-API.adoc +++ b/src/docs/asciidoc/AlarmHistory-API.adoc @@ -1,5 +1,8 @@ +[[AlarmHistory-API]] += AlarmHistory API + [[AlarmHistory-알림-모아보기]] -= AlarmHistory 알림 모아보기 +== AlarmHistory 알림 모아보기 operation::alarm-history-controller-test/get_all_alarm_history[snippets='http-request,http-response,response-fields'] == Type Category @@ -22,3 +25,7 @@ operation::alarm-history-controller-test/get_all_alarm_history[snippets='http-re | 소모임 반려 |=== + +[[AlarmHistory-알림-단건-조회하기]] +== AlarmHistory 알림 단건 조회하기 +operation::alarm-history-controller-test/read_alarm_history[snippets='http-request,http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java index 5e0392e9..024eb9cb 100644 --- a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java +++ b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java @@ -44,12 +44,9 @@ public ResponseEntity readAlarmHistory(@AuthenticationPrincipal return ResponseEntity.ok(SuccessResponse.create(READ_ALARM_HISTORY.getMessage())); } + //TODO /** * 안 읽은 알림 개수 조회 * [GET] api/history/alarm/count */ - @GetMapping("/count") - public ResponseEntity> getAlarmHistoryCount(@AuthenticationPrincipal User user){ - return ResponseEntity.ok(SuccessResponse.create()) - } } diff --git a/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java b/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java index eaf2daee..e8d66569 100644 --- a/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java +++ b/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java @@ -1,31 +1,28 @@ package com.moing.backend.domain.history.presentation; import com.moing.backend.config.CommonControllerTest; -import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; import com.moing.backend.domain.history.application.service.GetAlarmHistoryUseCase; +import com.moing.backend.domain.history.application.service.ReadAlarmHistoryUseCase; import com.moing.backend.domain.history.domain.entity.AlarmType; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; -import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import java.util.List; -import static com.moing.backend.domain.fire.presentation.constant.FireResponseMessage.GET_RECEIVERS_SUCCESS; import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.GET_ALL_ALARM_HISTORY; +import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.READ_ALARM_HISTORY; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -35,6 +32,9 @@ class AlarmHistoryControllerTest extends CommonControllerTest { @MockBean private GetAlarmHistoryUseCase getAlarmHistoryUseCase; + @MockBean + private ReadAlarmHistoryUseCase readAlarmHistoryUseCase; + @Test public void get_all_alarm_history() throws Exception { //given @@ -86,4 +86,34 @@ public void get_all_alarm_history() throws Exception { .andReturn(); } + + @Test + public void read_alarm_history() throws Exception { + + //when + ResultActions actions = mockMvc.perform( + post("/api/history/alarm/read?alarmHistoryId=1") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(READ_ALARM_HISTORY.getMessage()) + + ) + ) + ) + .andReturn(); + + } + } \ No newline at end of file From 74993015b025fabc0bae04a8ba72fe63b6b5e0d2 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 7 Dec 2023 00:48:29 +0900 Subject: [PATCH 331/619] =?UTF-8?q?refactor:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20=EC=A0=80=EC=9E=A5=20sin?= =?UTF-8?q?gle,=20multi=20=EA=B3=B5=ED=86=B5=20=ED=95=A8=EC=88=98=EB=A1=9C?= =?UTF-8?q?=20=EB=AC=B6=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendBoardAlarmUseCase.java | 35 +++---------------- .../mapper/AlarmHistoryMapper.java | 28 +++++++++++++-- .../service/SaveMultiAlarmHistoryUseCase.java | 28 +++++++++++++++ .../SaveSingleAlarmHistoryUseCase.java | 23 ++++++++++++ .../service/AlarmHistoryGetService.java | 2 +- .../service/AlarmHistorySaveService.java | 6 +++- .../service/MissionStateScheduleUseCase.java | 2 ++ 7 files changed, 89 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index bb5dfb46..a2e5dea9 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -3,10 +3,9 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; -import com.moing.backend.domain.history.domain.entity.AlarmHistory; +import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; -import com.moing.backend.domain.history.domain.service.AlarmHistorySaveService; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; @@ -18,10 +17,8 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; -import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import static com.moing.backend.global.config.fcm.constant.NewNoticeUploadMessage.NEW_NOTICE_UPLOAD_MESSAGE; @@ -32,7 +29,7 @@ public class SendBoardAlarmUseCase { private final TeamMemberGetService teamMemberGetService; private final ApplicationEventPublisher eventPublisher; - private final AlarmHistorySaveService alarmHistorySaveService; + private final SaveMultiAlarmHistoryUseCase saveAlarmHistory; private final AlarmHistoryMapper alarmHistoryMapper; public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board board) { @@ -45,38 +42,14 @@ public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board bo Optional> memberIdAndTokens = teamMemberGetService.getMemberInfoExceptMe(team.getTeamId(), member.getMemberId()); if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { //알림 보내기 - List fcmTokens = getFcmTokens(memberIdAndTokens); + List fcmTokens = alarmHistoryMapper.getFcmTokens(memberIdAndTokens); eventPublisher.publishEvent(new FcmEvent(title, body, fcmTokens)); //알림 저장하기 - List memberIds = getMemberIds(memberIdAndTokens); - String idInfo = createIdInfo(team.getTeamId(), board.getBoardId()); - saveAlarmHistory(idInfo, memberIds, title, body, team.getName()); + saveAlarmHistory.saveAlarmHistories(memberIdAndTokens, createIdInfo(team.getTeamId(), board.getBoardId()), title, body, team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue()); } } } - private List getFcmTokens(Optional> memberIdAndTokens) { - return memberIdAndTokens.map(list -> list.stream() - .map(MemberIdAndToken::getFcmToken) - .collect(Collectors.toList())) - .orElse(Collections.emptyList()); - } - - private List getMemberIds(Optional> memberIdAndTokens) { - return memberIdAndTokens.map(list -> list.stream() - .map(MemberIdAndToken::getMemberId) - .collect(Collectors.toList())) - .orElse(Collections.emptyList()); - } - - private void saveAlarmHistory(String idInfo, List memberIds, String title, String body, String teamName) { - List alarmHistories = memberIds.stream() - .map(memberId -> alarmHistoryMapper.toAlarmHistory(AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue(), idInfo, memberId, title, body, teamName)) - .collect(Collectors.toList()); - - alarmHistorySaveService.saveAlarmHistory(alarmHistories); // 여기서 saveAll은 일괄 삽입을 처리하는 메서드입니다. - } - private String createIdInfo(Long teamId, Long boardId) { JSONObject jo = new JSONObject(); jo.put("teamId", teamId); diff --git a/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java b/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java index 13ee5fa9..d2eb03bf 100644 --- a/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java +++ b/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java @@ -1,12 +1,15 @@ package com.moing.backend.domain.history.application.mapper; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.history.domain.entity.AlarmHistory; import com.moing.backend.domain.history.domain.entity.AlarmType; -import com.moing.backend.domain.member.domain.entity.Member; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import javax.persistence.*; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; @Component @RequiredArgsConstructor @@ -24,4 +27,25 @@ public AlarmHistory toAlarmHistory(AlarmType type, String path, String idInfo, L .isRead(false) .build(); } + + public List getFcmTokens(Optional> memberIdAndTokens) { + return memberIdAndTokens.map(list -> list.stream() + .map(MemberIdAndToken::getFcmToken) + .collect(Collectors.toList())) + .orElse(Collections.emptyList()); + } + + public List getMemberIds(Optional> memberIdAndTokens) { + return memberIdAndTokens.map(list -> list.stream() + .map(MemberIdAndToken::getMemberId) + .collect(Collectors.toList())) + .orElse(Collections.emptyList()); + } + + public List getAlarmHistories(String idInfo, List memberIds, String title, String body, String teamName, AlarmType alarmType, String path) { + return memberIds.stream() + .map(memberId -> toAlarmHistory(alarmType, path, idInfo, memberId, title, body, teamName)) + .collect(Collectors.toList()); + } + } diff --git a/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java new file mode 100644 index 00000000..10069ac9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.history.application.service; + +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.domain.entity.AlarmHistory; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.service.AlarmHistorySaveService; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class SaveMultiAlarmHistoryUseCase { + + private final AlarmHistoryMapper alarmHistoryMapper; + private final AlarmHistorySaveService alarmHistorySaveService; + + @Async + public void saveAlarmHistories(Optional> memberIdAndTokens, String idInfo, String title, String body, String name, AlarmType alarmType, String path) { + List memberIds = alarmHistoryMapper.getMemberIds(memberIdAndTokens); + List alarmHistories = alarmHistoryMapper.getAlarmHistories(idInfo, memberIds, title, body, name, alarmType, path); + alarmHistorySaveService.saveAlarmHistories(alarmHistories); + } +} diff --git a/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java new file mode 100644 index 00000000..fbfe00a0 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java @@ -0,0 +1,23 @@ +package com.moing.backend.domain.history.application.service; + +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.domain.entity.AlarmHistory; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.service.AlarmHistorySaveService; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class SaveSingleAlarmHistoryUseCase { + + private final AlarmHistoryMapper alarmHistoryMapper; + private final AlarmHistorySaveService alarmHistorySaveService; + + @Async + public void saveAlarmHistory(String fcmToken, Long memberId, String idInfo, String title, String body, String name, AlarmType alarmType, String path) { + AlarmHistory alarmHistory = alarmHistoryMapper.toAlarmHistory(alarmType, path, idInfo, memberId, title, body, name); + alarmHistorySaveService.saveAlarmHistory(alarmHistory); + } +} diff --git a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java index 08481283..6261c4e0 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java +++ b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java @@ -22,6 +22,6 @@ public List getAlarmHistories(Long memberId){ } public AlarmHistory getAlarmHistory(Long alarmHistoryId, Long memberId){ - return alarmHistoryRepository.findAlarmHistoryByIdAndReceiverId(alarmHistoryId, alarmHistoryId).orElseThrow(NotFoundAlarmHistoryException::new); + return alarmHistoryRepository.findAlarmHistoryByIdAndReceiverId(alarmHistoryId, memberId).orElseThrow(NotFoundAlarmHistoryException::new); } } diff --git a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistorySaveService.java b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistorySaveService.java index 4efef5d0..e758efff 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistorySaveService.java +++ b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistorySaveService.java @@ -15,8 +15,12 @@ public class AlarmHistorySaveService { private final AlarmHistoryRepository alarmHistoryRepository; - public void saveAlarmHistory(List alarmHistories){ + public void saveAlarmHistories(List alarmHistories){ alarmHistoryRepository.saveAll(alarmHistories); } + public void saveAlarmHistory(AlarmHistory alarmHistory){ + alarmHistoryRepository.save(alarmHistory); + } + } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 57d5b21c..67e56840 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -10,6 +10,7 @@ import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -21,6 +22,7 @@ @Slf4j @Service @Transactional +@EnableAsync @EnableScheduling // 스케줄링 활성화 @RequiredArgsConstructor public class MissionStateScheduleUseCase { From 039e93e4dc9bb1a5bd10a0a8b7d458de5b2d0d1f Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 7 Dec 2023 07:09:22 +0900 Subject: [PATCH 332/619] =?UTF-8?q?fix:=20import=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionCreateUseCase.java | 6 ------ .../mission/application/service/MissionReadUseCase.java | 4 ---- .../mission/application/service/MissionUpdateUseCase.java | 2 -- .../domain/mission/presentation/MissionController.java | 2 -- 4 files changed, 14 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index 5de9b428..41b71a33 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -1,7 +1,6 @@ package com.moing.backend.domain.mission.application.service; import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.repository.MemberRepository; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.application.dto.req.MissionReq; import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; @@ -15,12 +14,7 @@ import com.moing.backend.domain.mission.exception.NoAccessCreateMission; import com.moing.backend.domain.mission.exception.NoMoreCreateMission; import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.repository.TeamRepository; import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.global.config.fcm.dto.request.MultiRequest; -import com.moing.backend.global.config.fcm.dto.request.SingleRequest; -import com.moing.backend.global.config.fcm.service.FcmService; -import com.moing.backend.global.util.SecurityUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java index 6ed68694..3379903a 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java @@ -2,14 +2,10 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; -import com.moing.backend.domain.mission.application.mapper.MissionMapper; -import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.global.util.SecurityUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index 0e41b413..57cc5204 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -8,11 +8,9 @@ import com.moing.backend.domain.mission.application.mapper.MissionMapper; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.mission.domain.service.MissionSaveService; import com.moing.backend.domain.mission.exception.NoAccessCreateMission; -import com.moing.backend.global.util.SecurityUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 531e7ef5..b3d89e57 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -7,8 +7,6 @@ import com.moing.backend.domain.mission.application.service.MissionDeleteUseCase; import com.moing.backend.domain.mission.application.service.MissionReadUseCase; import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; -import com.moing.backend.domain.mission.domain.service.MissionDeleteService; -import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; From 3f737c83ac18c51337e079c5f38323d03a515ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 8 Dec 2023 14:45:39 +0900 Subject: [PATCH 333/619] =?UTF-8?q?feat=20:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=EC=9E=A5=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionCreateUseCase.java | 9 +++++++++ .../domain/mission/presentation/MissionController.java | 10 +++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index 5de9b428..665e60ba 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -74,4 +74,13 @@ public MissionRecommendRes getCategoryByTeam(Long teamId) { .build(); } + + public Boolean getIsLeader(String socialId, Long teamId) { + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + + return member.getMemberId().equals(team.getLeaderId()); + + } + } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 531e7ef5..fa0896e5 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -94,8 +94,16 @@ public ResponseEntity> deleteMission(@AuthenticationPrinci public ResponseEntity> recommendMission(@AuthenticationPrincipal User user,@PathVariable Long teamId) { return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getTeamCategory(teamId))); } + /** + * 미션 추천 + * [GET] {teamId}/missions/isLeader + * 작성자 : 정승연 + */ - + @GetMapping("/isLeader") + public ResponseEntity> isLeader(@AuthenticationPrincipal User user,@PathVariable Long teamId) { + return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionCreateUseCase.getIsLeader(user.getSocialId(),teamId))); + } From ee025b9a84540f7827b7910e748a06999a33303c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 8 Dec 2023 14:45:51 +0900 Subject: [PATCH 334/619] =?UTF-8?q?fix=20:=20=EC=B5=9C=EB=8C=80=20?= =?UTF-8?q?=EA=B8=80=EC=9E=90=EC=88=98=20=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionArchive/application/dto/req/MissionArchiveReq.java | 2 +- .../domain/missionArchive/domain/entity/MissionArchive.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java index 6bc71af4..a973aa29 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java @@ -10,7 +10,7 @@ public class MissionArchiveReq { private String status; - @Size(min = 1, max = 4000) + @Size(min = 1, max = 1000) private String archive; //사진일 경우 파일명, 이외에는 text,link @Builder diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index 670adbec..493c1448 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -39,7 +39,7 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 @Enumerated(value = EnumType.STRING) private MissionArchiveStatus status; - @Column(nullable = false, length = 4000) + @Column(nullable = false, columnDefinition="TEXT", length = 4000) private String archive; //링크, 글, 사진 뭐든 가능 private Long count; // 횟수 From 75fc19675a1bbf33142d22c92fe956e1fbd09185 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 8 Dec 2023 22:18:36 +0900 Subject: [PATCH 335/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=EC=9E=A5=20=EA=B6=8C=ED=95=9C=20=ED=95=A8=EC=88=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/application/service/CheckLeaderUseCase.java | 8 ++++++++ .../team/application/service/DisbandTeamUseCase.java | 9 ++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUseCase.java index f703245f..d3ae2ba7 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CheckLeaderUseCase.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.exception.NotAuthByTeamException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,4 +16,11 @@ public class CheckLeaderUseCase { public boolean isTeamLeader(Member member, Team team) { return Objects.equals(member.getMemberId(), team.getLeaderId()); } + + public void validateTeamLeader(Member member, Team team) { + if (!isTeamLeader(member, team)) { + throw new NotAuthByTeamException(); + } + } + } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java index 4abde79f..bcb9f4bf 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java @@ -5,7 +5,6 @@ import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.team.exception.NotAuthByTeamException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -23,12 +22,8 @@ public class DisbandTeamUseCase { public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); - - if (checkLeaderUseCase.isTeamLeader(member, team)) { - team.deleteTeam(); - } else { - throw new NotAuthByTeamException(); - } + checkLeaderUseCase.validateTeamLeader(member, team); + team.deleteTeam(); return new DeleteTeamResponse(teamId); } } From e2043fbff434901a843c3a477f07575695c83843 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 8 Dec 2023 22:18:51 +0900 Subject: [PATCH 336/619] =?UTF-8?q?refactor:=20=EC=96=B4=EB=85=B8=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moing/backend/global/utils/AesUtil.java | 4 +-- .../backend/global/utils/StartupRunner.java | 5 ++-- .../backend/global/utils/UpdateUtils.java | 26 +++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/moing/backend/global/utils/UpdateUtils.java diff --git a/src/main/java/com/moing/backend/global/utils/AesUtil.java b/src/main/java/com/moing/backend/global/utils/AesUtil.java index b66586d6..c9423f40 100644 --- a/src/main/java/com/moing/backend/global/utils/AesUtil.java +++ b/src/main/java/com/moing/backend/global/utils/AesUtil.java @@ -1,7 +1,7 @@ package com.moing.backend.global.utils; +import com.moing.backend.global.annotation.Util; import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; @@ -9,7 +9,7 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; -@Component +@Util public class AesUtil { private final String key; private final String alg; diff --git a/src/main/java/com/moing/backend/global/utils/StartupRunner.java b/src/main/java/com/moing/backend/global/utils/StartupRunner.java index 52205ec2..2927490f 100644 --- a/src/main/java/com/moing/backend/global/utils/StartupRunner.java +++ b/src/main/java/com/moing/backend/global/utils/StartupRunner.java @@ -6,13 +6,14 @@ import com.moing.backend.domain.member.domain.constant.SocialProvider; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberSaveService; +import com.moing.backend.global.annotation.Util; import lombok.RequiredArgsConstructor; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import java.time.LocalDate; -@Component +@Util @RequiredArgsConstructor public class StartupRunner implements CommandLineRunner { @@ -26,7 +27,7 @@ public void run(String... args) throws Exception { Member test01 = new Member(LocalDate.now(), "tester1@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester1", "undef", SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester01"); memberSaveService.saveMember(test01); - Member test02=new Member(LocalDate.now(), "tester2@test.com", "undef", Gender.MAN, "undef", "modagbul_tester2", "undef", SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester02"); + Member test02=new Member(LocalDate.now(), "tester2@test.com", "undef", Gender.MAN, null, "modagbul_tester2", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester02"); memberSaveService.saveMember(test02); Member test03=new Member(LocalDate.now(), "tester3@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester3", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester03"); diff --git a/src/main/java/com/moing/backend/global/utils/UpdateUtils.java b/src/main/java/com/moing/backend/global/utils/UpdateUtils.java new file mode 100644 index 00000000..52ead37b --- /dev/null +++ b/src/main/java/com/moing/backend/global/utils/UpdateUtils.java @@ -0,0 +1,26 @@ +package com.moing.backend.global.utils; + +import com.moing.backend.global.annotation.Util; +import com.moing.backend.global.config.s3.S3Service; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Util +@RequiredArgsConstructor +public class UpdateUtils { + + private final S3Service s3Service; + + public static T getUpdatedValue(T currentValue, T oldValue) { + if(currentValue!=null){ + return currentValue; + } + return oldValue; + } + + public void deleteOldImgUrl(String currentImageUrl, String oldImageUrl) { + if (currentImageUrl != null && oldImageUrl != null) { + s3Service.deleteImage(oldImageUrl); + } + } +} From 1095b42902094e8472d836a2670d0ee4a0c71355 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 8 Dec 2023 22:20:33 +0900 Subject: [PATCH 337/619] =?UTF-8?q?refactor:=20=EC=88=98=EC=A0=95=ED=95=A0?= =?UTF-8?q?=20=EB=95=8C=20request=20null=20=ED=97=88=EC=9A=A9=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/ProfileUseCase.java | 22 +++++--------- .../dto/request/UpdateTeamRequest.java | 6 +--- .../service/UpdateTeamUseCase.java | 29 +++++++++++-------- 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java index e2371ca4..6b6ce06f 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java @@ -4,7 +4,7 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mypage.application.dto.request.UpdateProfileRequest; import com.moing.backend.domain.mypage.application.dto.response.GetProfileResponse; -import com.moing.backend.global.config.s3.S3Service; +import com.moing.backend.global.utils.UpdateUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,7 +15,7 @@ public class ProfileUseCase { private final MemberGetService memberGetService; - private final S3Service s3Service; + private final UpdateUtils updateUtils; public GetProfileResponse getProfile(String socialId){ Member member=memberGetService.getMemberBySocialId(socialId); @@ -25,21 +25,15 @@ public GetProfileResponse getProfile(String socialId){ @Transactional public void updateProfile(String socialId, UpdateProfileRequest updateProfileRequest) { Member member = memberGetService.getMemberBySocialId(socialId); - if (updateProfileRequest.getProfileImage() != null && member.getProfileImage() != null) { - s3Service.deleteImage(member.getProfileImage()); - } + String oldProfileImageUrl = member.getProfileImage(); + member.updateProfile( - getUpdatedValue(updateProfileRequest.getProfileImage(), member.getProfileImage()), - getUpdatedValue(updateProfileRequest.getNickName(), member.getNickName()), - getUpdatedValue(updateProfileRequest.getIntroduction(), member.getIntroduction()) + UpdateUtils.getUpdatedValue(updateProfileRequest.getProfileImage(), member.getProfileImage()), + UpdateUtils.getUpdatedValue(updateProfileRequest.getNickName(), member.getNickName()), + UpdateUtils.getUpdatedValue(updateProfileRequest.getIntroduction(), member.getIntroduction()) ); - } - private String getUpdatedValue(String newValue, String currentValue) { - if (newValue != null) { - return newValue; - } - return currentValue; + updateUtils.deleteOldImgUrl(updateProfileRequest.getProfileImage(), oldProfileImageUrl); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/request/UpdateTeamRequest.java b/src/main/java/com/moing/backend/domain/team/application/dto/request/UpdateTeamRequest.java index 81f5f3ce..d5863c72 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/request/UpdateTeamRequest.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/request/UpdateTeamRequest.java @@ -13,14 +13,10 @@ @NoArgsConstructor @Getter public class UpdateTeamRequest { - @NotBlank(message = "name 을 입력해 주세요.") - @Size(min = 1, max = 10, message = "name 은 최소 1개, 최대 10개의 문자만 입력 가능합니다.") + private String name; - @NotBlank(message = "introduction 을 입력해 주세요.") - @Size(min = 1, max = 300, message = "introduction 은 최소 1개, 최대 300개의 문자만 입력 가능합니다.") private String introduction; - @NotBlank(message = "profileImgUrl 을 입력해 주세요.") private String profileImgUrl; } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java index 91976f63..8975d06f 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java @@ -6,32 +6,37 @@ import com.moing.backend.domain.team.application.dto.response.UpdateTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.team.exception.NotAuthByTeamException; -import com.moing.backend.global.config.s3.S3Service; +import com.moing.backend.global.utils.UpdateUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import javax.transaction.Transactional; @Service -@Transactional @RequiredArgsConstructor public class UpdateTeamUseCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; private final CheckLeaderUseCase checkLeaderUseCase; - private final S3Service s3Service; + private final UpdateUtils updateUtils; - public UpdateTeamResponse updateTeam(UpdateTeamRequest updateTeamRequest, String socialId, Long teamId){ + @Transactional + public UpdateTeamResponse updateTeam(UpdateTeamRequest updateTeamRequest, String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); - Team team=teamGetService.getTeamByTeamId(teamId); - if (checkLeaderUseCase.isTeamLeader(member, team)) { - s3Service.deleteImage(team.getProfileImgUrl()); - team.updateTeam(updateTeamRequest.getName(), updateTeamRequest.getIntroduction(), updateTeamRequest.getProfileImgUrl()); - } else { - throw new NotAuthByTeamException(); - } + Team team = teamGetService.getTeamByTeamId(teamId); + + checkLeaderUseCase.validateTeamLeader(member, team); + + String oldProfileImgUrl = team.getProfileImgUrl(); + team.updateTeam( + UpdateUtils.getUpdatedValue(updateTeamRequest.getName(), team.getName()), + UpdateUtils.getUpdatedValue(updateTeamRequest.getIntroduction(), team.getIntroduction()), + UpdateUtils.getUpdatedValue(updateTeamRequest.getProfileImgUrl(), team.getProfileImgUrl()) + ); + + updateUtils.deleteOldImgUrl(updateTeamRequest.getProfileImgUrl(), oldProfileImgUrl); + return new UpdateTeamResponse(team.getTeamId()); } } From 7f9b69a57e886c0f603d3678ff6e16de052a70ea Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 9 Dec 2023 01:10:37 +0900 Subject: [PATCH 338/619] =?UTF-8?q?fix:=20refresh=20token=20=EB=A7=8C?= =?UTF-8?q?=EB=A3=8C=EB=90=98=EC=97=88=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20500?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=20=EB=9C=A8=EB=8A=94=20=EB=AC=B8=EC=A0=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ReissueTokenUseCase.java | 2 +- .../backend/global/config/s3/S3Service.java | 2 +- .../security/jwt/NotFoundRefreshToken.java | 2 +- .../global/config/security/jwt/TokenUtil.java | 43 +++++++------------ 4 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUseCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUseCase.java index b4517a44..88714bab 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUseCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/ReissueTokenUseCase.java @@ -18,7 +18,7 @@ public class ReissueTokenUseCase { public ReissueTokenResponse reissueToken(String token) { // refresh 토큰이 유효한지 확인 - if (token != null && tokenUtil.verifyToken(token)) { + if (token != null && tokenUtil.verifyRefreshToken(token)) { // 토큰 새로 받아오기 TokenInfoResponse newToken = tokenUtil.tokenReissue(token); diff --git a/src/main/java/com/moing/backend/global/config/s3/S3Service.java b/src/main/java/com/moing/backend/global/config/s3/S3Service.java index 5f39dfdc..9e55e7c1 100644 --- a/src/main/java/com/moing/backend/global/config/s3/S3Service.java +++ b/src/main/java/com/moing/backend/global/config/s3/S3Service.java @@ -47,7 +47,7 @@ public void deleteImage(String fileUrl) { } } - private String createFileName(String fileExtension) { + private String createFileName(String fileExtension) { return UUID.randomUUID() + "." + fileExtension; } diff --git a/src/main/java/com/moing/backend/global/config/security/jwt/NotFoundRefreshToken.java b/src/main/java/com/moing/backend/global/config/security/jwt/NotFoundRefreshToken.java index 96a2402f..4c64a82c 100644 --- a/src/main/java/com/moing/backend/global/config/security/jwt/NotFoundRefreshToken.java +++ b/src/main/java/com/moing/backend/global/config/security/jwt/NotFoundRefreshToken.java @@ -7,7 +7,7 @@ public class NotFoundRefreshToken extends ApplicationException { public NotFoundRefreshToken() { super(ErrorCode.NOT_FOUND_REFRESH_TOKEN_ERROR, - HttpStatus.NOT_FOUND); + HttpStatus.UNAUTHORIZED); } } diff --git a/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java b/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java index bd691806..6b524846 100644 --- a/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java +++ b/src/main/java/com/moing/backend/global/config/security/jwt/TokenUtil.java @@ -7,6 +7,7 @@ import io.jsonwebtoken.*; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; +import io.jsonwebtoken.security.SecurityException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.InitializingBean; @@ -34,9 +35,6 @@ public class TokenUtil implements InitializingBean { @Value("${jwt.refresh-token-period}") private long refreshTokenValidityTime; - @Value("${jwt.reissue-token-period}") - private Long reissueTokenValidityTime; - private Key key; @Override @@ -99,48 +97,40 @@ public boolean verifyToken(String token) { } } + public boolean verifyRefreshToken(String token) { + try { + Jws claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); + return true; + } catch (Exception e) { + return false; + } + } + //refresh token 관련 public void storeRefreshToken(String socialId, TokenInfoResponse token) { redisUtil.save(token.getRefreshToken(), socialId); } public TokenInfoResponse tokenReissue(String token) { + String socialId = getSocialId(token); Member member = memberQueryService.getMemberBySocialId(socialId); - - // socialId 에 해당하는 refreshToken redis 에서 가져오기 String storedRefreshToken = redisUtil.findById(socialId).orElseThrow(NotFoundRefreshToken::new); - //가져온 refeshToken이랑 입력한 refeshToken이랑 비교 - if(storedRefreshToken == null || !storedRefreshToken.equals(token)) throw new NotFoundRefreshToken(); + if(storedRefreshToken == null || !storedRefreshToken.equals(token)) { + throw new NotFoundRefreshToken(); + } // Token 생성 TokenInfoResponse newToken = createToken(member, true); - // refreshToken 기간이 얼마남지 않았을 경우 (3일 미만) - if (isExpired(token)) { - log.info("Refresh token reissue"); - storeRefreshToken(socialId, newToken); - } - - // refreshToken 의 유효기간이 3일 이상 남았을 경우 (refreshToken 그대로 넣어서 응답) - else newToken.updateRefreshToken(token); + // Token 저장 + storeRefreshToken(socialId, newToken); return newToken; } - private boolean isExpired(String token) { - Date expireDate = getExpiration(token); - Date currentDate = new Date(); - - if (expireDate.getTime() - currentDate.getTime() < reissueTokenValidityTime) - return true; - else - return false; - } - - //토큰 만료시키기 public void expireRefreshToken(String socialId) { redisUtil.deleteById(socialId); @@ -167,6 +157,5 @@ public String getSocialId(String token) { return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); } - } From ad539ab3aea82a10cebfffb80e369706363ff9e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 9 Dec 2023 14:38:08 +0900 Subject: [PATCH 339/619] =?UTF-8?q?fix=20:=20=EC=99=84=EB=A3=8C=ED=95=9C?= =?UTF-8?q?=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0=EC=97=90=20=EC=95=88?= =?UTF-8?q?=EB=9C=A8=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionCustomRepositoryImpl.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index e35e1b7d..b2183bbf 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -6,10 +6,12 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; import com.moing.backend.domain.missionState.domain.entity.QMissionState; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -44,6 +46,8 @@ public Long findMissionsCountByTeam(Long teamId) { @Override public Optional> findRepeatMissionByMemberId(Long memberId,Listteams) { + QMissionArchive subMissionArchive = new QMissionArchive("subMissionArchive"); + return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherRepeatMissionRes.class, mission.id, @@ -58,15 +62,17 @@ public Optional> findRepeatMissionByMemberId(Long m .leftJoin(missionArchive) .on(missionArchive.mission.eq(mission), missionArchive.member.memberId.eq(memberId) -// ,missionArchive.count.max().loe(missionArchive.mission.number) ) .where( mission.team.teamId.in(teams), mission.status.eq(MissionStatus.ONGOING), mission.type.eq(MissionType.REPEAT) + ) - .groupBy(mission.id) - .orderBy(missionArchive.count().desc()) + .groupBy(mission.id,mission.number) +// .having(missionArchive.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 + + .orderBy(missionArchive.count().desc()) .fetch()); } From 82503e9b4317e01a85a2c97c706a698afb62825b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 9 Dec 2023 14:39:37 +0900 Subject: [PATCH 340/619] =?UTF-8?q?fix=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20subquery=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index b2183bbf..d19c1a12 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -46,8 +46,6 @@ public Long findMissionsCountByTeam(Long teamId) { @Override public Optional> findRepeatMissionByMemberId(Long memberId,Listteams) { - QMissionArchive subMissionArchive = new QMissionArchive("subMissionArchive"); - return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherRepeatMissionRes.class, mission.id, From be0adba52129be2fa1eb276c930014b03ecba4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 9 Dec 2023 14:43:18 +0900 Subject: [PATCH 341/619] =?UTF-8?q?fix=20:=20MissionArchiveCustomRepositor?= =?UTF-8?q?yImplTest=20=EC=A3=BC=EC=84=9D=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...issionArchiveCustomRepositoryImplTest.java | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java index dc94f7fc..37889c66 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java @@ -1,29 +1,29 @@ -package com.moing.backend.domain.missionArchive.domain.repository; - -import com.querydsl.jpa.impl.JPAQueryFactory; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import javax.persistence.EntityManager; -import java.util.List; -import java.util.Optional; - -import static com.moing.backend.domain.mission.domain.entity.QMission.mission; -import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; -@SpringBootTest -class MissionArchiveCustomRepositoryImplTest { - - @Autowired - EntityManager em; - - @Autowired - private MissionArchiveRepository missionArchiveRepository; - - @Test - void findPeopleRemainMission() { - - System.out.println("!!!"+ missionArchiveRepository.findPeopleRemainMission()); - - } -} \ No newline at end of file +//package com.moing.backend.domain.missionArchive.domain.repository; +// +//import com.querydsl.jpa.impl.JPAQueryFactory; +//import org.junit.jupiter.api.Test; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.context.SpringBootTest; +// +//import javax.persistence.EntityManager; +//import java.util.List; +//import java.util.Optional; +// +//import static com.moing.backend.domain.mission.domain.entity.QMission.mission; +//import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; +//@SpringBootTest +//class MissionArchiveCustomRepositoryImplTest { +// +// @Autowired +// EntityManager em; +// +// @Autowired +// private MissionArchiveRepository missionArchiveRepository; +// +// @Test +// void findPeopleRemainMission() { +// +// System.out.println("!!!"+ missionArchiveRepository.findPeopleRemainMission()); +// +// } +//} \ No newline at end of file From 786fa8bbcd55c8f66d8e4dd2c41c22f58ee0dc47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 9 Dec 2023 14:56:17 +0900 Subject: [PATCH 342/619] =?UTF-8?q?fix=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=95=84=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionArchive/application/dto/res/MissionArchiveRes.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index 31c9b26f..d562fcfd 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -19,8 +19,5 @@ public class MissionArchiveRes { private String heartStatus; private Long hearts; - private boolean isAbleToEdit; - - } From 80e28e5071b25f1433a0940d456d40532d58b3d3 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 9 Dec 2023 14:59:20 +0900 Subject: [PATCH 343/619] =?UTF-8?q?fix:=20ableToEdit=20response=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveControllerTest.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index bef311b4..0e6ea647 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -108,7 +108,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.status").description("미션 인증 상태"), fieldWithPath("data.count").description("미션 인증 횟수"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태") + fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태"), + fieldWithPath("data.ableToEdit").description("미션 편집 가능 여부") ) ) ) @@ -176,7 +177,9 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.status").description("미션 인증 상태"), fieldWithPath("data.count").description("미션 인증 횟수"), fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태"), - fieldWithPath("data.hearts").description("미션 인증 좋아요 수") + fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), + fieldWithPath("data.ableToEdit").description("미션 편집 가능 여부") + ) ) ) @@ -281,10 +284,10 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.archives[].status").description("미션 인증 상태"), fieldWithPath("data.archives[].count").description("미션 인증 횟수"), fieldWithPath("data.archives[].heartStatus").description("미션 인증 좋아요 상태"), - fieldWithPath("data.archives[].hearts").description("미션 인증 좋아요 수") + fieldWithPath("data.archives[].hearts").description("미션 인증 좋아요 수"), + fieldWithPath("data.archives[].ableToEdit").description("미션 편집 가능 여부") - - ) + ) ) ) .andReturn(); From 036b6b0178ced30f753f60806c13dab7103381de Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 9 Dec 2023 15:02:31 +0900 Subject: [PATCH 344/619] rollback --- .../MissionArchiveControllerTest.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 0e6ea647..bef311b4 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -108,8 +108,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.status").description("미션 인증 상태"), fieldWithPath("data.count").description("미션 인증 횟수"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태"), - fieldWithPath("data.ableToEdit").description("미션 편집 가능 여부") + fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태") ) ) ) @@ -177,9 +176,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.status").description("미션 인증 상태"), fieldWithPath("data.count").description("미션 인증 횟수"), fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태"), - fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data.ableToEdit").description("미션 편집 가능 여부") - + fieldWithPath("data.hearts").description("미션 인증 좋아요 수") ) ) ) @@ -284,10 +281,10 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.archives[].status").description("미션 인증 상태"), fieldWithPath("data.archives[].count").description("미션 인증 횟수"), fieldWithPath("data.archives[].heartStatus").description("미션 인증 좋아요 상태"), - fieldWithPath("data.archives[].hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data.archives[].ableToEdit").description("미션 편집 가능 여부") + fieldWithPath("data.archives[].hearts").description("미션 인증 좋아요 수") - ) + + ) ) ) .andReturn(); From 8f76a1e03a1b71cd0841bc1e5ea7f81cdad8cfdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 9 Dec 2023 15:36:45 +0900 Subject: [PATCH 345/619] =?UTF-8?q?fix=20:=20having=20=EC=A0=88=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=EC=B2=98=EB=A6=AC=20=EC=B7=A8=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index d19c1a12..aa6fe0be 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -68,7 +68,7 @@ public Optional> findRepeatMissionByMemberId(Long m ) .groupBy(mission.id,mission.number) -// .having(missionArchive.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 + .having(missionArchive.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 .orderBy(missionArchive.count().desc()) .fetch()); From 4c76f69efa79ef4f790e82b604984eecb5dc8264 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 9 Dec 2023 18:15:38 +0900 Subject: [PATCH 346/619] =?UTF-8?q?feat:=20=EC=95=88=20=EC=9D=BD=EC=9D=80?= =?UTF-8?q?=20=EC=95=8C=EB=A6=BC=20=EA=B0=9C=EC=88=98=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/GetAlarmHistoryUseCase.java | 8 ++++++++ .../repository/AlarmHistoryCustomRepository.java | 1 + .../AlarmHistoryCustomRepositoryImpl.java | 15 +++++++++++---- .../domain/repository/AlarmHistoryRepository.java | 1 + .../domain/service/AlarmHistoryGetService.java | 4 ++++ .../presentation/AlarmHistoryController.java | 8 +++++--- .../constant/AlarmHistoryResponseMessage.java | 3 ++- 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java index f509595f..bd1406b9 100644 --- a/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java +++ b/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java @@ -23,4 +23,12 @@ public List getAllAlarmHistories(String socialId) { Member member = memberGetService.getMemberBySocialId(socialId); return alarmHistoryGetService.getAlarmHistories(member.getMemberId()); } + + /** + * 안 읽은 알림 개수 조회 + */ + public String getUnreadAlarmCount(String socialId){ + Member member = memberGetService.getMemberBySocialId(socialId); + return alarmHistoryGetService.getUnreadAlarmCount(member.getMemberId()); + } } diff --git a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepository.java b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepository.java index 625ca22c..526a0e4b 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepository.java @@ -7,4 +7,5 @@ public interface AlarmHistoryCustomRepository { List findAlarmHistoriesByMemberId(Long memberId); + String findUnreadAlarmCount(Long memberId); } diff --git a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java index 38f36379..b7c816b4 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java @@ -2,16 +2,12 @@ import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; import com.moing.backend.domain.history.application.dto.response.QGetAlarmHistoryResponse; -import com.moing.backend.domain.team.domain.constant.ApprovalStatus; import com.querydsl.jpa.impl.JPAQueryFactory; -import com.querydsl.jpa.impl.JPAUpdateClause; import javax.persistence.EntityManager; -import java.time.LocalDateTime; import java.util.List; import static com.moing.backend.domain.history.domain.entity.QAlarmHistory.alarmHistory; -import static com.moing.backend.domain.team.domain.entity.QTeam.team; public class AlarmHistoryCustomRepositoryImpl implements AlarmHistoryCustomRepository { @@ -37,4 +33,15 @@ public List findAlarmHistoriesByMemberId(Long memberId) .orderBy(alarmHistory.createdDate.desc()) .fetch(); } + + @Override + public String findUnreadAlarmCount(Long memberId) { + Long count = queryFactory.select(alarmHistory.count()) + .from(alarmHistory) + .where(alarmHistory.receiverId.eq(memberId) + .and(alarmHistory.isRead.eq(false))) + .fetchOne(); + + return count != null ? (count > 99 ? "99+" : count.toString()) : "0"; + } } diff --git a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java index a076f7aa..f20e6bec 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java +++ b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java @@ -8,4 +8,5 @@ public interface AlarmHistoryRepository extends JpaRepository, AlarmHistoryCustomRepository { Optional findAlarmHistoryByIdAndReceiverId(Long id, Long receiverId); + } diff --git a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java index 6261c4e0..5f5ebae9 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java +++ b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryGetService.java @@ -24,4 +24,8 @@ public List getAlarmHistories(Long memberId){ public AlarmHistory getAlarmHistory(Long alarmHistoryId, Long memberId){ return alarmHistoryRepository.findAlarmHistoryByIdAndReceiverId(alarmHistoryId, memberId).orElseThrow(NotFoundAlarmHistoryException::new); } + + public String getUnreadAlarmCount(Long memberId){ + return alarmHistoryRepository.findUnreadAlarmCount(memberId); + } } diff --git a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java index 024eb9cb..548e9d58 100644 --- a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java +++ b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java @@ -12,8 +12,7 @@ import java.util.List; -import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.GET_ALL_ALARM_HISTORY; -import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.READ_ALARM_HISTORY; +import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.*; @RestController @@ -44,9 +43,12 @@ public ResponseEntity readAlarmHistory(@AuthenticationPrincipal return ResponseEntity.ok(SuccessResponse.create(READ_ALARM_HISTORY.getMessage())); } - //TODO /** * 안 읽은 알림 개수 조회 * [GET] api/history/alarm/count */ + @GetMapping("/count") + public ResponseEntity> getUnreadAlarmCount(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(GET_UNREAD_ALARM_HISTORY.getMessage(), getAlarmHistoryUseCase.getUnreadAlarmCount(user.getSocialId()))); + } } diff --git a/src/main/java/com/moing/backend/domain/history/presentation/constant/AlarmHistoryResponseMessage.java b/src/main/java/com/moing/backend/domain/history/presentation/constant/AlarmHistoryResponseMessage.java index ef6b52ab..8781c3a0 100644 --- a/src/main/java/com/moing/backend/domain/history/presentation/constant/AlarmHistoryResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/history/presentation/constant/AlarmHistoryResponseMessage.java @@ -7,6 +7,7 @@ @RequiredArgsConstructor public enum AlarmHistoryResponseMessage { GET_ALL_ALARM_HISTORY("알림 히스토리를 모두 조회했습니다."), - READ_ALARM_HISTORY("알림 히스토리 한 개를 조회했습니다."); + READ_ALARM_HISTORY("알림 히스토리 한 개를 조회했습니다."), + GET_UNREAD_ALARM_HISTORY("안읽은 알림 개수를 조회했습니다"); private final String message; } From 5d901ed66c3be4006dc1ae4a332710c6b5aebe97 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 9 Dec 2023 18:23:35 +0900 Subject: [PATCH 347/619] =?UTF-8?q?feat:=20=EC=95=88=20=EC=9D=BD=EC=9D=80?= =?UTF-8?q?=20=EC=95=8C=EB=A6=BC=20=EA=B0=9C=EC=88=98=20adoc=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/AlarmHistory-API.adoc | 4 ++ .../dto/response/GetAlarmCountResponse.java | 13 ++++++ .../service/GetAlarmHistoryUseCase.java | 5 ++- .../presentation/AlarmHistoryController.java | 3 +- .../AlarmHistoryControllerTest.java | 40 ++++++++++++++++++- 5 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmCountResponse.java diff --git a/src/docs/asciidoc/AlarmHistory-API.adoc b/src/docs/asciidoc/AlarmHistory-API.adoc index 0b380894..5c31a28d 100644 --- a/src/docs/asciidoc/AlarmHistory-API.adoc +++ b/src/docs/asciidoc/AlarmHistory-API.adoc @@ -29,3 +29,7 @@ operation::alarm-history-controller-test/get_all_alarm_history[snippets='http-re [[AlarmHistory-알림-단건-조회하기]] == AlarmHistory 알림 단건 조회하기 operation::alarm-history-controller-test/read_alarm_history[snippets='http-request,http-response,response-fields'] + +[[AlarmHistory-안읽은-알림개수-조회하기]] +== AlarmHistory 안읽은 알림 개수 조회하기 +operation::alarm-history-controller-test/get_alarm_count[snippets='http-request,http-response,response-fields'] diff --git a/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmCountResponse.java b/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmCountResponse.java new file mode 100644 index 00000000..a0976ba7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmCountResponse.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.history.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@Builder +public class GetAlarmCountResponse { + + private String count; +} diff --git a/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java index bd1406b9..cc4f911f 100644 --- a/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java +++ b/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.history.application.service; +import com.moing.backend.domain.history.application.dto.response.GetAlarmCountResponse; import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; import com.moing.backend.domain.history.domain.service.AlarmHistoryGetService; import com.moing.backend.domain.member.domain.entity.Member; @@ -27,8 +28,8 @@ public List getAllAlarmHistories(String socialId) { /** * 안 읽은 알림 개수 조회 */ - public String getUnreadAlarmCount(String socialId){ + public GetAlarmCountResponse getUnreadAlarmCount(String socialId) { Member member = memberGetService.getMemberBySocialId(socialId); - return alarmHistoryGetService.getUnreadAlarmCount(member.getMemberId()); + return new GetAlarmCountResponse(alarmHistoryGetService.getUnreadAlarmCount(member.getMemberId())); } } diff --git a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java index 548e9d58..ba847a61 100644 --- a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java +++ b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.history.presentation; +import com.moing.backend.domain.history.application.dto.response.GetAlarmCountResponse; import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; import com.moing.backend.domain.history.application.service.GetAlarmHistoryUseCase; import com.moing.backend.domain.history.application.service.ReadAlarmHistoryUseCase; @@ -48,7 +49,7 @@ public ResponseEntity readAlarmHistory(@AuthenticationPrincipal * [GET] api/history/alarm/count */ @GetMapping("/count") - public ResponseEntity> getUnreadAlarmCount(@AuthenticationPrincipal User user) { + public ResponseEntity> getUnreadAlarmCount(@AuthenticationPrincipal User user) { return ResponseEntity.ok(SuccessResponse.create(GET_UNREAD_ALARM_HISTORY.getMessage(), getAlarmHistoryUseCase.getUnreadAlarmCount(user.getSocialId()))); } } diff --git a/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java b/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java index e8d66569..4d69766d 100644 --- a/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java +++ b/src/test/java/com/moing/backend/domain/history/presentation/AlarmHistoryControllerTest.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.history.presentation; import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.history.application.dto.response.GetAlarmCountResponse; import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; import com.moing.backend.domain.history.application.service.GetAlarmHistoryUseCase; import com.moing.backend.domain.history.application.service.ReadAlarmHistoryUseCase; @@ -15,8 +16,7 @@ import java.util.List; -import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.GET_ALL_ALARM_HISTORY; -import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.READ_ALARM_HISTORY; +import static com.moing.backend.domain.history.presentation.constant.AlarmHistoryResponseMessage.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; @@ -116,4 +116,40 @@ public void read_alarm_history() throws Exception { } + @Test + public void get_alarm_count() throws Exception { + //given + GetAlarmCountResponse output = new GetAlarmCountResponse("99+"); + + given(getAlarmHistoryUseCase.getUnreadAlarmCount(any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform( + get("/api/history/alarm/count") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(GET_UNREAD_ALARM_HISTORY.getMessage()), + fieldWithPath("data.count").description("안 읽음 알림 개수 (99보다 크면 99+)") + + + ) + ) + ) + .andReturn(); + + } + } \ No newline at end of file From 1aadfbfdb2d6bad5ec11a17213640e617c619a7f Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 9 Dec 2023 20:33:33 +0900 Subject: [PATCH 348/619] =?UTF-8?q?fix:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/SaveSingleAlarmHistoryUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java index fbfe00a0..61030af7 100644 --- a/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java +++ b/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java @@ -16,7 +16,7 @@ public class SaveSingleAlarmHistoryUseCase { private final AlarmHistorySaveService alarmHistorySaveService; @Async - public void saveAlarmHistory(String fcmToken, Long memberId, String idInfo, String title, String body, String name, AlarmType alarmType, String path) { + public void saveAlarmHistory(Long memberId, String idInfo, String title, String body, String name, AlarmType alarmType, String path) { AlarmHistory alarmHistory = alarmHistoryMapper.toAlarmHistory(alarmType, path, idInfo, memberId, title, body, name); alarmHistorySaveService.saveAlarmHistory(alarmHistory); } From 7154942d2a20ef4e5942d6aa58174ec36a63a63f Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Dec 2023 11:58:57 +0900 Subject: [PATCH 349/619] =?UTF-8?q?feat:=20=EB=8C=93=EA=B8=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EC=8B=9C=EA=B0=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/BoardBlocks.java | 2 +- .../board/application/mapper/BoardMapper.java | 3 ++- .../repository/BoardCustomRepositoryImpl.java | 6 +++++ .../dto/response/CommentBlocks.java | 25 ++++++++++++++++++- .../BoardCommentCustomRepositoryImpl.java | 8 +++--- .../global/config/fcm/service/FcmService.java | 1 - 6 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java index 4c06d3c0..cb6d8f58 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java @@ -49,7 +49,7 @@ public void readBoard() { public void deleteMember() { if(Boolean.TRUE.equals(writerIsDeleted)) { this.writerNickName = "(알 수 없음)"; - this.writerProfileImage = "undef"; + this.writerProfileImage = null; } } } diff --git a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java index dbc36017..92552ec3 100644 --- a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java +++ b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java @@ -36,13 +36,14 @@ public Board toBoard(Member member, TeamMember teamMember, Team team, CreateBoar public GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter, boolean writerIsDeleted) { String nickName = writerIsDeleted ? "(알 수 없음)" : board.getWriterNickName(); + String writerProfileImage = writerIsDeleted ? null : board.getWriterProfileImage(); return GetBoardDetailResponse.builder() .boardId(board.getBoardId()) .title(board.getTitle()) .content(board.getContent()) .writerNickName(nickName) .writerIsLeader(board.isLeader()) - .writerProfileImage(board.getWriterProfileImage()) + .writerProfileImage(writerProfileImage) .createdDate(getFormattedDate(board.getCreatedDate())) .isWriter(isWriter) .isNotice(board.isNotice()) diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index 7dbf0074..1d58a06a 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.board.application.dto.response.BoardBlocks; import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -24,12 +25,16 @@ public BoardCustomRepositoryImpl(EntityManager em) { public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { // 전체 게시글 보기 List allBoards = queryFactory.selectFrom(board) + .distinct() + .leftJoin(board.teamMember, QTeamMember.teamMember).fetchJoin() // TeamMember를 함께 로드 .where(board.team.teamId.eq(teamId)) .orderBy(board.createdDate.desc()) .fetch(); // 읽은 게시글 보기 List readBoards = queryFactory.selectFrom(board) + .distinct() + .leftJoin(board.teamMember, QTeamMember.teamMember).fetchJoin() // TeamMember를 함께 로드 .join(boardRead).on(boardRead.board.eq(board)) .where(board.team.teamId.eq(teamId)) .where(boardRead.member.memberId.eq(memberId)) @@ -57,6 +62,7 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { if (isRead) { boardBlocks.readBoard(); } + return boardBlocks; }; diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java index beb1c057..d9f3fb83 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java @@ -5,6 +5,9 @@ import lombok.Builder; import lombok.Getter; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + @Getter @Builder @AllArgsConstructor @@ -24,10 +27,30 @@ public class CommentBlocks { private Boolean writerIsDeleted; + private String createdDate; + + @QueryProjection + public CommentBlocks(Long boardCommentId, String content, String writerNickName, Boolean writerIsLeader, String writerProfileImage, Boolean isWriter, Boolean writerIsDeleted, LocalDateTime createdDate) { + this.boardCommentId = boardCommentId; + this.writerNickName = writerNickName; + this.writerIsLeader = writerIsLeader; + this.writerProfileImage = writerProfileImage; + this.content = content; + this.isWriter = isWriter; + this.writerIsDeleted=writerIsDeleted; + this.createdDate = getFormattedDate(createdDate); + deleteMember(); + } + public void deleteMember() { if (Boolean.TRUE.equals(writerIsDeleted)) { this.writerNickName = "(알 수 없음)"; - this.writerProfileImage = "undef"; + this.writerProfileImage = null; } } + + public String getFormattedDate(LocalDateTime localDateTime) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"); + return localDateTime.format(formatter); + } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index 9b3ec7e4..603253b6 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.boardComment.application.dto.response.CommentBlocks; import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; +import com.moing.backend.domain.boardComment.application.dto.response.QCommentBlocks; import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.querydsl.core.types.ExpressionUtils; @@ -26,7 +27,7 @@ public BoardCommentCustomRepositoryImpl(EntityManager em) { @Override public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember teamMember) { List commentBlocks = queryFactory - .select(Projections.constructor(CommentBlocks.class, + .select(new QCommentBlocks( boardComment.boardCommentId, boardComment.content, boardComment.writerNickName, @@ -38,14 +39,13 @@ public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember team .where(QTeamMember.teamMember.eq(teamMember) .and(QTeamMember.teamMember.eq(boardComment.teamMember))) .exists(), "isWriter"), - boardComment.teamMember.isDeleted)) + boardComment.teamMember.isDeleted, + boardComment.createdDate)) .from(boardComment) .where(boardComment.board.boardId.eq(boardId)) .orderBy(boardComment.createdDate.asc()) .fetch(); - commentBlocks.forEach(CommentBlocks::deleteMember); - return new GetBoardCommentResponse(commentBlocks); } } diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java index 30276df5..fe5f10a9 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java +++ b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java @@ -24,7 +24,6 @@ public class FcmService { private final FirebaseMessaging firebaseMessaging; - @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { From 4768a202ce03aa270e07464d37a326742abc5546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 10 Dec 2023 12:02:50 +0900 Subject: [PATCH 350/619] =?UTF-8?q?fix=20:=20=EC=9D=B8=EC=A6=9D=EC=99=84?= =?UTF-8?q?=EB=A3=8C=ED=95=9C=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=B3=B4=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionCustomRepositoryImpl.java | 15 +++++++-------- .../domain/service/MissionQueryService.java | 1 + .../MissionArchiveCustomRepositoryImpl.java | 13 +++++++++---- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index aa6fe0be..0e5b28c9 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -53,24 +53,23 @@ public Optional> findRepeatMissionByMemberId(Long m mission.team.name, mission.title, mission.number.stringValue(), - missionArchive.count().stringValue() + missionState.count().stringValue() )) .from(mission) - .leftJoin(missionArchive) - .on(missionArchive.mission.eq(mission), - missionArchive.member.memberId.eq(memberId) + .leftJoin(missionState) + .on(missionState.mission.eq(mission), + missionState.member.memberId.eq(memberId) ) .where( mission.team.teamId.in(teams), - mission.status.eq(MissionStatus.ONGOING), + mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), mission.type.eq(MissionType.REPEAT) ) .groupBy(mission.id,mission.number) - .having(missionArchive.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 - - .orderBy(missionArchive.count().desc()) + .having(missionState.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 + .orderBy(missionState.count().desc()) .fetch()); } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 136f5c43..e2170124 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -39,6 +39,7 @@ public Long findMissionsCountByTeam(Long teamId) { public List findAllRepeatMission(Long memberId) { List teams = teamGetService.getTeamIdByMemberId(memberId); + System.out.println(teams); return missionRepository.findRepeatMissionByMemberId(memberId,teams).orElseThrow(NotFoundMissionException::new); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 4ac50f5d..d13ae3db 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -199,20 +199,25 @@ public Optional> findRepeatMissionArchivesByMemberId .select(Projections.constructor(RepeatMissionBoardRes.class, mission.id, mission.title, - missionArchive.count.max().coalesce(0L).as("done"), +// missionState.count().coalesce(0L).as("done"), + missionState.count(), mission.number, mission.way.stringValue(), mission.status.stringValue() )) .from(mission) - .leftJoin(mission.missionArchiveList,missionArchive) - .on( missionArchive.member.memberId.eq(memberId)) + .leftJoin(missionState) + .on(missionState.mission.eq(mission), + missionState.member.memberId.eq(memberId) + ) .where( mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT), mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)) ) - .groupBy(mission) + .groupBy(mission.id,mission.number) + .having(missionState.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 + .orderBy(missionState.count().desc()) .fetch()); } From 511d9dd2941343757f76c71c5468990d50431c21 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Dec 2023 12:18:56 +0900 Subject: [PATCH 351/619] =?UTF-8?q?feat:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EB=95=8C=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/GetMyPageTeamBlock.java | 1 + .../application/dto/response/TeamBlock.java | 5 +++-- .../repository/TeamCustomRepositoryImpl.java | 5 +++-- .../BoardCommentControllerTest.java | 16 +++++++++------- .../presentation/MypageControllerTest.java | 10 ++++++---- .../team/presentation/TeamControllerTest.java | 19 +++++++++++-------- 6 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java index a05783c9..fd6f6d19 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java @@ -11,4 +11,5 @@ public class GetMyPageTeamBlock { private Long teamId; private String teamName; private Category category; + private String profileImgUrl; } diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java index 7c2e1803..43c76e1c 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java @@ -7,7 +7,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; @@ -27,9 +26,10 @@ public class TeamBlock { private String category; private String startDate; private LocalDateTime deletionTime; + private String profileImgUrl; @QueryProjection - public TeamBlock(Long teamId, LocalDateTime approvalTime, Integer levelOfFire, String teamName, Integer numOfMember, Category category, LocalDateTime deletionTime){ + public TeamBlock(Long teamId, LocalDateTime approvalTime, Integer levelOfFire, String teamName, Integer numOfMember, Category category, LocalDateTime deletionTime, String profileImgUrl) { this.teamId=teamId; this.duration=calculateDuration(approvalTime); this.levelOfFire=levelOfFire; @@ -38,6 +38,7 @@ public TeamBlock(Long teamId, LocalDateTime approvalTime, Integer levelOfFire, S this.category=category.getMessage(); this.startDate=approvalTime.toLocalDate().format(DateTimeFormatter.ofPattern("yyyy.MM.dd")); this.deletionTime=deletionTime; + this.profileImgUrl = profileImgUrl; } public Long calculateDuration(LocalDateTime approvalTime) { diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index f5c764c8..41a03a07 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -71,7 +71,7 @@ public List findTeamIdByMemberId(Long memberId){ public List findMyPageTeamByMemberId(Long memberId) { return queryFactory .select(Projections.constructor(GetMyPageTeamBlock.class, - team.teamId, team.name, team.category)) + team.teamId, team.name, team.category, team.profileImgUrl)) .from(teamMember) .innerJoin(teamMember.team, team) .on(teamMember.member.memberId.eq(memberId)) @@ -91,7 +91,8 @@ private List getTeamBlock(Long memberId) { team.name, team.numOfMember, team.category, - team.deletionTime)) + team.deletionTime, + team.profileImgUrl)) .from(teamMember) .innerJoin(teamMember.team, team) .on(teamMember.member.memberId.eq(memberId)) diff --git a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java index 3175bc6f..637ef310 100644 --- a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java +++ b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java @@ -142,6 +142,7 @@ public void get_board_comment_all() throws Exception { .writerProfileImage("작성자 프로필 이미지") .writerIsDeleted(false) .isWriter(true) + .createdDate("2023/12/05 23:29") .build(); commentBlocks.add(commentBlock); @@ -174,13 +175,14 @@ public void get_board_comment_all() throws Exception { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("댓글 목록을 모두 조회했습니다."), - fieldWithPath("data.commentBlocks[0].boardCommentId").description("댓글 아이디"), - fieldWithPath("data.commentBlocks[0].content").description("댓글 내용"), - fieldWithPath("data.commentBlocks[0].writerIsLeader").description("작성자 소모임장 여부"), - fieldWithPath("data.commentBlocks[0].writerNickName").description("작성자 닉네임"), - fieldWithPath("data.commentBlocks[0].writerProfileImage").description("작성자 프로필 이미지"), - fieldWithPath("data.commentBlocks[0].writerIsDeleted").description("작성자 삭제 여부"), - fieldWithPath("data.commentBlocks[0].isWriter").description("댓글 작성자 여부") + fieldWithPath("data.commentBlocks[].boardCommentId").description("댓글 아이디"), + fieldWithPath("data.commentBlocks[].content").description("댓글 내용"), + fieldWithPath("data.commentBlocks[].writerIsLeader").description("작성자 소모임장 여부"), + fieldWithPath("data.commentBlocks[].writerNickName").description("작성자 닉네임"), + fieldWithPath("data.commentBlocks[].writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.commentBlocks[].writerIsDeleted").description("작성자 삭제 여부"), + fieldWithPath("data.commentBlocks[].isWriter").description("댓글 작성자 여부"), + fieldWithPath("data.commentBlocks[].createdDate").description("생성 시간") ) ) diff --git a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java index c2932b6a..125aa2ea 100644 --- a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java @@ -125,6 +125,7 @@ public void get_mypage() throws Exception{ .teamId(1L) .teamName("소모임이름") .category(Category.SPORTS) + .profileImgUrl("프로필 이미지 url") .build(); getMyPageTeamBlocks.add(blocks); @@ -160,10 +161,11 @@ public void get_mypage() throws Exception{ fieldWithPath("data.profileImage").description("프로필 이미지 URL"), fieldWithPath("data.nickName").description("닉네임"), fieldWithPath("data.introduction").description("한줄 소개"), - fieldWithPath("data.categories[0]").description("내 열정의 불 해시태그"), - fieldWithPath("data.getMyPageTeamBlocks[0].teamId").description("소모임 아이디"), - fieldWithPath("data.getMyPageTeamBlocks[0].teamName").description("소모임 이름"), - fieldWithPath("data.getMyPageTeamBlocks[0].category").description("소모임 카테고리") + fieldWithPath("data.categories[]").description("내 열정의 불 해시태그"), + fieldWithPath("data.getMyPageTeamBlocks[].teamId").description("소모임 아이디"), + fieldWithPath("data.getMyPageTeamBlocks[].teamName").description("소모임 이름"), + fieldWithPath("data.getMyPageTeamBlocks[].category").description("소모임 카테고리"), + fieldWithPath("data.getMyPageTeamBlocks[].profileImgUrl").description("소모임 프로필 이미지 URL") ) ) ); diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 7306ffe0..96b0cae6 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -112,6 +112,7 @@ public void get_team() throws Exception { .category("ETC") .startDate("2023.09.05") .deletionTime(LocalDateTime.now().withNano(0)) + .profileImgUrl("프로필 사진 url") .build(); TeamBlock teamBlock2=TeamBlock.builder() @@ -123,6 +124,7 @@ public void get_team() throws Exception { .category("SPORTS") .startDate("2023.09.01") .deletionTime(LocalDateTime.now().withNano(0)) + .profileImgUrl("프로필 사진 url") .build(); teamBlocks.add(teamBlock1); @@ -158,14 +160,15 @@ public void get_team() throws Exception { fieldWithPath("message").description("홈 화면에서 내 소모임을 모두 조회했습니다."), fieldWithPath("data.numOfTeam").description("소모임 개수(최대 3개)"), fieldWithPath("data.memberNickName").description("유저 닉네임"), - fieldWithPath("data.teamBlocks[0].teamId").description("소모임 아이디"), - fieldWithPath("data.teamBlocks[0].duration").description("소모임과 함께한 시간"), - fieldWithPath("data.teamBlocks[0].levelOfFire").description("불꽃 레벨"), - fieldWithPath("data.teamBlocks[0].teamName").description("소모임 이름"), - fieldWithPath("data.teamBlocks[0].numOfMember").description("소모임원 명 수"), - fieldWithPath("data.teamBlocks[0].category").description("소모임 카테고리"), - fieldWithPath("data.teamBlocks[0].startDate").description("소모임 시작일"), - fieldWithPath("data.teamBlocks[0].deletionTime").description("소모임 삭제 시간 (삭제 안했으면 null)") + fieldWithPath("data.teamBlocks[].teamId").description("소모임 아이디"), + fieldWithPath("data.teamBlocks[].duration").description("소모임과 함께한 시간"), + fieldWithPath("data.teamBlocks[].levelOfFire").description("불꽃 레벨"), + fieldWithPath("data.teamBlocks[].teamName").description("소모임 이름"), + fieldWithPath("data.teamBlocks[].numOfMember").description("소모임원 명 수"), + fieldWithPath("data.teamBlocks[].category").description("소모임 카테고리"), + fieldWithPath("data.teamBlocks[].startDate").description("소모임 시작일"), + fieldWithPath("data.teamBlocks[].deletionTime").description("소모임 삭제 시간 (삭제 안했으면 null)"), + fieldWithPath("data.teamBlocks[].profileImgUrl").description("프로필 사진 url") ) ) From 5ce05a0fddf6cd20cfbddd87cae32954abc05f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 10 Dec 2023 14:35:33 +0900 Subject: [PATCH 352/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EB=A7=88=EA=B0=90=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(=20missionState=20=EC=82=AD=EC=A0=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=82=AD=EC=A0=9C=20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionStateScheduleUseCase.java | 26 +------------------ .../MissionStateCustomRepositoryImpl.java | 13 +++++++++- .../service/TeamScoreLogicUseCase.java | 1 - .../teamScore/domain/entity/TeamScore.java | 3 ++- ...issionArchiveCustomRepositoryImplTest.java | 1 + 5 files changed, 16 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 09d728ab..5e5fe463 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -50,32 +50,9 @@ public void sundayRepeatMissionRoutine() { for (Long id : ongoingRepeatMissions) { teamScoreLogicUseCase.updateTeamScore(id); } - // 미션 state 에서 지우기 ( 이것도 대용량 ) - missionStateReset(ongoingRepeatMissions); - } - - public void missionStateReset(List missionIds) { - List missionStates = missionStateQueryService.findByMissionId(missionIds); - missionStateDeleteService.deleteMissionState(missionStates); } -// /** -// * 단일 미션 마감 -// * 미션 단위 마감 -// * 한시간 마다 실행 -// */ -// public void singleMissionEndRoutineByMission() { -// -// Mission mission = new Mission(); -// LocalDateTime now = LocalDateTime.now(); -// -// if (mission.getDueTo().isAfter(now)) { -// mission.updateStatus(MissionStatus.END); -// teamScoreLogicUseCase.updateTeamScore(mission.getId()); -// } -// } - /** * 단일 미션 마감 * 해당 시간 미션 마감 @@ -94,7 +71,6 @@ public void singleMissionEndRoutine() { } - /** * 미션 시작 * 월요일 아침 @@ -102,7 +78,7 @@ public void singleMissionEndRoutine() { @Scheduled(cron = "0 0 0 * * MON") public void RepeatMissionStart() { List startMission = missionQueryService.findMissionByStatus(MissionStatus.WAIT); - startMission.stream().forEach( + startMission.forEach( mission -> mission.updateStatus(MissionStatus.ONGOING) ); } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index a8aebddd..9e9c0c07 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -10,7 +10,10 @@ import javax.persistence.EntityManager; +import java.time.DayOfWeek; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.temporal.TemporalAdjusters; import java.util.List; import java.util.Optional; @@ -27,11 +30,19 @@ public MissionStateCustomRepositoryImpl(EntityManager entityManager) { @Override public int getCountsByMissionId(Long missionId) { + + LocalDate now = LocalDate.now(); + DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; // 한 주의 시작일을 월요일로 설정 + LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); + LocalDate endOfWeek = startOfWeek.plusDays(6); // 한 주의 마지막일을 일요일로 설정 + return queryFactory .select(missionState) .from(missionState) .where( - missionState.mission.id.eq(missionId)) + missionState.mission.id.eq(missionId), + missionState.createdDate.goe(startOfWeek.atStartOfDay()), + missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))) .fetch().size(); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index 5ffadc2b..02fa9c9a 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -46,7 +46,6 @@ public Long updateTeamScore(Long missionId) { teamScore.updateScore(getScoreByMission(mission)); teamScore.levelUp(); - team.updateLevelOfFire(); teamScoreSaveService.save(teamScore); teamSaveService.saveTeam(team); diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index efa1b47b..2b19759f 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -42,9 +42,10 @@ public void levelUp() { for (int i = 5; i > 0; i--) { if (steps[i-1] <= this.level && this.level <= steps[i]) { - if (20 + ((i-1) * 15) <= score) { + if ((20 + ((i-1) * 15)) <= score) { this.level+=1; this.score -= (20 + ((i-1) * 15)); + this.team.updateLevelOfFire(); return; } } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java index 37889c66..5b9db754 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java @@ -12,6 +12,7 @@ //import static com.moing.backend.domain.mission.domain.entity.QMission.mission; //import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; //@SpringBootTest +// //class MissionArchiveCustomRepositoryImplTest { // // @Autowired From 158420d64b8df88f23c2012cd122907584b518bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:34:23 +0900 Subject: [PATCH 353/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EB=A7=88=EA=B0=90=20=EB=A1=9C=EC=A7=81=20=20?= =?UTF-8?q?=EC=9C=84=ED=95=B4=20missionArchive=20->=20missionState?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveCustomRepositoryImpl.java | 113 +++++++++++++++--- .../service/MissionStateUseCase.java | 18 --- .../MissionStateCustomRepositoryImpl.java | 17 ++- 3 files changed, 107 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index d13ae3db..6c764172 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -15,6 +15,7 @@ import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -24,7 +25,10 @@ import javax.persistence.EntityManager; import javax.swing.text.html.Option; +import java.time.DayOfWeek; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -117,13 +121,20 @@ private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { @Override public Optional> findOneMyArchives(Long memberId,Long missionId,Long count) { + + BooleanExpression repeatTypeCondition = createRepeatTypeConditionByArchive(); + BooleanExpression baseCondition = missionArchive.mission.id.eq(missionId); + BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); + return Optional.ofNullable(queryFactory .select(missionArchive) .from(missionArchive) .where( - missionArchive.mission.id.eq(missionId), + finalCondition, missionArchive.member.memberId.eq(memberId), missionArchive.count.eq(count) + + ) .orderBy(missionArchive.createdDate.desc()) .fetch() @@ -134,11 +145,16 @@ public Optional> findOneMyArchives(Long memberId,Long missi @Override public Optional> findMyArchives(Long memberId,Long missionId) { + + BooleanExpression repeatTypeCondition = createRepeatTypeConditionByArchive(); + BooleanExpression baseCondition = missionArchive.mission.id.eq(missionId); + BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); + return Optional.ofNullable(queryFactory .select(missionArchive) .from(missionArchive) .where( - missionArchive.mission.id.eq(missionId), + finalCondition, missionArchive.member.memberId.eq(memberId) ) .orderBy(missionArchive.createdDate.desc()) @@ -151,11 +167,16 @@ public Optional> findMyArchives(Long memberId,Long missionI @Override public Optional> findOthersArchives(Long memberId, Long missionId) { + + BooleanExpression repeatTypeCondition = createRepeatTypeConditionByArchive(); + BooleanExpression baseCondition = missionArchive.mission.id.eq(missionId); + BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); + return Optional.ofNullable(queryFactory .select(missionArchive) .from(missionArchive) .where( - missionArchive.mission.id.eq(missionId), + finalCondition, missionArchive.member.memberId.ne(memberId), missionArchive.status.eq(MissionArchiveStatus.COMPLETE).or(missionArchive.status.eq(MissionArchiveStatus.SKIP)) ) @@ -167,13 +188,19 @@ public Optional> findOthersArchives(Long memberId, Long mis @Override public Optional findDonePeopleByMissionId(Long missionId) { + + BooleanExpression repeatTypeCondition = createRepeatTypeCondition(); + BooleanExpression baseCondition = missionState.mission.id.eq(missionId); + BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); + return Optional.of(queryFactory - .select(missionArchive) - .from(missionArchive) + .select(missionState) + .from(missionState) .where( - missionArchive.mission.id.eq(missionId) + finalCondition ) - .groupBy(missionArchive.member) + .groupBy(missionState.member,missionState.mission.number) + .having(missionState.count().goe(missionState.mission.number)) .fetchCount() ); @@ -181,12 +208,18 @@ public Optional findDonePeopleByMissionId(Long missionId) { @Override public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) { + + + BooleanExpression repeatTypeCondition = createRepeatTypeCondition(); + BooleanExpression baseCondition = missionState.mission.id.eq(missionId); + BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); + return Optional.ofNullable(queryFactory - .select(missionArchive.count()) - .from(missionArchive) + .select(missionState.count()) + .from(missionState) .where( - missionArchive.mission.id.eq(missionId), - missionArchive.member.memberId.eq(memberId) + finalCondition, + missionState.member.memberId.eq(memberId) ) .fetchFirst() ); @@ -195,6 +228,11 @@ public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) @Override public Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status) { + + + BooleanExpression repeatTypeCondition = createRepeatTypeCondition(); + + return Optional.ofNullable(queryFactory .select(Projections.constructor(RepeatMissionBoardRes.class, mission.id, @@ -213,10 +251,12 @@ public Optional> findRepeatMissionArchivesByMemberId .where( mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT), - mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)) + mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), + repeatTypeCondition + ) .groupBy(mission.id,mission.number) - .having(missionState.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 +// .having(missionState.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 .orderBy(missionState.count().desc()) .fetch()); @@ -230,19 +270,22 @@ public Optional> findFinishMissionsByStatus(Long mem Expression type = Expressions.stringTemplate(String.valueOf(mission.type)); + BooleanExpression repeatTypeCondition = createRepeatTypeCondition(); + return Optional.ofNullable(queryFactory .selectDistinct(Projections.constructor(FinishMissionBoardRes.class, mission.id, mission.dueTo.stringValue(), mission.title, - missionArchive.status.stringValue().coalesce("FAIL").as("status"), + missionState.status.stringValue().coalesce("FAIL").as("status"), mission.type.stringValue(), mission.way.stringValue() )) .from(mission) .leftJoin(mission.missionArchiveList,missionArchive) - .on(missionArchive.member.memberId.eq(memberId)) + .on(missionState.member.memberId.eq(memberId)) .where( + repeatTypeCondition, mission.team.teamId.eq(teamId), mission.status.eq(MissionStatus.SUCCESS).or(mission.status.eq(MissionStatus.END)) ) @@ -293,11 +336,11 @@ public Boolean findMyArchivesToday(Long memberId, Long missionId) { LocalDateTime endOfToday = today.withHour(23).withMinute(59).withSecond(59).withNano(999999999); long count = queryFactory - .selectFrom(missionArchive) + .selectFrom(missionState) .where( - missionArchive.member.memberId.eq(memberId), - missionArchive.mission.id.eq(missionId), - missionArchive.lastModifiedDate.between(startOfToday, endOfToday) // createdDate와 오늘의 시작과 끝을 비교 + missionState.member.memberId.eq(memberId), + missionState.mission.id.eq(missionId), + missionState.lastModifiedDate.between(startOfToday, endOfToday) // createdDate와 오늘의 시작과 끝을 비교 ) .fetchCount(); @@ -325,6 +368,38 @@ public Optional> findPeopleRemainMission() { // ).fetch()); } + // 날짜 조건 생성 메서드 + private BooleanExpression createRepeatTypeCondition() { + LocalDate now = LocalDate.now(); + DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; + LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); + LocalDate endOfWeek = startOfWeek.plusDays(6); + + // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 + BooleanExpression isRepeatType = missionState.mission.type.eq(MissionType.REPEAT); + BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) + .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + + // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 + return isRepeatType.and(dateInRange); + } + + // 날짜 조건 생성 메서드 + private BooleanExpression createRepeatTypeConditionByArchive() { + LocalDate now = LocalDate.now(); + DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; + LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); + LocalDate endOfWeek = startOfWeek.plusDays(6); + + // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 + BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); + BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) + .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + + // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 + return isRepeatType.and(dateInRange); + } + } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 43e90c1e..55c0ddfc 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -79,25 +79,7 @@ public void updateMissionState(Member member, Mission mission, MissionArchive mi teamScoreLogicUseCase.updateTeamScore(mission.getId()); } - - } - - public void deleteMissionState(Member member, Mission mission, MissionArchive missionArchive) { - - MissionState missionState = missionStateQueryService.findMissionState(member, mission); - missionStateDeleteService.deleteMissionState(missionState); - } - public void missionStateReset(List missionIds) { - List missionStates = missionStateQueryService.findByMissionId(missionIds); - missionStateDeleteService.deleteMissionState(missionStates); - } - - public void deleteAllMissionState(Long missionId) { - missionStateDeleteService.deleteMissionStateByMission(missionId); - } - - } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index 9e9c0c07..10b9e4b4 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -3,8 +3,10 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionState.domain.entity.MissionState; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -36,13 +38,20 @@ public int getCountsByMissionId(Long missionId) { LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); LocalDate endOfWeek = startOfWeek.plusDays(6); // 한 주의 마지막일을 일요일로 설정 + BooleanExpression repeatTypeCondition = missionState.mission.type.eq(MissionType.REPEAT) + .and(missionState.createdDate.goe(startOfWeek.atStartOfDay())) + .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + + // 기본 조건 + BooleanExpression baseCondition = missionState.mission.id.eq(missionId); + // 조건 적용 + BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); + + return queryFactory .select(missionState) .from(missionState) - .where( - missionState.mission.id.eq(missionId), - missionState.createdDate.goe(startOfWeek.atStartOfDay()), - missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))) + .where(finalCondition) .fetch().size(); } From 568b4900b7ae65f74cd923d81e84ac2e79f56674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:43:43 +0900 Subject: [PATCH 354/619] =?UTF-8?q?fix=20:=20=ED=83=88=ED=87=B4=ED=95=9C?= =?UTF-8?q?=20=EC=86=8C=EB=AA=A8=EC=9E=84=EC=9B=90=20=EB=B6=88=EB=8D=98?= =?UTF-8?q?=EC=A7=80=EA=B8=B0=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fire/domain/repository/FireCustomRepositoryImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 9b51a0a0..b865a2a9 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -92,7 +92,8 @@ public Optional> getFireReceivers(Long teamId, Long mission .where( teamMember.team.teamId.eq(teamId), teamMember.member.memberId.ne(memberId), - teamMember.member.memberId.notIn(missionDonePeople) + teamMember.member.memberId.notIn(missionDonePeople), + teamMember.member.isDeleted.ne(Boolean.TRUE) ) .fetch()); From 3c5861449aff9910c67d6e251b391f10514b439a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:46:50 +0900 Subject: [PATCH 355/619] =?UTF-8?q?fix=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EB=B3=B4=EB=93=9C=20=EB=B0=98=EB=B3=B5?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EA=B4=80=EB=A0=A8=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?->=20=EC=9D=B8=EC=A6=9D=20=EC=99=84=EB=A3=8C=ED=95=9C=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EB=9C=A8=EC=A7=80=20=EC=95=8A=EA=B2=8C,?= =?UTF-8?q?=20=EC=A7=84=ED=96=89=20=EC=98=88=EC=A0=95=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EB=9C=A8=EC=A7=80=20=EC=95=8A=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 6c764172..72efacde 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -251,12 +251,12 @@ public Optional> findRepeatMissionArchivesByMemberId .where( mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT), - mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), + mission.status.eq(MissionStatus.ONGOING), repeatTypeCondition ) .groupBy(mission.id,mission.number) -// .having(missionState.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 + .having(missionState.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 .orderBy(missionState.count().desc()) .fetch()); From bb84832a63757c9ff82b278a88f99ad9b5dc99ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 10 Dec 2023 17:21:48 +0900 Subject: [PATCH 356/619] =?UTF-8?q?fix=20:=20=EC=97=84=EC=B2=AD=EB=82=9C?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=EC=9D=BC=EB=8B=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionArchiveCustomRepositoryImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 72efacde..b02d8b60 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -376,12 +376,12 @@ private BooleanExpression createRepeatTypeCondition() { LocalDate endOfWeek = startOfWeek.plusDays(6); // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 - BooleanExpression isRepeatType = missionState.mission.type.eq(MissionType.REPEAT); +// BooleanExpression isRepeatType = missionState.mission.type.eq(MissionType.REPEAT); BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 - return isRepeatType.and(dateInRange); + return dateInRange.and(dateInRange); } // 날짜 조건 생성 메서드 @@ -392,12 +392,12 @@ private BooleanExpression createRepeatTypeConditionByArchive() { LocalDate endOfWeek = startOfWeek.plusDays(6); // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 - BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); +// BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 - return isRepeatType.and(dateInRange); + return dateInRange.and(dateInRange); } From cfbfa2a3b4e84841744df2c1bd6f017ee4fc661d Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Dec 2023 17:30:43 +0900 Subject: [PATCH 357/619] =?UTF-8?q?feat:=20=ED=91=B8=EC=8B=9C=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EB=B3=B4=EB=82=B4=EA=B8=B0=EB=9E=91=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=ED=95=98=EA=B8=B0=20=ED=95=A8=EC=88=98=20=ED=95=A9?= =?UTF-8?q?=EC=B9=98=EA=B8=B0=20=EB=B0=8F=20fcmService=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendBoardAlarmUseCase.java | 9 ++--- .../domain/entity/BoardComment.java | 2 ++ .../service/FireThrowAlarmUseCase.java | 33 ++++++++++++++----- .../application/service/FireThrowUseCase.java | 18 +++++----- .../fire/presentation/FireController.java | 6 ++-- .../mapper/AlarmHistoryMapper.java | 28 +++++++++------- .../service/SaveMultiAlarmHistoryUseCase.java | 5 +-- .../service/MissionRemindAlarmUseCase.java | 2 -- .../SendMissionCreateAlarmUseCase.java | 26 +++++++++------ .../service/ApproveTeamUseCase.java | 13 ++++---- .../service/RejectTeamUseCase.java | 8 +++-- .../domain/service/TeamUpdateService.java | 1 - .../global/config/fcm/dto/event/FcmEvent.java | 16 --------- .../config/fcm/dto/event/MultiFcmEvent.java | 22 +++++++++++++ .../config/fcm/dto/event/SingleFcmEvent.java | 22 +++++++++++++ .../config/fcm/dto/request/MultiRequest.java | 17 +++++++--- .../config/fcm/dto/request/SingleRequest.java | 18 +++++++--- .../global/config/fcm/service/FcmService.java | 17 ++++++++-- .../config/fcm/util/FcmMessageUtil.java | 17 ++++++---- .../representation/FireControllerTest.java | 7 ++-- 20 files changed, 183 insertions(+), 104 deletions(-) delete mode 100644 src/main/java/com/moing/backend/global/config/fcm/dto/event/FcmEvent.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/dto/event/MultiFcmEvent.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index a2e5dea9..91133868 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -9,7 +9,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; -import com.moing.backend.global.config.fcm.dto.event.FcmEvent; +import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; import com.moing.backend.global.response.BaseServiceResponse; import lombok.RequiredArgsConstructor; import net.minidev.json.JSONObject; @@ -29,8 +29,6 @@ public class SendBoardAlarmUseCase { private final TeamMemberGetService teamMemberGetService; private final ApplicationEventPublisher eventPublisher; - private final SaveMultiAlarmHistoryUseCase saveAlarmHistory; - private final AlarmHistoryMapper alarmHistoryMapper; public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board board) { Member member = baseServiceResponse.getMember(); @@ -42,10 +40,7 @@ public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board bo Optional> memberIdAndTokens = teamMemberGetService.getMemberInfoExceptMe(team.getTeamId(), member.getMemberId()); if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { //알림 보내기 - List fcmTokens = alarmHistoryMapper.getFcmTokens(memberIdAndTokens); - eventPublisher.publishEvent(new FcmEvent(title, body, fcmTokens)); - //알림 저장하기 - saveAlarmHistory.saveAlarmHistories(memberIdAndTokens, createIdInfo(team.getTeamId(), board.getBoardId()), title, body, team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue()); + eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokens.get(), createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); } } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java index 4fe54475..85660487 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java @@ -22,6 +22,8 @@ public class BoardComment extends BaseTimeEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "board_comment_id") private Long boardCommentId; + + @Column(nullable = false, length = 300) private String content; @ManyToOne(fetch = FetchType.LAZY) diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java index ffddb4b7..006dd25f 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -1,17 +1,23 @@ package com.moing.backend.domain.fire.application.service; +import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; import com.moing.backend.global.config.fcm.service.FcmService; import lombok.RequiredArgsConstructor; +import net.minidev.json.JSONObject; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.transaction.Transactional; - import java.util.Random; +import static com.moing.backend.domain.history.domain.entity.PagePath.MISSION_PATH; import static com.moing.backend.global.config.fcm.constant.FireThrowMessage.*; -import static java.lang.Math.random; @Service @Transactional @@ -19,25 +25,26 @@ public class FireThrowAlarmUseCase { private final FcmService fcmService; + private final ApplicationEventPublisher eventPublisher; + private final TeamMemberGetService teamMemberGetService; - public void sendFireThrowAlarm(Member throwMember, Member receiveMember) { + public void sendFireThrowAlarm(Member throwMember, Member receiveMember, Team team, Mission mission) { Random random = new Random(System.currentTimeMillis()); int randomNum = random.nextInt(2); String title = getTitle(throwMember.getNickName(), receiveMember.getNickName(), randomNum); String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), randomNum); + String idInfo = createIdInfo(mission.getType() == MissionType.REPEAT, mission.getTeam().getTeamId(), mission.getId()); - SingleRequest singleRequest = new SingleRequest(receiveMember.getFcmToken(), title, message); - - fcmService.sendSingleDevice(singleRequest); + eventPublisher.publishEvent(new SingleFcmEvent(receiveMember.getFcmToken(), title, message, receiveMember.getMemberId(), idInfo, team.getName(), AlarmType.FIRE, MISSION_PATH.getValue())); } public String getMessage(String pusher, String receiver, int num) { switch (num) { - case 0: return pusher + "님이" + receiver + NEW_FIRE_THROW_MESSAGE1.getMessage(); - case 1: return receiver + "님! " + pusher + NEW_FIRE_THROW_MESSAGE2.getMessage(); + case 0: return pusher + "님이 " + receiver + NEW_FIRE_THROW_MESSAGE1.getMessage(); + case 1: return receiver + "님! " + pusher + NEW_FIRE_THROW_MESSAGE2.getMessage(); } return pusher + "님이" + receiver + NEW_FIRE_THROW_MESSAGE1.getMessage(); } @@ -53,5 +60,13 @@ public String getTitle(String pusher, String receiver, int num) { return NEW_FIRE_THROW_TITLE1.getMessage(); } + private String createIdInfo(boolean isRepeated, Long teamId, Long missionId) { + JSONObject jo = new JSONObject(); + jo.put("isRepeated", isRepeated); + jo.put("teamId", teamId); + jo.put("missionId", missionId); + return jo.toJSONString(); + } + } diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java index 2c3faca8..7fd5015b 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -9,17 +9,17 @@ import com.moing.backend.domain.fire.exception.NoAuthThrowFireException; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; -import com.moing.backend.global.config.fcm.dto.request.SingleRequest; -import com.moing.backend.global.config.fcm.service.FcmService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; -import static java.lang.Math.random; - @Service @Transactional @RequiredArgsConstructor @@ -28,15 +28,17 @@ public class FireThrowUseCase { public final FireSaveService fireSaveService; public final FireQueryService fireQueryService; private final MemberGetService memberGetService; - private final FireThrowAlarmUseCase fireThrowAlarmUseCase; - private final MissionArchiveQueryService missionArchiveQueryService; + private final MissionQueryService missionQueryService; + private final TeamGetService teamGetService; - public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { + public FireThrowRes createFireThrow(String userId, Long receiveMemberId, Long missionId, Long teamId) { Member throwMember = memberGetService.getMemberBySocialId(userId); Member receiveMember = memberGetService.getMemberByMemberId(receiveMemberId); + Team team = teamGetService.getTeamByTeamId(teamId); + Mission mission = missionQueryService.findMissionById(missionId); // 나에게 던질 수 없음 if (throwMember.equals(receiveMember)) { @@ -48,7 +50,7 @@ public FireThrowRes createFireThrow(String userId, Long receiveMemberId) { throw new NoAuthThrowFireException(); } - fireThrowAlarmUseCase.sendFireThrowAlarm(throwMember, receiveMember); + fireThrowAlarmUseCase.sendFireThrowAlarm(throwMember, receiveMember, team, mission); return FireMapper.mapToFireThrowRes(fireSaveService.save(Fire.builder() .throwMemberId(throwMember.getMemberId()) diff --git a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java index f302d0f2..5de8aa94 100644 --- a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java +++ b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java @@ -3,7 +3,6 @@ import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; import com.moing.backend.domain.fire.application.service.FireThrowUseCase; -import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -15,7 +14,6 @@ import static com.moing.backend.domain.fire.presentation.constant.FireResponseMessage.GET_RECEIVERS_SUCCESS; import static com.moing.backend.domain.fire.presentation.constant.FireResponseMessage.THROW_FIRE_SUCCESS; -import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.READ_MISSION_SUCCESS; @RestController @AllArgsConstructor @@ -32,8 +30,8 @@ public class FireController { @PostMapping("/{receiveMemberId}") public ResponseEntity> throwFire (@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, - @PathVariable("receiveMemberId") Long receiveMemberId) { - return ResponseEntity.ok(SuccessResponse.create(THROW_FIRE_SUCCESS.getMessage(), this.fireThrowUseCase.createFireThrow(user.getSocialId(),receiveMemberId))); + @PathVariable("receiveMemberId") Long receiveMemberId, @PathVariable("missionId") Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(THROW_FIRE_SUCCESS.getMessage(), this.fireThrowUseCase.createFireThrow(user.getSocialId(), receiveMemberId, missionId, teamId))); } /** diff --git a/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java b/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java index d2eb03bf..21938d0d 100644 --- a/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java +++ b/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java @@ -8,7 +8,6 @@ import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; @Component @@ -28,18 +27,25 @@ public AlarmHistory toAlarmHistory(AlarmType type, String path, String idInfo, L .build(); } - public List getFcmTokens(Optional> memberIdAndTokens) { - return memberIdAndTokens.map(list -> list.stream() - .map(MemberIdAndToken::getFcmToken) - .collect(Collectors.toList())) - .orElse(Collections.emptyList()); + public static List getFcmTokens(List memberIdAndTokens) { + if (memberIdAndTokens == null || memberIdAndTokens.isEmpty()) { + return Collections.emptyList(); + } + + return memberIdAndTokens.stream() + .map(MemberIdAndToken::getFcmToken) + .collect(Collectors.toList()); } - public List getMemberIds(Optional> memberIdAndTokens) { - return memberIdAndTokens.map(list -> list.stream() - .map(MemberIdAndToken::getMemberId) - .collect(Collectors.toList())) - .orElse(Collections.emptyList()); + + public static List getMemberIds(List memberIdAndTokens) { + if (memberIdAndTokens == null || memberIdAndTokens.isEmpty()) { + return Collections.emptyList(); + } + + return memberIdAndTokens.stream() + .map(MemberIdAndToken::getMemberId) + .collect(Collectors.toList()); } public List getAlarmHistories(String idInfo, List memberIds, String title, String body, String teamName, AlarmType alarmType, String path) { diff --git a/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java index 10069ac9..0831b3b8 100644 --- a/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java +++ b/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java @@ -1,6 +1,5 @@ package com.moing.backend.domain.history.application.service; -import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; import com.moing.backend.domain.history.domain.entity.AlarmHistory; import com.moing.backend.domain.history.domain.entity.AlarmType; @@ -10,7 +9,6 @@ import org.springframework.stereotype.Service; import java.util.List; -import java.util.Optional; @Service @RequiredArgsConstructor @@ -20,8 +18,7 @@ public class SaveMultiAlarmHistoryUseCase { private final AlarmHistorySaveService alarmHistorySaveService; @Async - public void saveAlarmHistories(Optional> memberIdAndTokens, String idInfo, String title, String body, String name, AlarmType alarmType, String path) { - List memberIds = alarmHistoryMapper.getMemberIds(memberIdAndTokens); + public void saveAlarmHistories(List memberIds, String idInfo, String title, String body, String name, AlarmType alarmType, String path) { List alarmHistories = alarmHistoryMapper.getAlarmHistories(idInfo, memberIds, title, body, name, alarmType, path); alarmHistorySaveService.saveAlarmHistories(alarmHistories); } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index 1e651bdd..51f71ffe 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -7,11 +7,9 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; - import java.util.Random; import static com.moing.backend.global.config.fcm.constant.RemindMissionTitle.*; -import static java.lang.Math.random; @Service @Transactional diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java index b0a82df3..944ebe1d 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java @@ -1,25 +1,23 @@ package com.moing.backend.domain.mission.application.service; -import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; -import com.moing.backend.global.config.fcm.dto.event.FcmEvent; -import com.moing.backend.global.config.fcm.dto.request.MultiRequest; -import com.moing.backend.global.config.fcm.service.FcmService; -import com.moing.backend.global.response.BaseServiceResponse; +import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; import lombok.RequiredArgsConstructor; +import net.minidev.json.JSONObject; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.transaction.Transactional; -import java.util.EventListener; import java.util.List; import java.util.Optional; import static com.moing.backend.global.config.fcm.constant.NewMissionTitle.NEW_SINGLE_MISSION_COMING; -import static com.moing.backend.global.config.fcm.constant.NewUploadTitle.UPLOAD_NOTICE_NEW_TITLE; @Service @Transactional @@ -34,10 +32,18 @@ public void sendNewMissionUploadAlarm(Member member, Mission mission) { String title = team.getName() + " " + NEW_SINGLE_MISSION_COMING.getTitle(); String message = mission.getTitle(); - Optional> fcmTokens = teamMemberGetService.getFcmTokensExceptMe(team.getTeamId(), member.getMemberId()); - if (fcmTokens.isPresent() && !fcmTokens.get().isEmpty()) { - eventPublisher.publishEvent(new FcmEvent(title, message, fcmTokens.get())); + Optional> memberIdAndTokens = teamMemberGetService.getMemberInfoExceptMe(team.getTeamId(), member.getMemberId()); + if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { + eventPublisher.publishEvent(new MultiFcmEvent(title, message, memberIdAndTokens.get(), createIdInfo(team.getTeamId(), mission.getId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.MISSION_PATH.getValue())); } } + + private String createIdInfo(Long teamId, Long missionId) { + JSONObject jo = new JSONObject(); + jo.put("isRepeated", false); + jo.put("teamId", teamId); + jo.put("missionId", missionId); + return jo.toJSONString(); + } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java index c58ba97c..4daedf88 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java @@ -1,20 +1,18 @@ package com.moing.backend.domain.team.application.service; +import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.team.application.dto.response.GetLeaderInfoResponse; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.team.domain.service.TeamUpdateService; -import com.moing.backend.global.config.fcm.FcmConfig; -import com.moing.backend.global.config.fcm.dto.event.FcmEvent; -import com.moing.backend.global.config.fcm.dto.request.SingleRequest; -import com.moing.backend.global.config.fcm.service.FcmService; +import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.transaction.Transactional; -import java.util.Collections; import java.util.List; +import static com.moing.backend.domain.history.domain.entity.PagePath.HOME_PATH; import static com.moing.backend.global.config.fcm.constant.ApproveTeamMessage.APPROVE_TEAM_MESSAGE; @Service @@ -24,7 +22,7 @@ public class ApproveTeamUseCase { private final TeamUpdateService teamUpdateService; private final TeamGetService teamGetService; - private final FcmService fcmService; + private final ApplicationEventPublisher eventPublisher; public void approveTeams(List teamIds){ teamUpdateService.updateTeamStatus(true, teamIds); @@ -32,7 +30,8 @@ public void approveTeams(List teamIds){ for(GetLeaderInfoResponse info: leaderInfos){ String title=APPROVE_TEAM_MESSAGE.title(info.getLeaderName(), info.getTeamName()); String body= APPROVE_TEAM_MESSAGE.body(); - fcmService.sendSingleDevice(new SingleRequest(info.getLeaderFcmToken(), title, body)); + + eventPublisher.publishEvent(new SingleFcmEvent(info.getLeaderFcmToken(), title, body, info.getLeaderId(), "", info.getTeamName(), AlarmType.APPROVE_TEAM, HOME_PATH.getValue())); } } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java index 7b80720a..f52b379c 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java @@ -1,17 +1,18 @@ package com.moing.backend.domain.team.application.service; +import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.team.application.dto.response.GetLeaderInfoResponse; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.team.domain.service.TeamUpdateService; -import com.moing.backend.global.config.fcm.dto.event.FcmEvent; +import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.transaction.Transactional; -import java.util.Collections; import java.util.List; +import static com.moing.backend.domain.history.domain.entity.PagePath.HOME_PATH; import static com.moing.backend.global.config.fcm.constant.ApproveTeamMessage.REJECT_TEAM_MESSAGE; @Service @@ -29,7 +30,8 @@ public void rejectTeams(List teamIds) { for (GetLeaderInfoResponse info : leaderInfos) { String title = REJECT_TEAM_MESSAGE.title(info.getLeaderName(), info.getTeamName()); String body = REJECT_TEAM_MESSAGE.body(); - eventPublisher.publishEvent(new FcmEvent(title, body, Collections.singletonList(info.getLeaderFcmToken()))); + + eventPublisher.publishEvent(new SingleFcmEvent(info.getLeaderFcmToken(), title, body, info.getLeaderId(), "", info.getTeamName(), AlarmType.REJECT_TEAM, HOME_PATH.getValue())); } } } diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamUpdateService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamUpdateService.java index a5603e61..e7563277 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamUpdateService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamUpdateService.java @@ -2,7 +2,6 @@ import com.moing.backend.domain.team.domain.repository.TeamRepository; import com.moing.backend.global.annotation.DomainService; -import com.moing.backend.global.config.fcm.dto.event.FcmEvent; import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/event/FcmEvent.java b/src/main/java/com/moing/backend/global/config/fcm/dto/event/FcmEvent.java deleted file mode 100644 index d5c29fa4..00000000 --- a/src/main/java/com/moing/backend/global/config/fcm/dto/event/FcmEvent.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.moing.backend.global.config.fcm.dto.event; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.List; - -@Getter -@AllArgsConstructor -public class FcmEvent { - - private String title; - private String body; - private List tokens; - -} diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/event/MultiFcmEvent.java b/src/main/java/com/moing/backend/global/config/fcm/dto/event/MultiFcmEvent.java new file mode 100644 index 00000000..cecd5b6a --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/event/MultiFcmEvent.java @@ -0,0 +1,22 @@ +package com.moing.backend.global.config.fcm.dto.event; + +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class MultiFcmEvent { + + private String title; + private String body; + private List memberIdAndTokens; + private String idInfo; + private String name; + private AlarmType alarmType; + private String path; + +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java b/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java new file mode 100644 index 00000000..bb584296 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java @@ -0,0 +1,22 @@ +package com.moing.backend.global.config.fcm.dto.event; + +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class SingleFcmEvent { + + private String registrationToken; + private String title; + private String body; + private Long memberId; + private String idInfo; + private String name; + private AlarmType alarmType; + private String path; +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/request/MultiRequest.java b/src/main/java/com/moing/backend/global/config/fcm/dto/request/MultiRequest.java index 222e1258..2a0cdfed 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/dto/request/MultiRequest.java +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/request/MultiRequest.java @@ -1,23 +1,32 @@ package com.moing.backend.global.config.fcm.dto.request; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.domain.entity.AlarmType; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import javax.validation.constraints.NotNull; import java.util.List; +import java.util.Optional; @Getter @NoArgsConstructor @AllArgsConstructor public class MultiRequest { - @NotNull(message = "기기 등록 토큰들을 입력해 주세요.") - private List registrationToken; - @NotNull(message = "알림 제목을 입력해 주세요.") + private List memberIdAndTokens; + private String title; - @NotNull(message = "알림 내용을 입력해 주세요.") private String body; + private String idInfo; + + private String name; + + private AlarmType alarmType; + + private String path; + } diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/request/SingleRequest.java b/src/main/java/com/moing/backend/global/config/fcm/dto/request/SingleRequest.java index 01f2a37a..a27a067a 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/dto/request/SingleRequest.java +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/request/SingleRequest.java @@ -1,21 +1,29 @@ package com.moing.backend.global.config.fcm.dto.request; +import com.moing.backend.domain.history.domain.entity.AlarmType; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; - @Getter @NoArgsConstructor @AllArgsConstructor public class SingleRequest { - @NotNull(message = "기기 등록 토큰을 입력해 주세요.") + private String registrationToken; - @NotNull(message = "알림 제목을 입력해 주세요.") private String title; - @NotNull(message = "알림 내용을 입력해 주세요.") private String body; + + private Long memberId; + + private String idInfo; + + private String name; + + private AlarmType alarmType; + + private String path; + } diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java index fe5f10a9..129ddb72 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java +++ b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java @@ -1,6 +1,9 @@ package com.moing.backend.global.config.fcm.service; import com.google.firebase.messaging.*; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; +import com.moing.backend.domain.history.application.service.SaveSingleAlarmHistoryUseCase; import com.moing.backend.global.config.fcm.dto.request.MultiRequest; import com.moing.backend.global.config.fcm.dto.request.SingleRequest; import com.moing.backend.global.config.fcm.dto.response.MultiResponse; @@ -23,6 +26,8 @@ public class FcmService { private final FirebaseMessaging firebaseMessaging; + private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; + private final SaveSingleAlarmHistoryUseCase saveSingleAlarmHistoryUseCase; @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { @@ -62,6 +67,7 @@ public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { try { String response = firebaseMessaging.send(message); + saveSingleAlarmHistoryUseCase.saveAlarmHistory(toSingleRequest.getMemberId(), toSingleRequest.getIdInfo(), toSingleRequest.getTitle(), toSingleRequest.getBody(), toSingleRequest.getName(), toSingleRequest.getAlarmType(), toSingleRequest.getPath()); return new SingleResponse(response); } catch (FirebaseMessagingException e) { throw handleException(e); @@ -72,6 +78,8 @@ public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) public MultiResponse sendMultipleDevices(MultiRequest toMultiRequest) { + + List fcmTokens = AlarmHistoryMapper.getFcmTokens(toMultiRequest.getMemberIdAndTokens()); Notification notification = Notification.builder() .setTitle(toMultiRequest.getTitle()) .setBody(toMultiRequest.getBody()) @@ -99,7 +107,7 @@ public MultiResponse sendMultipleDevices(MultiRequest toMultiRequest) { .build(); MulticastMessage message = MulticastMessage.builder() - .addAllTokens(toMultiRequest.getRegistrationToken()) + .addAllTokens(fcmTokens) .setNotification(notification) .setAndroidConfig(androidConfig) // Applying Android configuration .setApnsConfig(apnsConfig) // Applying APNs configuration @@ -107,15 +115,20 @@ public MultiResponse sendMultipleDevices(MultiRequest toMultiRequest) { try { BatchResponse response = firebaseMessaging.sendMulticast(message); + + List failedTokens = new ArrayList<>(); if (response.getFailureCount() > 0) { List responses = response.getResponses(); + List memberIds = AlarmHistoryMapper.getMemberIds(toMultiRequest.getMemberIdAndTokens()); + saveMultiAlarmHistoryUseCase.saveAlarmHistories(memberIds, toMultiRequest.getIdInfo(), toMultiRequest.getTitle(), toMultiRequest.getBody(), toMultiRequest.getName(), toMultiRequest.getAlarmType(), toMultiRequest.getPath()); + for (int i = 0; i < responses.size(); i++) { if (!responses.get(i).isSuccessful()) { // Add the failed tokens to the list - failedTokens.add(toMultiRequest.getRegistrationToken().get(i)); + failedTokens.add(fcmTokens.get(i)); } } } diff --git a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java index ebc7771f..1bc65d22 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java +++ b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java @@ -1,6 +1,7 @@ package com.moing.backend.global.config.fcm.util; -import com.moing.backend.global.config.fcm.dto.event.FcmEvent; +import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; +import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; import com.moing.backend.global.config.fcm.dto.request.MultiRequest; import com.moing.backend.global.config.fcm.dto.request.SingleRequest; import com.moing.backend.global.config.fcm.service.FcmService; @@ -18,12 +19,14 @@ public class FcmMessageUtil { @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) - public void onFcmMessageEvent(FcmEvent event) { - if (event.getTokens().size() == 1) { - fcmService.sendSingleDevice(new SingleRequest(event.getTitle(), event.getBody(), event.getTokens().get(0))); - } else { - fcmService.sendMultipleDevices(new MultiRequest(event.getTokens(), event.getTitle(), event.getBody())); - } + public void onMultiFcmEvent(MultiFcmEvent event) { + fcmService.sendMultipleDevices(new MultiRequest(event.getMemberIdAndTokens(), event.getTitle(), event.getBody(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onSingleFcmEvent(SingleFcmEvent event) { + fcmService.sendSingleDevice(new SingleRequest(event.getRegistrationToken(), event.getTitle(), event.getBody(), event.getMemberId(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); } } diff --git a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java index 5a2b61a5..0cdd119b 100644 --- a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java +++ b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java @@ -5,8 +5,6 @@ import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; import com.moing.backend.domain.fire.application.service.FireThrowUseCase; import com.moing.backend.domain.fire.presentation.FireController; -import com.moing.backend.domain.mission.application.dto.req.MissionReq; -import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -24,7 +22,8 @@ import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; -import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; @@ -94,7 +93,7 @@ public class FireControllerTest extends CommonControllerTest { .receiveMemberId(1L) .build(); - given(fireThrowUseCase.createFireThrow(any(),any())).willReturn(output); + given(fireThrowUseCase.createFireThrow(any(), any(), any(), any())).willReturn(output); Long teamId = 2L; Long missionId = 2L; From e3f88e957b3b4a79f9383a692222b75d7eed1210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 10 Dec 2023 17:44:09 +0900 Subject: [PATCH 358/619] =?UTF-8?q?fix=20:=20mission=20board=20=EC=97=90?= =?UTF-8?q?=EC=84=9C=20wait=20=EC=83=81=ED=83=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index b02d8b60..1edae340 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -251,7 +251,7 @@ public Optional> findRepeatMissionArchivesByMemberId .where( mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT), - mission.status.eq(MissionStatus.ONGOING), + mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), repeatTypeCondition ) From bb6512558d8f3edd576ac70c33948302ce0d33b6 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Dec 2023 23:30:34 +0900 Subject: [PATCH 359/619] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83,=20=EC=95=8C=EB=A6=BC=20off=ED=95=98=EB=A9=B4=20?= =?UTF-8?q?=ED=91=B8=EC=8B=9C=20=EC=95=8C=EB=A6=BC=EC=9D=80=20=EC=95=88=20?= =?UTF-8?q?=EB=B3=B4=EB=82=B4=EA=B3=A0=20=EC=95=8C=EB=A6=BC=20=ED=9E=88?= =?UTF-8?q?=EC=8A=A4=ED=86=A0=EB=A6=AC=EC=97=90=EB=8A=94=20=EC=8C=93?= =?UTF-8?q?=EC=9D=B4=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendBoardAlarmUseCase.java | 11 ++--- .../service/FireThrowAlarmUseCase.java | 2 +- .../domain/member/domain/entity/Member.java | 10 ++++ .../domain/service/MemberSaveService.java | 1 + .../SendMissionCreateAlarmUseCase.java | 8 ++-- .../application/service/SignOutUseCase.java | 4 +- .../service/ApproveTeamUseCase.java | 2 +- .../service/RejectTeamUseCase.java | 2 +- .../TeamMemberCustomRepository.java | 5 +- .../TeamMemberCustomRepositoryImpl.java | 47 ++++++++++++++++++- .../domain/service/TeamMemberGetService.java | 17 ++++++- .../config/fcm/dto/event/MultiFcmEvent.java | 4 +- .../config/fcm/dto/event/SingleFcmEvent.java | 4 +- .../global/config/fcm/service/FcmService.java | 6 +-- .../config/fcm/util/FcmMessageUtil.java | 17 ++++++- 15 files changed, 111 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index 91133868..408afc17 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -2,8 +2,6 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; -import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; -import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; @@ -37,11 +35,10 @@ public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board bo if (board.isNotice()) { String title = NEW_NOTICE_UPLOAD_MESSAGE.title(team.getName()); String body = NEW_NOTICE_UPLOAD_MESSAGE.body(board.getTitle()); - Optional> memberIdAndTokens = teamMemberGetService.getMemberInfoExceptMe(team.getTeamId(), member.getMemberId()); - if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { - //알림 보내기 - eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokens.get(), createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); - } + Optional> memberIdAndTokensByPush = teamMemberGetService.getNewUploadPushInfo(team.getTeamId(), member.getMemberId()); + Optional> memberIdAndTokensBySave = teamMemberGetService.getNewUploadSaveInfo(team.getTeamId(), member.getMemberId()); + // 알림 보내기 + eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); } } diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java index 006dd25f..c76c180b 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -37,7 +37,7 @@ public void sendFireThrowAlarm(Member throwMember, Member receiveMember, Team te String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), randomNum); String idInfo = createIdInfo(mission.getType() == MissionType.REPEAT, mission.getTeam().getTeamId(), mission.getId()); - eventPublisher.publishEvent(new SingleFcmEvent(receiveMember.getFcmToken(), title, message, receiveMember.getMemberId(), idInfo, team.getName(), AlarmType.FIRE, MISSION_PATH.getValue())); + eventPublisher.publishEvent(new SingleFcmEvent(receiveMember, title, message, idInfo, team.getName(), AlarmType.FIRE, MISSION_PATH.getValue())); } public String getMessage(String pusher, String receiver, int num) { diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index b2c6b0f0..fbaf5da5 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -82,6 +82,8 @@ public class Member extends BaseTimeEntity { private LocalDateTime lastSignInTime; + private boolean isSignOut; + @OneToMany(mappedBy = "member") private List teamMembers = new ArrayList<>(); //최대 3개이므로 양방향 @@ -165,4 +167,12 @@ public void deleteMember(){ this.isDeleted=true; } + public void signOut() { + this.isSignOut = true; + } + + public void signIn() { + this.isSignOut = false; + } + } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java index 3aeff0eb..842027d4 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java @@ -23,6 +23,7 @@ public Member saveMember(Member member) { } else { findMember.get().updateFcmToken(member.getFcmToken()); findMember.get().updateLastSignInTime(LocalDateTime.now()); + findMember.get().signIn(); return findMember.get(); } } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java index 944ebe1d..5b22d1db 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java @@ -32,10 +32,10 @@ public void sendNewMissionUploadAlarm(Member member, Mission mission) { String title = team.getName() + " " + NEW_SINGLE_MISSION_COMING.getTitle(); String message = mission.getTitle(); - Optional> memberIdAndTokens = teamMemberGetService.getMemberInfoExceptMe(team.getTeamId(), member.getMemberId()); - if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { - eventPublisher.publishEvent(new MultiFcmEvent(title, message, memberIdAndTokens.get(), createIdInfo(team.getTeamId(), mission.getId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.MISSION_PATH.getValue())); - } + Optional> memberIdAndTokensByPush = teamMemberGetService.getNewUploadPushInfo(team.getTeamId(), member.getMemberId()); + Optional> memberIdAndTokensBySave = teamMemberGetService.getNewUploadSaveInfo(team.getTeamId(), member.getMemberId()); + // 알림 보내기 + eventPublisher.publishEvent(new MultiFcmEvent(title, message, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.MISSION_PATH.getValue())); } private String createIdInfo(Long teamId, Long missionId) { diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java index 26180396..864b080e 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.mypage.application.service; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.global.config.security.jwt.TokenUtil; import lombok.RequiredArgsConstructor; @@ -11,8 +12,9 @@ public class SignOutUseCase { private final TokenUtil tokenUtil; private final MemberGetService memberGetService; - public void signOut(String socialId){ tokenUtil.expireRefreshToken(socialId); + Member member=memberGetService.getMemberBySocialId(socialId); + member.signOut(); } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java index 4daedf88..51b8a1db 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java @@ -31,7 +31,7 @@ public void approveTeams(List teamIds){ String title=APPROVE_TEAM_MESSAGE.title(info.getLeaderName(), info.getTeamName()); String body= APPROVE_TEAM_MESSAGE.body(); - eventPublisher.publishEvent(new SingleFcmEvent(info.getLeaderFcmToken(), title, body, info.getLeaderId(), "", info.getTeamName(), AlarmType.APPROVE_TEAM, HOME_PATH.getValue())); +// eventPublisher.publishEvent(new SingleFcmEvent(info.getLeaderFcmToken(), title, body, info.getLeaderId(), "", info.getTeamName(), AlarmType.APPROVE_TEAM, HOME_PATH.getValue())); } } } diff --git a/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java index f52b379c..8d4a3c3e 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/RejectTeamUseCase.java @@ -31,7 +31,7 @@ public void rejectTeams(List teamIds) { String title = REJECT_TEAM_MESSAGE.title(info.getLeaderName(), info.getTeamName()); String body = REJECT_TEAM_MESSAGE.body(); - eventPublisher.publishEvent(new SingleFcmEvent(info.getLeaderFcmToken(), title, body, info.getLeaderId(), "", info.getTeamName(), AlarmType.REJECT_TEAM, HOME_PATH.getValue())); +// eventPublisher.publishEvent(new SingleFcmEvent(info.getLeaderFcmToken(), title, body, info.getLeaderId(), "", info.getTeamName(), AlarmType.REJECT_TEAM, HOME_PATH.getValue())); } } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index a9f0bdfa..15028f4f 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -10,7 +10,10 @@ public interface TeamMemberCustomRepository { List findMemberIdsByTeamId(Long teamId); - Optional> findIdAndTokensByTeamIdAndMemberId(Long teamId, Long memberId); + Optional> findNewUploadPushInfo(Long teamId, Long memberId); + Optional> findNewUploadSaveInfo(Long teamId, Long memberId); + Optional> findRemindPushInfo(Long teamId, Long memberId); + Optional> findRemindSaveInfo(Long teamId, Long memberId); Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId); List findTeamMemberInfoByTeamId(Long teamId); List findTeamMemberByMemberId(Long memberId); diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index db8e8ce5..41bf94b2 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -32,13 +32,57 @@ public List findMemberIdsByTeamId(Long teamId) { } @Override - public Optional> findIdAndTokensByTeamIdAndMemberId(Long teamId, Long memberId) { + public Optional> findNewUploadPushInfo(Long teamId, Long memberId) { List result = queryFactory.select(Projections.constructor(MemberIdAndToken.class, teamMember.member.fcmToken, teamMember.member.memberId)) .from(teamMember) .where(teamMember.team.teamId.eq(teamId) .and(teamMember.member.isNewUploadPush.eq(true)) + .and(teamMember.member.isSignOut.eq(false)) + .and(teamMember.member.memberId.ne(memberId)) + .and(teamMember.isDeleted.eq(false))) + .fetch(); + + return result.isEmpty() ? Optional.empty() : Optional.of(result); + } + + @Override + public Optional> findNewUploadSaveInfo(Long teamId, Long memberId) { + List result = queryFactory.select(Projections.constructor(MemberIdAndToken.class, + teamMember.member.fcmToken, + teamMember.member.memberId)) + .from(teamMember) + .where(teamMember.team.teamId.eq(teamId) + .and(teamMember.member.memberId.ne(memberId)) + .and(teamMember.isDeleted.eq(false))) + .fetch(); + + return result.isEmpty() ? Optional.empty() : Optional.of(result); + } + @Override + public Optional> findRemindPushInfo(Long teamId, Long memberId) { + List result = queryFactory.select(Projections.constructor(MemberIdAndToken.class, + teamMember.member.fcmToken, + teamMember.member.memberId)) + .from(teamMember) + .where(teamMember.team.teamId.eq(teamId) + .and(teamMember.member.isRemindPush.eq(true)) + .and(teamMember.member.isSignOut.eq(false)) + .and(teamMember.member.memberId.ne(memberId)) + .and(teamMember.isDeleted.eq(false))) + .fetch(); + + return result.isEmpty() ? Optional.empty() : Optional.of(result); + } + + @Override + public Optional> findRemindSaveInfo(Long teamId, Long memberId) { + List result = queryFactory.select(Projections.constructor(MemberIdAndToken.class, + teamMember.member.fcmToken, + teamMember.member.memberId)) + .from(teamMember) + .where(teamMember.team.teamId.eq(teamId) .and(teamMember.member.memberId.ne(memberId)) .and(teamMember.isDeleted.eq(false))) .fetch(); @@ -52,6 +96,7 @@ public Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long .from(teamMember) .where(teamMember.team.teamId.eq(teamId) .and(teamMember.member.isNewUploadPush.eq(true)) + .and(teamMember.member.isSignOut.eq(false)) .and(teamMember.member.memberId.ne(memberId)) .and(teamMember.isDeleted.eq(false))) .fetch(); diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index 8b76cd09..87d6af25 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -38,7 +38,20 @@ public List getNotDeletedTeamMember(Long memberId){ return teamMemberRepository.findTeamMemberByMemberId(memberId); } - public Optional> getMemberInfoExceptMe(Long teamId, Long memberId) { - return teamMemberRepository.findIdAndTokensByTeamIdAndMemberId(teamId, memberId); + public Optional> getNewUploadPushInfo(Long teamId, Long memberId) { + return teamMemberRepository.findNewUploadPushInfo(teamId, memberId); } + + public Optional> getNewUploadSaveInfo(Long teamId, Long memberId) { + return teamMemberRepository.findNewUploadSaveInfo(teamId, memberId); + } + + public Optional> getRemindPushInfo(Long teamId, Long memberId) { + return teamMemberRepository.findRemindPushInfo(teamId, memberId); + } + + public Optional> getRemindSaveInfo(Long teamId, Long memberId) { + return teamMemberRepository.findRemindSaveInfo(teamId, memberId); + } + } diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/event/MultiFcmEvent.java b/src/main/java/com/moing/backend/global/config/fcm/dto/event/MultiFcmEvent.java index cecd5b6a..f944e40c 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/dto/event/MultiFcmEvent.java +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/event/MultiFcmEvent.java @@ -6,6 +6,7 @@ import lombok.Getter; import java.util.List; +import java.util.Optional; @Getter @AllArgsConstructor @@ -13,7 +14,8 @@ public class MultiFcmEvent { private String title; private String body; - private List memberIdAndTokens; + private Optional> idAndTokensByPush; + private Optional> idAndTokensBySave; private String idInfo; private String name; private AlarmType alarmType; diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java b/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java index bb584296..02b9ab2f 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.member.domain.entity.Member; import lombok.AllArgsConstructor; import lombok.Getter; @@ -11,10 +12,9 @@ @AllArgsConstructor public class SingleFcmEvent { - private String registrationToken; + private Member member; private String title; private String body; - private Long memberId; private String idInfo; private String name; private AlarmType alarmType; diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java index 129ddb72..37983a5c 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java +++ b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java @@ -26,9 +26,6 @@ public class FcmService { private final FirebaseMessaging firebaseMessaging; - private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; - private final SaveSingleAlarmHistoryUseCase saveSingleAlarmHistoryUseCase; - @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { @@ -67,7 +64,7 @@ public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { try { String response = firebaseMessaging.send(message); - saveSingleAlarmHistoryUseCase.saveAlarmHistory(toSingleRequest.getMemberId(), toSingleRequest.getIdInfo(), toSingleRequest.getTitle(), toSingleRequest.getBody(), toSingleRequest.getName(), toSingleRequest.getAlarmType(), toSingleRequest.getPath()); +// saveSingleAlarmHistoryUseCase.saveAlarmHistory(toSingleRequest.getMemberId(), toSingleRequest.getIdInfo(), toSingleRequest.getTitle(), toSingleRequest.getBody(), toSingleRequest.getName(), toSingleRequest.getAlarmType(), toSingleRequest.getPath()); return new SingleResponse(response); } catch (FirebaseMessagingException e) { throw handleException(e); @@ -123,7 +120,6 @@ public MultiResponse sendMultipleDevices(MultiRequest toMultiRequest) { List responses = response.getResponses(); List memberIds = AlarmHistoryMapper.getMemberIds(toMultiRequest.getMemberIdAndTokens()); - saveMultiAlarmHistoryUseCase.saveAlarmHistories(memberIds, toMultiRequest.getIdInfo(), toMultiRequest.getTitle(), toMultiRequest.getBody(), toMultiRequest.getName(), toMultiRequest.getAlarmType(), toMultiRequest.getPath()); for (int i = 0; i < responses.size(); i++) { if (!responses.get(i).isSuccessful()) { diff --git a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java index 1bc65d22..de18a5a6 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java +++ b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java @@ -1,5 +1,8 @@ package com.moing.backend.global.config.fcm.util; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; +import com.moing.backend.domain.history.application.service.SaveSingleAlarmHistoryUseCase; import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; import com.moing.backend.global.config.fcm.dto.request.MultiRequest; @@ -16,17 +19,27 @@ public class FcmMessageUtil { private final FcmService fcmService; + private final SaveSingleAlarmHistoryUseCase saveSingleAlarmHistoryUseCase; + private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void onMultiFcmEvent(MultiFcmEvent event) { - fcmService.sendMultipleDevices(new MultiRequest(event.getMemberIdAndTokens(), event.getTitle(), event.getBody(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); + if (event.getIdAndTokensByPush().isPresent() && !event.getIdAndTokensByPush().get().isEmpty()) { + fcmService.sendMultipleDevices(new MultiRequest(event.getIdAndTokensByPush().get(), event.getTitle(), event.getBody(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); + } + if (event.getIdAndTokensBySave().isPresent() && !event.getIdAndTokensBySave().get().isEmpty()) { + saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(event.getIdAndTokensBySave().get()), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); + } } @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void onSingleFcmEvent(SingleFcmEvent event) { - fcmService.sendSingleDevice(new SingleRequest(event.getRegistrationToken(), event.getTitle(), event.getBody(), event.getMemberId(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); + if (event.getMember().isFirePush() && !event.getMember().isSignOut()) { //알림 on, 로그아웃 안함 + fcmService.sendSingleDevice(new SingleRequest(event.getMember().getFcmToken(), event.getTitle(), event.getBody(), event.getMember().getMemberId(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); + } + saveSingleAlarmHistoryUseCase.saveAlarmHistory(event.getMember().getMemberId(), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); } } From 6d6887098cefc405ecf9b17244b3351b595e9686 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Dec 2023 23:34:19 +0900 Subject: [PATCH 360/619] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=95=8C=EB=A6=BC=20=EB=B3=B4=EB=82=B4?= =?UTF-8?q?=EA=B8=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendBoardAlarmUseCase.java | 2 +- .../backend/global/utils/StartupRunner.java | 86 +++++++++---------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index 408afc17..0fd19fe0 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -38,7 +38,7 @@ public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board bo Optional> memberIdAndTokensByPush = teamMemberGetService.getNewUploadPushInfo(team.getTeamId(), member.getMemberId()); Optional> memberIdAndTokensBySave = teamMemberGetService.getNewUploadSaveInfo(team.getTeamId(), member.getMemberId()); // 알림 보내기 - eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); + eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); } } diff --git a/src/main/java/com/moing/backend/global/utils/StartupRunner.java b/src/main/java/com/moing/backend/global/utils/StartupRunner.java index 2927490f..7857d309 100644 --- a/src/main/java/com/moing/backend/global/utils/StartupRunner.java +++ b/src/main/java/com/moing/backend/global/utils/StartupRunner.java @@ -1,43 +1,43 @@ -package com.moing.backend.global.utils; - -import com.moing.backend.domain.member.domain.constant.Gender; -import com.moing.backend.domain.member.domain.constant.RegistrationStatus; -import com.moing.backend.domain.member.domain.constant.Role; -import com.moing.backend.domain.member.domain.constant.SocialProvider; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.service.MemberSaveService; -import com.moing.backend.global.annotation.Util; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.CommandLineRunner; -import org.springframework.stereotype.Component; - -import java.time.LocalDate; - -@Util -@RequiredArgsConstructor -public class StartupRunner implements CommandLineRunner { - - /** - * 테스트용 insert - */ - - private final MemberSaveService memberSaveService; - @Override - public void run(String... args) throws Exception { - Member test01 = new Member(LocalDate.now(), "tester1@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester1", "undef", SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester01"); - memberSaveService.saveMember(test01); - - Member test02=new Member(LocalDate.now(), "tester2@test.com", "undef", Gender.MAN, null, "modagbul_tester2", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester02"); - memberSaveService.saveMember(test02); - - Member test03=new Member(LocalDate.now(), "tester3@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester3", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester03"); - memberSaveService.saveMember(test03); - - Member test04=new Member(LocalDate.now(), "tester4@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester4", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester04"); - memberSaveService.saveMember(test04); - - Member test05=new Member(LocalDate.now(), "tester5@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester5", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester05"); - memberSaveService.saveMember(test05); - - } -} +//package com.moing.backend.global.utils; +// +//import com.moing.backend.domain.member.domain.constant.Gender; +//import com.moing.backend.domain.member.domain.constant.RegistrationStatus; +//import com.moing.backend.domain.member.domain.constant.Role; +//import com.moing.backend.domain.member.domain.constant.SocialProvider; +//import com.moing.backend.domain.member.domain.entity.Member; +//import com.moing.backend.domain.member.domain.service.MemberSaveService; +//import com.moing.backend.global.annotation.Util; +//import lombok.RequiredArgsConstructor; +//import org.springframework.boot.CommandLineRunner; +//import org.springframework.stereotype.Component; +// +//import java.time.LocalDate; +// +//@Util +//@RequiredArgsConstructor +//public class StartupRunner implements CommandLineRunner { +// +// /** +// * 테스트용 insert +// */ +// +// private final MemberSaveService memberSaveService; +// @Override +// public void run(String... args) throws Exception { +// Member test01 = new Member(LocalDate.now(), "tester1@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester1", "undef", SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester01"); +// memberSaveService.saveMember(test01); +// +// Member test02=new Member(LocalDate.now(), "tester2@test.com", "undef", Gender.MAN, null, "modagbul_tester2", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tester02"); +// memberSaveService.saveMember(test02); +// +// Member test03=new Member(LocalDate.now(), "tester3@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester3", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester03"); +// memberSaveService.saveMember(test03); +// +// Member test04=new Member(LocalDate.now(), "tester4@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester4", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester04"); +// memberSaveService.saveMember(test04); +// +// Member test05=new Member(LocalDate.now(), "tester5@test.com", "undef", Gender.WOMAN, "undef", "modagbul_tester5", "undef", SocialProvider.APPLE, RegistrationStatus.COMPLETED, Role.USER, "APPLE@tester05"); +// memberSaveService.saveMember(test05); +// +// } +//} From 2b081a461af438087f8d0f5e668225fc15db0c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:53:33 +0900 Subject: [PATCH 361/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=9B=90=EC=83=81=EB=B3=B5=EA=B5=AC=20mis?= =?UTF-8?q?sionState=20->=20missionArchive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveCustomRepositoryImpl.java | 157 +++++------------- 1 file changed, 41 insertions(+), 116 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 1edae340..0c04a24f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -15,7 +15,6 @@ import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; -import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -25,10 +24,7 @@ import javax.persistence.EntityManager; import javax.swing.text.html.Option; -import java.time.DayOfWeek; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -52,7 +48,7 @@ public MissionArchiveCustomRepositoryImpl(EntityManager em) { @Override public Optional> findSingleMissionInComplete(Long memberId, Long teamId, MissionStatus status, - OrderCondition orderCondition) { + OrderCondition orderCondition) { OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); return Optional.ofNullable(queryFactory .select(Projections.constructor(SingleMissionBoardRes.class, @@ -83,7 +79,7 @@ public Optional> findSingleMissionInComplete(Long me } @Override public Optional> findSingleMissionComplete(Long memberId, Long teamId, MissionStatus status, - OrderCondition orderCondition) { + OrderCondition orderCondition) { OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); return Optional.ofNullable(queryFactory .select(Projections.constructor(SingleMissionBoardRes.class, @@ -118,23 +114,16 @@ private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { return orderSpecifiers.toArray(new OrderSpecifier[orderSpecifiers.size()]); } - @Override + @Override public Optional> findOneMyArchives(Long memberId,Long missionId,Long count) { - - BooleanExpression repeatTypeCondition = createRepeatTypeConditionByArchive(); - BooleanExpression baseCondition = missionArchive.mission.id.eq(missionId); - BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); - return Optional.ofNullable(queryFactory .select(missionArchive) - .from(missionArchive) - .where( - finalCondition, + .from(missionArchive) + .where( + missionArchive.mission.id.eq(missionId), missionArchive.member.memberId.eq(memberId), - missionArchive.count.eq(count) - - + missionArchive.count.eq(count) ) .orderBy(missionArchive.createdDate.desc()) .fetch() @@ -145,16 +134,11 @@ public Optional> findOneMyArchives(Long memberId,Long missi @Override public Optional> findMyArchives(Long memberId,Long missionId) { - - BooleanExpression repeatTypeCondition = createRepeatTypeConditionByArchive(); - BooleanExpression baseCondition = missionArchive.mission.id.eq(missionId); - BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); - return Optional.ofNullable(queryFactory .select(missionArchive) - .from(missionArchive) - .where( - finalCondition, + .from(missionArchive) + .where( + missionArchive.mission.id.eq(missionId), missionArchive.member.memberId.eq(memberId) ) .orderBy(missionArchive.createdDate.desc()) @@ -167,16 +151,11 @@ public Optional> findMyArchives(Long memberId,Long missionI @Override public Optional> findOthersArchives(Long memberId, Long missionId) { - - BooleanExpression repeatTypeCondition = createRepeatTypeConditionByArchive(); - BooleanExpression baseCondition = missionArchive.mission.id.eq(missionId); - BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); - return Optional.ofNullable(queryFactory .select(missionArchive) .from(missionArchive) .where( - finalCondition, + missionArchive.mission.id.eq(missionId), missionArchive.member.memberId.ne(memberId), missionArchive.status.eq(MissionArchiveStatus.COMPLETE).or(missionArchive.status.eq(MissionArchiveStatus.SKIP)) ) @@ -188,19 +167,13 @@ public Optional> findOthersArchives(Long memberId, Long mis @Override public Optional findDonePeopleByMissionId(Long missionId) { - - BooleanExpression repeatTypeCondition = createRepeatTypeCondition(); - BooleanExpression baseCondition = missionState.mission.id.eq(missionId); - BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); - return Optional.of(queryFactory - .select(missionState) - .from(missionState) + .select(missionArchive) + .from(missionArchive) .where( - finalCondition + missionArchive.mission.id.eq(missionId) ) - .groupBy(missionState.member,missionState.mission.number) - .having(missionState.count().goe(missionState.mission.number)) + .groupBy(missionArchive.member) .fetchCount() ); @@ -208,18 +181,12 @@ public Optional findDonePeopleByMissionId(Long missionId) { @Override public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) { - - - BooleanExpression repeatTypeCondition = createRepeatTypeCondition(); - BooleanExpression baseCondition = missionState.mission.id.eq(missionId); - BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); - return Optional.ofNullable(queryFactory - .select(missionState.count()) - .from(missionState) + .select(missionArchive.count()) + .from(missionArchive) .where( - finalCondition, - missionState.member.memberId.eq(memberId) + missionArchive.mission.id.eq(missionId), + missionArchive.member.memberId.eq(memberId) ) .fetchFirst() ); @@ -228,21 +195,16 @@ public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) @Override public Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status) { - - - BooleanExpression repeatTypeCondition = createRepeatTypeCondition(); - - return Optional.ofNullable(queryFactory .select(Projections.constructor(RepeatMissionBoardRes.class, - mission.id, - mission.title, + mission.id, + mission.title, // missionState.count().coalesce(0L).as("done"), - missionState.count(), - mission.number, - mission.way.stringValue(), - mission.status.stringValue() - )) + missionState.count(), + mission.number, + mission.way.stringValue(), + mission.status.stringValue() + )) .from(mission) .leftJoin(missionState) .on(missionState.mission.eq(mission), @@ -251,12 +213,10 @@ public Optional> findRepeatMissionArchivesByMemberId .where( mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT), - mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), - repeatTypeCondition - + mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)) ) .groupBy(mission.id,mission.number) - .having(missionState.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 +// .having(missionState.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 .orderBy(missionState.count().desc()) .fetch()); @@ -270,22 +230,19 @@ public Optional> findFinishMissionsByStatus(Long mem Expression type = Expressions.stringTemplate(String.valueOf(mission.type)); - BooleanExpression repeatTypeCondition = createRepeatTypeCondition(); - return Optional.ofNullable(queryFactory .selectDistinct(Projections.constructor(FinishMissionBoardRes.class, - mission.id, - mission.dueTo.stringValue(), - mission.title, - missionState.status.stringValue().coalesce("FAIL").as("status"), - mission.type.stringValue(), + mission.id, + mission.dueTo.stringValue(), + mission.title, + missionArchive.status.stringValue().coalesce("FAIL").as("status"), + mission.type.stringValue(), mission.way.stringValue() )) .from(mission) .leftJoin(mission.missionArchiveList,missionArchive) - .on(missionState.member.memberId.eq(memberId)) + .on(missionArchive.member.memberId.eq(memberId)) .where( - repeatTypeCondition, mission.team.teamId.eq(teamId), mission.status.eq(MissionStatus.SUCCESS).or(mission.status.eq(MissionStatus.END)) ) @@ -336,11 +293,11 @@ public Boolean findMyArchivesToday(Long memberId, Long missionId) { LocalDateTime endOfToday = today.withHour(23).withMinute(59).withSecond(59).withNano(999999999); long count = queryFactory - .selectFrom(missionState) + .selectFrom(missionArchive) .where( - missionState.member.memberId.eq(memberId), - missionState.mission.id.eq(missionId), - missionState.lastModifiedDate.between(startOfToday, endOfToday) // createdDate와 오늘의 시작과 끝을 비교 + missionArchive.member.memberId.eq(memberId), + missionArchive.mission.id.eq(missionId), + missionArchive.lastModifiedDate.between(startOfToday, endOfToday) // createdDate와 오늘의 시작과 끝을 비교 ) .fetchCount(); @@ -355,8 +312,8 @@ public Optional> findPeopleRemainMission() { .join(teamMember.team, team) .join(team.missions, mission) .join(mission.missionStateList,missionState) - .where(missionState.isNull()) - .fetch()); + .where(missionState.isNull()) + .fetch()); // .where( // // active 한 미션 필터링 // (((mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT))).and(mission.type.eq(MissionType.ONCE))) @@ -368,38 +325,6 @@ public Optional> findPeopleRemainMission() { // ).fetch()); } - // 날짜 조건 생성 메서드 - private BooleanExpression createRepeatTypeCondition() { - LocalDate now = LocalDate.now(); - DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; - LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); - LocalDate endOfWeek = startOfWeek.plusDays(6); - - // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 -// BooleanExpression isRepeatType = missionState.mission.type.eq(MissionType.REPEAT); - BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) - .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); - - // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 - return dateInRange.and(dateInRange); - } - - // 날짜 조건 생성 메서드 - private BooleanExpression createRepeatTypeConditionByArchive() { - LocalDate now = LocalDate.now(); - DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; - LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); - LocalDate endOfWeek = startOfWeek.plusDays(6); - - // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 -// BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); - BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) - .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); - - // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 - return dateInRange.and(dateInRange); - } - -} +} \ No newline at end of file From 527792e81a60500232c99499e1fb0bcd32866188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:51:18 +0900 Subject: [PATCH 362/619] =?UTF-8?q?fix=20:=20=EC=96=B4=EC=A0=9C=EC=9D=98?= =?UTF-8?q?=20=EC=97=84=EC=B2=AD=EB=82=9C=20=EC=98=A4=EB=A5=98=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0(=20missionArchive=20->=20missionState=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EC=A4=91=EC=97=90=20=EC=83=9D=EA=B8=B4=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionCustomRepositoryImpl.java | 44 +++++++++- .../MissionArchiveCustomRepositoryImpl.java | 85 +++++++++++++++++-- 2 files changed, 120 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 0e5b28c9..1afc2552 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -16,7 +16,10 @@ import javax.persistence.EntityManager; +import java.time.DayOfWeek; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.temporal.TemporalAdjusters; import java.util.List; import java.util.Optional; @@ -46,6 +49,9 @@ public Long findMissionsCountByTeam(Long teamId) { @Override public Optional> findRepeatMissionByMemberId(Long memberId,Listteams) { + + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherRepeatMissionRes.class, mission.id, @@ -59,7 +65,8 @@ public Optional> findRepeatMissionByMemberId(Long m .from(mission) .leftJoin(missionState) .on(missionState.mission.eq(mission), - missionState.member.memberId.eq(memberId) + missionState.member.memberId.eq(memberId), + dateInRange ) .where( mission.team.teamId.in(teams), @@ -68,7 +75,8 @@ public Optional> findRepeatMissionByMemberId(Long m ) .groupBy(mission.id,mission.number) - .having(missionState.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 + .having(missionState.count().lt(mission.number) + ) // HAVING 절을 사용하여 조건 적용 .orderBy(missionState.count().desc()) .fetch()); } @@ -165,4 +173,36 @@ public Optional findByIds(Long memberId, Long missionId) { } + private BooleanExpression createRepeatTypeConditionByArchive() { + LocalDate now = LocalDate.now(); + DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; + LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); + LocalDate endOfWeek = startOfWeek.plusDays(6); + + // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 +// BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); + BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) + .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + + // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 + return dateInRange.and(dateInRange); + } + + private BooleanExpression createRepeatTypeConditionByState() { + LocalDate now = LocalDate.now(); + DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; + LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); + LocalDate endOfWeek = startOfWeek.plusDays(6); + + // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 +// BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); + BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) + .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + + // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 + return dateInRange.and(dateInRange); + } + + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 0c04a24f..bd232cf8 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -15,6 +15,7 @@ import com.querydsl.core.types.Order; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -24,7 +25,10 @@ import javax.persistence.EntityManager; import javax.swing.text.html.Option; +import java.time.DayOfWeek; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -117,13 +121,18 @@ private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { @Override public Optional> findOneMyArchives(Long memberId,Long missionId,Long count) { + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + return Optional.ofNullable(queryFactory .select(missionArchive) .from(missionArchive) .where( missionArchive.mission.id.eq(missionId), missionArchive.member.memberId.eq(memberId), - missionArchive.count.eq(count) + missionArchive.count.eq(count), + + missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) + .or(missionArchive.mission.type.eq(MissionType.ONCE)) ) .orderBy(missionArchive.createdDate.desc()) .fetch() @@ -134,12 +143,17 @@ public Optional> findOneMyArchives(Long memberId,Long missi @Override public Optional> findMyArchives(Long memberId,Long missionId) { + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + return Optional.ofNullable(queryFactory .select(missionArchive) .from(missionArchive) .where( missionArchive.mission.id.eq(missionId), - missionArchive.member.memberId.eq(memberId) + missionArchive.member.memberId.eq(memberId), + missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) + .or(missionArchive.mission.type.eq(MissionType.ONCE)) + ) .orderBy(missionArchive.createdDate.desc()) .fetch() @@ -151,13 +165,18 @@ public Optional> findMyArchives(Long memberId,Long missionI @Override public Optional> findOthersArchives(Long memberId, Long missionId) { + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + return Optional.ofNullable(queryFactory .select(missionArchive) .from(missionArchive) .where( missionArchive.mission.id.eq(missionId), missionArchive.member.memberId.ne(memberId), - missionArchive.status.eq(MissionArchiveStatus.COMPLETE).or(missionArchive.status.eq(MissionArchiveStatus.SKIP)) + missionArchive.status.eq(MissionArchiveStatus.COMPLETE).or(missionArchive.status.eq(MissionArchiveStatus.SKIP)), + + missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) + .or(missionArchive.mission.type.eq(MissionType.ONCE)) ) .orderBy(missionArchive.createdDate.desc()) .fetch() @@ -167,11 +186,17 @@ public Optional> findOthersArchives(Long memberId, Long mis @Override public Optional findDonePeopleByMissionId(Long missionId) { + + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + return Optional.of(queryFactory .select(missionArchive) .from(missionArchive) .where( - missionArchive.mission.id.eq(missionId) + missionArchive.mission.id.eq(missionId), + + missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) + .or(missionArchive.mission.type.eq(MissionType.ONCE)) ) .groupBy(missionArchive.member) .fetchCount() @@ -181,12 +206,16 @@ public Optional findDonePeopleByMissionId(Long missionId) { @Override public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) { + + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); return Optional.ofNullable(queryFactory .select(missionArchive.count()) .from(missionArchive) .where( missionArchive.mission.id.eq(missionId), - missionArchive.member.memberId.eq(memberId) + missionArchive.member.memberId.eq(memberId), + missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) + .or(missionArchive.mission.type.eq(MissionType.ONCE)) ) .fetchFirst() ); @@ -195,6 +224,8 @@ public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) @Override public Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status) { + + BooleanExpression dateInRange = createRepeatTypeConditionByState(); return Optional.ofNullable(queryFactory .select(Projections.constructor(RepeatMissionBoardRes.class, mission.id, @@ -208,7 +239,8 @@ public Optional> findRepeatMissionArchivesByMemberId .from(mission) .leftJoin(missionState) .on(missionState.mission.eq(mission), - missionState.member.memberId.eq(memberId) + missionState.member.memberId.eq(memberId), + dateInRange ) .where( mission.team.teamId.eq(teamId), @@ -292,12 +324,17 @@ public Boolean findMyArchivesToday(Long memberId, Long missionId) { LocalDateTime startOfToday = today.withHour(0).withMinute(0).withSecond(0).withNano(0); LocalDateTime endOfToday = today.withHour(23).withMinute(59).withSecond(59).withNano(999999999); + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + long count = queryFactory .selectFrom(missionArchive) .where( missionArchive.member.memberId.eq(memberId), missionArchive.mission.id.eq(missionId), - missionArchive.lastModifiedDate.between(startOfToday, endOfToday) // createdDate와 오늘의 시작과 끝을 비교 + missionArchive.lastModifiedDate.between(startOfToday, endOfToday), // createdDate와 오늘의 시작과 끝을 비교, + + missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) + .or(missionArchive.mission.type.eq(MissionType.ONCE)) ) .fetchCount(); @@ -325,6 +362,40 @@ public Optional> findPeopleRemainMission() { // ).fetch()); } + private BooleanExpression createRepeatTypeConditionByArchive() { + LocalDate now = LocalDate.now(); + DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; + LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); + LocalDate endOfWeek = startOfWeek.plusDays(6); + + // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 +// BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); + BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) + .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + + // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 + return dateInRange.and(dateInRange); + } + + private BooleanExpression createRepeatTypeConditionByState() { + LocalDate now = LocalDate.now(); + DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; + LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); + LocalDate endOfWeek = startOfWeek.plusDays(6); + + // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 +// BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); +// BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) +// .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + + BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) + .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + + // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 + return dateInRange.and(dateInRange); + } + + } \ No newline at end of file From ff6ac14b1e504a5ed79dfaab1b74beaedc90952c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:04:29 +0900 Subject: [PATCH 363/619] =?UTF-8?q?fix=20:=20dateInRangeByState=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index bd232cf8..6b75c97d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -388,8 +388,8 @@ private BooleanExpression createRepeatTypeConditionByState() { // BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) // .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); - BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) - .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) + .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 return dateInRange.and(dateInRange); From b430ff13a5dfa3509b8ec62ef5bc22bfd1a832f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:10:05 +0900 Subject: [PATCH 364/619] =?UTF-8?q?fix=20:=20dateInRange=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EC=97=90=EC=84=9C=20missionState,=20missionArchive=20?= =?UTF-8?q?=ED=98=BC=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 1afc2552..bdb8a444 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -50,7 +50,7 @@ public Long findMissionsCountByTeam(Long teamId) { public Optional> findRepeatMissionByMemberId(Long memberId,Listteams) { - BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + BooleanExpression dateInRange = createRepeatTypeConditionByState(); return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherRepeatMissionRes.class, From 76234750794a90f9bb56936169d3978a4537e21b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:09:45 +0900 Subject: [PATCH 365/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=ED=8C=80=EB=8B=B9=202=EA=B0=9C=EA=B9=8C=EC=A7=80?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EA=B0=80=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index bdb8a444..935d59c4 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -148,7 +148,7 @@ public boolean findRepeatMissionsByTeamId(Long teamId) { mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT), mission.status.eq(MissionStatus.ONGOING) - ).fetchCount() > 2; + ).fetchCount() < 2; } @Override From ff4ed43a1dd420869484a0c502e3b8197a8f4664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:16:47 +0900 Subject: [PATCH 366/619] =?UTF-8?q?fix=20:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=20=ED=87=B4=EC=9E=A5=ED=95=9C=20=EC=82=AC=EB=9E=8C=20=EB=B6=88?= =?UTF-8?q?=EB=8D=98=EC=A7=80=EA=B8=B0=20=EB=AA=A9=EB=A1=9D=EC=97=90=20?= =?UTF-8?q?=EB=9C=A8=EC=A7=80=20=EC=95=8A=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/fire/domain/repository/FireCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index b865a2a9..0383d08d 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -93,7 +93,7 @@ public Optional> getFireReceivers(Long teamId, Long mission teamMember.team.teamId.eq(teamId), teamMember.member.memberId.ne(memberId), teamMember.member.memberId.notIn(missionDonePeople), - teamMember.member.isDeleted.ne(Boolean.TRUE) + teamMember.isDeleted.ne(Boolean.TRUE) ) .fetch()); From 6e8bdb5bc3498f8595ee1d311f73c4595b9601a2 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 11 Dec 2023 20:16:08 +0900 Subject: [PATCH 367/619] =?UTF-8?q?fix:=20transactional=20=EC=96=B4?= =?UTF-8?q?=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mypage/application/service/SignOutUseCase.java | 4 ++++ .../domain/mypage/application/service/WithdrawUseCase.java | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java index 864b080e..80587f0e 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java @@ -6,12 +6,16 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import javax.transaction.Transactional; + @Service @RequiredArgsConstructor public class SignOutUseCase { private final TokenUtil tokenUtil; private final MemberGetService memberGetService; + + @Transactional public void signOut(String socialId){ tokenUtil.expireRefreshToken(socialId); Member member=memberGetService.getMemberBySocialId(socialId); diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUseCase.java index 02e1b99e..bfda5361 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/WithdrawUseCase.java @@ -11,6 +11,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import javax.transaction.Transactional; import java.io.IOException; import java.util.Map; @@ -24,16 +25,17 @@ public class WithdrawUseCase { private final TeamGetService teamGetService; private final Map withdrawProviders; + @Transactional public void withdraw(String socialId, String providerInfo, WithdrawRequest withdrawRequest) throws IOException { Member member = memberGetService.getMemberBySocialId(socialId); checkMemberIsNotPartOfAnyTeam(member); - withdraw(providerInfo, withdrawRequest.getSocialToken()); + socialWithdraw(providerInfo, withdrawRequest.getSocialToken()); member.deleteMember(); feedbackSaveService.saveFeedback(member, withdrawRequest); tokenUtil.expireRefreshToken(socialId); } - private void withdraw(String providerInfo, String token) throws IOException { + private void socialWithdraw(String providerInfo, String token) throws IOException { WithdrawProvider withdrawProvider=withdrawProviders.get(providerInfo+"Withdraw"); if (withdrawProvider == null) { throw new IllegalArgumentException("Unknown provider: " + providerInfo); From 29968138f18167e926414ea5393a744107801440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 11 Dec 2023 20:52:05 +0900 Subject: [PATCH 368/619] =?UTF-8?q?fix=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98=EC=97=90=20WAIT=20=EC=9D=B8=20=EB=B0=98?= =?UTF-8?q?=EB=B3=B5=EB=AF=B8=EC=85=98=20=EB=9C=A8=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 935d59c4..28d5ba91 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -70,7 +70,7 @@ public Optional> findRepeatMissionByMemberId(Long m ) .where( mission.team.teamId.in(teams), - mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), + mission.status.eq(MissionStatus.ONGOING), mission.type.eq(MissionType.REPEAT) ) From 8acb0a9884f12858ce4e0969b38f460208f9c3c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 11 Dec 2023 20:52:15 +0900 Subject: [PATCH 369/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=B0=9C=EC=86=A1=20=EA=B5=AC=ED=98=84=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveCustomRepositoryImpl.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 6b75c97d..0fe57dc1 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -349,12 +349,20 @@ public Optional> findPeopleRemainMission() { .join(teamMember.team, team) .join(team.missions, mission) .join(mission.missionStateList,missionState) - .where(missionState.isNull()) - .fetch()); + .on( + mission.eq(missionState.mission), + teamMember.member.eq(missionState.member), + mission.number.loe(missionState.count())) +// .on(missionState.isNull()) + .where( + mission.status.eq(MissionStatus.END).or(mission.status.eq(MissionStatus.SUCCESS)).not() +// missionState.isNull()) + ).fetch()); // .where( // // active 한 미션 필터링 // (((mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT))).and(mission.type.eq(MissionType.ONCE))) // .or((mission.status.eq(MissionStatus.ONGOING)).and(mission.type.eq(MissionType.REPEAT)))), + // // 인증하지 않은값 // missionState.id.isNull() From 9cfce71c17e7039e5be4b5a440439f4aaf9b6442 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 11 Dec 2023 23:05:17 +0900 Subject: [PATCH 370/619] =?UTF-8?q?fix:=20=EC=8B=9C=EA=B0=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/GetAlarmHistoryResponse.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java b/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java index 75560e49..d69e0d71 100644 --- a/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java +++ b/src/main/java/com/moing/backend/domain/history/application/dto/response/GetAlarmHistoryResponse.java @@ -47,16 +47,16 @@ public GetAlarmHistoryResponse(Long alarmHistoryId, AlarmType type, String path, public String formatCreatedDate(LocalDateTime createdDate) { LocalDateTime currentDateTime = LocalDateTime.now(); - LocalDateTime midnightOfCreatedDate = createdDate.toLocalDate().atStartOfDay(); if (currentDateTime.isAfter(midnightOfCreatedDate.plusDays(1))) { DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("M월 d일"); - return midnightOfCreatedDate.plusDays(1).format(dateFormatter); + return createdDate.format(dateFormatter); } else { DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("a h:mm"); - return currentDateTime.format(timeFormatter); + return createdDate.format(timeFormatter); } } + } From 106a5bff6207d4b7e5060b97ed427685c13277eb Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 12 Dec 2023 00:25:58 +0900 Subject: [PATCH 371/619] =?UTF-8?q?refactor:=20transactional=20readOnly=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/service/CheckNicknameUseCase.java | 6 +++--- .../domain/auth/application/service/MemberAuthUseCase.java | 1 - .../domain/board/application/service/GetBoardUseCase.java | 6 +++--- .../com/moing/backend/domain/board/domain/entity/Board.java | 2 ++ .../history/application/service/GetAlarmHistoryUseCase.java | 3 +++ .../domain/member/domain/service/MemberCheckService.java | 6 +++--- .../domain/member/domain/service/MemberSaveService.java | 4 ++-- .../domain/mypage/application/service/AlarmUseCase.java | 6 +++--- .../domain/mypage/application/service/GetMyPageUseCase.java | 4 ++-- .../domain/mypage/application/service/ProfileUseCase.java | 4 ++-- .../domain/mypage/application/service/SignOutUseCase.java | 2 +- .../domain/mypage/domain/service/FeedbackSaveService.java | 2 +- .../domain/team/application/service/UpdateTeamUseCase.java | 2 +- 13 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUseCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUseCase.java index 89c292b6..7893e1b8 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUseCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/CheckNicknameUseCase.java @@ -4,15 +4,15 @@ import com.moing.backend.domain.member.domain.service.MemberCheckService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; +import org.springframework.transaction.annotation.Transactional; @Service -@Transactional @RequiredArgsConstructor public class CheckNicknameUseCase { private final MemberCheckService memberCheckService; + + @Transactional(readOnly=true) public CheckNicknameResponse checkNickname(String nickname){ boolean isDuplicated=memberCheckService.checkNickname(nickname); return new CheckNicknameResponse(isDuplicated); diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUseCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUseCase.java index 12a85a5b..6f5d1e2c 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUseCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/MemberAuthUseCase.java @@ -15,7 +15,6 @@ public class MemberAuthUseCase { private final MemberSaveService memberSaveService; - @Transactional public Member auth(String fcmToken, Member member, String providerInfo) { member.updateFcmToken(fcmToken); Member signInMember = memberSaveService.saveMember(member); diff --git a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java index 83d0104c..ae8b14ce 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java @@ -11,11 +11,9 @@ import com.moing.backend.global.utils.BaseBoardService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; +import org.springframework.transaction.annotation.Transactional; @Service -@Transactional @RequiredArgsConstructor public class GetBoardUseCase { @@ -30,6 +28,7 @@ public class GetBoardUseCase { /** * 게시글 상세 조회 */ + @Transactional public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long boardId) { // 1. 게시글 조회 BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); @@ -41,6 +40,7 @@ public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long /** * 게시글 전체 조회 */ + @Transactional(readOnly = true) public GetAllBoardResponse getAllBoard(String socialId, Long teamId){ Member member=memberGetService.getMemberBySocialId(socialId); return boardGetService.getBoardAll(teamId, member.getMemberId()); diff --git a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java index bc8690ed..d5aef112 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java +++ b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java @@ -11,6 +11,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.BatchSize; import javax.persistence.*; import java.util.ArrayList; @@ -58,6 +59,7 @@ public class Board extends BaseTimeEntity { @OneToMany(mappedBy = "board", cascade = CascadeType.ALL) private List boardReads = new ArrayList<>(); + @BatchSize(size=10) @OneToMany(mappedBy = "board", cascade = CascadeType.ALL) private List boardComments = new ArrayList<>(); diff --git a/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java index cc4f911f..b0eba8af 100644 --- a/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java +++ b/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.member.domain.service.MemberGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; @@ -20,6 +21,7 @@ public class GetAlarmHistoryUseCase { /** * 알림 히스토리 조회 */ + @Transactional(readOnly = true) public List getAllAlarmHistories(String socialId) { Member member = memberGetService.getMemberBySocialId(socialId); return alarmHistoryGetService.getAlarmHistories(member.getMemberId()); @@ -28,6 +30,7 @@ public List getAllAlarmHistories(String socialId) { /** * 안 읽은 알림 개수 조회 */ + @Transactional(readOnly = true) public GetAlarmCountResponse getUnreadAlarmCount(String socialId) { Member member = memberGetService.getMemberBySocialId(socialId); return new GetAlarmCountResponse(alarmHistoryGetService.getUnreadAlarmCount(member.getMemberId())); diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberCheckService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberCheckService.java index 299dceb2..226a10c0 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberCheckService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberCheckService.java @@ -3,14 +3,14 @@ import com.moing.backend.domain.member.domain.repository.MemberRepository; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; - -import javax.transaction.Transactional; +import org.springframework.transaction.annotation.Transactional; @DomainService -@Transactional @RequiredArgsConstructor public class MemberCheckService { private final MemberRepository memberRepository; + + @Transactional(readOnly = true) public boolean checkNickname(String nickname) { return memberRepository.checkNickname(nickname); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java index 842027d4..ad1906b9 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberSaveService.java @@ -4,18 +4,18 @@ import com.moing.backend.domain.member.domain.repository.MemberRepository; import com.moing.backend.global.annotation.DomainService; import lombok.AllArgsConstructor; +import org.springframework.transaction.annotation.Transactional; -import javax.transaction.Transactional; import java.time.LocalDateTime; import java.util.Optional; @DomainService -@Transactional @AllArgsConstructor public class MemberSaveService { private final MemberRepository memberRepository; + @Transactional public Member saveMember(Member member) { OptionalfindMember=memberRepository.findNotDeletedBySocialId(member.getSocialId()); if(findMember.isEmpty()){ diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java index 2ad0e803..e632e679 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java @@ -6,21 +6,21 @@ import com.moing.backend.domain.mypage.exception.AlarmInvalidException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; +import org.springframework.transaction.annotation.Transactional; @Service -@Transactional @RequiredArgsConstructor public class AlarmUseCase { private final MemberGetService memberGetService; + @Transactional(readOnly = true) public GetAlarmResponse getAlarm(String socialId){ Member member=memberGetService.getMemberBySocialId(socialId); return new GetAlarmResponse(member.isNewUploadPush(),member.isRemindPush(), member.isFirePush()); } + @Transactional public GetAlarmResponse updateAlarm(String socialId, String type, String status) { Member member = memberGetService.getMemberBySocialId(socialId); boolean push = "on".equals(status); diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java index 544aa3fc..3e1db9b4 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java @@ -9,13 +9,12 @@ import com.moing.backend.domain.team.domain.service.TeamGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; -import javax.transaction.Transactional; import java.util.List; import java.util.stream.Collectors; @Service -@Transactional @RequiredArgsConstructor public class GetMyPageUseCase { @@ -23,6 +22,7 @@ public class GetMyPageUseCase { private final TeamGetService teamGetService; private final MyPageMapper myPageMapper; + @Transactional(readOnly = true) public GetMyPageResponse getMyPageResponse(String socialId) { Member member = memberGetService.getMemberBySocialId(socialId); List getMyPageTeamBlocks = teamGetService.getMyPageTeamBlockByMemberId(member.getMemberId()); diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java index 6b6ce06f..9d22bde5 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java @@ -7,8 +7,7 @@ import com.moing.backend.global.utils.UpdateUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -17,6 +16,7 @@ public class ProfileUseCase { private final MemberGetService memberGetService; private final UpdateUtils updateUtils; + @Transactional(readOnly = true) public GetProfileResponse getProfile(String socialId){ Member member=memberGetService.getMemberBySocialId(socialId); return new GetProfileResponse(member.getProfileImage(), member.getNickName(), member.getIntroduction()); diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java index 80587f0e..af504fd4 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/SignOutUseCase.java @@ -9,13 +9,13 @@ import javax.transaction.Transactional; @Service +@Transactional @RequiredArgsConstructor public class SignOutUseCase { private final TokenUtil tokenUtil; private final MemberGetService memberGetService; - @Transactional public void signOut(String socialId){ tokenUtil.expireRefreshToken(socialId); Member member=memberGetService.getMemberBySocialId(socialId); diff --git a/src/main/java/com/moing/backend/domain/mypage/domain/service/FeedbackSaveService.java b/src/main/java/com/moing/backend/domain/mypage/domain/service/FeedbackSaveService.java index 2548ef1f..163b692c 100644 --- a/src/main/java/com/moing/backend/domain/mypage/domain/service/FeedbackSaveService.java +++ b/src/main/java/com/moing/backend/domain/mypage/domain/service/FeedbackSaveService.java @@ -10,11 +10,11 @@ import javax.transaction.Transactional; @DomainService -@Transactional @RequiredArgsConstructor public class FeedbackSaveService { private final FeedbackRepository feedbackRepository; + @Transactional public void saveFeedback(Member member, WithdrawRequest withdrawRequest){ Feedback feedback=new Feedback(member.getMemberId(), withdrawRequest.getReason()); feedbackRepository.save(feedback); diff --git a/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java index 8975d06f..0564f58d 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/UpdateTeamUseCase.java @@ -13,6 +13,7 @@ import javax.transaction.Transactional; @Service +@Transactional @RequiredArgsConstructor public class UpdateTeamUseCase { @@ -21,7 +22,6 @@ public class UpdateTeamUseCase { private final CheckLeaderUseCase checkLeaderUseCase; private final UpdateUtils updateUtils; - @Transactional public UpdateTeamResponse updateTeam(UpdateTeamRequest updateTeamRequest, String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); From e5475b5096ba65eb0c8510766e4fbf650e297f97 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 12 Dec 2023 00:26:12 +0900 Subject: [PATCH 372/619] =?UTF-8?q?fix:=201=EB=AA=85=EC=9D=B8=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20=EB=B0=94=EB=A1=9C=20=EC=82=AD=EC=A0=9C=EB=90=98?= =?UTF-8?q?=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/application/service/DisbandTeamUseCase.java | 7 +++++++ .../com/moing/backend/domain/team/domain/entity/Team.java | 4 +--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java index bcb9f4bf..5e5f29df 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java @@ -5,6 +5,8 @@ import com.moing.backend.domain.team.application.dto.response.DeleteTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -18,12 +20,17 @@ public class DisbandTeamUseCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; private final CheckLeaderUseCase checkLeaderUseCase; + private final TeamMemberGetService teamMemberGetService; public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); checkLeaderUseCase.validateTeamLeader(member, team); team.deleteTeam(); + if (team.getNumOfMember() == 1) { // 1명인 경우 3일 유예기간 없음 + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + teamMember.deleteMember(team); + } return new DeleteTeamResponse(teamId); } } diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java index 5086ada7..29e6d530 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -81,9 +81,7 @@ public void updateTeam(String name, String introduction, String profileImgUrl) { public void deleteTeam() { this.isDeleted=true; - //TODO 테스트 용으로 현재 시간이 아닌 4일 전으로 -// this.deletionTime = LocalDateTime.now().withNano(0); - this.deletionTime=LocalDateTime.now().minusDays(4).withNano(0); + this.deletionTime = LocalDateTime.now().withNano(0); } public void addTeamMember(){ From d13b090ddd6c736ddf0df061c12d6da56383ed51 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 12 Dec 2023 00:57:28 +0900 Subject: [PATCH 373/619] =?UTF-8?q?feat:=20=EB=A7=A4=EC=9D=BC=20=EC=9E=90?= =?UTF-8?q?=EC=A0=95=EC=97=90=207=EC=9D=BC=20=EC=A0=84=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=82=AD=EC=A0=9C=ED=95=98=EB=8A=94=20=EC=8A=A4?= =?UTF-8?q?=EC=BC=80=EC=A4=84=EB=9F=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/CleanupUseCase.java | 25 +++++++++++++++++++ .../repository/AlarmHistoryRepository.java | 2 ++ .../service/AlarmHistoryDeleteService.java | 20 +++++++++++++++ .../auth/presentation/AuthControllerTest.java | 4 +-- 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/history/application/service/CleanupUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryDeleteService.java diff --git a/src/main/java/com/moing/backend/domain/history/application/service/CleanupUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/CleanupUseCase.java new file mode 100644 index 00000000..ed6d156c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/application/service/CleanupUseCase.java @@ -0,0 +1,25 @@ +package com.moing.backend.domain.history.application.service; + +import com.moing.backend.domain.history.domain.service.AlarmHistoryDeleteService; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.concurrent.CompletableFuture; + +@Service +@RequiredArgsConstructor +public class CleanupUseCase { + + private final AlarmHistoryDeleteService alarmHistoryDeleteService; + + @Scheduled(cron = "0 0 0 * * ?") + public void cleanupOldAlarmHistories() { + CompletableFuture.runAsync(() -> { + LocalDateTime oneWeekAgo = LocalDateTime.now().minusWeeks(1); + alarmHistoryDeleteService.deleteByCreatedDateBefore(oneWeekAgo); + }); + } +} diff --git a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java index f20e6bec..5f2808c4 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java +++ b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryRepository.java @@ -3,10 +3,12 @@ import com.moing.backend.domain.history.domain.entity.AlarmHistory; import org.springframework.data.jpa.repository.JpaRepository; +import java.time.LocalDateTime; import java.util.Optional; public interface AlarmHistoryRepository extends JpaRepository, AlarmHistoryCustomRepository { Optional findAlarmHistoryByIdAndReceiverId(Long id, Long receiverId); + void deleteByCreatedDateBefore(LocalDateTime dateTime); } diff --git a/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryDeleteService.java b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryDeleteService.java new file mode 100644 index 00000000..2a822728 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/domain/service/AlarmHistoryDeleteService.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.history.domain.service; + +import com.moing.backend.domain.history.domain.repository.AlarmHistoryRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class AlarmHistoryDeleteService { + + private final AlarmHistoryRepository alarmHistoryRepository; + + public void deleteByCreatedDateBefore(LocalDateTime oneWeekAgo) { + alarmHistoryRepository.deleteByCreatedDateBefore(oneWeekAgo); + } +} diff --git a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java index c7fe00a3..434e4321 100644 --- a/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java +++ b/src/test/java/com/moing/backend/domain/auth/presentation/AuthControllerTest.java @@ -36,7 +36,7 @@ class AuthControllerTest extends CommonControllerTest { private SignInUseCase authService; @MockBean - private SignUpUseCase signUpUserCase; + private SignUpUseCase signUpUseCase; @MockBean private ReissueTokenUseCase reissueTokenUseCase; @@ -333,7 +333,7 @@ public void sign_up() throws Exception { .build(); - given(signUpUserCase.signUp(any(), any())).willReturn(output); + given(signUpUseCase.signUp(any(), any())).willReturn(output); //when ResultActions actions = mockMvc.perform( From 6076f0237d52caeafa59cf52e9580e77504dbf1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 12 Dec 2023 02:08:09 +0900 Subject: [PATCH 374/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=A4=91=EC=97=90=20=ED=95=9C=EB=B2=88?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=95=88=EB=9C=A8=EB=8A=94=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionCustomRepositoryImpl.java | 9 ++++++--- .../mission/domain/service/MissionQueryService.java | 1 - 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 28d5ba91..1c68138b 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -129,12 +129,15 @@ public Optional> findSingleMissionByMemberId(Long m mission.dueTo.stringValue() )) .from(mission) - .leftJoin(missionState).on(mission.id.eq(missionState.mission.id)) + .leftJoin(missionState).on( + mission.eq(missionState.mission), + missionState.member.memberId.eq(memberId) + ) .where( mission.team.teamId.in(teams), mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), - mission.type.eq(MissionType.ONCE), - missionState.id.isNull() + mission.type.eq(MissionType.ONCE) + //missionState.id.isNull() ) .orderBy(mission.dueTo.asc()) .fetch()); diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index e2170124..136f5c43 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -39,7 +39,6 @@ public Long findMissionsCountByTeam(Long teamId) { public List findAllRepeatMission(Long memberId) { List teams = teamGetService.getTeamIdByMemberId(memberId); - System.out.println(teams); return missionRepository.findRepeatMissionByMemberId(memberId,teams).orElseThrow(NotFoundMissionException::new); } From 224dbb46cbf7cc229683dedb3e9486a289a51d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 12 Dec 2023 04:28:54 +0900 Subject: [PATCH 375/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=EC=9D=B4=EB=A9=B4=EC=84=9C=20=EC=98=A4=EB=8A=98=20?= =?UTF-8?q?=EC=9D=B4=EC=A0=84=EC=97=90=20=ED=95=9C=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=EC=9D=80=20=EC=9D=B8=EC=A6=9D=20=EC=B7=A8=EC=86=8C=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=97=86=EB=8F=84=EB=A1=9D=20=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveDeleteUseCase.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java index ddf6df7a..d596bed9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java @@ -58,15 +58,18 @@ public Long deleteArchive(String userSocialId, Long missionId,Long count) { Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); - // 사진 제출 했다면, s3 삭제 로직 - if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(memberId, missionId)) { + MissionArchive deleteArchive = missionArchiveQueryService.findOneMyArchive(memberId, missionId,count).get(0); + MissionState missionState = missionStateQueryService.findMissionState(member, mission); + + LocalDateTime createdDate = deleteArchive.getCreatedDate(); + LocalDateTime today = LocalDateTime.now(); + // 반복미션이면서 오늘 이전에 한 인증은 인증 취소할 수 없도록 + if (mission.getType().equals(MissionType.REPEAT) && createdDate.toLocalDate().isBefore(today.toLocalDate())) { + throw new NoAccessMissionArchiveException(); } - MissionArchive deleteArchive = missionArchiveQueryService.findOneMyArchive(memberId, missionId,count).get(0); missionArchiveDeleteService.deleteMissionArchive(deleteArchive); - - MissionState missionState = missionStateQueryService.findMissionState(member, mission); missionStateDeleteService.deleteMissionState(missionState); return deleteArchive.getId(); From 3728fb3628abbb8e9b87ede40b30353755be6cac Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 12 Dec 2023 20:45:46 +0900 Subject: [PATCH 376/619] =?UTF-8?q?feat:=20member=20=EC=9D=B8=EB=8D=B1?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moing/backend/domain/member/domain/entity/Member.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index fbaf5da5..b423671d 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -27,6 +27,7 @@ @NoArgsConstructor @AllArgsConstructor @Getter +@Table(indexes = @Index(name = "idx_social_id", columnList = "socialId")) public class Member extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) From ef288d0ec4b156dbbf452ec81d04eb9fd07debbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 13 Dec 2023 18:15:46 +0900 Subject: [PATCH 377/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionRemindAlarmUseCase.java | 28 ++++++++--- .../presentation/MissionController.java | 12 +++-- .../MissionArchiveCustomRepository.java | 3 -- .../MissionArchiveCustomRepositoryImpl.java | 29 ++--------- .../repository/MissionArchiveRepository.java | 50 +++++++++++++++++++ .../MissionArchiveScheduleQueryService.java | 40 ++++++++++++++- ...issionArchiveCustomRepositoryImplTest.java | 18 ++++++- 7 files changed, 139 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index 51f71ffe..f8cf8e54 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -1,12 +1,22 @@ package com.moing.backend.domain.mission.application.service; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveScheduleQueryService; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; import com.moing.backend.global.config.fcm.dto.request.MultiRequest; import com.moing.backend.global.config.fcm.service.FcmService; import lombok.RequiredArgsConstructor; +import net.minidev.json.JSONObject; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; import java.util.Random; import static com.moing.backend.global.config.fcm.constant.RemindMissionTitle.*; @@ -16,22 +26,26 @@ @RequiredArgsConstructor public class MissionRemindAlarmUseCase { - private final FcmService fcmService; - - public void sendRemindMissionAlarm(Mission mission) { + private final MissionArchiveScheduleQueryService missionArchiveScheduleQueryService; + private final ApplicationEventPublisher eventPublisher; + public Boolean sendRemindMissionAlarm() { Random random = new Random(System.currentTimeMillis()); - - - String title = getTitle(random.nextInt(4)); String message = getMessage(random.nextInt(4)); - MultiRequest multiRequest = new MultiRequest(); + String REMIND_NAME = "미션 리마인드"; + + Optional> remainMissionPeople = missionArchiveScheduleQueryService.getRemainMissionPeople(); + + eventPublisher.publishEvent(new MultiFcmEvent(title, message, remainMissionPeople, remainMissionPeople, + null,REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + return true; } + public String getTitle(int num) { switch (num) { case 0: diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 95d853cf..241f4eca 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -3,10 +3,7 @@ import com.moing.backend.domain.mission.application.dto.req.MissionReq; import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; -import com.moing.backend.domain.mission.application.service.MissionCreateUseCase; -import com.moing.backend.domain.mission.application.service.MissionDeleteUseCase; -import com.moing.backend.domain.mission.application.service.MissionReadUseCase; -import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; +import com.moing.backend.domain.mission.application.service.*; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -28,6 +25,8 @@ public class MissionController { private final MissionUpdateUseCase missionUpdateUseCase; private final MissionDeleteUseCase missionDeleteUseCase; +// private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; + /** * 미션 조회 * [GET] {teamId}/missions/{missionId} @@ -103,6 +102,11 @@ public ResponseEntity> isLeader(@AuthenticationPrincipa return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionCreateUseCase.getIsLeader(user.getSocialId(),teamId))); } +// @PostMapping("/remind") +// public ResponseEntity> remindAlarm(@AuthenticationPrincipal User user,@PathVariable Long teamId) { +// return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionRemindAlarmUseCase.sendRemindMissionAlarm())); +// } + diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 3bd7464f..db18bb38 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -32,7 +32,4 @@ public interface MissionArchiveCustomRepository { Boolean findMyArchivesToday(Long memberId,Long missionId); - Optional> findPeopleRemainMission(); - - } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 0fe57dc1..d0b635ca 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -4,12 +4,16 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; +import com.moing.backend.domain.mission.domain.entity.QMission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; +import com.moing.backend.domain.team.domain.entity.QTeam; +import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; import com.querydsl.core.Tuple; import com.querydsl.core.types.Expression; import com.querydsl.core.types.Order; @@ -18,6 +22,7 @@ import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; import feign.Param; import lombok.extern.slf4j.Slf4j; @@ -342,34 +347,11 @@ public Boolean findMyArchivesToday(Long memberId, Long missionId) { } - public Optional> findPeopleRemainMission() { - return Optional.ofNullable(queryFactory - .select(teamMember.member.nickName).distinct() - .from(teamMember) - .join(teamMember.team, team) - .join(team.missions, mission) - .join(mission.missionStateList,missionState) - .on( - mission.eq(missionState.mission), - teamMember.member.eq(missionState.member), - mission.number.loe(missionState.count())) -// .on(missionState.isNull()) - .where( - mission.status.eq(MissionStatus.END).or(mission.status.eq(MissionStatus.SUCCESS)).not() -// missionState.isNull()) - ).fetch()); // .where( // // active 한 미션 필터링 // (((mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT))).and(mission.type.eq(MissionType.ONCE))) // .or((mission.status.eq(MissionStatus.ONGOING)).and(mission.type.eq(MissionType.REPEAT)))), -// // 인증하지 않은값 -// missionState.id.isNull() - - -// ).fetch()); - } - private BooleanExpression createRepeatTypeConditionByArchive() { LocalDate now = LocalDate.now(); DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; @@ -405,5 +387,4 @@ private BooleanExpression createRepeatTypeConditionByState() { - } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java index 4b6065b5..e4459dc9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -1,15 +1,22 @@ package com.moing.backend.domain.missionArchive.domain.repository; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.querydsl.core.Tuple; import feign.Param; +import org.hibernate.annotations.NamedNativeQuery; import org.hibernate.annotations.Parameter; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import javax.persistence.ColumnResult; +import javax.persistence.ConstructorResult; +import javax.persistence.SqlResultSetMapping; import java.util.List; +import java.util.Map; import java.util.Optional; @Repository @@ -28,4 +35,47 @@ public interface MissionArchiveRepository extends JpaRepository> findRepeatMissionArchivesByMission (@Param("memberId") Long memberId, @Param("missionIds") List missionIds); + +// @Query(value = "SELECT distinct tmSub.fcm_token, tmSub.member_id" + +// "FROM ( " + +// " SELECT distinct COALESCE(tm.member_id, 0) AS member_id, t.team_id, me.fcm_token " + +// " FROM mission m " + +// " LEFT JOIN team t ON m.team_id = t.team_id " + +// " LEFT JOIN team_member tm ON t.team_id = tm.team_id AND tm.is_deleted = 'False' " + +// " LEFT JOIN member me on tm.member_id = me.member_id " + +// " ) tmSub " + +// " LEFT JOIN mission m ON NOT (m.status = 'END' OR m.status = 'SUCCESS') and m.team_id = tmSub.team_id " + +// " LEFT JOIN mission_archive ms ON m.mission_id = ms.mission_id and ms.member_id = tmSub.member_id " + +// "GROUP BY tmSub.member_id, m.mission_id, m.number " + +// "having COUNT(ms.mission_archive_id) < m.number", nativeQuery = true) +// Optional> findHavingRemainMissions(); + + + @Query(value = "SELECT distinct COALESCE(tmSub.fcm_token,'undef') as fcmToken, tmSub.member_id as memberId " + + "FROM (SELECT distinct COALESCE(tm.member_id, 0) AS member_id, t.team_id, me.fcm_token " + + "FROM mission m " + + "LEFT JOIN team t ON m.team_id = t.team_id " + + "LEFT JOIN team_member tm ON t.team_id = tm.team_id AND tm.is_deleted = 'False' " + + "LEFT JOIN member me on tm.member_id = me.member_id) tmSub " + + "LEFT JOIN mission m ON NOT (m.status = 'END' OR m.status = 'SUCCESS') and m.team_id = tmSub.team_id " + + "LEFT JOIN mission_archive ms ON m.mission_id = ms.mission_id and ms.member_id = tmSub.member_id " + + "GROUP BY tmSub.member_id, m.mission_id, m.number " + + "HAVING COUNT(ms.mission_archive_id) < m.number", nativeQuery = true + ) + Optional>> findHavingRemainMissions(); + + +// @Query(value = "SELECT distinct tmSub.fcm_token as fcmToken, tmSub.member_id as memberId " + +// "FROM (SELECT distinct COALESCE(tm.member_id, 0) AS member_id, t.team_id, me.fcm_token " + +// "FROM mission m " + +// "LEFT JOIN team t ON m.team_id = t.team_id " + +// "LEFT JOIN team_member tm ON t.team_id = tm.team_id AND tm.is_deleted = 'False' " + +// "LEFT JOIN member me on tm.member_id = me.member_id) tmSub " + +// "LEFT JOIN mission m ON NOT (m.status = 'END' OR m.status = 'SUCCESS') and m.team_id = tmSub.team_id " + +// "LEFT JOIN mission_archive ms ON m.mission_id = ms.mission_id and ms.member_id = tmSub.member_id " + +// "GROUP BY tmSub.member_id, m.mission_id, m.number " + +// "HAVING COUNT(ms.mission_archive_id) < m.number", nativeQuery = true +// ) +// Optional> findHavingRemainMissions(); + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java index e2f8585c..b0df8228 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.domain.service; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; @@ -7,7 +8,11 @@ import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; +import java.math.BigInteger; import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; @DomainService @Transactional @@ -17,8 +22,39 @@ public class MissionArchiveScheduleQueryService { private final MissionArchiveRepository missionArchiveRepository; - public List getRemainMissionPeople() { - return missionArchiveRepository.findPeopleRemainMission().orElseThrow(); + public Optional> getRemainMissionPeople() { + List> maps = missionArchiveRepository.findHavingRemainMissions().orElseThrow(); + + return Optional.ofNullable(maps.stream() + .map(map -> { + Object memberIdObject = map.get("memberId"); + Long memberId = ((BigInteger) memberIdObject).longValue(); + + Object fcmObject = map.get("fcmToken"); + String fcmToken = fcmObject.toString(); + + return MemberIdAndToken.builder() + .fcmToken(fcmToken) + .memberId(memberId) + .build(); + }) + .collect(Collectors.toList())); + +// return null; + +// return maps.stream() +// .map(map -> { +// String fcmToken = Optional.ofNullable(map.get("fcmToken")).map(Object::toString).orElse("undef"); +// Long memberId = map.get("memberId"); +// +// return MemberIdAndToken.builder() +// .fcmToken(fcmToken) +// .memberId(memberId) +// .build(); +// +// }) +// .collect(Collectors.toList()); + } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java index 5b9db754..b836a936 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java @@ -1,5 +1,8 @@ //package com.moing.backend.domain.missionArchive.domain.repository; // +//import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +//import com.moing.backend.domain.mission.application.service.MissionRemindAlarmUseCase; +//import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveScheduleQueryService; //import com.querydsl.jpa.impl.JPAQueryFactory; //import org.junit.jupiter.api.Test; //import org.springframework.beans.factory.annotation.Autowired; @@ -21,10 +24,23 @@ // @Autowired // private MissionArchiveRepository missionArchiveRepository; // +// @Autowired +// MissionRemindAlarmUseCase missionRemindAlarmUseCase; +// +// @Autowired +// MissionArchiveScheduleQueryService missionArchiveScheduleQueryService; +// +// // @Test // void findPeopleRemainMission() { // -// System.out.println("!!!"+ missionArchiveRepository.findPeopleRemainMission()); +// //System.out.println("!!!"+ missionArchiveRepository.findHavingRemainMissions().get().size()); +// +// List remainMissionPeople = missionArchiveScheduleQueryService.getRemainMissionPeople().orElseThrow(); +// for (MemberIdAndToken remainMissionPerson : remainMissionPeople) { +// System.out.println("!!"+remainMissionPerson.getFcmToken() + " " + remainMissionPerson.getMemberId()); // +// } +// missionRemindAlarmUseCase.sendRemindMissionAlarm(); // } //} \ No newline at end of file From 20ce5e3ae68cd95ad2f1ef158f5e7037453c88d6 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 13 Dec 2023 20:46:10 +0900 Subject: [PATCH 378/619] =?UTF-8?q?fix:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20=EB=8B=89=EB=84=A4=EC=9E=84=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mypage/application/service/ProfileUseCase.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java index 9d22bde5..45ed4cb5 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java @@ -1,6 +1,8 @@ package com.moing.backend.domain.mypage.application.service; +import com.moing.backend.domain.auth.exception.NicknameDuplicationException; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberCheckService; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mypage.application.dto.request.UpdateProfileRequest; import com.moing.backend.domain.mypage.application.dto.response.GetProfileResponse; @@ -15,6 +17,7 @@ public class ProfileUseCase { private final MemberGetService memberGetService; private final UpdateUtils updateUtils; + private final MemberCheckService memberCheckService; @Transactional(readOnly = true) public GetProfileResponse getProfile(String socialId){ @@ -33,6 +36,10 @@ public void updateProfile(String socialId, UpdateProfileRequest updateProfileReq UpdateUtils.getUpdatedValue(updateProfileRequest.getIntroduction(), member.getIntroduction()) ); + if(updateProfileRequest.getNickName()!=null){ + if(memberCheckService.checkNickname(updateProfileRequest.getNickName())) throw new NicknameDuplicationException(); //닉네임 중복검사 (이중체크) + } + updateUtils.deleteOldImgUrl(updateProfileRequest.getProfileImage(), oldProfileImageUrl); } From fc57b2a322f78eca59bb60b9a9d297a4ff138088 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 13 Dec 2023 21:37:54 +0900 Subject: [PATCH 379/619] =?UTF-8?q?fix:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20=EB=8B=89=EB=84=A4=EC=9E=84=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=EA=B2=80=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mypage/application/service/ProfileUseCase.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java index 45ed4cb5..f498edaa 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/ProfileUseCase.java @@ -29,6 +29,9 @@ public GetProfileResponse getProfile(String socialId){ public void updateProfile(String socialId, UpdateProfileRequest updateProfileRequest) { Member member = memberGetService.getMemberBySocialId(socialId); String oldProfileImageUrl = member.getProfileImage(); + if(updateProfileRequest.getNickName()!=null){ + if(memberCheckService.checkNickname(updateProfileRequest.getNickName())) throw new NicknameDuplicationException(); //닉네임 중복검사 (이중체크) + } member.updateProfile( UpdateUtils.getUpdatedValue(updateProfileRequest.getProfileImage(), member.getProfileImage()), @@ -36,10 +39,6 @@ public void updateProfile(String socialId, UpdateProfileRequest updateProfileReq UpdateUtils.getUpdatedValue(updateProfileRequest.getIntroduction(), member.getIntroduction()) ); - if(updateProfileRequest.getNickName()!=null){ - if(memberCheckService.checkNickname(updateProfileRequest.getNickName())) throw new NicknameDuplicationException(); //닉네임 중복검사 (이중체크) - } - updateUtils.deleteOldImgUrl(updateProfileRequest.getProfileImage(), oldProfileImageUrl); } From 7b9274ed34f3153ec2f01e70cfeca1823bd384ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 13 Dec 2023 23:50:20 +0900 Subject: [PATCH 380/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=20=EC=B2=98=EB=A6=AC=EA=B0=80=20=EC=95=88?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EC=9D=B4=EC=8A=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionRemindAlarmUseCase.java | 2 +- .../presentation/MissionController.java | 2 +- .../service/MissionStateScheduleUseCase.java | 3 +-- ...issionArchiveCustomRepositoryImplTest.java | 27 +++++++++++++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index f8cf8e54..1df2ad82 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -41,7 +41,7 @@ public Boolean sendRemindMissionAlarm() { Optional> remainMissionPeople = missionArchiveScheduleQueryService.getRemainMissionPeople(); eventPublisher.publishEvent(new MultiFcmEvent(title, message, remainMissionPeople, remainMissionPeople, - null,REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); return true; } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 241f4eca..9a088b08 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -25,7 +25,7 @@ public class MissionController { private final MissionUpdateUseCase missionUpdateUseCase; private final MissionDeleteUseCase missionDeleteUseCase; -// private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; + private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; /** * 미션 조회 diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 5e5fe463..a73440eb 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.mission.domain.service.MissionSaveService; import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; @@ -33,7 +34,6 @@ public class MissionStateScheduleUseCase { private final MissionStateQueryService missionStateQueryService; private final MissionStateDeleteService missionStateDeleteService; - private final TeamScoreLogicUseCase teamScoreLogicUseCase; /** @@ -68,7 +68,6 @@ public void singleMissionEndRoutine() { teamScoreLogicUseCase.updateTeamScore(mission.getId()); }); - } /** diff --git a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java index b836a936..823795a4 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java @@ -1,7 +1,11 @@ //package com.moing.backend.domain.missionArchive.domain.repository; // //import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +//import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; //import com.moing.backend.domain.mission.application.service.MissionRemindAlarmUseCase; +//import com.moing.backend.domain.mission.domain.entity.Mission; +//import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +//import com.moing.backend.domain.mission.domain.repository.MissionRepository; //import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveScheduleQueryService; //import com.querydsl.jpa.impl.JPAQueryFactory; //import org.junit.jupiter.api.Test; @@ -25,6 +29,9 @@ // private MissionArchiveRepository missionArchiveRepository; // // @Autowired +// private MissionRepository missionRepository; +// +// @Autowired // MissionRemindAlarmUseCase missionRemindAlarmUseCase; // // @Autowired @@ -43,4 +50,24 @@ // } // missionRemindAlarmUseCase.sendRemindMissionAlarm(); // } +// +// +// @Test +// void findEndMission() { +// List missionByDueTo = missionRepository.findMissionByDueTo().orElseThrow(); +// for (Mission mission1 : missionByDueTo) { +// System.out.println(mission1.getTitle()+ mission1.getStatus()); +// mission1.updateStatus(MissionStatus.END); +// System.out.println(mission1.getStatus()); +// } +// } +// +// +// @Test +// void findInCompleteMission() { +// List singleMissionBoardResList = missionArchiveRepository.findSingleMissionInComplete(33L, 48L, MissionStatus.ONGOING, OrderCondition.DUETO).orElseThrow(); +// for (SingleMissionBoardRes singleMissionBoardRes : singleMissionBoardResList) { +// System.out.println(singleMissionBoardRes.getTitle()); +// } +// } //} \ No newline at end of file From f66283457b129fe0a2de7546dab37fc3aed1c601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 14 Dec 2023 00:08:39 +0900 Subject: [PATCH 381/619] =?UTF-8?q?fix=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98=EC=97=90=20=EC=99=84=EB=A3=8C=ED=95=9C=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EB=9C=A8=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionCustomRepositoryImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 1c68138b..2c0d4bda 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -136,8 +136,8 @@ public Optional> findSingleMissionByMemberId(Long m .where( mission.team.teamId.in(teams), mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), - mission.type.eq(MissionType.ONCE) - //missionState.id.isNull() + mission.type.eq(MissionType.ONCE), + missionState.id.isNull() ) .orderBy(mission.dueTo.asc()) .fetch()); From 185f3f125a4fe63d28a2929c807733bae19446c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 14 Dec 2023 00:14:40 +0900 Subject: [PATCH 382/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=83=9D=EC=84=B1=20=EA=B0=9C=EC=88=98=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 2c0d4bda..900cffb5 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -151,7 +151,7 @@ public boolean findRepeatMissionsByTeamId(Long teamId) { mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT), mission.status.eq(MissionStatus.ONGOING) - ).fetchCount() < 2; + ).fetchCount() < 3; } @Override From 8cbc5813b720ad77a5a5ffc629459941d3536d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 14 Dec 2023 00:15:14 +0900 Subject: [PATCH 383/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=83=9D=EC=84=B1=20=EC=97=90=EB=9F=AC=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/moing/backend/global/response/ErrorCode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 2bfa13ad..2534fdb6 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -29,7 +29,7 @@ public enum ErrorCode { NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), NOT_FOUND_MISSION("M0002", "미션을 찾을 수 없습니다."), NOT_FOUND_END_MISSION("M0003", "기한이 지난 미션을 찾을 수 없습니다."), - NO_MORE_CREATE_MISSION("M0004", "반복미션은 3개까지 생성할 수 있습니다."), + NO_MORE_CREATE_MISSION("M0004", "반복미션은 2개까지 생성할 수 있습니다."), NOT_FOUND_MISSION_ARCHIVE("MA0001", "아직 미션을 제출하지 않았습니다."), NOT_YET_MISSION_ARCHIVE("MA0001", "아직 미션을 제출할 수 없습니다."), NO_MORE_ARCHIVE_ERROR("MA0001", "지정한 횟수 이상 미션을 인증할 수 없습니다."), From 6d0eb4115e0d3e9dec668f7098609aa5bfec1f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 14 Dec 2023 00:22:39 +0900 Subject: [PATCH 384/619] =?UTF-8?q?fix=20:=20Missioncontroller=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/mission/presentation/MissionController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 9a088b08..241f4eca 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -25,7 +25,7 @@ public class MissionController { private final MissionUpdateUseCase missionUpdateUseCase; private final MissionDeleteUseCase missionDeleteUseCase; - private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; +// private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; /** * 미션 조회 From 201091ffb655a38c081de6d2ae2534109481911f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 14 Dec 2023 00:38:03 +0900 Subject: [PATCH 385/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=83=9D=EC=84=B1=20=EA=B0=9C=EC=88=98=EC=A0=9C?= =?UTF-8?q?=ED=95=9C=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 900cffb5..8b495648 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -151,7 +151,7 @@ public boolean findRepeatMissionsByTeamId(Long teamId) { mission.team.teamId.eq(teamId), mission.type.eq(MissionType.REPEAT), mission.status.eq(MissionStatus.ONGOING) - ).fetchCount() < 3; + ).fetchCount() > 2; } @Override From e6d25acb04ce4ac127d132728cfae6e06b30afe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 14 Dec 2023 00:51:52 +0900 Subject: [PATCH 386/619] =?UTF-8?q?fix=20:=20missionArchive=20=EC=99=80=20?= =?UTF-8?q?missionHeart=20Cascade=20=EA=B4=80=EA=B3=84=20=EC=9E=AC?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/missionArchive/domain/entity/MissionArchive.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index a3c684dc..9cc2a7bf 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -45,7 +45,7 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 private Long count; // 횟수 - @OneToMany(mappedBy = "missionArchive") + @OneToMany(mappedBy = "missionArchive", cascade = CascadeType.REMOVE) private List heartList = new ArrayList<>(); From 5310d664f144e69ed64a72bf4be675bcaa33cad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:21:48 +0900 Subject: [PATCH 387/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=EB=8B=A4=ED=95=9C=20=EC=9D=B8?= =?UTF-8?q?=EC=9B=90=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveReadUseCase.java | 11 +++++++++- .../MissionArchiveCustomRepository.java | 1 + .../MissionArchiveCustomRepositoryImpl.java | 20 +++++++++++++++++++ .../service/MissionArchiveQueryService.java | 9 ++++----- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java index 4b018484..497ddb9a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.application.dto.res.*; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; @@ -58,9 +59,17 @@ public MissionArchiveStatusRes getMissionDoneStatus(Long missionId) { Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); + String done = "0"; + + if (mission.getType().equals(MissionType.ONCE)) { + done = missionArchiveQueryService.findDoneSingleArchives(missionId).toString(); + } else { + done = missionArchiveQueryService.findDoneRepeatArchives(missionId).toString(); + } + return MissionArchiveStatusRes.builder() .total(team.getNumOfMember().toString()) - .done(missionArchiveQueryService.findDoneArchives(missionId).toString()) + .done(done) .build(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index db18bb38..d5514aaa 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -22,6 +22,7 @@ public interface MissionArchiveCustomRepository { Optional> findOthersArchives(Long memberId, Long missionId) ; Optional findDonePeopleByMissionId(Long missionId); + Optional findDonePeopleByRepeatMissionId(Long missionId); Optional findMyDoneCountByMissionId(Long missionId,Long memberId); Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index d0b635ca..a330416e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -208,6 +208,26 @@ public Optional findDonePeopleByMissionId(Long missionId) { ); } + @Override + public Optional findDonePeopleByRepeatMissionId(Long missionId) { + + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + + return Optional.of(queryFactory + .select(missionArchive) + .from(missionArchive) + .where( + missionArchive.mission.id.eq(missionId), + + missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) + .or(missionArchive.mission.type.eq(MissionType.ONCE)) + ) + .groupBy(missionArchive.member,missionArchive.mission.number) + .having(missionArchive.count().goe(missionArchive.mission.number)) + .fetchCount() + + ); + } @Override public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 9e081919..a374bbbd 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -1,7 +1,6 @@ package com.moing.backend.domain.missionArchive.domain.service; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; -import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; @@ -18,9 +17,6 @@ import java.util.*; -import static com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus.*; -import static com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus.INCOMPLETE; - @DomainService @Transactional @RequiredArgsConstructor @@ -109,9 +105,12 @@ public List findMyRepeatMissionArchives(Long memberId, Lo } - public Long findDoneArchives(Long missionId) { + public Long findDoneSingleArchives(Long missionId) { return missionArchiveRepository.findDonePeopleByMissionId(missionId).orElseThrow(NotFoundMissionArchiveException::new); } + public Long findDoneRepeatArchives(Long missionId) { + return missionArchiveRepository.findDonePeopleByRepeatMissionId(missionId).orElseThrow(NotFoundMissionArchiveException::new); + } public Long findMyDoneArchives(Long memberId, Long missionId) { return missionArchiveRepository.findMyDoneCountByMissionId(missionId, memberId).orElseThrow(NotFoundMissionArchiveException::new); From 2119f9181855d84e9d39b18f0592db1888943408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:44:17 +0900 Subject: [PATCH 388/619] =?UTF-8?q?fix=20:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=EC=A7=81=ED=9B=84=20?= =?UTF-8?q?=EC=9D=B8=EC=9B=90=EC=88=98=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/MissionArchiveRes.java | 4 ++++ .../service/MissionArchiveCreateUseCase.java | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index d562fcfd..10b73af9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -19,5 +19,9 @@ public class MissionArchiveRes { private String heartStatus; private Long hearts; + public void updateCount(Long count) { + this.count = count; + } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 5a1463fd..97dc7273 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -62,6 +62,8 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss throw new NoMoreMissionArchiveException(); } + MissionArchiveRes missionArchiveRes; + // 반복 미션일 경우 if (mission.getType() == MissionType.REPEAT) { // 예정된 반복미션 접근 제한 @@ -74,12 +76,21 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss else throw new NoMoreMissionArchiveException(); - }else { + missionStateUseCase.updateMissionState(member, mission, newArchive); + missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); + + + } else { newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); + + missionStateUseCase.updateMissionState(member, mission, newArchive); + missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); + missionArchiveRes.updateCount(missionArchiveQueryService.findDoneSingleArchives(missionId)); } - missionStateUseCase.updateMissionState(member, mission, newArchive); - return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive),memberId); +// missionStateUseCase.updateMissionState(member, mission, newArchive); +// missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); + return missionArchiveRes; } From fd486506b6996f8e780fd60c8dc8a192cd95c3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 14 Dec 2023 16:19:32 +0900 Subject: [PATCH 389/619] =?UTF-8?q?fix=20:=20=ED=8C=80=20=EC=8A=A4?= =?UTF-8?q?=EC=BD=94=EC=96=B4=20=EB=A1=9C=EC=A7=81=200=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EB=82=98=EB=88=84=EA=B8=B0=20=EC=98=88=EC=99=B8=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/TeamScoreLogicUseCase.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index 02fa9c9a..8323c1b5 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -65,7 +65,11 @@ public Long getScoreByMission(Mission mission) { Long total = totalPeople(mission); Long done = donePeople(mission); - return (done / total * 100) / 5 ; + if (done == 0) { + return 0L; + } else { + return (done / total * 100) / 5 ; + } } From d75a2ab53164eb70747df053c9b29cac254f5a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 15 Dec 2023 19:41:50 +0900 Subject: [PATCH 390/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=8B=9C=EC=9E=91=20d-1=20=EB=A6=AC=EB=A7=88?= =?UTF-8?q?=EC=9D=B8=EB=93=9C=20=EC=95=8C=EB=A6=BC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionRemindAlarmUseCase.java | 34 ++++++++++++++++++- .../repository/MissionCustomRepository.java | 6 +++- .../MissionCustomRepositoryImpl.java | 17 ++++++++++ .../domain/service/MissionQueryService.java | 6 +++- .../presentation/MissionController.java | 2 +- .../MissionArchiveScheduleQueryService.java | 2 +- .../service/MissionStateScheduleUseCase.java | 12 +++---- .../fcm/constant/RemindMissionTitle.java | 14 +++++--- 8 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index 1df2ad82..c95fe319 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -3,7 +3,10 @@ import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveScheduleQueryService; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; @@ -18,6 +21,7 @@ import java.util.List; import java.util.Optional; import java.util.Random; +import java.util.stream.Collectors; import static com.moing.backend.global.config.fcm.constant.RemindMissionTitle.*; @@ -27,8 +31,11 @@ public class MissionRemindAlarmUseCase { private final MissionArchiveScheduleQueryService missionArchiveScheduleQueryService; + private final MissionQueryService missionQueryService; private final ApplicationEventPublisher eventPublisher; + String REMIND_NAME = "미션 리마인드"; + public Boolean sendRemindMissionAlarm() { @@ -36,7 +43,6 @@ public Boolean sendRemindMissionAlarm() { String title = getTitle(random.nextInt(4)); String message = getMessage(random.nextInt(4)); - String REMIND_NAME = "미션 리마인드"; Optional> remainMissionPeople = missionArchiveScheduleQueryService.getRemainMissionPeople(); @@ -75,4 +81,30 @@ public String getMessage(int num) { } + + public Boolean sendRepeatMissionRemind() { + + List repeatMissionByStatus = missionQueryService.findRepeatMissionPeopleByStatus(MissionStatus.WAIT); + + Optional> memberIdAndTokens = mapToMemberAndToken(repeatMissionByStatus); + + eventPublisher.publishEvent(new MultiFcmEvent(REMIND_ON_SUNDAY_TITLE.getMessage(), REMIND_ON_SUNDAY_MESSAGE.getMessage(), memberIdAndTokens, memberIdAndTokens, + "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + return true; + + + } + + public Optional> mapToMemberAndToken(List members) { + return Optional.of(members.stream() + .map(member -> MemberIdAndToken.builder() + .fcmToken(member.getFcmToken()) + .memberId(member.getMemberId()) + .build()) + .collect(Collectors.toList())); + } + + + + } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index e0610615..ee3cd340 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.mission.domain.repository; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; @@ -24,7 +25,10 @@ public interface MissionCustomRepository { Optional> findRepeatMissionByStatus(MissionStatus missionStatus); - boolean findRepeatMissionsByTeamId(Long teamId); + Optional> findRepeatMissionPeopleByStatus(MissionStatus missionStatus); + + + boolean findRepeatMissionsByTeamId(Long teamId); Optional findByIds(Long memberId, Long missionId); diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 8b495648..007bdb2a 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.mission.domain.repository; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; @@ -26,6 +27,7 @@ import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; +import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; public class MissionCustomRepositoryImpl implements MissionCustomRepository{ @@ -106,6 +108,21 @@ public Optional> findOngoingRepeatMissions() { .fetch()); } + @Override + public Optional> findRepeatMissionPeopleByStatus(MissionStatus missionStatus) { + + return Optional.ofNullable(queryFactory + .select(teamMember.member).distinct() + .from(teamMember) + .join(mission) + .on(teamMember.team.eq(mission.team)) + .where( + mission.status.eq(missionStatus), + mission.type.eq(MissionType.REPEAT) + ).fetch()); + + + } @Override public Optional> findRepeatMissionByStatus(MissionStatus missionStatus) { return Optional.ofNullable(queryFactory diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 136f5c43..324540ad 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -75,7 +75,11 @@ public boolean isAbleCreateRepeatMission(Long teamId) { return missionRepository.findRepeatMissionsByTeamId(teamId); } - public List findMissionByStatus(MissionStatus missionStatus) { + public List findRepeatMissionPeopleByStatus(MissionStatus missionStatus) { + return missionRepository.findRepeatMissionPeopleByStatus(missionStatus).orElseThrow(NotFoundMissionException::new + ); + } + public List findRepeatMissionByStatus(MissionStatus missionStatus) { return missionRepository.findRepeatMissionByStatus(missionStatus).orElseThrow(NotFoundMissionException::new ); } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 241f4eca..35c456fe 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -104,7 +104,7 @@ public ResponseEntity> isLeader(@AuthenticationPrincipa // @PostMapping("/remind") // public ResponseEntity> remindAlarm(@AuthenticationPrincipal User user,@PathVariable Long teamId) { -// return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionRemindAlarmUseCase.sendRemindMissionAlarm())); +// return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionRemindAlarmUseCase.sendRepeatMissionRemind())); // } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java index b0df8228..152d78ad 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java @@ -25,7 +25,7 @@ public class MissionArchiveScheduleQueryService { public Optional> getRemainMissionPeople() { List> maps = missionArchiveRepository.findHavingRemainMissions().orElseThrow(); - return Optional.ofNullable(maps.stream() + return Optional.of(maps.stream() .map(map -> { Object memberIdObject = map.get("memberId"); Long memberId = ((BigInteger) memberIdObject).longValue(); diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index a73440eb..0a1b3e1d 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -76,17 +76,15 @@ public void singleMissionEndRoutine() { */ @Scheduled(cron = "0 0 0 * * MON") public void RepeatMissionStart() { - List startMission = missionQueryService.findMissionByStatus(MissionStatus.WAIT); + List startMission = missionQueryService.findRepeatMissionByStatus(MissionStatus.WAIT); startMission.forEach( mission -> mission.updateStatus(MissionStatus.ONGOING) ); } -// @Scheduled(cron = "8 0 0 * * *") -// public void MissionRemindAlarm() { -// -// -// missionRemindAlarmUseCase.sendRemindMissionAlarm(); -// } + @Scheduled(cron = "8 0 0 * * *") + public void MissionRemindAlarm() { + missionRemindAlarmUseCase.sendRemindMissionAlarm(); + } } diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java index 662d90e9..1e0c64f4 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java @@ -13,10 +13,16 @@ public enum RemindMissionTitle { REMIND_MISSION_TITLE4("오늘의 열정이 타오르불\uD83D\uDD25"), - REMIND_MISSION_MESSAGE1(" 자기계발 미션 도전과 함께⚡\uFE0F "), - REMIND_MISSION_MESSAGE2(" 미션 인증을 모임원들이 기다리고 있어요!"), - REMIND_MISSION_MESSAGE3(" 미션 인증하고 이번주도 도전해요👊 "), - REMIND_MISSION_MESSAGE4(" 미션 도전하고 성취감 뿜뿜💪 "); + REMIND_MISSION_MESSAGE1("자기계발 미션 도전과 함께⚡\uFE0F "), + REMIND_MISSION_MESSAGE2("미션 인증을 모임원들이 기다리고 있어요!"), + REMIND_MISSION_MESSAGE3("미션 인증하고 이번주도 도전해요👊"), + REMIND_MISSION_MESSAGE4("미션 도전하고 성취감 뿜뿜💪"), + + + REMIND_ON_SUNDAY_TITLE("이번 한 주도 고생 많았어요\uD83D\uDE0A"), + REMIND_ON_SUNDAY_MESSAGE("내일부터 미션을 다시 시작해봐요\uD83D\uDCAA"); + + private final String message; From 99e3a35470fd2c536f424e074dd86a9c1fb86156 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 15 Dec 2023 20:13:20 +0900 Subject: [PATCH 391/619] =?UTF-8?q?fix:=20eventListener=20=EC=96=B4?= =?UTF-8?q?=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/global/config/fcm/util/FcmMessageUtil.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java index de18a5a6..39cb3d92 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java +++ b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java @@ -9,10 +9,9 @@ import com.moing.backend.global.config.fcm.dto.request.SingleRequest; import com.moing.backend.global.config.fcm.service.FcmService; import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import org.springframework.transaction.event.TransactionPhase; -import org.springframework.transaction.event.TransactionalEventListener; @Component @RequiredArgsConstructor @@ -23,7 +22,7 @@ public class FcmMessageUtil { private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; @Async - @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + @EventListener public void onMultiFcmEvent(MultiFcmEvent event) { if (event.getIdAndTokensByPush().isPresent() && !event.getIdAndTokensByPush().get().isEmpty()) { fcmService.sendMultipleDevices(new MultiRequest(event.getIdAndTokensByPush().get(), event.getTitle(), event.getBody(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); @@ -34,7 +33,7 @@ public void onMultiFcmEvent(MultiFcmEvent event) { } @Async - @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + @EventListener public void onSingleFcmEvent(SingleFcmEvent event) { if (event.getMember().isFirePush() && !event.getMember().isSignOut()) { //알림 on, 로그아웃 안함 fcmService.sendSingleDevice(new SingleRequest(event.getMember().getFcmToken(), event.getTitle(), event.getBody(), event.getMember().getMemberId(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); From 8b733a1efb356825c5f60d8a46c1c4127a30da9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 17 Dec 2023 02:29:54 +0900 Subject: [PATCH 392/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionRemindAlarmUseCase.java | 35 +++++++++++++++++-- .../service/MissionStateScheduleUseCase.java | 9 +++++ .../fcm/constant/RemindMissionTitle.java | 5 ++- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index c95fe319..ef226b86 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -19,6 +19,7 @@ import javax.transaction.Transactional; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Random; import java.util.stream.Collectors; @@ -82,13 +83,29 @@ public String getMessage(int num) { } - public Boolean sendRepeatMissionRemind() { + public Boolean sendRepeatMissionRemindOnSunday() { List repeatMissionByStatus = missionQueryService.findRepeatMissionPeopleByStatus(MissionStatus.WAIT); Optional> memberIdAndTokens = mapToMemberAndToken(repeatMissionByStatus); + Optional> pushMemberIdAndToken = isPushMemberIdAndToken(repeatMissionByStatus); - eventPublisher.publishEvent(new MultiFcmEvent(REMIND_ON_SUNDAY_TITLE.getMessage(), REMIND_ON_SUNDAY_MESSAGE.getMessage(), memberIdAndTokens, memberIdAndTokens, + + eventPublisher.publishEvent(new MultiFcmEvent(REMIND_ON_SUNDAY_TITLE.getMessage(), REMIND_ON_SUNDAY_MESSAGE.getMessage(), pushMemberIdAndToken, memberIdAndTokens, + "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + return true; + + + } + + public Boolean sendRepeatMissionRemindOnMonday() { + + List repeatMissionByStatus = missionQueryService.findRepeatMissionPeopleByStatus(MissionStatus.ONGOING); + + Optional> memberIdAndTokens = mapToMemberAndToken(repeatMissionByStatus); + Optional> pushMemberIdAndToken = isPushMemberIdAndToken(repeatMissionByStatus); + + eventPublisher.publishEvent(new MultiFcmEvent(REMIND_ON_MONDAY_TITLE.getMessage(), REMIND_ON_MONDAY_MESSAGE.getMessage(), pushMemberIdAndToken, memberIdAndTokens, "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); return true; @@ -103,6 +120,20 @@ public Optional> mapToMemberAndToken(List members .build()) .collect(Collectors.toList())); } + public Optional> isPushMemberIdAndToken(List members) { + return Optional.of(members.stream() + .map(member -> { + if (member.isRemindPush() && !member.isSignOut()) { + return MemberIdAndToken.builder() + .fcmToken(member.getFcmToken()) + .memberId(member.getMemberId()) + .build(); + } + return null; + }) + .filter(Objects::nonNull) + .collect(Collectors.toList())); + } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 0a1b3e1d..572a2ac1 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -87,4 +87,13 @@ public void RepeatMissionStart() { public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } + @Scheduled(cron = "0 0 20 * * 0") + public void RepeatMissionRemindAlarmOnSunday() { + missionRemindAlarmUseCase.sendRepeatMissionRemindOnSunday(); + } + + @Scheduled(cron = "0 0 20 * * 1") + public void RepeatMissionRemindAlarmOnMonday() { + missionRemindAlarmUseCase.sendRepeatMissionRemindOnMonday(); + } } diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java index 1e0c64f4..d3455586 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java @@ -20,9 +20,12 @@ public enum RemindMissionTitle { REMIND_ON_SUNDAY_TITLE("이번 한 주도 고생 많았어요\uD83D\uDE0A"), - REMIND_ON_SUNDAY_MESSAGE("내일부터 미션을 다시 시작해봐요\uD83D\uDCAA"); + REMIND_ON_SUNDAY_MESSAGE("내일부터 미션을 다시 시작해봐요\uD83D\uDCAA"), + REMIND_ON_MONDAY_TITLE("경쾌한 한 주의 시작이에요!"), + REMIND_ON_MONDAY_MESSAGE("이번주에도 미션 도전을 응원해요\uD83D\uDE0A\n"); + private final String message; From 4f43225959f2244816bcf6a78f552bf60623a9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 17 Dec 2023 02:34:25 +0900 Subject: [PATCH 393/619] =?UTF-8?q?fix=20:=20=EB=A6=AC=EB=A7=88=EC=9D=B8?= =?UTF-8?q?=EB=93=9C=20=EC=95=8C=EB=A6=BC=20=EC=8B=9C=EC=9E=91=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionStateScheduleUseCase.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 572a2ac1..a094b41f 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -83,16 +83,16 @@ public void RepeatMissionStart() { } - @Scheduled(cron = "8 0 0 * * *") + @Scheduled(cron = "0 0 8 * * *") public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } - @Scheduled(cron = "0 0 20 * * 0") + @Scheduled(cron = "0 1 20 * * 0") public void RepeatMissionRemindAlarmOnSunday() { missionRemindAlarmUseCase.sendRepeatMissionRemindOnSunday(); } - @Scheduled(cron = "0 0 20 * * 1") + @Scheduled(cron = "0 1 20 * * 1") public void RepeatMissionRemindAlarmOnMonday() { missionRemindAlarmUseCase.sendRepeatMissionRemindOnMonday(); } From 85ee6a374a56227bac4f5c6fd35496f11540cbe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 17 Dec 2023 02:34:49 +0900 Subject: [PATCH 394/619] =?UTF-8?q?fix=20:=20=EC=9B=94=EC=9A=94=EC=9D=BC?= =?UTF-8?q?=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=EB=A6=AC=EB=A7=88?= =?UTF-8?q?=EC=9D=B8=EB=93=9C=20=EC=95=8C=EB=A6=BC=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/fcm/constant/RemindMissionTitle.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java index d3455586..7abd7a5d 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java @@ -23,8 +23,8 @@ public enum RemindMissionTitle { REMIND_ON_SUNDAY_MESSAGE("내일부터 미션을 다시 시작해봐요\uD83D\uDCAA"), - REMIND_ON_MONDAY_TITLE("경쾌한 한 주의 시작이에요!"), - REMIND_ON_MONDAY_MESSAGE("이번주에도 미션 도전을 응원해요\uD83D\uDE0A\n"); + REMIND_ON_MONDAY_TITLE("이번주의 도전을 응원할게요\uD83D\uDC4A"), + REMIND_ON_MONDAY_MESSAGE("모잉과 함께 달려볼까요?"); private final String message; From e1bc12ac587091bf27b9a530a2587c2e38213d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 17 Dec 2023 15:47:57 +0900 Subject: [PATCH 395/619] =?UTF-8?q?feat=20:=20=EC=8B=A0=EA=B3=A0=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20(=EA=B2=8C=EC=8B=9C=EB=AC=BC/=EB=AF=B8=EC=85=98?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D)=20=20=EB=82=B4=EC=9A=A9=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/mapper/ReportMapper.java | 3 +- .../service/ReportCreateUseCase.java | 56 ++++++++++++++++++- .../domain/report/domain/entity/Report.java | 1 + 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/report/application/mapper/ReportMapper.java b/src/main/java/com/moing/backend/domain/report/application/mapper/ReportMapper.java index 2190cec0..2d2d4472 100644 --- a/src/main/java/com/moing/backend/domain/report/application/mapper/ReportMapper.java +++ b/src/main/java/com/moing/backend/domain/report/application/mapper/ReportMapper.java @@ -7,11 +7,12 @@ @Mapper public class ReportMapper { - public static Report mapToReport(Long memberId, Long targetId, String reportType) { + public static Report mapToReport(Long memberId, Long targetId, String reportType,String targetMemberNickName) { return Report.builder() .reportMemberId(memberId) .reportType(ReportType.valueOf(reportType)) .targetId(targetId) + .targetMemberNickName(targetMemberNickName) .build(); } diff --git a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java index 73a2d2fa..a674cfce 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java @@ -1,8 +1,18 @@ package com.moing.backend.domain.report.application.service; +import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.report.application.mapper.ReportMapper; import com.moing.backend.domain.report.domain.entity.Report; +import com.moing.backend.domain.report.domain.entity.constant.ReportType; import com.moing.backend.domain.report.domain.service.ReportSaveService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -16,9 +26,53 @@ public class ReportCreateUseCase { private final ReportSaveService reportSaveService; private final MemberGetService memberGetService; + private final BoardGetService boardGetService; + private final MissionArchiveQueryService missionArchiveQueryService; + + private final String REPORT_BOARD_TITLE ="신고 접수된 게시물입니다."; + private final String REPORT_BOARD_MESSAGE ="신고 접수로 삭제된 게시물입니다."; + private final String REPORT_MISSION_MESSAGE ="신고 접수로 삭제된 인증입니다."; + private final String REPORT_MISSION_PHOTO ="https://modagbul.s3.ap-northeast-2.amazonaws.com/reportImage.png"; + + public Long createReport(String socialId, Long targetId, String reportType) { Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); - Report save = reportSaveService.save(ReportMapper.mapToReport(memberId, targetId, reportType)); + String targetMemberNickName = null ; + + if (reportType.equals(ReportType.BOARD.name())) { + Board board = boardGetService.getBoard(targetId); + + targetMemberNickName = board.getWriterNickName(); + + board.updateBoard(UpdateBoardRequest.builder() + .title(REPORT_BOARD_TITLE) + .content(REPORT_BOARD_MESSAGE) + .isNotice(board.isNotice()) + .build()); + } else { + + MissionArchive missionArchive = missionArchiveQueryService.findByMissionArchiveId(targetId); + Mission mission = missionArchive.getMission(); + + targetMemberNickName = missionArchive.getMember().getNickName(); + + if (mission.getWay().equals(MissionWay.PHOTO)) { + missionArchive.updateArchive(MissionArchiveReq.builder() + .archive(REPORT_MISSION_PHOTO) + .status(missionArchive.getStatus().name()) + .build()); + } else { + missionArchive.updateArchive(MissionArchiveReq.builder() + .archive(REPORT_MISSION_MESSAGE) + .status(missionArchive.getStatus().name()) + .build()); + + } + + } + + Report save = reportSaveService.save(ReportMapper.mapToReport(memberId, targetId, reportType,targetMemberNickName)); + return save.getTargetId(); } } diff --git a/src/main/java/com/moing/backend/domain/report/domain/entity/Report.java b/src/main/java/com/moing/backend/domain/report/domain/entity/Report.java index 505d0a2c..36146585 100644 --- a/src/main/java/com/moing/backend/domain/report/domain/entity/Report.java +++ b/src/main/java/com/moing/backend/domain/report/domain/entity/Report.java @@ -27,4 +27,5 @@ public class Report extends BaseTimeEntity { private Long reportMemberId; private Long targetId; + private String targetMemberNickName; } From fbba53c2d1a0eefbb9352b3abaeac3997f6f24eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 17 Dec 2023 15:58:04 +0900 Subject: [PATCH 396/619] =?UTF-8?q?fix=20:=20=EC=8B=A0=EA=B3=A0=EB=8B=B9?= =?UTF-8?q?=ED=95=9C=20=EC=9D=B8=EC=A6=9D=20=EC=82=AC=EC=A7=84=20=EC=86=8C?= =?UTF-8?q?=EB=AA=A8=EC=9E=84=20=EB=A9=94=EC=9D=B8=EC=97=90=20=EB=B3=B4?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=95=8A=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index a330416e..27bf4e3f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -314,7 +314,8 @@ public Optional> findTop5ArchivesByTeam(List .from(missionArchive) .where(missionArchive.mission.team.teamId.in(teamIds), missionArchive.mission.way.eq(MissionWay.PHOTO), - missionArchive.status.eq(MissionArchiveStatus.COMPLETE)) + missionArchive.status.eq(MissionArchiveStatus.COMPLETE), + missionArchive.archive.ne("https://modagbul.s3.ap-northeast-2.amazonaws.com/reportImage.png")) .orderBy(missionArchive.createdDate.desc()) .limit(14) .fetch(); From 6a8f9ccc96bf5064b25a1376f2373bcf4c89789b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 17 Dec 2023 18:17:47 +0900 Subject: [PATCH 397/619] =?UTF-8?q?fix=20:=20=EC=98=A4=EC=A0=84=208?= =?UTF-8?q?=EC=8B=9C=20=EB=AF=B8=EC=85=98=20=EB=A6=AC=EB=A7=88=EC=9D=B8?= =?UTF-8?q?=EB=93=9C=20=EC=95=8C=EB=A6=BC=20=EB=A1=9C=EC=A7=81=20=EA=B3=A0?= =?UTF-8?q?=EB=8F=84=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionRemindAlarmUseCase.java | 6 +- .../MissionArchiveCustomRepository.java | 2 + .../MissionArchiveCustomRepositoryImpl.java | 61 +++++++++++++++++++ .../repository/MissionArchiveRepository.java | 6 +- .../MissionArchiveScheduleQueryService.java | 34 +++++------ 5 files changed, 89 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index ef226b86..a9fb37f6 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -44,10 +44,12 @@ public Boolean sendRemindMissionAlarm() { String title = getTitle(random.nextInt(4)); String message = getMessage(random.nextInt(4)); + List remainMissionPeople = missionArchiveScheduleQueryService.getRemainMissionPeople(); - Optional> remainMissionPeople = missionArchiveScheduleQueryService.getRemainMissionPeople(); + Optional> memberIdAndTokens = mapToMemberAndToken(remainMissionPeople); + Optional> pushMemberIdAndToken = isPushMemberIdAndToken(remainMissionPeople); - eventPublisher.publishEvent(new MultiFcmEvent(title, message, remainMissionPeople, remainMissionPeople, + eventPublisher.publishEvent(new MultiFcmEvent(title, message, pushMemberIdAndToken, memberIdAndTokens, "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); return true; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index d5514aaa..20265798 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -33,4 +33,6 @@ public interface MissionArchiveCustomRepository { Boolean findMyArchivesToday(Long memberId,Long missionId); + Optional> findHavingRemainMissionsByQuerydsl() ; + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 27bf4e3f..0bc185f7 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -44,6 +44,7 @@ import static com.moing.backend.domain.team.domain.entity.QTeam.team; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; import static javax.swing.Spring.constant; +import static org.springframework.data.jpa.domain.Specification.not; import static org.springframework.data.jpa.domain.Specification.where; @Slf4j @@ -406,6 +407,66 @@ private BooleanExpression createRepeatTypeConditionByState() { return dateInRange.and(dateInRange); } +// +// @Query(value = "SELECT distinct COALESCE(tmSub.fcm_token,'undef') as fcmToken, tmSub.member_id as memberId " + +// "FROM (SELECT distinct COALESCE(tm.member_id, 0) AS member_id, t.team_id, me.fcm_token " + +// "FROM mission m " + +// "LEFT JOIN team t ON m.team_id = t.team_id " + +// "LEFT JOIN team_member tm ON t.team_id = tm.team_id AND tm.is_deleted = 'False' " + +// "LEFT JOIN member me on tm.member_id = me.member_id) tmSub " + +// "LEFT JOIN mission m ON NOT (m.status = 'END' OR m.status = 'SUCCESS') and m.team_id = tmSub.team_id " + +// "LEFT JOIN mission_archive ms ON m.mission_id = ms.mission_id and ms.member_id = tmSub.member_id " + +// "GROUP BY tmSub.member_id, m.mission_id, m.number " + +// "HAVING COUNT(ms.mission_archive_id) < m.number", nativeQuery = true +// ) + + @Override + public Optional> findHavingRemainMissionsByQuerydsl() { + + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + + return Optional.ofNullable(queryFactory + .select(teamMember.member).distinct() + .from(teamMember) + .join(mission) + .on(teamMember.team.eq(mission.team), + ((mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT))) + .and(mission.type.eq(MissionType.ONCE))) + .or(mission.status.eq(MissionStatus.ONGOING).and(mission.type.eq(MissionType.REPEAT))) + ) + .leftJoin(missionArchive) + .on(missionArchive.mission.eq(mission), + missionArchive.member.eq(teamMember.member), + ((mission.type.eq(MissionType.REPEAT).and(dateInRange)) + .or(mission.type.eq(MissionType.ONCE))) + ) + .groupBy(teamMember.member,mission,mission.number) + .having(missionArchive.count().lt(mission.number)) + .fetch()); + + + +// return Optional.ofNullable(queryFactory +// .select(teamMember.member).distinct() +// .from(teamMember) +// .join(mission) +// .on( +// teamMember.team.eq(mission.team), +// ((((mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT))).and(mission.type.eq(MissionType.ONCE))) +// .or((mission.status.eq(MissionStatus.ONGOING)).and(mission.type.eq(MissionType.REPEAT))))) +// ) +// .join(missionArchive) +// .on( +// missionArchive.mission.eq(mission), +// missionArchive.member.eq(teamMember.member), +// (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) +// ) +// .groupBy(teamMember.member,mission,mission.number) +// .having(missionArchive.count().loe(mission.number)) +// .fetch() +// ); + } + } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java index e4459dc9..7d9726a6 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.missionArchive.domain.repository; import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; @@ -78,4 +79,7 @@ public interface MissionArchiveRepository extends JpaRepository> findHavingRemainMissions(); -} + + + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java index 152d78ad..8747de95 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java @@ -22,23 +22,23 @@ public class MissionArchiveScheduleQueryService { private final MissionArchiveRepository missionArchiveRepository; - public Optional> getRemainMissionPeople() { - List> maps = missionArchiveRepository.findHavingRemainMissions().orElseThrow(); - - return Optional.of(maps.stream() - .map(map -> { - Object memberIdObject = map.get("memberId"); - Long memberId = ((BigInteger) memberIdObject).longValue(); - - Object fcmObject = map.get("fcmToken"); - String fcmToken = fcmObject.toString(); - - return MemberIdAndToken.builder() - .fcmToken(fcmToken) - .memberId(memberId) - .build(); - }) - .collect(Collectors.toList())); + public List getRemainMissionPeople() { + return missionArchiveRepository.findHavingRemainMissionsByQuerydsl().orElseThrow(); + +// return Optional.of(maps.stream() +// .map(map -> { +// Object memberIdObject = map.get("memberId"); +// Long memberId = ((BigInteger) memberIdObject).longValue(); +// +// Object fcmObject = map.get("fcmToken"); +// String fcmToken = fcmObject.toString(); +// +// return MemberIdAndToken.builder() +// .fcmToken(fcmToken) +// .memberId(memberId) +// .build(); +// }) +// .collect(Collectors.toList())); // return null; From b58fabfeabc82588a50b549dbc6fd3231573201b Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 17 Dec 2023 21:48:28 +0900 Subject: [PATCH 398/619] =?UTF-8?q?fix:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=ED=95=A0=20=EB=95=8C=20=EB=8B=89=EB=84=A4=EC=9E=84?= =?UTF-8?q?=EB=A7=8C=20=ED=95=84=EC=88=98=EB=A1=9C=20=EB=B0=9B=EA=B2=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/dto/request/SignUpRequest.java | 3 --- .../moing/backend/domain/member/domain/entity/Member.java | 8 ++++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java index 96d182d1..6ee3836f 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java @@ -20,10 +20,7 @@ public class SignUpRequest { @Size(min = 1, max = 10, message="nickName 은 최소 1개, 최대 10개의 문자만 입력 가능합니다.") private String nickName; - @NotNull(message = "유효하지 않은 gender가 입력되었습니다.") private Gender gender; - @NotNull(message="birthDate 을 입력해주세요.") - @Pattern(regexp = "^\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$", message = "날짜 형식이 잘못되었습니다. YYYY-MM-DD 형식으로 입력해주세요.") private String birthDate; } diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index b423671d..d13b5886 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -103,8 +103,12 @@ public static Member valueOf(OAuth2User oAuth2User) { public void signUp(SignUpRequest signUpRequest) { this.nickName = signUpRequest.getNickName(); - this.gender = signUpRequest.getGender(); - this.birthDate = LocalDate.parse(signUpRequest.getBirthDate(), DateTimeFormatter.ISO_DATE);; + if(signUpRequest.getGender()!=null) { + this.gender = signUpRequest.getGender(); + } + if(signUpRequest.getBirthDate()!=null) { + this.birthDate = LocalDate.parse(signUpRequest.getBirthDate(), DateTimeFormatter.ISO_DATE); + } this.registrationStatus = RegistrationStatus.COMPLETED; updateAllPush(true); } From 5309e7fab54f9c61de5fc2fea1a4103ff3bcfdc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 17 Dec 2023 23:14:29 +0900 Subject: [PATCH 399/619] =?UTF-8?q?fix=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98=20=EB=A6=AC=ED=84=B4=EA=B0=92=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/GatherRepeatMissionRes.java | 2 ++ .../dto/res/GatherSingleMissionRes.java | 1 + .../repository/MissionCustomRepositoryImpl.java | 6 ++++-- .../MissionGatherControllerTest.java | 16 ++++++++++++---- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java index 5249ce34..993fd70e 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java @@ -15,5 +15,7 @@ public class GatherRepeatMissionRes { private String missionTitle; private String totalNum; private String doneNum; + private String status; + } diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java index 1afe2085..0b173365 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java @@ -13,6 +13,7 @@ public class GatherSingleMissionRes { private String teamName; private String missionTitle; private String dueTo; + private String status; } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 007bdb2a..1ed71992 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -61,7 +61,8 @@ public Optional> findRepeatMissionByMemberId(Long m mission.team.name, mission.title, mission.number.stringValue(), - missionState.count().stringValue() + missionState.count().stringValue(), + mission.status.stringValue() )) .from(mission) @@ -143,7 +144,8 @@ public Optional> findSingleMissionByMemberId(Long m mission.team.teamId, mission.team.name, mission.title, - mission.dueTo.stringValue() + mission.dueTo.stringValue(), + mission.status.stringValue() )) .from(mission) .leftJoin(missionState).on( diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index 6103418b..eb414ec2 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -45,6 +45,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .dueTo("2023-09-03T21:32:33.888") .teamName("team name") .missionTitle("mission title") + .status("WAIT/ONGOING/END/FAIL/SUCCESS") .build()); given(missionGatherBoardUseCase.getAllActiveSingleMissions(any())).willReturn(output); @@ -73,7 +74,8 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].teamId").description("팀 아이디"), fieldWithPath("data[].dueTo").description("미션 마감 시각"), fieldWithPath("data[].teamName").description("팀 이름"), - fieldWithPath("data[].missionTitle").description("미션 제목") + fieldWithPath("data[].missionTitle").description("미션 제목"), + fieldWithPath("data[].status").description("미션 상태") ) ) @@ -93,6 +95,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .missionTitle("mission title") .doneNum("0") .totalNum("0") + .status("WAIT/ONGOING/END/FAIL/SUCCESS") .build()); given(missionGatherBoardUseCase.getAllActiveRepeatMissions(any())).willReturn(output); @@ -122,7 +125,8 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목"), fieldWithPath("data[].doneNum").description("완료한 횟수"), - fieldWithPath("data[].totalNum").description("전체 횟수") + fieldWithPath("data[].totalNum").description("전체 횟수"), + fieldWithPath("data[].status").description("미션 상태") ) @@ -142,6 +146,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .dueTo("2023-09-03T21:32:33.888") .teamName("team name") .missionTitle("mission title") + .status("WAIT/ONGOING/END/FAIL/SUCCESS") .build()); given(missionGatherBoardUseCase.getTeamActiveSingleMissions(any(),any())).willReturn(output); @@ -171,7 +176,8 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].teamId").description("팀 아이디"), fieldWithPath("data[].dueTo").description("미션 마감 시각"), fieldWithPath("data[].teamName").description("팀 이름"), - fieldWithPath("data[].missionTitle").description("미션 제목") + fieldWithPath("data[].missionTitle").description("미션 제목"), + fieldWithPath("data[].status").description("미션 상태") ) ) @@ -191,6 +197,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .missionTitle("mission title") .doneNum("0") .totalNum("0") + .status("WAIT/ONGOING/END/FAIL/SUCCESS") .build()); given(missionGatherBoardUseCase.getTeamActiveRepeatMissions(any(),any())).willReturn(output); @@ -221,7 +228,8 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목"), fieldWithPath("data[].doneNum").description("완료한 횟수"), - fieldWithPath("data[].totalNum").description("전체 횟수") + fieldWithPath("data[].totalNum").description("전체 횟수"), + fieldWithPath("data[].status").description("미션 상태") ) From 17c77838f4bc5c1affddccb690f1341db570660d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 18 Dec 2023 01:02:39 +0900 Subject: [PATCH 400/619] =?UTF-8?q?feat=20:=20Imgurl=20=EB=A1=9C=20s3=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EB=8B=A8=EC=88=9C=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/moing/backend/global/utils/UpdateUtils.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/moing/backend/global/utils/UpdateUtils.java b/src/main/java/com/moing/backend/global/utils/UpdateUtils.java index 52ead37b..246ce8e2 100644 --- a/src/main/java/com/moing/backend/global/utils/UpdateUtils.java +++ b/src/main/java/com/moing/backend/global/utils/UpdateUtils.java @@ -23,4 +23,10 @@ public void deleteOldImgUrl(String currentImageUrl, String oldImageUrl) { s3Service.deleteImage(oldImageUrl); } } + + public void deleteImgUrl(String imageUrl) { + if (imageUrl != null) { + s3Service.deleteImage(imageUrl); + } + } } From 172bbaef70a399baaa538f29daf5f15471d92169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 18 Dec 2023 01:02:55 +0900 Subject: [PATCH 401/619] =?UTF-8?q?fix=20:=20=EB=8B=A4=EC=8B=9C=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=ED=95=98=EA=B8=B0=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=EC=97=90=20s3=20=EC=82=AD=EC=A0=9C=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveDeleteUseCase.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java index d596bed9..a66bc217 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java @@ -23,6 +23,7 @@ import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.global.utils.UpdateUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -43,13 +44,12 @@ public class MissionArchiveDeleteUseCase { private final MemberGetService memberGetService; - private final IssuePresignedUrlUseCase getPresignedUrlUseCase; - - private final MissionStateSaveService missionStateSaveService; - private final MissionStateUseCase missionStateUseCase; private final MissionStateDeleteService missionStateDeleteService; private final MissionStateQueryService missionStateQueryService; + private final UpdateUtils updateUtils; + + public Long deleteArchive(String userSocialId, Long missionId,Long count) { @@ -69,6 +69,11 @@ public Long deleteArchive(String userSocialId, Long missionId,Long count) { throw new NoAccessMissionArchiveException(); } + if (mission.getWay().equals(MissionWay.PHOTO)) { + String archive = deleteArchive.getArchive(); + updateUtils.deleteImgUrl(archive); + } + missionArchiveDeleteService.deleteMissionArchive(deleteArchive); missionStateDeleteService.deleteMissionState(missionState); From d0aa96a7acf95c21ce6be3a9604c3160bf1e11ed Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 19 Dec 2023 22:22:03 +0900 Subject: [PATCH 402/619] =?UTF-8?q?fix:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EB=95=8C=20=EB=8B=89=EB=84=A4?= =?UTF-8?q?=EC=9E=84,=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EB=B0=94=EB=80=90=20=EA=B2=83=20=EB=B0=98=EC=98=81?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/BoardBlocks.java | 10 ++- .../board/application/mapper/BoardMapper.java | 8 +- .../service/CreateBoardUseCase.java | 2 +- .../domain/board/domain/entity/Board.java | 8 +- .../repository/BoardCustomRepositoryImpl.java | 75 +++++++++---------- .../mapper/BoardCommentMapper.java | 5 +- .../service/CreateBoardCommentUseCase.java | 2 +- .../domain/entity/BoardComment.java | 8 -- .../BoardCommentCustomRepositoryImpl.java | 8 +- .../domain/mypage/domain/entity/Feedback.java | 9 ++- .../presentation/BoardControllerTest.java | 8 +- 11 files changed, 68 insertions(+), 75 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java index cb6d8f58..fb6c7f3e 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java @@ -28,8 +28,11 @@ public class BoardBlocks { private Boolean writerIsDeleted; + private boolean isNotice; + + @QueryProjection - public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, String writerProfileImage, String title, String content, Integer commentNum, Boolean writerIsDeleted) { + public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, String writerProfileImage, String title, String content, Integer commentNum, Boolean writerIsDeleted, boolean isNotice) { this.boardId = boardId; this.writerNickName = writerNickName; this.writerIsLeader = writerIsLeader; @@ -39,6 +42,7 @@ public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, this.commentNum = commentNum; this.isRead = false; this.writerIsDeleted=writerIsDeleted; + this.isNotice=isNotice; deleteMember(); } @@ -46,6 +50,10 @@ public void readBoard() { this.isRead = true; } + public boolean isNotice() { + return isNotice; + } + public void deleteMember() { if(Boolean.TRUE.equals(writerIsDeleted)) { this.writerNickName = "(알 수 없음)"; diff --git a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java index 92552ec3..1337f692 100644 --- a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java +++ b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java @@ -17,10 +17,8 @@ @RequiredArgsConstructor public class BoardMapper { - public Board toBoard(Member member, TeamMember teamMember, Team team, CreateBoardRequest createBoardRequest, boolean isLeader) { + public Board toBoard(TeamMember teamMember, Team team, CreateBoardRequest createBoardRequest, boolean isLeader) { Board board = Board.builder() - .writerNickName(member.getNickName()) - .writerProfileImage(member.getProfileImage()) .title(createBoardRequest.getTitle()) .content(createBoardRequest.getContent()) .isNotice(createBoardRequest.getIsNotice()) @@ -35,8 +33,8 @@ public Board toBoard(Member member, TeamMember teamMember, Team team, CreateBoar } public GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter, boolean writerIsDeleted) { - String nickName = writerIsDeleted ? "(알 수 없음)" : board.getWriterNickName(); - String writerProfileImage = writerIsDeleted ? null : board.getWriterProfileImage(); + String nickName = writerIsDeleted ? "(알 수 없음)" : board.getTeamMember().getMember().getNickName(); + String writerProfileImage = writerIsDeleted ? null : board.getTeamMember().getMember().getProfileImage(); return GetBoardDetailResponse.builder() .boardId(board.getBoardId()) .title(board.getTitle()) diff --git a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java index 953eab1e..35ec9102 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java @@ -39,7 +39,7 @@ public CreateBoardResponse createBoard(String socialId, Long teamId, CreateBoard //1, 게시글 생성, 저장 BaseServiceResponse data=baseService.getCommonData(socialId, teamId); boolean isLeader = checkLeaderUseCase.isTeamLeader(data.getMember(), data.getTeam()); //작성자 리더 여부 - Board board=boardSaveService.saveBoard(boardMapper.toBoard(data.getMember(), data.getTeamMember(), data.getTeam(), createBoardRequest, isLeader)); + Board board=boardSaveService.saveBoard(boardMapper.toBoard(data.getTeamMember(), data.getTeam(), createBoardRequest, isLeader)); //2. 읽음 처리 - 생성한 사람은 무조건 읽음 createBoardReadUseCase.createBoardRead(data.getTeam(), data.getMember(), board); diff --git a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java index d5aef112..77b40344 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java +++ b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java @@ -6,7 +6,6 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.entity.BaseTimeEntity; -import com.moing.backend.global.utils.AesConverter; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -28,14 +27,8 @@ public class Board extends BaseTimeEntity { @Column(name = "board_id") private Long boardId; - //반정규화 -> 작성자에 대한 정보 - @Convert(converter = AesConverter.class) - @Column(nullable = false) - private String writerNickName; /*작성자 닉네임*/ - private boolean isLeader; /*작성자 소모임장유무*/ - private String writerProfileImage; /*작성자 프로필 사진*/ @Column(nullable = false, length = 15) private String title; @@ -52,6 +45,7 @@ public class Board extends BaseTimeEntity { @JoinColumn(name = "team_member_id") private TeamMember teamMember; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_id") private Team team; diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index 1d58a06a..eb3ee18e 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -2,17 +2,17 @@ import com.moing.backend.domain.board.application.dto.response.BoardBlocks; import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; -import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; +import com.moing.backend.domain.board.application.dto.response.QBoardBlocks; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; import java.util.List; -import java.util.function.Function; import java.util.stream.Collectors; import static com.moing.backend.domain.board.domain.entity.QBoard.board; import static com.moing.backend.domain.boardRead.domain.entity.QBoardRead.boardRead; +import static com.moing.backend.domain.member.domain.entity.QMember.member; +import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; public class BoardCustomRepositoryImpl implements BoardCustomRepository { @@ -20,54 +20,51 @@ public class BoardCustomRepositoryImpl implements BoardCustomRepository { public BoardCustomRepositoryImpl(EntityManager em) { this.queryFactory = new JPAQueryFactory(em); } - @Override public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { + // 전체 게시글 보기 - List allBoards = queryFactory.selectFrom(board) - .distinct() - .leftJoin(board.teamMember, QTeamMember.teamMember).fetchJoin() // TeamMember를 함께 로드 + List allBoardBlocks = queryFactory + .select(new QBoardBlocks( + board.boardId, + board.teamMember.member.nickName, + board.isLeader, + board.teamMember.member.profileImage, + board.title, + board.content, + board.commentNum, + board.teamMember.isDeleted, + board.isNotice + )) + .from(board) + .leftJoin(board.teamMember, teamMember) + .leftJoin(board.teamMember.member, member) .where(board.team.teamId.eq(teamId)) .orderBy(board.createdDate.desc()) .fetch(); - // 읽은 게시글 보기 - List readBoards = queryFactory.selectFrom(board) - .distinct() - .leftJoin(board.teamMember, QTeamMember.teamMember).fetchJoin() // TeamMember를 함께 로드 - .join(boardRead).on(boardRead.board.eq(board)) - .where(board.team.teamId.eq(teamId)) + // 읽은 게시글 목록 조회 + List readBoardIds = queryFactory + .select(boardRead.board.boardId) + .from(boardRead) .where(boardRead.member.memberId.eq(memberId)) - .groupBy(board.boardId) - .orderBy(board.createdDate.desc()) + .where(boardRead.board.team.teamId.eq(teamId)) .fetch(); - // 공지와 일반 게시글로 나누기 - List notices = allBoards.stream().filter(Board::isNotice).collect(Collectors.toList()); - List regularPosts = allBoards.stream().filter(b -> !b.isNotice()).collect(Collectors.toList()); - - // Board -> BoardBlocks 변환 - Function toBoardBlocks = b -> { - boolean isRead = readBoards.contains(b); - BoardBlocks boardBlocks = new BoardBlocks( - b.getBoardId(), - b.getWriterNickName(), - b.isLeader(), - b.getWriterProfileImage(), - b.getTitle(), - b.getContent(), - b.getCommentNum(), - b.getTeamMember().isDeleted() - ); - if (isRead) { - boardBlocks.readBoard(); + // 읽은 게시글 표시 + allBoardBlocks.forEach(boardBlock -> { + if (readBoardIds.contains(boardBlock.getBoardId())) { + boardBlock.readBoard(); } + }); - return boardBlocks; - }; - - List noticeBlocks = notices.stream().map(toBoardBlocks).collect(Collectors.toList()); - List regularBlocks = regularPosts.stream().map(toBoardBlocks).collect(Collectors.toList()); + // 공지와 일반 게시글로 나누기 + List noticeBlocks = allBoardBlocks.stream() + .filter(BoardBlocks::isNotice) + .collect(Collectors.toList()); + List regularBlocks = allBoardBlocks.stream() + .filter(b -> !b.isNotice()) + .collect(Collectors.toList()); return new GetAllBoardResponse(noticeBlocks.size(), noticeBlocks, regularBlocks.size(), regularBlocks); } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java b/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java index f191d0e5..8e0fe2e2 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java @@ -3,7 +3,6 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; -import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -11,11 +10,9 @@ @Component @RequiredArgsConstructor public class BoardCommentMapper { - public BoardComment toBoardComment(Member member, TeamMember teamMember, Board board, CreateBoardCommentRequest createBoardCommentRequest, boolean isLeader){ + public BoardComment toBoardComment(TeamMember teamMember, Board board, CreateBoardCommentRequest createBoardCommentRequest, boolean isLeader) { BoardComment boardComment= BoardComment.builder() .content(createBoardCommentRequest.getContent()) - .writerNickName(member.getNickName()) - .writerProfileImage(member.getProfileImage()) .isLeader(isLeader) .build(); boardComment.updateBoard(board); diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java index 60ef6b4f..f51b5172 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java @@ -30,7 +30,7 @@ public CreateBoardCommentResponse createBoardComment(String socialId, Long teamI // 1. 게시글 댓글 생성 BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); boolean isLeader = checkLeaderUseCase.isTeamLeader(data.getMember(), data.getTeam()); - BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(data.getMember(), data.getTeamMember(), data.getBoard(), createBoardCommentRequest, isLeader)); + BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(data.getTeamMember(), data.getBoard(), createBoardCommentRequest, isLeader)); // 2. 게시글 댓글 개수 증가 data.getBoard().incrComNum(); return new CreateBoardCommentResponse(boardComment.getBoardCommentId()); diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java index 85660487..ab437a2a 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java @@ -3,7 +3,6 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.entity.BaseTimeEntity; -import com.moing.backend.global.utils.AesConverter; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -34,15 +33,8 @@ public class BoardComment extends BaseTimeEntity { @JoinColumn(name = "board_id") private Board board; - //반정규화 -> 작성자에 대한 정보 - @Convert(converter = AesConverter.class) - @Column(nullable = false) - private String writerNickName; /*작성자 닉네임*/ - private boolean isLeader; /*작성자 소모임장유무*/ - private String writerProfileImage; /*작성자 프로필 사진*/ - /** * 연관관계 매핑 */ diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index 603253b6..5a4d22b3 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -6,7 +6,6 @@ import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.querydsl.core.types.ExpressionUtils; -import com.querydsl.core.types.Projections; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -14,6 +13,7 @@ import java.util.List; import static com.moing.backend.domain.boardComment.domain.entity.QBoardComment.boardComment; +import static com.moing.backend.domain.member.domain.entity.QMember.member; public class BoardCommentCustomRepositoryImpl implements BoardCommentCustomRepository{ @@ -30,9 +30,9 @@ public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember team .select(new QCommentBlocks( boardComment.boardCommentId, boardComment.content, - boardComment.writerNickName, + boardComment.teamMember.member.nickName, boardComment.isLeader, - boardComment.writerProfileImage, + boardComment.teamMember.member.profileImage, ExpressionUtils.as(JPAExpressions .selectOne() .from(QTeamMember.teamMember) @@ -42,6 +42,8 @@ public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember team boardComment.teamMember.isDeleted, boardComment.createdDate)) .from(boardComment) + .leftJoin(boardComment.teamMember, QTeamMember.teamMember) + .leftJoin(boardComment.teamMember.member, member) .where(boardComment.board.boardId.eq(boardId)) .orderBy(boardComment.createdDate.asc()) .fetch(); diff --git a/src/main/java/com/moing/backend/domain/mypage/domain/entity/Feedback.java b/src/main/java/com/moing/backend/domain/mypage/domain/entity/Feedback.java index 9ea6010b..c6ed237b 100644 --- a/src/main/java/com/moing/backend/domain/mypage/domain/entity/Feedback.java +++ b/src/main/java/com/moing/backend/domain/mypage/domain/entity/Feedback.java @@ -1,14 +1,15 @@ package com.moing.backend.domain.mypage.domain.entity; import com.moing.backend.global.entity.BaseTimeEntity; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.NoArgsConstructor; -import lombok.RequiredArgsConstructor; +import lombok.*; import javax.persistence.*; +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter @Entity public class Feedback extends BaseTimeEntity { diff --git a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java index f93c223f..ec018e6a 100644 --- a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java @@ -199,6 +199,7 @@ public void get_board_all() throws Exception { .content("공지 내용") .commentNum(2) .isRead(false) + .isNotice(true) .build(); BoardBlocks notNoticeBlock = BoardBlocks.builder() @@ -211,6 +212,7 @@ public void get_board_all() throws Exception { .content("게시글 내용") .commentNum(2) .isRead(false) + .isNotice(false) .build(); noticeBlocks.add(noticeBlock); @@ -253,6 +255,7 @@ public void get_board_all() throws Exception { fieldWithPath("data.noticeBlocks[0].content").description("공지 내용"), fieldWithPath("data.noticeBlocks[0].commentNum").description("공지 댓글 개수"), fieldWithPath("data.noticeBlocks[0].isRead").description("공지 읽음 처리 여부"), + fieldWithPath("data.noticeBlocks[0].notice").description("true"), fieldWithPath("data.notNoticeNum").description("일반 게시글 개수"), fieldWithPath("data.notNoticeBlocks[0].boardId").description("일반 게시글 아이디"), fieldWithPath("data.notNoticeBlocks[0].writerNickName").description("작성자 닉네임"), @@ -262,8 +265,9 @@ public void get_board_all() throws Exception { fieldWithPath("data.notNoticeBlocks[0].title").description("일반 게시글 제목"), fieldWithPath("data.notNoticeBlocks[0].content").description("일반 게시글 내용"), fieldWithPath("data.notNoticeBlocks[0].commentNum").description("일반 게시글 댓글 개수"), - fieldWithPath("data.notNoticeBlocks[0].isRead").description("일반 게시글 읽음 처리 여부") - ) + fieldWithPath("data.notNoticeBlocks[0].isRead").description("일반 게시글 읽음 처리 여부"), + fieldWithPath("data.notNoticeBlocks[0].notice").description("false") + ) ) ); From 110c9b3c54dc9aeb51d5e2c295880c02334609e0 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 19 Dec 2023 22:28:53 +0900 Subject: [PATCH 403/619] =?UTF-8?q?fix:=20report=20=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/report/application/service/ReportCreateUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java index a674cfce..3fcc15de 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java @@ -42,7 +42,7 @@ public Long createReport(String socialId, Long targetId, String reportType) { if (reportType.equals(ReportType.BOARD.name())) { Board board = boardGetService.getBoard(targetId); - targetMemberNickName = board.getWriterNickName(); + targetMemberNickName = board.getTeamMember().getMember().getNickName(); board.updateBoard(UpdateBoardRequest.builder() .title(REPORT_BOARD_TITLE) From 8200e0defce96fdba99edd879a44f69ac45d046d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Dec 2023 01:46:50 +0900 Subject: [PATCH 404/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=82=B4=EC=9A=A9=20=EA=B8=80=EC=9E=90=EC=88=98=20=EC=A0=9C?= =?UTF-8?q?=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moing/backend/domain/mission/domain/entity/Mission.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index f99d2e9e..e0096d3a 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -32,7 +32,10 @@ public class Mission extends BaseTimeEntity { private String title; private LocalDateTime dueTo; private String rule; + + @Column(nullable = false, columnDefinition="TEXT", length = 300) private String content; + private int number; @ManyToOne(fetch = FetchType.LAZY) From 2e0b2ff894da7c2fbf7270ab6259201371613415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Dec 2023 02:21:48 +0900 Subject: [PATCH 405/619] =?UTF-8?q?fix=20:=20=EC=82=AD=EC=A0=9C=EB=90=9C?= =?UTF-8?q?=20member=20=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=95=88=EA=B0=80=EB=8F=84=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionCustomRepositoryImpl.java | 3 ++- .../MissionArchiveCustomRepositoryImpl.java | 23 ++----------------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 1ed71992..0e2db2b2 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -116,7 +116,8 @@ public Optional> findRepeatMissionPeopleByStatus(MissionStatus miss .select(teamMember.member).distinct() .from(teamMember) .join(mission) - .on(teamMember.team.eq(mission.team)) + .on(teamMember.team.eq(mission.team), + teamMember.member.isDeleted.ne(true)) .where( mission.status.eq(missionStatus), mission.type.eq(MissionType.REPEAT) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 0bc185f7..a63a25d9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -441,30 +441,11 @@ public Optional> findHavingRemainMissionsByQuerydsl() { .or(mission.type.eq(MissionType.ONCE))) ) .groupBy(teamMember.member,mission,mission.number) - .having(missionArchive.count().lt(mission.number)) + .having(missionArchive.count().lt(mission.number), + teamMember.member.isDeleted.ne(true)) .fetch()); - -// return Optional.ofNullable(queryFactory -// .select(teamMember.member).distinct() -// .from(teamMember) -// .join(mission) -// .on( -// teamMember.team.eq(mission.team), -// ((((mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT))).and(mission.type.eq(MissionType.ONCE))) -// .or((mission.status.eq(MissionStatus.ONGOING)).and(mission.type.eq(MissionType.REPEAT))))) -// ) -// .join(missionArchive) -// .on( -// missionArchive.mission.eq(mission), -// missionArchive.member.eq(teamMember.member), -// (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) -// ) -// .groupBy(teamMember.member,mission,mission.number) -// .having(missionArchive.count().loe(mission.number)) -// .fetch() -// ); } From 4ef7c4ac56d54b4cecabdf6c540eb2013ecb8bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Dec 2023 15:24:37 +0900 Subject: [PATCH 406/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=EB=AC=BC=20=EC=A2=8B=EC=95=84=EC=9A=94=20hea?= =?UTF-8?q?rtStatus=20type=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/missionHeart/domain/entity/MissionHeart.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java b/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java index c0290eec..cecd17db 100644 --- a/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java +++ b/src/main/java/com/moing/backend/domain/missionHeart/domain/entity/MissionHeart.java @@ -28,6 +28,7 @@ public class MissionHeart extends BaseTimeEntity { @JoinColumn(name = "missionArchiveId") private MissionArchive missionArchive; + @Enumerated(EnumType.STRING) private MissionHeartStatus heartStatus; public void updateHeartStatus(MissionHeartStatus heartStatus) { From 6d66f39d09802fd241617b9ee7bf05abf7866fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Dec 2023 15:28:20 +0900 Subject: [PATCH 407/619] =?UTF-8?q?fix=20:=EB=AA=A8=EC=9E=84=EC=9B=90=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=EB=AC=BC=20=EC=A2=8B=EC=95=84=EC=9A=94=20map?= =?UTF-8?q?per=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/MissionArchiveMapper.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 36810af0..3f92a03a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -14,9 +14,11 @@ import com.moing.backend.domain.missionHeart.domain.constant.MissionHeartStatus; import com.moing.backend.global.annotation.Mapper; +import javax.transaction.Transactional; import java.util.ArrayList; import java.util.List; +@Transactional @Mapper public class MissionArchiveMapper { @@ -39,12 +41,13 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc .status(missionArchive.getStatus().name()) .count(missionArchive.getCount()) .heartStatus( - String.valueOf(missionArchive.getHeartList().stream().anyMatch( - missionHeart -> missionHeart.getPushMemberId().equals(memberId) && - missionHeart.getHeartStatus().equals(MissionHeartStatus.True) + String.valueOf( + missionArchive.getHeartList().stream().anyMatch( + missionHeart -> missionHeart.getPushMemberId().equals(memberId) + && missionHeart.getHeartStatus() == (MissionHeartStatus.True) ))) .hearts(missionArchive.getHeartList().stream() - .filter(heart -> heart.getHeartStatus().equals( MissionHeartStatus.True)) + .filter(heart -> heart.getHeartStatus() == ( MissionHeartStatus.True)) .filter(heart -> heart.getMissionArchive().equals( missionArchive))// heartStatus가 true인 요소만 필터링 .count()) .build(); @@ -71,8 +74,11 @@ public static PersonalArchiveRes mapToPersonalArchive(MissionArchive missionArch .status(missionArchive.getStatus().name()) .count(missionArchive.getCount()) .heartStatus( - String.valueOf(missionArchive.getHeartList().stream().anyMatch( - missionHeart -> missionHeart.getPushMemberId().equals(memberId)))) + String.valueOf( + missionArchive.getHeartList().stream().anyMatch( + missionHeart -> missionHeart.getPushMemberId().equals(memberId) + && missionHeart.getHeartStatus() == (MissionHeartStatus.True) + ))) .hearts((int) missionArchive.getHeartList().stream() .filter(heart -> heart.getHeartStatus().equals( MissionHeartStatus.True)) .filter(heart -> heart.getMissionArchive().equals( missionArchive))// heartStatus가 true인 요소만 필터링 From b77ca1376434f93635546095e19a1543bdfd9f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Dec 2023 16:13:20 +0900 Subject: [PATCH 408/619] =?UTF-8?q?fix=20:=20=EC=A2=85=EB=A3=8C=EB=90=9C?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98=20=EC=A0=95=EB=A0=AC=EA=B8=B0=EC=A4=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index a63a25d9..9f6c7ef7 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -303,7 +303,7 @@ public Optional> findFinishMissionsByStatus(Long mem .where( mission.team.teamId.eq(teamId), mission.status.eq(MissionStatus.SUCCESS).or(mission.status.eq(MissionStatus.END)) - ) + ).orderBy(mission.lastModifiedDate.desc()) .fetch() ); } From 8490fd6ab8b02d30d3aece2f6dae0abb93ebc243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Dec 2023 18:10:23 +0900 Subject: [PATCH 409/619] =?UTF-8?q?fix=20:=20=EC=A2=85=EB=A3=8C=EB=90=9C?= =?UTF-8?q?=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=97=85=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveCustomRepositoryImpl.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 9f6c7ef7..720c237f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -157,7 +157,10 @@ public Optional> findMyArchives(Long memberId,Long missionI .where( missionArchive.mission.id.eq(missionId), missionArchive.member.memberId.eq(memberId), - missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) + (missionArchive.mission.type.eq(MissionType.REPEAT) + .and(missionArchive.mission.status.eq(MissionStatus.ONGOING)).and(dateInRange)) + .or(missionArchive.mission.type.eq(MissionType.REPEAT) + .and(missionArchive.mission.status.eq(MissionStatus.END))) .or(missionArchive.mission.type.eq(MissionType.ONCE)) ) @@ -180,9 +183,12 @@ public Optional> findOthersArchives(Long memberId, Long mis missionArchive.mission.id.eq(missionId), missionArchive.member.memberId.ne(memberId), missionArchive.status.eq(MissionArchiveStatus.COMPLETE).or(missionArchive.status.eq(MissionArchiveStatus.SKIP)), - - missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) + (missionArchive.mission.type.eq(MissionType.REPEAT) + .and(missionArchive.mission.status.eq(MissionStatus.ONGOING)).and(dateInRange)) + .or(missionArchive.mission.type.eq(MissionType.REPEAT) + .and(missionArchive.mission.status.eq(MissionStatus.END))) .or(missionArchive.mission.type.eq(MissionType.ONCE)) + ) .orderBy(missionArchive.createdDate.desc()) .fetch() From b778bc0918747ea3d85c83fa2c0b93f83393ee38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Dec 2023 18:56:28 +0900 Subject: [PATCH 410/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EC=95=8C=EB=A6=BC=20=EC=A0=84?= =?UTF-8?q?=EC=86=A1=20=ED=95=A0=20=EB=95=8C=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=20=EA=B0=92=20=EC=A3=BC=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendMissionCreateAlarmUseCase.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java index 5b22d1db..5f4c7db7 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java @@ -5,6 +5,8 @@ import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; @@ -31,18 +33,21 @@ public void sendNewMissionUploadAlarm(Member member, Mission mission) { Team team = mission.getTeam(); String title = team.getName() + " " + NEW_SINGLE_MISSION_COMING.getTitle(); String message = mission.getTitle(); + String type = mission.getType().toString(); + String status = mission.getStatus().toString(); Optional> memberIdAndTokensByPush = teamMemberGetService.getNewUploadPushInfo(team.getTeamId(), member.getMemberId()); Optional> memberIdAndTokensBySave = teamMemberGetService.getNewUploadSaveInfo(team.getTeamId(), member.getMemberId()); // 알림 보내기 - eventPublisher.publishEvent(new MultiFcmEvent(title, message, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.MISSION_PATH.getValue())); + eventPublisher.publishEvent(new MultiFcmEvent(title, message, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId(),mission.getType(),mission.getStatus()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.MISSION_PATH.getValue())); } - private String createIdInfo(Long teamId, Long missionId) { + private String createIdInfo(Long teamId, Long missionId,MissionType type, MissionStatus status) { JSONObject jo = new JSONObject(); - jo.put("isRepeated", false); + jo.put("isRepeated", type.equals(MissionType.REPEAT)); jo.put("teamId", teamId); jo.put("missionId", missionId); + jo.put("status", status.name()); return jo.toJSONString(); } } From 51d3ea366fe7a0eaee6bdca95f10937777d93513 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 20 Dec 2023 22:16:28 +0900 Subject: [PATCH 411/619] =?UTF-8?q?refactor:=20=EC=95=8C=EB=A6=BC=EB=B3=B4?= =?UTF-8?q?=EB=82=BC=20=EB=95=8C=20=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83,?= =?UTF-8?q?=20=EC=95=8C=EB=A6=BC=20=EC=97=AC=EB=B6=80=20=EC=BF=BC=EB=A6=AC?= =?UTF-8?q?=EA=B0=80=20=EC=95=84=EB=8B=8C=20mapper=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendBoardAlarmUseCase.java | 7 ++- .../dto/response/NewUploadInfo.java | 19 +++++++ .../mapper/AlarmHistoryMapper.java | 20 +++++++ .../SendMissionCreateAlarmUseCase.java | 8 ++- .../TeamMemberCustomRepository.java | 6 +-- .../TeamMemberCustomRepositoryImpl.java | 54 +++---------------- .../domain/service/TeamMemberGetService.java | 16 ++---- 7 files changed, 61 insertions(+), 69 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/history/application/dto/response/NewUploadInfo.java diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index 0fd19fe0..3ed5f384 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -2,6 +2,8 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; @@ -35,8 +37,9 @@ public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board bo if (board.isNotice()) { String title = NEW_NOTICE_UPLOAD_MESSAGE.title(team.getName()); String body = NEW_NOTICE_UPLOAD_MESSAGE.body(board.getTitle()); - Optional> memberIdAndTokensByPush = teamMemberGetService.getNewUploadPushInfo(team.getTeamId(), member.getMemberId()); - Optional> memberIdAndTokensBySave = teamMemberGetService.getNewUploadSaveInfo(team.getTeamId(), member.getMemberId()); + Optional> newUploadInfos=teamMemberGetService.getNewUploadInfo(team.getTeamId(), member.getMemberId()); + Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); + Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); // 알림 보내기 eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); } diff --git a/src/main/java/com/moing/backend/domain/history/application/dto/response/NewUploadInfo.java b/src/main/java/com/moing/backend/domain/history/application/dto/response/NewUploadInfo.java new file mode 100644 index 00000000..5b5e2967 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/history/application/dto/response/NewUploadInfo.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.history.application.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class NewUploadInfo { + + private String fcmToken; + private Long memberId; + private boolean isNewUploadPush; + private boolean isSignOut; + +} diff --git a/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java b/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java index 21938d0d..e00f121e 100644 --- a/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java +++ b/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.history.application.mapper; import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.history.domain.entity.AlarmHistory; import com.moing.backend.domain.history.domain.entity.AlarmType; import lombok.RequiredArgsConstructor; @@ -8,6 +9,7 @@ import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @Component @@ -54,4 +56,22 @@ public List getAlarmHistories(String idInfo, List memberIds, .collect(Collectors.toList()); } + public static Optional> getNewUploadSaveInfo(Optional> optionalNewUploadInfos) { + return optionalNewUploadInfos.map(newUploadInfos -> + newUploadInfos.stream() + .map(info -> new MemberIdAndToken(info.getFcmToken(), info.getMemberId())) + .collect(Collectors.toList()) + ); + } + + public static Optional> getNewUploadPushInfo(Optional> optionalNewUploadInfos) { + return optionalNewUploadInfos.map(newUploadInfos -> + newUploadInfos.stream() + .filter(NewUploadInfo::isNewUploadPush) + .filter(info -> !info.isSignOut()) + .map(info -> new MemberIdAndToken(info.getFcmToken(), info.getMemberId())) + .collect(Collectors.toList()) + ); + } + } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java index 5f4c7db7..aabe793f 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java @@ -1,6 +1,8 @@ package com.moing.backend.domain.mission.application.service; import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; @@ -36,8 +38,10 @@ public void sendNewMissionUploadAlarm(Member member, Mission mission) { String type = mission.getType().toString(); String status = mission.getStatus().toString(); - Optional> memberIdAndTokensByPush = teamMemberGetService.getNewUploadPushInfo(team.getTeamId(), member.getMemberId()); - Optional> memberIdAndTokensBySave = teamMemberGetService.getNewUploadSaveInfo(team.getTeamId(), member.getMemberId()); + Optional> newUploadInfos=teamMemberGetService.getNewUploadInfo(team.getTeamId(), member.getMemberId()); + + Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); + Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); // 알림 보내기 eventPublisher.publishEvent(new MultiFcmEvent(title, message, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId(),mission.getType(),mission.getStatus()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.MISSION_PATH.getValue())); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index 15028f4f..b321c2cf 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.teamMember.domain.repository; import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; @@ -10,10 +11,7 @@ public interface TeamMemberCustomRepository { List findMemberIdsByTeamId(Long teamId); - Optional> findNewUploadPushInfo(Long teamId, Long memberId); - Optional> findNewUploadSaveInfo(Long teamId, Long memberId); - Optional> findRemindPushInfo(Long teamId, Long memberId); - Optional> findRemindSaveInfo(Long teamId, Long memberId); + Optional> findNewUploadInfo(Long teamId, Long memberId); Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId); List findTeamMemberInfoByTeamId(Long teamId); List findTeamMemberByMemberId(Long memberId); diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index 41bf94b2..dcc7f39b 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.teamMember.domain.repository; import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.team.application.dto.response.QTeamMemberInfo; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; @@ -32,55 +33,12 @@ public List findMemberIdsByTeamId(Long teamId) { } @Override - public Optional> findNewUploadPushInfo(Long teamId, Long memberId) { - List result = queryFactory.select(Projections.constructor(MemberIdAndToken.class, + public Optional> findNewUploadInfo(Long teamId, Long memberId) { + List result = queryFactory.select(Projections.constructor(NewUploadInfo.class, teamMember.member.fcmToken, - teamMember.member.memberId)) - .from(teamMember) - .where(teamMember.team.teamId.eq(teamId) - .and(teamMember.member.isNewUploadPush.eq(true)) - .and(teamMember.member.isSignOut.eq(false)) - .and(teamMember.member.memberId.ne(memberId)) - .and(teamMember.isDeleted.eq(false))) - .fetch(); - - return result.isEmpty() ? Optional.empty() : Optional.of(result); - } - - @Override - public Optional> findNewUploadSaveInfo(Long teamId, Long memberId) { - List result = queryFactory.select(Projections.constructor(MemberIdAndToken.class, - teamMember.member.fcmToken, - teamMember.member.memberId)) - .from(teamMember) - .where(teamMember.team.teamId.eq(teamId) - .and(teamMember.member.memberId.ne(memberId)) - .and(teamMember.isDeleted.eq(false))) - .fetch(); - - return result.isEmpty() ? Optional.empty() : Optional.of(result); - } - @Override - public Optional> findRemindPushInfo(Long teamId, Long memberId) { - List result = queryFactory.select(Projections.constructor(MemberIdAndToken.class, - teamMember.member.fcmToken, - teamMember.member.memberId)) - .from(teamMember) - .where(teamMember.team.teamId.eq(teamId) - .and(teamMember.member.isRemindPush.eq(true)) - .and(teamMember.member.isSignOut.eq(false)) - .and(teamMember.member.memberId.ne(memberId)) - .and(teamMember.isDeleted.eq(false))) - .fetch(); - - return result.isEmpty() ? Optional.empty() : Optional.of(result); - } - - @Override - public Optional> findRemindSaveInfo(Long teamId, Long memberId) { - List result = queryFactory.select(Projections.constructor(MemberIdAndToken.class, - teamMember.member.fcmToken, - teamMember.member.memberId)) + teamMember.member.memberId, + teamMember.member.isNewUploadPush, + teamMember.member.isSignOut)) .from(teamMember) .where(teamMember.team.teamId.eq(teamId) .and(teamMember.member.memberId.ne(memberId)) diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index 87d6af25..00d065a3 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.teamMember.domain.service; import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; import com.moing.backend.domain.team.domain.entity.Team; @@ -38,20 +39,9 @@ public List getNotDeletedTeamMember(Long memberId){ return teamMemberRepository.findTeamMemberByMemberId(memberId); } - public Optional> getNewUploadPushInfo(Long teamId, Long memberId) { - return teamMemberRepository.findNewUploadPushInfo(teamId, memberId); + public Optional> getNewUploadInfo(Long teamId, Long memberId) { + return teamMemberRepository.findNewUploadInfo(teamId, memberId); } - public Optional> getNewUploadSaveInfo(Long teamId, Long memberId) { - return teamMemberRepository.findNewUploadSaveInfo(teamId, memberId); - } - - public Optional> getRemindPushInfo(Long teamId, Long memberId) { - return teamMemberRepository.findRemindPushInfo(teamId, memberId); - } - - public Optional> getRemindSaveInfo(Long teamId, Long memberId) { - return teamMemberRepository.findRemindSaveInfo(teamId, memberId); - } } From 5c5a9e725e6c1dcba1629fcbff1affbcc79cb231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Dec 2023 22:38:18 +0900 Subject: [PATCH 412/619] =?UTF-8?q?feat=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=83=81=ED=83=9C=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/MissionArchive-API.adoc | 7 ++ .../com/moing/backend/BackendApplication.java | 2 + .../application/dto/res/MyArchiveStatus.java | 13 +++ .../service/MissionArchiveReadUseCase.java | 9 ++ .../MissionArchiveCustomRepository.java | 4 + .../MissionArchiveCustomRepositoryImpl.java | 28 ++++++ .../service/MissionArchiveQueryService.java | 5 + .../MissionArchiveScheduleQueryService.java | 30 ------ .../MissionArchiveController.java | 14 ++- ...issionArchiveCustomRepositoryImplTest.java | 98 +++++++++++++++++-- .../MissionArchiveControllerTest.java | 51 +++++++++- 11 files changed, 213 insertions(+), 48 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyArchiveStatus.java diff --git a/src/docs/asciidoc/MissionArchive-API.adoc b/src/docs/asciidoc/MissionArchive-API.adoc index b6bfb4e1..fee04ef4 100644 --- a/src/docs/asciidoc/MissionArchive-API.adoc +++ b/src/docs/asciidoc/MissionArchive-API.adoc @@ -50,3 +50,10 @@ operation::mission-archive-controller-test/미션_인증물_좋아요[snippets=' --- + +[[MissionArchive-미션상태조회]] +== 미션 상태 조회 +operation::mission-archive-controller-test/미션_상태_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + diff --git a/src/main/java/com/moing/backend/BackendApplication.java b/src/main/java/com/moing/backend/BackendApplication.java index 8e3ecf24..d60008aa 100644 --- a/src/main/java/com/moing/backend/BackendApplication.java +++ b/src/main/java/com/moing/backend/BackendApplication.java @@ -4,7 +4,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.scheduling.annotation.EnableAsync; +@EnableAsync @EnableFeignClients @SpringBootApplication @EnableJpaAuditing diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyArchiveStatus.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyArchiveStatus.java new file mode 100644 index 00000000..102b47ea --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MyArchiveStatus.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.missionArchive.application.dto.res; + +import lombok.*; + +@ToString +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class MyArchiveStatus { + private boolean end; + private String status; +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java index 497ddb9a..763726a7 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java @@ -75,6 +75,15 @@ public MissionArchiveStatusRes getMissionDoneStatus(Long missionId) { } + public MyArchiveStatus getMissionArchiveStatus(String userSocialId,Long missionId , Long teamId) { + + Long memberId = memberGetService.getMemberBySocialId(userSocialId).getMemberId(); + + return missionArchiveQueryService.findMissionStatusById(memberId, missionId, teamId); + + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 20265798..ac242d4c 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -6,6 +6,7 @@ import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MyArchiveStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import org.springframework.stereotype.Repository; @@ -35,4 +36,7 @@ public interface MissionArchiveCustomRepository { Optional> findHavingRemainMissionsByQuerydsl() ; + + MyArchiveStatus findMissionStatusById(Long memberId, Long missionId, Long teamId); + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 720c237f..8d342bf2 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -9,6 +9,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MyArchiveStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; @@ -20,6 +21,7 @@ import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.CaseBuilder; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQuery; @@ -454,6 +456,32 @@ public Optional> findHavingRemainMissionsByQuerydsl() { } + @Override + public MyArchiveStatus findMissionStatusById(Long memberId, Long missionId, Long teamId) { + + return queryFactory + .select(Projections.constructor(MyArchiveStatus.class, + mission.status.eq(MissionStatus.END), + new CaseBuilder() + .when(mission.status.eq(MissionStatus.WAIT).or(mission.status.eq(MissionStatus.ONGOING))) + .then(missionArchive.status.stringValue().coalesce(mission.status.stringValue())) + .otherwise(missionArchive.status.stringValue().coalesce("FAIL")) + + )).distinct() + .from(mission) + .leftJoin(missionArchive) + .on( + missionArchive.mission.eq(mission), + missionArchive.member.memberId.eq(memberId)) + .where( + mission.team.teamId.eq(teamId), + mission.id.eq(missionId) + ) + .fetchFirst(); + + } + + } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index a374bbbd..2e46966e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -6,6 +6,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; +import com.moing.backend.domain.missionArchive.application.dto.res.MyArchiveStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; import com.moing.backend.domain.missionArchive.exception.NotFoundMissionArchiveException; @@ -129,6 +130,10 @@ public boolean findDoneTodayArchive(Long memberId, Long missionId) { return missionArchiveRepository.findMyArchivesToday(memberId, missionId); } + public MyArchiveStatus findMissionStatusById(Long memberId, Long missionId, Long teamId) { + return missionArchiveRepository.findMissionStatusById(memberId, missionId, teamId); + } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java index 8747de95..3560526b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveScheduleQueryService.java @@ -25,36 +25,6 @@ public class MissionArchiveScheduleQueryService { public List getRemainMissionPeople() { return missionArchiveRepository.findHavingRemainMissionsByQuerydsl().orElseThrow(); -// return Optional.of(maps.stream() -// .map(map -> { -// Object memberIdObject = map.get("memberId"); -// Long memberId = ((BigInteger) memberIdObject).longValue(); -// -// Object fcmObject = map.get("fcmToken"); -// String fcmToken = fcmObject.toString(); -// -// return MemberIdAndToken.builder() -// .fcmToken(fcmToken) -// .memberId(memberId) -// .build(); -// }) -// .collect(Collectors.toList())); - -// return null; - -// return maps.stream() -// .map(map -> { -// String fcmToken = Optional.ofNullable(map.get("fcmToken")).map(Object::toString).orElse("undef"); -// Long memberId = map.get("memberId"); -// -// return MemberIdAndToken.builder() -// .fcmToken(fcmToken) -// .memberId(memberId) -// .build(); -// -// }) -// .collect(Collectors.toList()); - } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java index 3f0a41f5..a321467f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionArchiveController.java @@ -3,10 +3,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; -import com.moing.backend.domain.missionArchive.application.dto.res.MyMissionArchiveRes; -import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.*; import com.moing.backend.domain.missionArchive.application.service.*; @@ -152,4 +149,13 @@ public ResponseEntity> getMyMissionDone } + @GetMapping("/mission-status") + public ResponseEntity> getMyMissionStatus(@AuthenticationPrincipal User user, + @PathVariable("teamId") Long teamId, + @PathVariable("missionId") Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage(), this.missionArchiveReadUseCase.getMissionArchiveStatus(user.getSocialId(), missionId,teamId))); + } + + + } \ No newline at end of file diff --git a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java index 823795a4..e2dd262b 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImplTest.java @@ -1,11 +1,21 @@ //package com.moing.backend.domain.missionArchive.domain.repository; // //import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +//import com.moing.backend.domain.member.domain.entity.Member; +//import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; //import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; //import com.moing.backend.domain.mission.application.service.MissionRemindAlarmUseCase; //import com.moing.backend.domain.mission.domain.entity.Mission; //import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; //import com.moing.backend.domain.mission.domain.repository.MissionRepository; +//import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +//import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +//import com.moing.backend.domain.missionArchive.application.dto.res.MyArchiveStatus; +//import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; +//import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; +//import com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateUseCase; +//import com.moing.backend.domain.missionArchive.application.service.MissionArchiveReadUseCase; +//import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; //import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveScheduleQueryService; //import com.querydsl.jpa.impl.JPAQueryFactory; //import org.junit.jupiter.api.Test; @@ -37,19 +47,13 @@ // @Autowired // MissionArchiveScheduleQueryService missionArchiveScheduleQueryService; // +// @Autowired +// MissionArchiveCreateUseCase missionArchiveCreateUseCase; // -// @Test -// void findPeopleRemainMission() { +// @Autowired +// MissionArchiveReadUseCase missionArchiveReadUseCase; // -// //System.out.println("!!!"+ missionArchiveRepository.findHavingRemainMissions().get().size()); // -// List remainMissionPeople = missionArchiveScheduleQueryService.getRemainMissionPeople().orElseThrow(); -// for (MemberIdAndToken remainMissionPerson : remainMissionPeople) { -// System.out.println("!!"+remainMissionPerson.getFcmToken() + " " + remainMissionPerson.getMemberId()); -// -// } -// missionRemindAlarmUseCase.sendRemindMissionAlarm(); -// } // // // @Test @@ -70,4 +74,78 @@ // System.out.println(singleMissionBoardRes.getTitle()); // } // } +// +// @Test +// void findMissionStatus() { +// MissionArchive missionArchive = missionArchiveRepository.findById(198L).orElseThrow(); +// MissionArchiveRes missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchive,33L); +// System.out.println(missionArchiveRes.toString()); +// } +// +// @Test +// void createMissionArchive() { +// System.out.println(missionArchiveCreateUseCase.createArchive("KAKAO@tester02", 211L, MissionArchiveReq.builder() +// .status("SKIP") +// .archive("hihi") +// .build())); +// +// System.out.println(); +// +// +// } +// +// +// @Test +// void findRemainPeople() { +// +// List members = missionRepository.findRepeatMissionPeopleByStatus(MissionStatus.WAIT).orElseThrow(); +// for (Member member : members) { +// System.out.println(member.getNickName()); +// } } +// +//// @Test +//// void report() { +//// +//// reportCreateUseCase.createReport("KAKAO@tester02", 550L, "MISSION"); +//// +//// List teams = new ArrayList<>(); +//// teams.add(48L); +//// List top5ArchivesByTeam = missionArchiveRepository.findTop5ArchivesByTeam(teams).orElseThrow(); +//// +//// System.out.println(top5ArchivesByTeam.get(0).getPhoto().get(0).toString()); +//// +//// } +// +// +// @Test +// void catHeartList() { +// +// List personalArchive = missionArchiveReadUseCase.getPersonalArchive("APPLE@001616.4e6d97f481fa441aa3a6169666c5552a.0841", 234L); +// for (PersonalArchiveRes personalArchiveRes : personalArchive) { +// System.out.println(personalArchiveRes); +// } +// } +// +// @Test +// void finishiMissions() { +// List finishMissionBoardResList = missionArchiveRepository.findFinishMissionsByStatus(33L, 48L).orElseThrow(); +// for (FinishMissionBoardRes finishMissionBoardRes : finishMissionBoardResList) { +// System.out.println(finishMissionBoardRes.toString()); +// } +// } +// +// @Test +// void finishArchives() { +// List missionArchives = missionArchiveRepository.findMyArchives(33L, 323L).orElseThrow(); +// for (MissionArchive missionArchive : missionArchives) { +// System.out.println(missionArchive.toString()); +// } +// } +// +// @Test +// void isstatus() { +// +// MyArchiveStatus missionStatusById = missionArchiveRepository.findMissionStatusById(51L, 323L, 48L); +// System.out.println(missionStatusById); +// } //} \ No newline at end of file diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index bef311b4..9c189db1 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -3,10 +3,7 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveHeartReq; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveStatusRes; -import com.moing.backend.domain.missionArchive.application.dto.res.MyMissionArchiveRes; -import com.moing.backend.domain.missionArchive.application.dto.res.PersonalArchiveRes; +import com.moing.backend.domain.missionArchive.application.dto.res.*; import com.moing.backend.domain.missionArchive.application.service.*; import com.moing.backend.domain.missionArchive.presentation.MissionArchiveController; import com.moing.backend.domain.missionHeart.application.dto.MissionHeartRes; @@ -497,6 +494,52 @@ public class MissionArchiveControllerTest extends CommonControllerTest { } + @Test + public void 미션_상태_조회() throws Exception { + //given + + MyArchiveStatus output = MyArchiveStatus.builder() + .end(Boolean.TRUE) + .status("WAIT/ONGOING/COMPLETE/SKIP/FAIL") + .build(); + + given(missionArchiveReadUseCase.getMissionArchiveStatus(any(),any(),any())).willReturn(output); + + Long teamId = 1L; + Long missionId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/{teamId}/missions/{missionId}/archive/mission-status",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("미션 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage()), + fieldWithPath("data.end").description("미션 종료 여부"), + fieldWithPath("data.status").description("미션 인증 상태 ") + ) + ) + ) + .andReturn(); + + } + + From 6470a020dc9a44fbcd36aae13c93fa3091106e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 20 Dec 2023 22:45:33 +0900 Subject: [PATCH 413/619] =?UTF-8?q?fix=20:=20=EB=A6=AC=EB=A7=88=EC=9D=B8?= =?UTF-8?q?=EB=93=9C=20=EC=95=8C=EB=A6=BC=20team.isDeleted.ne(true)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionCustomRepositoryImpl.java | 3 ++- .../MissionArchiveCustomRepositoryImpl.java | 15 ++------------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 0e2db2b2..a585c651 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -117,7 +117,8 @@ public Optional> findRepeatMissionPeopleByStatus(MissionStatus miss .from(teamMember) .join(mission) .on(teamMember.team.eq(mission.team), - teamMember.member.isDeleted.ne(true)) + teamMember.member.isDeleted.ne(true), + teamMember.team.isDeleted.ne(true)) .where( mission.status.eq(missionStatus), mission.type.eq(MissionType.REPEAT) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 8d342bf2..f373f849 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -377,19 +377,12 @@ public Boolean findMyArchivesToday(Long memberId, Long missionId) { } -// .where( -// // active 한 미션 필터링 -// (((mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT))).and(mission.type.eq(MissionType.ONCE))) -// .or((mission.status.eq(MissionStatus.ONGOING)).and(mission.type.eq(MissionType.REPEAT)))), - private BooleanExpression createRepeatTypeConditionByArchive() { LocalDate now = LocalDate.now(); DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); LocalDate endOfWeek = startOfWeek.plusDays(6); - // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 -// BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); @@ -403,11 +396,6 @@ private BooleanExpression createRepeatTypeConditionByState() { LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); LocalDate endOfWeek = startOfWeek.plusDays(6); - // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 -// BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); -// BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) -// .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); - BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); @@ -450,7 +438,8 @@ public Optional> findHavingRemainMissionsByQuerydsl() { ) .groupBy(teamMember.member,mission,mission.number) .having(missionArchive.count().lt(mission.number), - teamMember.member.isDeleted.ne(true)) + teamMember.member.isDeleted.ne(true), + teamMember.team.isDeleted.ne(true)) .fetch()); From c7fca3ce910d438ea60c5b2aaf582b8f475dee95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 21 Dec 2023 00:10:03 +0900 Subject: [PATCH 414/619] =?UTF-8?q?fix=20:=20=EC=82=AC=EC=A7=84=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=8B=9C=20=EA=B1=B4=EB=84=88=EB=9B=B0?= =?UTF-8?q?=EA=B8=B0=20=ED=95=A0=20=EB=95=8C=20=ED=85=8D=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EB=A9=94=EC=8B=9C=EC=A7=80=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/report/application/service/ReportCreateUseCase.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java index 3fcc15de..2fec4fc1 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java @@ -8,6 +8,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.report.application.mapper.ReportMapper; @@ -56,7 +57,7 @@ public Long createReport(String socialId, Long targetId, String reportType) { targetMemberNickName = missionArchive.getMember().getNickName(); - if (mission.getWay().equals(MissionWay.PHOTO)) { + if (mission.getWay().equals(MissionWay.PHOTO) && missionArchive.getStatus().equals(MissionArchiveStatus.COMPLETE)) { missionArchive.updateArchive(MissionArchiveReq.builder() .archive(REPORT_MISSION_PHOTO) .status(missionArchive.getStatus().name()) From c0ea38e544c35fa376128752172a71d70aff0940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 21 Dec 2023 10:25:16 +0900 Subject: [PATCH 415/619] =?UTF-8?q?fix=20:=20team.isDeleted=20=EB=8B=A4?= =?UTF-8?q?=EC=8B=9C=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionRemindAlarmUseCase.java | 16 ++++++++++++++-- .../MissionArchiveCustomRepositoryImpl.java | 4 ++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index a9fb37f6..a946a6b0 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -1,6 +1,8 @@ package com.moing.backend.domain.mission.application.service; import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; @@ -35,6 +37,9 @@ public class MissionRemindAlarmUseCase { private final MissionQueryService missionQueryService; private final ApplicationEventPublisher eventPublisher; + private final FcmService fcmService; + private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; + String REMIND_NAME = "미션 리마인드"; @@ -49,8 +54,15 @@ public Boolean sendRemindMissionAlarm() { Optional> memberIdAndTokens = mapToMemberAndToken(remainMissionPeople); Optional> pushMemberIdAndToken = isPushMemberIdAndToken(remainMissionPeople); - eventPublisher.publishEvent(new MultiFcmEvent(title, message, pushMemberIdAndToken, memberIdAndTokens, - "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); +// eventPublisher.publishEvent(new MultiFcmEvent(title, message, pushMemberIdAndToken, memberIdAndTokens, +// "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + + if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { + fcmService.sendMultipleDevices(new MultiRequest(pushMemberIdAndToken.get(), title,message, "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + } + if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { + saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()),"",title,message,REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); + } return true; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index f373f849..331c3f57 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -426,6 +426,7 @@ public Optional> findHavingRemainMissionsByQuerydsl() { .from(teamMember) .join(mission) .on(teamMember.team.eq(mission.team), + teamMember.team.isDeleted.ne(true), ((mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT))) .and(mission.type.eq(MissionType.ONCE))) .or(mission.status.eq(MissionStatus.ONGOING).and(mission.type.eq(MissionType.REPEAT))) @@ -438,8 +439,7 @@ public Optional> findHavingRemainMissionsByQuerydsl() { ) .groupBy(teamMember.member,mission,mission.number) .having(missionArchive.count().lt(mission.number), - teamMember.member.isDeleted.ne(true), - teamMember.team.isDeleted.ne(true)) + teamMember.member.isDeleted.ne(true)) .fetch()); From 3aa876922e269348e6cdaa24238fdf02aff1072b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:13:39 +0900 Subject: [PATCH 416/619] =?UTF-8?q?fix=20:=20=EB=A6=AC=EB=A7=88=EC=9D=B8?= =?UTF-8?q?=EB=93=9C=20=EC=95=8C=EB=A6=BC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=8A=A4=EC=BC=80=EC=A5=B4=EB=9F=AC=20?= =?UTF-8?q?=EC=A3=BC=EA=B8=B0=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionStateScheduleUseCase.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index a094b41f..e13660f2 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -83,7 +83,8 @@ public void RepeatMissionStart() { } - @Scheduled(cron = "0 0 8 * * *") +// @Scheduled(cron = "0 0 8 * * *") + @Scheduled(cron = "0 0/10 * * * *") public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } From 94d90f2806b7c8d5575631d1e55ce0753411463a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:23:11 +0900 Subject: [PATCH 417/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=8A=A4=EC=BC=80=EC=A5=B4=EB=9F=AC=20=EC=A3=BC=EA=B8=B0=20?= =?UTF-8?q?=EC=9B=90=EC=83=81=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionStateScheduleUseCase.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index e13660f2..a094b41f 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -83,8 +83,7 @@ public void RepeatMissionStart() { } -// @Scheduled(cron = "0 0 8 * * *") - @Scheduled(cron = "0 0/10 * * * *") + @Scheduled(cron = "0 0 8 * * *") public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } From f5c0f7997e227ce1f850c534fc98daf9d6459d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:44:07 +0900 Subject: [PATCH 418/619] =?UTF-8?q?feat=20:=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EC=B0=A8=EB=8B=A8=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/application/mapper/BlockMapper.java | 15 +++++++ .../service/BlockCreateUseCase.java | 39 ++++++++++++++++ .../service/BlockDeleteUseCase.java | 37 ++++++++++++++++ .../application/service/BlockReadUseCase.java | 34 ++++++++++++++ .../domain/block/domain/entity/Block.java | 27 ++++++++++++ .../repository/BlockCustomRepository.java | 16 +++++++ .../repository/BlockCustomRepositoryImpl.java | 42 ++++++++++++++++++ .../domain/repository/BlockRepository.java | 8 ++++ .../domain/service/BlockDeleteService.java | 18 ++++++++ .../domain/service/BlockQueryService.java | 24 ++++++++++ .../domain/service/BlockSaveService.java | 18 ++++++++ .../block/exception/BlockException.java | 11 +++++ .../exception/NotFoundBlockException.java | 11 +++++ .../block/presentation/BlockController.java | 44 +++++++++++++++++++ .../constant/BlockResponseMessage.java | 16 +++++++ 15 files changed, 360 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/block/application/mapper/BlockMapper.java create mode 100644 src/main/java/com/moing/backend/domain/block/application/service/BlockCreateUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/block/application/service/BlockDeleteUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/block/domain/entity/Block.java create mode 100644 src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepository.java create mode 100644 src/main/java/com/moing/backend/domain/block/domain/service/BlockDeleteService.java create mode 100644 src/main/java/com/moing/backend/domain/block/domain/service/BlockQueryService.java create mode 100644 src/main/java/com/moing/backend/domain/block/domain/service/BlockSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/block/exception/BlockException.java create mode 100644 src/main/java/com/moing/backend/domain/block/exception/NotFoundBlockException.java create mode 100644 src/main/java/com/moing/backend/domain/block/presentation/BlockController.java create mode 100644 src/main/java/com/moing/backend/domain/block/presentation/constant/BlockResponseMessage.java diff --git a/src/main/java/com/moing/backend/domain/block/application/mapper/BlockMapper.java b/src/main/java/com/moing/backend/domain/block/application/mapper/BlockMapper.java new file mode 100644 index 00000000..a9c1e42d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/application/mapper/BlockMapper.java @@ -0,0 +1,15 @@ +package com.moing.backend.domain.block.application.mapper; + +import com.moing.backend.domain.block.domain.entity.Block; +import com.moing.backend.global.annotation.Mapper; + +@Mapper +public class BlockMapper { + + public static Block mapToBlock(Long memberId, Long targetId) { + return Block.builder() + .blockMemberId(memberId) + .targetId(targetId) + .build(); + } +} diff --git a/src/main/java/com/moing/backend/domain/block/application/service/BlockCreateUseCase.java b/src/main/java/com/moing/backend/domain/block/application/service/BlockCreateUseCase.java new file mode 100644 index 00000000..2094c929 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/application/service/BlockCreateUseCase.java @@ -0,0 +1,39 @@ +package com.moing.backend.domain.block.application.service; + +import com.moing.backend.domain.block.application.mapper.BlockMapper; +import com.moing.backend.domain.block.domain.service.BlockDeleteService; +import com.moing.backend.domain.block.domain.service.BlockQueryService; +import com.moing.backend.domain.block.domain.service.BlockSaveService; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class BlockCreateUseCase { + + private final MemberGetService memberGetService; + private final BoardGetService boardGetService; + private final MissionArchiveQueryService missionArchiveQueryService; + + private final BlockSaveService blockSaveService; + + + /** + * 차단 하기 + */ + + public Long createBlock(String socialId, Long targetId) { + Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); + + blockSaveService.save(BlockMapper.mapToBlock(memberId, targetId)); + + return targetId; + } + + +} diff --git a/src/main/java/com/moing/backend/domain/block/application/service/BlockDeleteUseCase.java b/src/main/java/com/moing/backend/domain/block/application/service/BlockDeleteUseCase.java new file mode 100644 index 00000000..f262c244 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/application/service/BlockDeleteUseCase.java @@ -0,0 +1,37 @@ +package com.moing.backend.domain.block.application.service; + +import com.moing.backend.domain.block.application.mapper.BlockMapper; +import com.moing.backend.domain.block.domain.service.BlockDeleteService; +import com.moing.backend.domain.block.domain.service.BlockQueryService; +import com.moing.backend.domain.block.domain.service.BlockSaveService; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class BlockDeleteUseCase { + + private final MemberGetService memberGetService; + private final BoardGetService boardGetService; + private final MissionArchiveQueryService missionArchiveQueryService; + + private final BlockDeleteService blockDeleteService; + + + /** + * 차단 철회하기 + */ + + public Long deleteBlock(String socialId, Long targetId) { + Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); + blockDeleteService.delete(memberId, targetId); + + return targetId; + } + +} diff --git a/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java b/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java new file mode 100644 index 00000000..db51546e --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java @@ -0,0 +1,34 @@ +package com.moing.backend.domain.block.application.service; + +import com.moing.backend.domain.block.application.mapper.BlockMapper; +import com.moing.backend.domain.block.domain.service.BlockDeleteService; +import com.moing.backend.domain.block.domain.service.BlockQueryService; +import com.moing.backend.domain.block.domain.service.BlockSaveService; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class BlockReadUseCase { + + private final MemberGetService memberGetService; + private final BoardGetService boardGetService; + private final MissionArchiveQueryService missionArchiveQueryService; + + private final BlockQueryService blockQueryService; + + /** + * 차단한 리스트 조회하기 + */ + public List getMyBlockList(String socialId) { + Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); + + return blockQueryService.getBlockLists(memberId); + } + +} diff --git a/src/main/java/com/moing/backend/domain/block/domain/entity/Block.java b/src/main/java/com/moing/backend/domain/block/domain/entity/Block.java new file mode 100644 index 00000000..853c3eb3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/domain/entity/Block.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.block.domain.entity; + +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Builder +public class Block extends BaseTimeEntity { + + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "block_id") + private Long id; + + private Long blockMemberId; + private Long targetId; + +} diff --git a/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepository.java b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepository.java new file mode 100644 index 00000000..ebf0e006 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepository.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.block.domain.repository; + +import com.moing.backend.domain.block.domain.entity.Block; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + + +public interface BlockCustomRepository{ + + Optional> getMyBlockList(Long memberId); + Optional getBlockById(Long memberId, Long targetId); + + } diff --git a/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepositoryImpl.java new file mode 100644 index 00000000..9acdedb7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepositoryImpl.java @@ -0,0 +1,42 @@ +package com.moing.backend.domain.block.domain.repository; + +import com.moing.backend.domain.block.domain.entity.Block; +import com.moing.backend.domain.block.domain.entity.QBlock; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import javax.persistence.EntityManager; +import java.util.List; +import java.util.Optional; + +import static com.moing.backend.domain.block.domain.entity.QBlock.block; + +public class BlockCustomRepositoryImpl implements BlockCustomRepository { + + private final JPAQueryFactory queryFactory; + + public BlockCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + + @Override + public Optional> getMyBlockList(Long memberId) { + return Optional.ofNullable(queryFactory + .select(block.targetId) + .from(block) + .where(block.blockMemberId.eq(memberId)) + .fetch()); + } + + @Override + public Optional getBlockById(Long memberId, Long targetId) { + return Optional.ofNullable(queryFactory + .selectFrom(block) + .where( + block.blockMemberId.eq(memberId), + block.targetId.eq(targetId)).fetchFirst()); + + } +} diff --git a/src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepository.java b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepository.java new file mode 100644 index 00000000..8de0870a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepository.java @@ -0,0 +1,8 @@ +package com.moing.backend.domain.block.domain.repository; + +import com.moing.backend.domain.block.domain.entity.Block; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface BlockRepository extends JpaRepository,BlockCustomRepository { + +} diff --git a/src/main/java/com/moing/backend/domain/block/domain/service/BlockDeleteService.java b/src/main/java/com/moing/backend/domain/block/domain/service/BlockDeleteService.java new file mode 100644 index 00000000..0c23769d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/domain/service/BlockDeleteService.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.block.domain.service; + +import com.moing.backend.domain.block.domain.entity.Block; +import com.moing.backend.domain.block.domain.repository.BlockRepository; +import com.moing.backend.domain.block.exception.NotFoundBlockException; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class BlockDeleteService { + private final BlockRepository blockRepository; + + public void delete(Long memberId, Long targetId) { + Block block = blockRepository.getBlockById(memberId, targetId).orElseThrow(NotFoundBlockException::new); + blockRepository.delete(block); + } +} diff --git a/src/main/java/com/moing/backend/domain/block/domain/service/BlockQueryService.java b/src/main/java/com/moing/backend/domain/block/domain/service/BlockQueryService.java new file mode 100644 index 00000000..20147e79 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/domain/service/BlockQueryService.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.block.domain.service; + +import com.moing.backend.domain.block.domain.entity.Block; +import com.moing.backend.domain.block.domain.repository.BlockRepository; +import com.moing.backend.domain.block.exception.NotFoundBlockException; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@DomainService +@RequiredArgsConstructor +public class BlockQueryService { + + private final BlockRepository blockRepository; + + public List getBlockLists(Long memberId) { + return blockRepository.getMyBlockList(memberId).orElseThrow(NotFoundBlockException::new); + } + + public Block getBlock(Long memberId, Long targetId) { + return blockRepository.getBlockById(memberId, targetId).orElseThrow(NotFoundBlockException::new); + } +} diff --git a/src/main/java/com/moing/backend/domain/block/domain/service/BlockSaveService.java b/src/main/java/com/moing/backend/domain/block/domain/service/BlockSaveService.java new file mode 100644 index 00000000..fd6e764a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/domain/service/BlockSaveService.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.block.domain.service; + +import com.moing.backend.domain.block.domain.entity.Block; +import com.moing.backend.domain.block.domain.repository.BlockRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class BlockSaveService { + + private final BlockRepository blockRepository; + + + public Block save(Block block) { + return blockRepository.save(block); + } +} diff --git a/src/main/java/com/moing/backend/domain/block/exception/BlockException.java b/src/main/java/com/moing/backend/domain/block/exception/BlockException.java new file mode 100644 index 00000000..31375d3b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/exception/BlockException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.block.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class BlockException extends ApplicationException { + protected BlockException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/block/exception/NotFoundBlockException.java b/src/main/java/com/moing/backend/domain/block/exception/NotFoundBlockException.java new file mode 100644 index 00000000..2d15c0d7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/exception/NotFoundBlockException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.block.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundBlockException extends BlockException { + public NotFoundBlockException() { + super(ErrorCode.NOT_FOUND_BY_BOARD_ID_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/block/presentation/BlockController.java b/src/main/java/com/moing/backend/domain/block/presentation/BlockController.java new file mode 100644 index 00000000..d8818657 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/presentation/BlockController.java @@ -0,0 +1,44 @@ +package com.moing.backend.domain.block.presentation; + +import com.moing.backend.domain.block.application.service.BlockCreateUseCase; +import com.moing.backend.domain.block.application.service.BlockDeleteUseCase; +import com.moing.backend.domain.block.application.service.BlockReadUseCase; +import com.moing.backend.domain.block.domain.service.BlockDeleteService; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static com.moing.backend.domain.block.presentation.constant.BlockResponseMessage.*; +import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.CREATE_REPORT_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/block") +public class BlockController { + + private final BlockReadUseCase blockReadUseCase; + private final BlockCreateUseCase blockCreateUseCase; + private final BlockDeleteUseCase blockDeleteUseCase; + + @PostMapping("/{targetId}") + public ResponseEntity> createBlock(@AuthenticationPrincipal User user, + @PathVariable("targetId") Long targetId) { + return ResponseEntity.ok(SuccessResponse.create(CREATE_BLOCK_SUCCESS.getMessage(), this.blockCreateUseCase.createBlock(user.getSocialId(), targetId))); + } + + @DeleteMapping("/{targetId}") + public ResponseEntity> deleteBlock(@AuthenticationPrincipal User user, + @PathVariable("targetId") Long targetId) { + return ResponseEntity.ok(SuccessResponse.create(DELETE_BLOCK_SUCCESS.getMessage(), this.blockDeleteUseCase.deleteBlock(user.getSocialId(), targetId))); + } + + @GetMapping("") + public ResponseEntity>> getBlocks(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(GET_BLOCK_SUCCESS.getMessage(), this.blockReadUseCase.getMyBlockList(user.getSocialId()))); + } +} diff --git a/src/main/java/com/moing/backend/domain/block/presentation/constant/BlockResponseMessage.java b/src/main/java/com/moing/backend/domain/block/presentation/constant/BlockResponseMessage.java new file mode 100644 index 00000000..ab3e5734 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/presentation/constant/BlockResponseMessage.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.block.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum BlockResponseMessage { + + CREATE_BLOCK_SUCCESS("사용자 차단을 완료했습니다."), + GET_BLOCK_SUCCESS("사용자 차단 목록 조회를 완료했습니다."), + DELETE_BLOCK_SUCCESS("사용자 차단 해제를 완료했습니다."); + + private final String message; + +} From 38d3d5af519c55a043ffa0075b1cb74811f6fa2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:44:19 +0900 Subject: [PATCH 419/619] =?UTF-8?q?feat=20:=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EC=B0=A8=EB=8B=A8=ED=95=98=EA=B8=B0=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/BlockControllerTest.java | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/test/java/com/moing/backend/domain/block/presentation/BlockControllerTest.java diff --git a/src/test/java/com/moing/backend/domain/block/presentation/BlockControllerTest.java b/src/test/java/com/moing/backend/domain/block/presentation/BlockControllerTest.java new file mode 100644 index 00000000..bb727dcf --- /dev/null +++ b/src/test/java/com/moing/backend/domain/block/presentation/BlockControllerTest.java @@ -0,0 +1,159 @@ +package com.moing.backend.domain.block.presentation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.block.application.service.BlockCreateUseCase; +import com.moing.backend.domain.block.application.service.BlockDeleteUseCase; +import com.moing.backend.domain.block.application.service.BlockReadUseCase; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.ArrayList; +import java.util.List; + +import static com.moing.backend.domain.block.presentation.constant.BlockResponseMessage.*; +import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.CREATE_REPORT_SUCCESS; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; + +@WebMvcTest(BlockController.class) +class BlockControllerTest extends CommonControllerTest { + + @MockBean + private BlockReadUseCase blockReadUseCase; + @MockBean + private BlockCreateUseCase blockCreateUseCase; + @MockBean + private BlockDeleteUseCase blockDeleteUseCase; + + @Test + public void 차단_하기() throws Exception{ + + Long targetId = 1L; + + given(blockCreateUseCase.createBlock(any(),any())).willReturn(targetId); + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + post("/api/block/{targetId}", targetId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + pathParameters( + parameterWithName("targetId").description("신고할 사용자 아이디") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(CREATE_BLOCK_SUCCESS.getMessage()), + fieldWithPath("data").description("신고한 유저 번호") + + ) + ) + ) + .andReturn(); + + } + + @Test + public void 차단_해제_하기() throws Exception{ + + Long targetId = 1L; + + given(blockDeleteUseCase.deleteBlock(any(),any())).willReturn(targetId); + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/block/{targetId}", targetId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + pathParameters( + parameterWithName("targetId").description("신고할 사용자 아이디") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(DELETE_BLOCK_SUCCESS.getMessage()), + fieldWithPath("data").description("신고한 유저 번호") + + ) + ) + ) + .andReturn(); + + } + + @Test + public void 차단한_유저_목록() throws Exception{ + + + List response = new ArrayList<>(); + + given(blockReadUseCase.getMyBlockList(any())).willReturn(response); + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/block/") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(GET_BLOCK_SUCCESS.getMessage()), + fieldWithPath("data").description("차단한 유저 목록") + + ) + ) + ) + .andReturn(); + + } + + + +} \ No newline at end of file From 30ac67222140f6dcf948c213842573ee04c10369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:44:34 +0900 Subject: [PATCH 420/619] =?UTF-8?q?feat=20:=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EC=B0=A8=EB=8B=A8=ED=95=98=EA=B8=B0=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94(2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Block-API.adoc | 19 +++++++++++++++++++ .../backend/global/response/ErrorCode.java | 5 ++++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/docs/asciidoc/Block-API.adoc diff --git a/src/docs/asciidoc/Block-API.adoc b/src/docs/asciidoc/Block-API.adoc new file mode 100644 index 00000000..9f9d7464 --- /dev/null +++ b/src/docs/asciidoc/Block-API.adoc @@ -0,0 +1,19 @@ + + +[[Block-API]] += Block API + +[[Block-차단하기]] +=== 차단하기 +operation::block-controller-test/차단_하기[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- +=== 차단 해제 하기 +operation::block-controller-test/차단_해제_하기[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- + +=== 차단한 유저 조회 List +operation::block-controller-test/차단한_유저_목록[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 2534fdb6..9a82564b 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -60,7 +60,10 @@ public enum ErrorCode { NOT_AUTH_BY_BOARD_COMMENT_ID_ERROR("BC0002","권한이 없습니다."), //알림 관련 에러 코드 - NOT_FOUND_BY_ALARM_HISOTRY_ID_ERROR("AH0001","해당 alarmHistoryId인 알림이 존재하지 않습니다."); + NOT_FOUND_BY_ALARM_HISOTRY_ID_ERROR("AH0001","해당 alarmHistoryId인 알림이 존재하지 않습니다."), + + //차단 관련 에러 코드 + NOT_FOUND_BLOCK_LIST("BL0001","차단한 사용자를 찾을 수 없습니다"); private String errorCode; private String message; From c738abd6741a8d1ee6003c3d6e359bc4f5af033a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 27 Dec 2023 00:06:48 +0900 Subject: [PATCH 421/619] =?UTF-8?q?feat=20:=20=EC=B0=A8=EB=8B=A8=ED=95=9C?= =?UTF-8?q?=20=EC=9C=A0=EC=A0=80=20=EC=A0=95=EB=B3=B4=20=EB=AA=A9=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Block-API.adoc | 5 ++ .../application/service/BlockReadUseCase.java | 6 +++ .../repository/BlockCustomRepository.java | 2 + .../repository/BlockCustomRepositoryImpl.java | 19 ++++++++ .../domain/service/BlockQueryService.java | 4 ++ .../block/presentation/BlockController.java | 7 +++ .../application/dto/BlockMemberRes.java | 15 ++++++ .../presentation/BlockControllerTest.java | 46 +++++++++++++++++++ 8 files changed, 104 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/report/application/dto/BlockMemberRes.java diff --git a/src/docs/asciidoc/Block-API.adoc b/src/docs/asciidoc/Block-API.adoc index 9f9d7464..99baf903 100644 --- a/src/docs/asciidoc/Block-API.adoc +++ b/src/docs/asciidoc/Block-API.adoc @@ -17,3 +17,8 @@ operation::block-controller-test/차단_해제_하기[snippets='http-request,pat operation::block-controller-test/차단한_유저_목록[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- + +=== 차단한 유저 정보 조회 +operation::block-controller-test/차단한_유저_정보_목록[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- diff --git a/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java b/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java index db51546e..c66922dd 100644 --- a/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.report.application.dto.BlockMemberRes; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -30,5 +31,10 @@ public List getMyBlockList(String socialId) { return blockQueryService.getBlockLists(memberId); } + public List getMyBlockInfoList(String socialId) { + Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); + + return blockQueryService.getBlockInfoLists(memberId); + } } diff --git a/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepository.java b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepository.java index ebf0e006..8dd0685e 100644 --- a/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepository.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.block.domain.repository; import com.moing.backend.domain.block.domain.entity.Block; +import com.moing.backend.domain.report.application.dto.BlockMemberRes; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; @@ -11,6 +12,7 @@ public interface BlockCustomRepository{ Optional> getMyBlockList(Long memberId); + Optional> getMyBlockInfoList(Long memberId); Optional getBlockById(Long memberId, Long targetId); } diff --git a/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepositoryImpl.java index 9acdedb7..1856d27a 100644 --- a/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockCustomRepositoryImpl.java @@ -2,6 +2,9 @@ import com.moing.backend.domain.block.domain.entity.Block; import com.moing.backend.domain.block.domain.entity.QBlock; +import com.moing.backend.domain.member.domain.entity.QMember; +import com.moing.backend.domain.report.application.dto.BlockMemberRes; +import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; @@ -11,6 +14,7 @@ import java.util.Optional; import static com.moing.backend.domain.block.domain.entity.QBlock.block; +import static com.moing.backend.domain.member.domain.entity.QMember.member; public class BlockCustomRepositoryImpl implements BlockCustomRepository { @@ -29,6 +33,21 @@ public Optional> getMyBlockList(Long memberId) { .where(block.blockMemberId.eq(memberId)) .fetch()); } + @Override + public Optional> getMyBlockInfoList(Long memberId) { + return Optional.ofNullable(queryFactory + .select(Projections.constructor(BlockMemberRes.class, + block.targetId, + member.nickName, + member.introduction, + member.profileImage + )) + .from(block) + .join(member) + .on(member.memberId.eq(block.targetId)) + .where(block.blockMemberId.eq(memberId)) + .fetch()); + } @Override public Optional getBlockById(Long memberId, Long targetId) { diff --git a/src/main/java/com/moing/backend/domain/block/domain/service/BlockQueryService.java b/src/main/java/com/moing/backend/domain/block/domain/service/BlockQueryService.java index 20147e79..8614a9a9 100644 --- a/src/main/java/com/moing/backend/domain/block/domain/service/BlockQueryService.java +++ b/src/main/java/com/moing/backend/domain/block/domain/service/BlockQueryService.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.block.domain.entity.Block; import com.moing.backend.domain.block.domain.repository.BlockRepository; import com.moing.backend.domain.block.exception.NotFoundBlockException; +import com.moing.backend.domain.report.application.dto.BlockMemberRes; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; @@ -17,6 +18,9 @@ public class BlockQueryService { public List getBlockLists(Long memberId) { return blockRepository.getMyBlockList(memberId).orElseThrow(NotFoundBlockException::new); } + public List getBlockInfoLists(Long memberId) { + return blockRepository.getMyBlockInfoList(memberId).orElseThrow(NotFoundBlockException::new); + } public Block getBlock(Long memberId, Long targetId) { return blockRepository.getBlockById(memberId, targetId).orElseThrow(NotFoundBlockException::new); diff --git a/src/main/java/com/moing/backend/domain/block/presentation/BlockController.java b/src/main/java/com/moing/backend/domain/block/presentation/BlockController.java index d8818657..4d999ef4 100644 --- a/src/main/java/com/moing/backend/domain/block/presentation/BlockController.java +++ b/src/main/java/com/moing/backend/domain/block/presentation/BlockController.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.block.application.service.BlockDeleteUseCase; import com.moing.backend.domain.block.application.service.BlockReadUseCase; import com.moing.backend.domain.block.domain.service.BlockDeleteService; +import com.moing.backend.domain.report.application.dto.BlockMemberRes; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -41,4 +42,10 @@ public ResponseEntity> deleteBlock(@AuthenticationPrincipa public ResponseEntity>> getBlocks(@AuthenticationPrincipal User user) { return ResponseEntity.ok(SuccessResponse.create(GET_BLOCK_SUCCESS.getMessage(), this.blockReadUseCase.getMyBlockList(user.getSocialId()))); } + + @GetMapping("/info") + public ResponseEntity>> getBlockList(@AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(GET_BLOCK_SUCCESS.getMessage(), this.blockReadUseCase.getMyBlockInfoList(user.getSocialId()))); + } + } diff --git a/src/main/java/com/moing/backend/domain/report/application/dto/BlockMemberRes.java b/src/main/java/com/moing/backend/domain/report/application/dto/BlockMemberRes.java new file mode 100644 index 00000000..746351e5 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/application/dto/BlockMemberRes.java @@ -0,0 +1,15 @@ +package com.moing.backend.domain.report.application.dto; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Builder +@Getter +@Setter +public class BlockMemberRes { + private Long targetId; + private String nickName; + private String introduce; + private String profileImg; +} diff --git a/src/test/java/com/moing/backend/domain/block/presentation/BlockControllerTest.java b/src/test/java/com/moing/backend/domain/block/presentation/BlockControllerTest.java index bb727dcf..2d9b9d47 100644 --- a/src/test/java/com/moing/backend/domain/block/presentation/BlockControllerTest.java +++ b/src/test/java/com/moing/backend/domain/block/presentation/BlockControllerTest.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.block.application.service.BlockCreateUseCase; import com.moing.backend.domain.block.application.service.BlockDeleteUseCase; import com.moing.backend.domain.block.application.service.BlockReadUseCase; +import com.moing.backend.domain.report.application.dto.BlockMemberRes; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -11,6 +12,7 @@ import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.assertj.core.util.Lists; import java.util.ArrayList; import java.util.List; @@ -153,6 +155,50 @@ class BlockControllerTest extends CommonControllerTest { .andReturn(); } + @Test + public void 차단한_유저_정보_목록() throws Exception{ + + + List output = Lists.newArrayList(BlockMemberRes.builder() + .targetId(1L) + .introduce("차단한 사용자 소개") + .nickName("차단한 사용자 닉네임") + .profileImg("프로필 이미지") + .build()); + + given(blockReadUseCase.getMyBlockInfoList(any())).willReturn(output); + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/block/info") + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(GET_BLOCK_SUCCESS.getMessage()), + fieldWithPath("data[].targetId").description("차단한 유저 아이디"), + fieldWithPath("data[].nickName").description("차단한 유저 닉네임"), + fieldWithPath("data[].profileImg").description("차단한 유저 프로필 이미지"), + fieldWithPath("data[].introduce").description("차단한 유저 소개") + + ) + ) + ) + .andReturn(); + + } From d660541b0b734ffb9f4cefcf673b166219a008f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 27 Dec 2023 00:14:49 +0900 Subject: [PATCH 422/619] =?UTF-8?q?feat=20:=20=EB=AA=A8=EB=91=90=EC=9D=98?= =?UTF-8?q?=20=EC=9D=B8=EC=A6=9D=20=EB=A6=AC=ED=84=B4=EA=B0=92=EC=97=90=20?= =?UTF-8?q?makerId=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/PersonalArchiveRes.java | 3 +++ .../application/mapper/MissionArchiveMapper.java | 1 + .../representation/MissionArchiveControllerTest.java | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java index 70dc9df0..47df8949 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java @@ -22,4 +22,7 @@ public class PersonalArchiveRes { private String status; private Long count; + private Long makerId; + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 3f92a03a..deac83d6 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -83,6 +83,7 @@ public static PersonalArchiveRes mapToPersonalArchive(MissionArchive missionArch .filter(heart -> heart.getHeartStatus().equals( MissionHeartStatus.True)) .filter(heart -> heart.getMissionArchive().equals( missionArchive))// heartStatus가 true인 요소만 필터링 .count()) + .makerId(missionArchive.getMember().getMemberId()) .build(); } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 9c189db1..97ea9614 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -303,6 +303,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .count(1L) .heartStatus("[True/False]") .hearts(3) + .makerId(1L) .build()); given(missionArchiveReadUseCase.getPersonalArchive(any(),any())).willReturn(output); @@ -341,7 +342,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data[].status").description("미션 인증 상태"), fieldWithPath("data[].count").description("미션 인증 횟수"), fieldWithPath("data[].heartStatus").description("미션 인증 좋아요 상태 "), - fieldWithPath("data[].hearts").description("미션 인증 좋아요 수 ") + fieldWithPath("data[].hearts").description("미션 인증 좋아요 수 "), + fieldWithPath("data[].makerId").description("미션 인증한 사람 ") ) From 204d75df359327a659b22436efe5e970c12d10b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 27 Dec 2023 00:29:41 +0900 Subject: [PATCH 423/619] =?UTF-8?q?feat=20:=20=EC=8B=A0=EA=B3=A0=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EC=9C=84=ED=95=9C=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EB=A6=AC=ED=84=B4=EA=B0=92=20makerId=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/GetBoardDetailResponse.java | 2 ++ .../backend/domain/board/application/mapper/BoardMapper.java | 3 ++- .../domain/board/presentation/BoardControllerTest.java | 5 ++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/GetBoardDetailResponse.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/GetBoardDetailResponse.java index 9d9b4197..92ac6ad7 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/response/GetBoardDetailResponse.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/GetBoardDetailResponse.java @@ -28,4 +28,6 @@ public class GetBoardDetailResponse { private Boolean isWriter; private Boolean isNotice; + + private Long makerId; } diff --git a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java index 1337f692..0d2bb359 100644 --- a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java +++ b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java @@ -3,7 +3,6 @@ import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; import com.moing.backend.domain.board.application.dto.response.GetBoardDetailResponse; import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import lombok.RequiredArgsConstructor; @@ -35,6 +34,7 @@ public Board toBoard(TeamMember teamMember, Team team, CreateBoardRequest create public GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter, boolean writerIsDeleted) { String nickName = writerIsDeleted ? "(알 수 없음)" : board.getTeamMember().getMember().getNickName(); String writerProfileImage = writerIsDeleted ? null : board.getTeamMember().getMember().getProfileImage(); + Long writerId = writerIsDeleted ? null : board.getTeamMember().getMember().getMemberId(); return GetBoardDetailResponse.builder() .boardId(board.getBoardId()) .title(board.getTitle()) @@ -45,6 +45,7 @@ public GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter, boole .createdDate(getFormattedDate(board.getCreatedDate())) .isWriter(isWriter) .isNotice(board.isNotice()) + .makerId(writerId) .build(); } diff --git a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java index ec018e6a..f3fe5379 100644 --- a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java @@ -289,6 +289,7 @@ public void get_board_detail() throws Exception { .createdDate("2023/09/29 23:42") .isWriter(false) .isNotice(false) + .makerId(1L) .build(); given(getBoardUseCase.getBoardDetail(any(), any(), any())).willReturn(output); @@ -325,7 +326,9 @@ public void get_board_detail() throws Exception { fieldWithPath("data.content").description("게시글 내용"), fieldWithPath("data.createdDate").description("게시글 생성 날짜, 시간"), fieldWithPath("data.isWriter").description("게시글 작성자 여부"), - fieldWithPath("data.isNotice").description("게시글 공지 여부") + fieldWithPath("data.isNotice").description("게시글 공지 여부"), + fieldWithPath("data.makerId").description("작성자 아이디") + ) ) From a7f7473323fc9085e236874ca806ddd915b06247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 27 Dec 2023 00:39:27 +0900 Subject: [PATCH 424/619] =?UTF-8?q?feat=20:=20API=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/api.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 014423fb..41519d3c 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -36,3 +36,4 @@ include::TeamScore-API.adoc[] include::Report-API.adoc[] +include::Block-API.adoc[] \ No newline at end of file From 34da3d77b239a573c0223f4b1e57f0174d7d0a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 27 Dec 2023 23:56:54 +0900 Subject: [PATCH 425/619] =?UTF-8?q?feat=20:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=8B=A0=EA=B3=A0=ED=95=98=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boardComment/domain/entity/BoardComment.java | 5 +++++ .../application/service/ReportCreateUseCase.java | 12 ++++++++++++ .../report/domain/entity/constant/ReportType.java | 2 +- .../board/presentation/BoardControllerTest.java | 2 +- .../report/presentation/ReportControllerTest.java | 7 +++++++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java index ab437a2a..7edf67cb 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.boardComment.domain.entity; import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; @@ -47,4 +48,8 @@ public void updateTeamMember(TeamMember teamMember) { this.teamMember = teamMember; } + public void updateBoardComment(CreateBoardCommentRequest createBoardCommentRequest) { + this.content = createBoardCommentRequest.getContent(); + } + } diff --git a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java index 2fec4fc1..999140b9 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java @@ -3,6 +3,9 @@ import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardGetService; +import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; @@ -29,6 +32,7 @@ public class ReportCreateUseCase { private final BoardGetService boardGetService; private final MissionArchiveQueryService missionArchiveQueryService; + private final BoardCommentGetService boardCommentGetService; private final String REPORT_BOARD_TITLE ="신고 접수된 게시물입니다."; private final String REPORT_BOARD_MESSAGE ="신고 접수로 삭제된 게시물입니다."; @@ -50,6 +54,14 @@ public Long createReport(String socialId, Long targetId, String reportType) { .content(REPORT_BOARD_MESSAGE) .isNotice(board.isNotice()) .build()); + } + else if (reportType.equals(ReportType.COMMENT.name())) { + BoardComment boardComment = boardCommentGetService.getBoardComment(targetId); + targetMemberNickName = boardComment.getTeamMember().getMember().getNickName(); + + boardComment.updateBoardComment(CreateBoardCommentRequest.builder() + .content(REPORT_BOARD_MESSAGE) + .build()); } else { MissionArchive missionArchive = missionArchiveQueryService.findByMissionArchiveId(targetId); diff --git a/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java b/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java index 2c844a0c..3d95530d 100644 --- a/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java +++ b/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java @@ -1,5 +1,5 @@ package com.moing.backend.domain.report.domain.entity.constant; public enum ReportType { - MISSION,BOARD + MISSION,BOARD,COMMENT } diff --git a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java index f3fe5379..fadb1d3a 100644 --- a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java @@ -328,7 +328,7 @@ public void get_board_detail() throws Exception { fieldWithPath("data.isWriter").description("게시글 작성자 여부"), fieldWithPath("data.isNotice").description("게시글 공지 여부"), fieldWithPath("data.makerId").description("작성자 아이디") - + ) ) diff --git a/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java b/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java index d7fe241f..6d791bae 100644 --- a/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java +++ b/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java @@ -22,6 +22,8 @@ import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; @WebMvcTest(ReportController.class) public class ReportControllerTest extends CommonControllerTest { @@ -56,6 +58,11 @@ public class ReportControllerTest extends CommonControllerTest { headerWithName("Authorization").description("접근 토큰") ), + pathParameters( + parameterWithName("reportType").description("MISSION/BOARD/COMMENT"), + parameterWithName("targetId").description("신고할 board,missionArchive,comment 아이디") + ), + responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description(CREATE_REPORT_SUCCESS.getMessage()), From afecf965d26dc74aa932f953ea8be8a5ced4b2cd Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 28 Dec 2023 20:08:25 +0900 Subject: [PATCH 426/619] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=EC=9E=90=20id=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/BoardBlocks.java | 6 ++- .../repository/BoardCustomRepositoryImpl.java | 3 +- .../presentation/BoardControllerTest.java | 44 ++++++++++--------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java index fb6c7f3e..b00a78b5 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java @@ -30,9 +30,11 @@ public class BoardBlocks { private boolean isNotice; + private Long makerId; + @QueryProjection - public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, String writerProfileImage, String title, String content, Integer commentNum, Boolean writerIsDeleted, boolean isNotice) { + public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, String writerProfileImage, String title, String content, Integer commentNum, Boolean writerIsDeleted, boolean isNotice, Long makerId) { this.boardId = boardId; this.writerNickName = writerNickName; this.writerIsLeader = writerIsLeader; @@ -43,6 +45,7 @@ public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, this.isRead = false; this.writerIsDeleted=writerIsDeleted; this.isNotice=isNotice; + this.makerId = makerId; deleteMember(); } @@ -58,6 +61,7 @@ public void deleteMember() { if(Boolean.TRUE.equals(writerIsDeleted)) { this.writerNickName = "(알 수 없음)"; this.writerProfileImage = null; + this.makerId = null; } } } diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index eb3ee18e..8b864967 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -34,7 +34,8 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { board.content, board.commentNum, board.teamMember.isDeleted, - board.isNotice + board.isNotice, + board.teamMember.member.memberId )) .from(board) .leftJoin(board.teamMember, teamMember) diff --git a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java index fadb1d3a..6a06f669 100644 --- a/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/board/presentation/BoardControllerTest.java @@ -200,6 +200,7 @@ public void get_board_all() throws Exception { .commentNum(2) .isRead(false) .isNotice(true) + .makerId(1L) .build(); BoardBlocks notNoticeBlock = BoardBlocks.builder() @@ -213,6 +214,7 @@ public void get_board_all() throws Exception { .commentNum(2) .isRead(false) .isNotice(false) + .makerId(1L) .build(); noticeBlocks.add(noticeBlock); @@ -246,27 +248,29 @@ public void get_board_all() throws Exception { fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("게시글 목록을 모두 조회했습니다."), fieldWithPath("data.noticeNum").description("공지 개수"), - fieldWithPath("data.noticeBlocks[0].boardId").description("공지 아이디"), - fieldWithPath("data.noticeBlocks[0].writerNickName").description("작성자 닉네임"), - fieldWithPath("data.noticeBlocks[0].writerIsLeader").description("작성자 소모임장 여부"), - fieldWithPath("data.noticeBlocks[0].writerProfileImage").description("작성자 프로필 이미지"), - fieldWithPath("data.noticeBlocks[0].writerIsDeleted").description("작성자 삭제 여부"), - fieldWithPath("data.noticeBlocks[0].title").description("공지 제목"), - fieldWithPath("data.noticeBlocks[0].content").description("공지 내용"), - fieldWithPath("data.noticeBlocks[0].commentNum").description("공지 댓글 개수"), - fieldWithPath("data.noticeBlocks[0].isRead").description("공지 읽음 처리 여부"), - fieldWithPath("data.noticeBlocks[0].notice").description("true"), + fieldWithPath("data.noticeBlocks[].boardId").description("공지 아이디"), + fieldWithPath("data.noticeBlocks[].writerNickName").description("작성자 닉네임"), + fieldWithPath("data.noticeBlocks[].writerIsLeader").description("작성자 소모임장 여부"), + fieldWithPath("data.noticeBlocks[].writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.noticeBlocks[].writerIsDeleted").description("작성자 삭제 여부"), + fieldWithPath("data.noticeBlocks[].title").description("공지 제목"), + fieldWithPath("data.noticeBlocks[].content").description("공지 내용"), + fieldWithPath("data.noticeBlocks[].commentNum").description("공지 댓글 개수"), + fieldWithPath("data.noticeBlocks[].isRead").description("공지 읽음 처리 여부"), + fieldWithPath("data.noticeBlocks[].notice").description("true"), + fieldWithPath("data.noticeBlocks[].makerId").description("작성자 Id"), fieldWithPath("data.notNoticeNum").description("일반 게시글 개수"), - fieldWithPath("data.notNoticeBlocks[0].boardId").description("일반 게시글 아이디"), - fieldWithPath("data.notNoticeBlocks[0].writerNickName").description("작성자 닉네임"), - fieldWithPath("data.notNoticeBlocks[0].writerIsLeader").description("작성자 소모임장 여부"), - fieldWithPath("data.notNoticeBlocks[0].writerProfileImage").description("작성자 프로필 이미지"), - fieldWithPath("data.notNoticeBlocks[0].writerIsDeleted").description("작성자 삭제 여부"), - fieldWithPath("data.notNoticeBlocks[0].title").description("일반 게시글 제목"), - fieldWithPath("data.notNoticeBlocks[0].content").description("일반 게시글 내용"), - fieldWithPath("data.notNoticeBlocks[0].commentNum").description("일반 게시글 댓글 개수"), - fieldWithPath("data.notNoticeBlocks[0].isRead").description("일반 게시글 읽음 처리 여부"), - fieldWithPath("data.notNoticeBlocks[0].notice").description("false") + fieldWithPath("data.notNoticeBlocks[].boardId").description("일반 게시글 아이디"), + fieldWithPath("data.notNoticeBlocks[].writerNickName").description("작성자 닉네임"), + fieldWithPath("data.notNoticeBlocks[].writerIsLeader").description("작성자 소모임장 여부"), + fieldWithPath("data.notNoticeBlocks[].writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.notNoticeBlocks[].writerIsDeleted").description("작성자 삭제 여부"), + fieldWithPath("data.notNoticeBlocks[].title").description("일반 게시글 제목"), + fieldWithPath("data.notNoticeBlocks[].content").description("일반 게시글 내용"), + fieldWithPath("data.notNoticeBlocks[].commentNum").description("일반 게시글 댓글 개수"), + fieldWithPath("data.notNoticeBlocks[].isRead").description("일반 게시글 읽음 처리 여부"), + fieldWithPath("data.notNoticeBlocks[].notice").description("false"), + fieldWithPath("data.notNoticeBlocks[].makerId").description("작성자 Id") ) ) From 7050b9c92825deb21639bc1a8f8d56db5f4580ac Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 30 Dec 2023 00:25:20 +0900 Subject: [PATCH 427/619] =?UTF-8?q?feat:=20=EB=8C=93=EA=B8=80=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=EC=97=90=EC=84=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=EC=9E=90=20id=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/CommentBlocks.java | 6 +++++- .../domain/repository/BoardCommentCustomRepositoryImpl.java | 3 ++- .../presentation/BoardCommentControllerTest.java | 6 ++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java index d9f3fb83..a9cf080f 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java @@ -29,8 +29,10 @@ public class CommentBlocks { private String createdDate; + private Long makerId; + @QueryProjection - public CommentBlocks(Long boardCommentId, String content, String writerNickName, Boolean writerIsLeader, String writerProfileImage, Boolean isWriter, Boolean writerIsDeleted, LocalDateTime createdDate) { + public CommentBlocks(Long boardCommentId, String content, String writerNickName, Boolean writerIsLeader, String writerProfileImage, Boolean isWriter, Boolean writerIsDeleted, LocalDateTime createdDate, Long makerId) { this.boardCommentId = boardCommentId; this.writerNickName = writerNickName; this.writerIsLeader = writerIsLeader; @@ -39,11 +41,13 @@ public CommentBlocks(Long boardCommentId, String content, String writerNickName, this.isWriter = isWriter; this.writerIsDeleted=writerIsDeleted; this.createdDate = getFormattedDate(createdDate); + this.makerId = makerId; deleteMember(); } public void deleteMember() { if (Boolean.TRUE.equals(writerIsDeleted)) { + this.makerId = null; this.writerNickName = "(알 수 없음)"; this.writerProfileImage = null; } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index 5a4d22b3..56b3b862 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -40,7 +40,8 @@ public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember team .and(QTeamMember.teamMember.eq(boardComment.teamMember))) .exists(), "isWriter"), boardComment.teamMember.isDeleted, - boardComment.createdDate)) + boardComment.createdDate, + boardComment.teamMember.member.memberId)) .from(boardComment) .leftJoin(boardComment.teamMember, QTeamMember.teamMember) .leftJoin(boardComment.teamMember.member, member) diff --git a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java index 637ef310..0b8ea674 100644 --- a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java +++ b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java @@ -143,6 +143,7 @@ public void get_board_comment_all() throws Exception { .writerIsDeleted(false) .isWriter(true) .createdDate("2023/12/05 23:29") + .makerId(1L) .build(); commentBlocks.add(commentBlock); @@ -182,8 +183,9 @@ public void get_board_comment_all() throws Exception { fieldWithPath("data.commentBlocks[].writerProfileImage").description("작성자 프로필 이미지"), fieldWithPath("data.commentBlocks[].writerIsDeleted").description("작성자 삭제 여부"), fieldWithPath("data.commentBlocks[].isWriter").description("댓글 작성자 여부"), - fieldWithPath("data.commentBlocks[].createdDate").description("생성 시간") - ) + fieldWithPath("data.commentBlocks[].createdDate").description("생성 시간"), + fieldWithPath("data.commentBlocks[].makerId").description("작성자 Id") + ) ) ); From 438482e42e8006feedf5c6da710dee16539d985c Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 30 Dec 2023 00:39:15 +0900 Subject: [PATCH 428/619] =?UTF-8?q?fix:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=B0=A8=EB=8B=A8=ED=95=A0=20=EB=95=8C=20=EB=8F=99=EC=9D=BC?= =?UTF-8?q?=ED=95=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=EA=B0=80=20=EC=B0=A8?= =?UTF-8?q?=EB=8B=A8=ED=95=9C=20=EA=B2=BD=EC=9A=B0=20=EC=A4=91=EB=B3=B5?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/block/domain/service/BlockSaveService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/block/domain/service/BlockSaveService.java b/src/main/java/com/moing/backend/domain/block/domain/service/BlockSaveService.java index fd6e764a..c79a8920 100644 --- a/src/main/java/com/moing/backend/domain/block/domain/service/BlockSaveService.java +++ b/src/main/java/com/moing/backend/domain/block/domain/service/BlockSaveService.java @@ -5,6 +5,8 @@ import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; +import java.util.Optional; + @DomainService @RequiredArgsConstructor public class BlockSaveService { @@ -13,6 +15,8 @@ public class BlockSaveService { public Block save(Block block) { - return blockRepository.save(block); + //기존에 동일한 사람이 차단했으면 중복 제거 + Optional findBlock=blockRepository.getBlockById(block.getBlockMemberId(), block.getTargetId()); + return findBlock.orElseGet(() -> blockRepository.save(block)); } } From 784778d8008da3ebf51dde3c47de6c8ff45af2ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 30 Dec 2023 21:07:50 +0900 Subject: [PATCH 429/619] =?UTF-8?q?fix=20:=20BlockMemerRes=20Constructor?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/report/application/dto/BlockMemberRes.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/report/application/dto/BlockMemberRes.java b/src/main/java/com/moing/backend/domain/report/application/dto/BlockMemberRes.java index 746351e5..1c7563d0 100644 --- a/src/main/java/com/moing/backend/domain/report/application/dto/BlockMemberRes.java +++ b/src/main/java/com/moing/backend/domain/report/application/dto/BlockMemberRes.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.report.application.dto; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.Setter; @@ -7,6 +8,7 @@ @Builder @Getter @Setter +@AllArgsConstructor public class BlockMemberRes { private Long targetId; private String nickName; From 82af1b089c1275ec7d66fbc37d46320519654198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 31 Dec 2023 17:40:39 +0900 Subject: [PATCH 430/619] =?UTF-8?q?fix=20:=20=EA=B2=8C=EC=8B=9C=EB=AC=BC?= =?UTF-8?q?=20=EC=A0=84=EC=B2=B4=EC=A1=B0=ED=9A=8C=20null=20=EA=B0=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/domain/repository/BoardCustomRepositoryImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index 8b864967..44ec1dc8 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -27,7 +27,7 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { List allBoardBlocks = queryFactory .select(new QBoardBlocks( board.boardId, - board.teamMember.member.nickName, + board.teamMember.member.nickName.coalesce("알수없음"), board.isLeader, board.teamMember.member.profileImage, board.title, @@ -35,7 +35,7 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { board.commentNum, board.teamMember.isDeleted, board.isNotice, - board.teamMember.member.memberId + board.teamMember.member.memberId.coalesce(0L) )) .from(board) .leftJoin(board.teamMember, teamMember) From 96ef753e12f21ddb751e292c54a7a8d070b1f905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 31 Dec 2023 17:50:17 +0900 Subject: [PATCH 431/619] =?UTF-8?q?fix=20:=20=ED=83=88=ED=87=B4=ED=95=9C?= =?UTF-8?q?=20=EB=A9=A4=EB=B2=84=20makerId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/board/application/dto/response/BoardBlocks.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java index b00a78b5..a33dcc21 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java @@ -61,7 +61,7 @@ public void deleteMember() { if(Boolean.TRUE.equals(writerIsDeleted)) { this.writerNickName = "(알 수 없음)"; this.writerProfileImage = null; - this.makerId = null; + this.makerId = 0L; } } } From a1bdb32e1a54c81ff28c2e2c0d2ad8453da1b078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 31 Dec 2023 17:57:02 +0900 Subject: [PATCH 432/619] =?UTF-8?q?fix=20:=20=EA=B2=8C=EC=8B=9C=EB=AC=BC?= =?UTF-8?q?=20=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=ED=83=88=ED=87=B4?= =?UTF-8?q?=ED=95=9C=20=EC=9D=B8=EC=9B=90=20=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/board/application/mapper/BoardMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java index 0d2bb359..9d98f4c3 100644 --- a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java +++ b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java @@ -34,7 +34,7 @@ public Board toBoard(TeamMember teamMember, Team team, CreateBoardRequest create public GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter, boolean writerIsDeleted) { String nickName = writerIsDeleted ? "(알 수 없음)" : board.getTeamMember().getMember().getNickName(); String writerProfileImage = writerIsDeleted ? null : board.getTeamMember().getMember().getProfileImage(); - Long writerId = writerIsDeleted ? null : board.getTeamMember().getMember().getMemberId(); + Long writerId = writerIsDeleted ? 0L : board.getTeamMember().getMember().getMemberId(); return GetBoardDetailResponse.builder() .boardId(board.getBoardId()) .title(board.getTitle()) From f87bdd0e67da23ef98119f141b3586531dedfb85 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 1 Jan 2024 19:33:15 +0900 Subject: [PATCH 433/619] =?UTF-8?q?fix:=20=EC=95=88=20=EC=9D=BD=EC=9D=80?= =?UTF-8?q?=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=9D=8C=EC=88=98=20=EB=B0=A9?= =?UTF-8?q?=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/BoardCustomRepositoryImpl.java | 5 +++-- .../domain/boardRead/domain/entity/BoardRead.java | 3 ++- .../boardRead/domain/repository/BoardReadRepository.java | 3 ++- .../boardRead/domain/service/BoardReadSaveService.java | 9 ++++++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index 8b864967..2d0dee81 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -81,11 +81,12 @@ public Integer findUnReadBoardNum(Long teamId, Long memberId) { // 멤버가 읽은 게시글 수 Long readBoards = queryFactory - .select(boardRead.count()) + .select(boardRead.board.boardId) + .distinct() .from(boardRead) .where(boardRead.member.memberId.eq(memberId)) .where(boardRead.board.team.teamId.eq(teamId)) - .fetchFirst(); + .stream().count(); return Math.toIntExact(allBoards - readBoards); } diff --git a/src/main/java/com/moing/backend/domain/boardRead/domain/entity/BoardRead.java b/src/main/java/com/moing/backend/domain/boardRead/domain/entity/BoardRead.java index 4c5d6334..63ea5c98 100644 --- a/src/main/java/com/moing/backend/domain/boardRead/domain/entity/BoardRead.java +++ b/src/main/java/com/moing/backend/domain/boardRead/domain/entity/BoardRead.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -15,7 +16,7 @@ @NoArgsConstructor @AllArgsConstructor @Getter -public class BoardRead { +public class BoardRead extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java b/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java index b17cca58..0053ac5b 100644 --- a/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java +++ b/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java @@ -6,8 +6,9 @@ import com.moing.backend.domain.team.domain.entity.Team; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; import java.util.Optional; public interface BoardReadRepository extends JpaRepository { - Optional findBoardReadByBoardAndMemberAndTeam(Board board, Member member, Team team); + List findBoardReadByBoardAndMemberAndTeam(Board board, Member member, Team team); } diff --git a/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java b/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java index 1e81792d..c15ca2c7 100644 --- a/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java +++ b/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java @@ -7,6 +7,7 @@ import lombok.RequiredArgsConstructor; import javax.transaction.Transactional; +import java.util.List; @DomainService @RequiredArgsConstructor @@ -16,7 +17,13 @@ public class BoardReadSaveService { private final BoardReadRepository boardReadRepository; public void saveBoardRead(Board board, BoardRead boardRead) { - if ((boardReadRepository.findBoardReadByBoardAndMemberAndTeam(board, boardRead.getMember(), boardRead.getTeam())).isEmpty()) { + List existingBoardReads = boardReadRepository.findBoardReadByBoardAndMemberAndTeam(board, boardRead.getMember(), boardRead.getTeam()); + + if (existingBoardReads.size() > 1) { + // 첫 번째 엔티티를 제외하고 나머지 삭제 + List duplicates = existingBoardReads.subList(1, existingBoardReads.size()); + boardReadRepository.deleteAll(duplicates); + } else if (existingBoardReads.isEmpty()) { boardRead.updateBoard(board); boardReadRepository.save(boardRead); } From 76a153886dce313cca084edf5255dbfc4e683b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 1 Jan 2024 23:03:11 +0900 Subject: [PATCH 434/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A2=85=EB=A3=8C=20=EB=A1=9C=EC=A7=81=EC=97=90=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=20=EC=8B=9C=EA=B0=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionUpdateUseCase.java | 3 +++ .../moing/backend/domain/mission/domain/entity/Mission.java | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index 57cc5204..7dc1119d 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -15,6 +15,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; + @Service @Transactional @RequiredArgsConstructor @@ -46,6 +48,7 @@ public MissionReadRes updateMissionStatus(String userSocialId, Long missionId) { if (findMission.getTeam().getLeaderId().equals(member.getMemberId())) { findMission.updateStatus(MissionStatus.END); + findMission.updateDueTo(LocalDateTime.now()); } else { throw new NoAccessCreateMission(); } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index e0096d3a..60fd58d3 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -91,4 +91,8 @@ public void setTeam(Team team) { public void updateStatus(MissionStatus missionStatus) { this.status = missionStatus; } + + public void updateDueTo(LocalDateTime dueTo) { + this.dueTo = dueTo; + } } From 8e2e0a190af4d34b2bc10e7ba97b940ce0acd7a7 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 3 Jan 2024 19:37:03 +0900 Subject: [PATCH 435/619] =?UTF-8?q?deploy:=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=84=B8=EC=8A=A4=20prod,=20dev=20=EB=82=98?= =?UTF-8?q?=EB=88=84=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .deploy/Dockerfile | 16 +++++ .deploy/deploy_dev.sh | 67 ++++++++++++++++++ .deploy/deploy_prod.sh | 67 ++++++++++++++++++ .github/workflows/CD-dev.yml | 123 ++++++++++++++++++++++++++++++++++ .github/workflows/CD-prod.yml | 123 ++++++++++++++++++++++++++++++++++ .github/workflows/CI-dev.yml | 57 ++++++++++++++++ .github/workflows/CI-prod.yml | 57 ++++++++++++++++ 7 files changed, 510 insertions(+) create mode 100644 .deploy/Dockerfile create mode 100644 .deploy/deploy_dev.sh create mode 100644 .deploy/deploy_prod.sh create mode 100644 .github/workflows/CD-dev.yml create mode 100644 .github/workflows/CD-prod.yml create mode 100644 .github/workflows/CI-dev.yml create mode 100644 .github/workflows/CI-prod.yml diff --git a/.deploy/Dockerfile b/.deploy/Dockerfile new file mode 100644 index 00000000..25848cbe --- /dev/null +++ b/.deploy/Dockerfile @@ -0,0 +1,16 @@ +FROM openjdk:11-jdk + +# 타임존 설정 +ENV TZ=Asia/Seoul +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +ARG CACHEBREAKER=1 +ARG JAR_FILE=./build/libs/backend-0.0.1-SNAPSHOT.jar +COPY ${JAR_FILE} app.jar + +# 문서를 이미지의 /static/docs 디렉토리에 복사 +COPY ./build/docs/asciidoc/*.html /static/docs/ + +# 애플리케이션 실행 시 -cp 옵션을 사용하여 /static/docs 디렉토리를 클래스패스에 추가 +ENTRYPOINT ["java","-cp",".:/static/docs","-jar","/app.jar"] + diff --git a/.deploy/deploy_dev.sh b/.deploy/deploy_dev.sh new file mode 100644 index 00000000..0c2181d8 --- /dev/null +++ b/.deploy/deploy_dev.sh @@ -0,0 +1,67 @@ +DOCKER_APP_NAME=meetup +DOCKER_USERNAME=modagbul + +# 최신 이미지 가져오기 +docker pull ${DOCKER_USERNAME}/moing_dev:blue +docker pull ${DOCKER_USERNAME}/moing_dev:green + +# 현재 실행 중인 컨테이너를 확인 (blue 또는 green) +EXIST_BLUE=$(docker ps --filter name=${DOCKER_APP_NAME}-blue --filter status=running -q) +EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --filter status=running -q) + +# 둘 다 실행 중이지 않을 경우 blue 실행 +if [ -z "$EXIST_BLUE" ] && [ -z "$EXIST_GREEN" ]; then + echo "No containers running. Starting blue up" + + # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. + if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-blue -q)" ]; then + docker rm ${DOCKER_APP_NAME}-blue + fi + + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_dev:blue + BEFORE_COMPOSE_COLOR="green" + AFTER_COMPOSE_COLOR="blue" +elif [ -z "$EXIST_BLUE" ]; then + echo "blue up" + + # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. + if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-blue -q)" ]; then + docker rm ${DOCKER_APP_NAME}-blue + fi + + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_dev:blue + BEFORE_COMPOSE_COLOR="green" + AFTER_COMPOSE_COLOR="blue" +else + echo "green up" + + # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. + if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-green -q)" ]; then + docker rm ${DOCKER_APP_NAME}-green + fi + + docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_dev:green + BEFORE_COMPOSE_COLOR="blue" + AFTER_COMPOSE_COLOR="green" +fi + + +sleep 40 + +# 새로운 컨테이너가 제대로 실행되었는지 확인 +EXIST_AFTER=$(docker ps --filter name=${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} --filter status=running -q) +if [ -n "$EXIST_AFTER" ]; then + # nginx.config를 컨테이너에 맞게 변경해주고 reload 한다 + cp ./nginx.${AFTER_COMPOSE_COLOR}.conf /etc/nginx/nginx.conf + sudo nginx -s reload + + # 이전 컨테이너 종료 + docker stop ${DOCKER_APP_NAME}-${BEFORE_COMPOSE_COLOR} + docker rm ${DOCKER_APP_NAME}-${BEFORE_COMPOSE_COLOR} + echo "$BEFORE_COMPOSE_COLOR down" +else + # Docker logs + LOGS=$(docker logs ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} 2>&1) + echo "Error: ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} failed to start." + echo "$LOGS" +fi \ No newline at end of file diff --git a/.deploy/deploy_prod.sh b/.deploy/deploy_prod.sh new file mode 100644 index 00000000..91c86b59 --- /dev/null +++ b/.deploy/deploy_prod.sh @@ -0,0 +1,67 @@ +DOCKER_APP_NAME=meetup +DOCKER_USERNAME=modagbul + +# 최신 이미지 가져오기 +docker pull ${DOCKER_USERNAME}/moing_prod:blue +docker pull ${DOCKER_USERNAME}/moing_prod:green + +# 현재 실행 중인 컨테이너를 확인 (blue 또는 green) +EXIST_BLUE=$(docker ps --filter name=${DOCKER_APP_NAME}-blue --filter status=running -q) +EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --filter status=running -q) + +# 둘 다 실행 중이지 않을 경우 blue 실행 +if [ -z "$EXIST_BLUE" ] && [ -z "$EXIST_GREEN" ]; then + echo "No containers running. Starting blue up" + + # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. + if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-blue -q)" ]; then + docker rm ${DOCKER_APP_NAME}-blue + fi + + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_prod:blue + BEFORE_COMPOSE_COLOR="green" + AFTER_COMPOSE_COLOR="blue" +elif [ -z "$EXIST_BLUE" ]; then + echo "blue up" + + # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. + if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-blue -q)" ]; then + docker rm ${DOCKER_APP_NAME}-blue + fi + + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_prod:blue + BEFORE_COMPOSE_COLOR="green" + AFTER_COMPOSE_COLOR="blue" +else + echo "green up" + + # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. + if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-green -q)" ]; then + docker rm ${DOCKER_APP_NAME}-green + fi + + docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_prod:green + BEFORE_COMPOSE_COLOR="blue" + AFTER_COMPOSE_COLOR="green" +fi + + +sleep 40 + +# 새로운 컨테이너가 제대로 실행되었는지 확인 +EXIST_AFTER=$(docker ps --filter name=${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} --filter status=running -q) +if [ -n "$EXIST_AFTER" ]; then + # nginx.config를 컨테이너에 맞게 변경해주고 reload 한다 + cp ./nginx.${AFTER_COMPOSE_COLOR}.conf /etc/nginx/nginx.conf + sudo nginx -s reload + + # 이전 컨테이너 종료 + docker stop ${DOCKER_APP_NAME}-${BEFORE_COMPOSE_COLOR} + docker rm ${DOCKER_APP_NAME}-${BEFORE_COMPOSE_COLOR} + echo "$BEFORE_COMPOSE_COLOR down" +else + # Docker logs + LOGS=$(docker logs ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} 2>&1) + echo "Error: ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} failed to start." + echo "$LOGS" +fi \ No newline at end of file diff --git a/.github/workflows/CD-dev.yml b/.github/workflows/CD-dev.yml new file mode 100644 index 00000000..40cd9a33 --- /dev/null +++ b/.github/workflows/CD-dev.yml @@ -0,0 +1,123 @@ +name: CD-dev + +on: + push: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + env: + working-directory: ./ + APPLICATION: ${{ secrets.APPLICATION_DEV }} + GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_DEV }} + APPLE_KEY: ${{ secrets.APPLE_KEY_DEV }} + + steps: + # 소스 코드 체크아웃 + - uses: actions/checkout@v2 + + # JDK 11 설정 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + + # Gradle 패키지 캐시 + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + # 설정 파일 생성 + - run: | + mkdir ./src/main/resources + cd ./src/main/resources + touch ./application.yml + echo "${{env.APPLICATION}}" > ./application.yml + touch ./firebase-key.json + echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json + touch ./apple-key.p8 + echo "${{env.APPLE_KEY}}" > ./apple-key.p8 + + # 설정 파일을 작업공간에 저장 + - uses: actions/upload-artifact@v2 + with: + name: application.yml + path: ./src/main/resources/application.yml + + - uses: actions/upload-artifact@v2 + with: + name: firebase-key.json + path: ./src/main/resources/firebase-key.json + + - uses: actions/upload-artifact@v2 + with: + name: apple-key.p8 + path: ./src/main/resources/apple-key.p8 + + # gradlew 권한 설정 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + working-directory: ${{ env.working-directory }} + + # Gradle로 빌드 + - name: Build with Gradle + run: ./gradlew build + working-directory: ${{ env.working-directory }} + + # Gradle 캐시 정리 + - name: Cleanup Gradle Cache + if: ${{ always() }} + run: | + rm -f ~/.gradle/caches/modules-2/modules-2.lock + rm -f ~/.gradle/caches/modules-2/gc.properties + + # Docker 이미지 빌드 및 푸시 + - name: Docker build + run: | + docker build --no-cache -f ./.deploy/Dockerfile -t ${{ secrets.DOCKER_USERNAME_DEV }}/moing_dev:green . + docker build --no-cache -f ./.deploy/Dockerfile -t ${{ secrets.DOCKER_USERNAME_DEV }}/moing_dev:blue . + + + - name: Docker Hub Login + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME_DEV }} + password: ${{ secrets.DOCKER_PASSWORD_DEV }} + + - name: Docker push + run: | + docker push ${{ secrets.DOCKER_USERNAME_DEV }}/moing_dev:green + docker push ${{ secrets.DOCKER_USERNAME_DEV }}/moing_dev:blue + + # EC2로 deploy.sh 전송 + - name: Deploy deploy.sh to EC2 + uses: appleboy/scp-action@master + with: + host: ${{ secrets.EC2_SERVER_HOST_DEV }} + username: ec2-user + key: ${{ secrets.PRIVATE_KEY_DEV }} + source: "./.deploy/deploy_dev.sh" + target: "/home/ec2-user/" + + # 배포 스크립트 실행 + - name: Deploy on EC2 + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.EC2_SERVER_HOST_DEV }} + username: ec2-user + key: ${{ secrets.PRIVATE_KEY_DEV }} + envs: GITHUB_SHA + script: | + chmod +x /home/ec2-user/deploy_dev.sh + /home/ec2-user/deploy_dev.sh \ No newline at end of file diff --git a/.github/workflows/CD-prod.yml b/.github/workflows/CD-prod.yml new file mode 100644 index 00000000..2c132f0c --- /dev/null +++ b/.github/workflows/CD-prod.yml @@ -0,0 +1,123 @@ +name: CD-prod + +on: + push: + branches: [ "release" ] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + env: + working-directory: ./ + APPLICATION: ${{ secrets.APPLICATION_PROD }} + GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_PROD }} + APPLE_KEY: ${{ secrets.APPLE_KEY_PROD }} + + steps: + # 소스 코드 체크아웃 + - uses: actions/checkout@v2 + + # JDK 11 설정 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + + # Gradle 패키지 캐시 + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + # 설정 파일 생성 + - run: | + mkdir ./src/main/resources + cd ./src/main/resources + touch ./application.yml + echo "${{env.APPLICATION}}" > ./application.yml + touch ./firebase-key.json + echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json + touch ./apple-key.p8 + echo "${{env.APPLE_KEY}}" > ./apple-key.p8 + + # 설정 파일을 작업공간에 저장 + - uses: actions/upload-artifact@v2 + with: + name: application.yml + path: ./src/main/resources/application.yml + + - uses: actions/upload-artifact@v2 + with: + name: firebase-key.json + path: ./src/main/resources/firebase-key.json + + - uses: actions/upload-artifact@v2 + with: + name: apple-key.p8 + path: ./src/main/resources/apple-key.p8 + + # gradlew 권한 설정 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + working-directory: ${{ env.working-directory }} + + # Gradle로 빌드 + - name: Build with Gradle + run: ./gradlew build + working-directory: ${{ env.working-directory }} + + # Gradle 캐시 정리 + - name: Cleanup Gradle Cache + if: ${{ always() }} + run: | + rm -f ~/.gradle/caches/modules-2/modules-2.lock + rm -f ~/.gradle/caches/modules-2/gc.properties + + # Docker 이미지 빌드 및 푸시 + - name: Docker build + run: | + docker build --no-cache -f ./.deploy/Dockerfile -t ${{ secrets.DOCKER_USERNAME_PROD }}/moing_prod:green . + docker build --no-cache -f ./.deploy/Dockerfile -t ${{ secrets.DOCKER_USERNAME_PROD }}/moing_prod:blue . + + + - name: Docker Hub Login + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME_PROD }} + password: ${{ secrets.DOCKER_PASSWORD_PROD }} + + - name: Docker push + run: | + docker push ${{ secrets.DOCKER_USERNAME_PROD }}/moing_prod:green + docker push ${{ secrets.DOCKER_USERNAME_PROD }}/moing_prod:blue + + # EC2로 deploy.sh 전송 + - name: Deploy deploy.sh to EC2 + uses: appleboy/scp-action@master + with: + host: ${{ secrets.EC2_SERVER_HOST_PROD }} + username: ec2-user + key: ${{ secrets.PRIVATE_KEY_PROD }} + source: "./.deploy/deploy_prod.sh" + target: "/home/ec2-user/" + + # 배포 스크립트 실행 + - name: Deploy on EC2 + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.EC2_SERVER_HOST_PROD }} + username: ec2-user + key: ${{ secrets.PRIVATE_KEY_PROD }} + envs: GITHUB_SHA + script: | + chmod +x /home/ec2-user/deploy_prod.sh + /home/ec2-user/deploy_prod.sh \ No newline at end of file diff --git a/.github/workflows/CI-dev.yml b/.github/workflows/CI-dev.yml new file mode 100644 index 00000000..5970e76f --- /dev/null +++ b/.github/workflows/CI-dev.yml @@ -0,0 +1,57 @@ +name: CI-dev + +on: + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + env: + working-directory: ./ + APPLICATION: ${{ secrets.APPLICATION_DEV }} + GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_DEV }} + APPLE_KEY: ${{ secrets.APPLE_KEY_DEV }} + + steps: + # 소스 코드 체크아웃 + - uses: actions/checkout@v2 + + # JDK 11 설정 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + + # Gradle 패키지 캐시 + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + # gradlew 권한 설정 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + working-directory: ${{ env.working-directory }} + + # Gradle로 빌드 + - name: Build with Gradle + run: ./gradlew build + working-directory: ${{ env.working-directory }} + + # Gradle 캐시 정리 + - name: Cleanup Gradle Cache + if: ${{ always() }} + run: | + rm -f ~/.gradle/caches/modules-2/modules-2.lock + rm -f ~/.gradle/caches/modules-2/gc.properties diff --git a/.github/workflows/CI-prod.yml b/.github/workflows/CI-prod.yml new file mode 100644 index 00000000..8a4b599a --- /dev/null +++ b/.github/workflows/CI-prod.yml @@ -0,0 +1,57 @@ +name: CI-prod + +on: + pull_request: + branches: + - release + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + env: + working-directory: ./ + APPLICATION: ${{ secrets.APPLICATION_PROD }} + GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_PROD }} + APPLE_KEY: ${{ secrets.APPLE_KEY_PROD }} + + steps: + # 소스 코드 체크아웃 + - uses: actions/checkout@v2 + + # JDK 11 설정 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + + # Gradle 패키지 캐시 + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + # gradlew 권한 설정 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + working-directory: ${{ env.working-directory }} + + # Gradle로 빌드 + - name: Build with Gradle + run: ./gradlew build + working-directory: ${{ env.working-directory }} + + # Gradle 캐시 정리 + - name: Cleanup Gradle Cache + if: ${{ always() }} + run: | + rm -f ~/.gradle/caches/modules-2/modules-2.lock + rm -f ~/.gradle/caches/modules-2/gc.properties From 937354033aa75d0875c1d311f9af85b4b5436c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 3 Jan 2024 21:44:28 +0900 Subject: [PATCH 436/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A2=85=EB=A3=8C=20=EB=A1=9C=EC=A7=81=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionState/application/service/MissionStateUseCase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 55c0ddfc..9c9ed7a1 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -42,7 +42,7 @@ public boolean isAbleToEnd(Long missionId) { Long total = totalPeople(mission); Long done = donePeople(mission); - return done.equals(total); + return done >= total; } public boolean isAbleToScoreUp(Long missionId) { @@ -70,7 +70,7 @@ public Long totalPeople(Mission mission) { public void updateMissionState(Member member, Mission mission, MissionArchive missionArchive) { // 마지막 인증 시 - if (isAbleToEnd(mission.getId())) { + if (mission.getType().equals(MissionType.ONCE) && isAbleToEnd(mission.getId())) { mission.updateStatus(MissionStatus.SUCCESS); } missionStateSaveService.saveMissionState(member,mission, missionArchive.getStatus()); From fc8ce7eeb46d06fa720ae0c313679afd0008d26a Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 4 Jan 2024 00:21:42 +0900 Subject: [PATCH 437/619] =?UTF-8?q?fix:=20=EC=86=8C=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EA=B0=80=EC=9E=85=ED=95=A0=20=EB=95=8C=20=EC=86=8C=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=20=EC=82=AD=EC=A0=9C=20=EC=97=AC=EB=B6=80=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-cd.yml | 228 +++++++++--------- src/docs/asciidoc/Overview.adoc | 4 + .../service/SignInTeamUseCase.java | 2 + .../team/exception/DeletedTeamException.java | 11 + .../domain/service/TeamMemberSaveService.java | 8 + .../backend/global/response/ErrorCode.java | 1 + 6 files changed, 140 insertions(+), 114 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/team/exception/DeletedTeamException.java diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 2c3bec49..38c626f3 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -1,114 +1,114 @@ -name: CI/CD - -on: - push: - branches: [ "main" ] - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-latest - env: - working-directory: ./ - APPLICATION: ${{ secrets.APPLICATION }} - GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }} - APPLE_KEY: ${{ secrets.APPLE_KEY }} - - steps: - # 소스 코드 체크아웃 - - uses: actions/checkout@v2 - - # JDK 11 설정 - - name: Set up JDK 11 - uses: actions/setup-java@v2 - with: - java-version: '11' - distribution: 'adopt' - - # Gradle 패키지 캐시 - - name: Cache Gradle packages - uses: actions/cache@v2 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - # 설정 파일 생성 - - run: | - mkdir ./src/main/resources - cd ./src/main/resources - touch ./application.yml - echo "${{env.APPLICATION}}" > ./application.yml - touch ./firebase-key.json - echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json - touch ./apple-key.p8 - echo "${{env.APPLE_KEY}}" > ./apple-key.p8 - - # 설정 파일을 작업공간에 저장 - - uses: actions/upload-artifact@v2 - with: - name: application.yml - path: ./src/main/resources/application.yml - - - uses: actions/upload-artifact@v2 - with: - name: firebase-key.json - path: ./src/main/resources/firebase-key.json - - - uses: actions/upload-artifact@v2 - with: - name: apple-key.p8 - path: ./src/main/resources/apple-key.p8 - - # gradlew 권한 설정 - - name: Grant execute permission for gradlew - run: chmod +x gradlew - working-directory: ${{ env.working-directory }} - - # Gradle로 빌드 - - name: Build with Gradle - run: ./gradlew build - working-directory: ${{ env.working-directory }} - - # Gradle 캐시 정리 - - name: Cleanup Gradle Cache - if: ${{ always() }} - run: | - rm -f ~/.gradle/caches/modules-2/modules-2.lock - rm -f ~/.gradle/caches/modules-2/gc.properties - - # Docker 이미지 빌드 및 푸시 - - name: Docker build - run: | - docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} - docker build --no-cache -t ${{ secrets.DOCKER_USERNAME }}/moing:green . - docker build --no-cache -t ${{ secrets.DOCKER_USERNAME }}/moing:blue . - docker push ${{ secrets.DOCKER_USERNAME }}/moing:green - docker push ${{ secrets.DOCKER_USERNAME }}/moing:blue - - # EC2로 deploy.sh 전송 - - name: Deploy deploy.sh to EC2 - uses: appleboy/scp-action@master - with: - host: ${{ secrets.EC2_SERVER_HOST }} - username: ec2-user - key: ${{ secrets.PRIVATE_KEY }} - source: "./deploy.sh" - target: "/home/ec2-user/" - - # 배포 스크립트 실행 - - name: Deploy on EC2 - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.EC2_SERVER_HOST }} - username: ec2-user - key: ${{ secrets.PRIVATE_KEY }} - envs: GITHUB_SHA - script: | - chmod +x /home/ec2-user/deploy.sh - /home/ec2-user/deploy.sh +#name: CI/CD +# +#on: +# push: +# branches: [ "main" ] +# +#permissions: +# contents: read +# +#jobs: +# build: +# runs-on: ubuntu-latest +# env: +# working-directory: ./ +# APPLICATION: ${{ secrets.APPLICATION }} +# GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }} +# APPLE_KEY: ${{ secrets.APPLE_KEY }} +# +# steps: +# # 소스 코드 체크아웃 +# - uses: actions/checkout@v2 +# +# # JDK 11 설정 +# - name: Set up JDK 11 +# uses: actions/setup-java@v2 +# with: +# java-version: '11' +# distribution: 'adopt' +# +# # Gradle 패키지 캐시 +# - name: Cache Gradle packages +# uses: actions/cache@v2 +# with: +# path: | +# ~/.gradle/caches +# ~/.gradle/wrapper +# key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} +# restore-keys: | +# ${{ runner.os }}-gradle- +# +# # 설정 파일 생성 +# - run: | +# mkdir ./src/main/resources +# cd ./src/main/resources +# touch ./application.yml +# echo "${{env.APPLICATION}}" > ./application.yml +# touch ./firebase-key.json +# echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json +# touch ./apple-key.p8 +# echo "${{env.APPLE_KEY}}" > ./apple-key.p8 +# +# # 설정 파일을 작업공간에 저장 +# - uses: actions/upload-artifact@v2 +# with: +# name: application.yml +# path: ./src/main/resources/application.yml +# +# - uses: actions/upload-artifact@v2 +# with: +# name: firebase-key.json +# path: ./src/main/resources/firebase-key.json +# +# - uses: actions/upload-artifact@v2 +# with: +# name: apple-key.p8 +# path: ./src/main/resources/apple-key.p8 +# +# # gradlew 권한 설정 +# - name: Grant execute permission for gradlew +# run: chmod +x gradlew +# working-directory: ${{ env.working-directory }} +# +# # Gradle로 빌드 +# - name: Build with Gradle +# run: ./gradlew build +# working-directory: ${{ env.working-directory }} +# +# # Gradle 캐시 정리 +# - name: Cleanup Gradle Cache +# if: ${{ always() }} +# run: | +# rm -f ~/.gradle/caches/modules-2/modules-2.lock +# rm -f ~/.gradle/caches/modules-2/gc.properties +# +# # Docker 이미지 빌드 및 푸시 +# - name: Docker build +# run: | +# docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} +# docker build --no-cache -t ${{ secrets.DOCKER_USERNAME }}/moing:green . +# docker build --no-cache -t ${{ secrets.DOCKER_USERNAME }}/moing:blue . +# docker push ${{ secrets.DOCKER_USERNAME }}/moing:green +# docker push ${{ secrets.DOCKER_USERNAME }}/moing:blue +# +# # EC2로 deploy.sh 전송 +# - name: Deploy deploy.sh to EC2 +# uses: appleboy/scp-action@master +# with: +# host: ${{ secrets.EC2_SERVER_HOST }} +# username: ec2-user +# key: ${{ secrets.PRIVATE_KEY }} +# source: "./deploy.sh" +# target: "/home/ec2-user/" +# +# # 배포 스크립트 실행 +# - name: Deploy on EC2 +# uses: appleboy/ssh-action@master +# with: +# host: ${{ secrets.EC2_SERVER_HOST }} +# username: ec2-user +# key: ${{ secrets.PRIVATE_KEY }} +# envs: GITHUB_SHA +# script: | +# chmod +x /home/ec2-user/deploy.sh +# /home/ec2-user/deploy.sh diff --git a/src/docs/asciidoc/Overview.adoc b/src/docs/asciidoc/Overview.adoc index fc4553d3..f9d7db68 100644 --- a/src/docs/asciidoc/Overview.adoc +++ b/src/docs/asciidoc/Overview.adoc @@ -103,6 +103,10 @@ | 소모임을 가입할 때 | 소모임을 이미 가입함 +| `T0005` +| 소모임을 가입할 때 +| 소모임이 삭제됨 + |=== === MyPage ErrorCode diff --git a/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java index 093a098a..0603d156 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.team.application.dto.response.CreateTeamResponse; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.team.exception.DeletedTeamException; import com.moing.backend.domain.teamMember.domain.service.TeamMemberSaveService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -25,4 +26,5 @@ public CreateTeamResponse signInTeam(String socialId, Long teamId){ teamMemberSaveService.addTeamMember(team, member); return new CreateTeamResponse(team.getTeamId()); } + } diff --git a/src/main/java/com/moing/backend/domain/team/exception/DeletedTeamException.java b/src/main/java/com/moing/backend/domain/team/exception/DeletedTeamException.java new file mode 100644 index 00000000..53bfdd47 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/team/exception/DeletedTeamException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.team.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class DeletedTeamException extends TeamException{ + public DeletedTeamException(){ + super(ErrorCode.DELETED_TEAM_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java index d60d33a2..94830dd3 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java @@ -4,6 +4,7 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.exception.AlreadyJoinTeamException; import com.moing.backend.domain.team.exception.AlreadyWithdrawTeamException; +import com.moing.backend.domain.team.exception.DeletedTeamException; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; import com.moing.backend.global.annotation.DomainService; @@ -20,6 +21,8 @@ public class TeamMemberSaveService { public void addTeamMember(Team team, Member member) { Optional teamMember = teamMemberRepository.findTeamMemberByTeamAndMember(team, member); + checkDeletion(team); + if (teamMember.isPresent()) { handleExistingMember(teamMember.get()); } else { @@ -43,4 +46,9 @@ private void addNewTeamMember(Team team, Member member) { this.teamMemberRepository.save(newMember); } + private void checkDeletion(Team team){ + if(team.isDeleted()) + throw new DeletedTeamException(); + } + } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 9a82564b..d5aa9c43 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -46,6 +46,7 @@ public enum ErrorCode { NOT_AUTH_BY_TEAM_ERROR("T0002","권한이 없습니다."), ALREADY_WITHDRAW_ERROR("T0003","이미 탈퇴한 회원입니다."), ALREADY_JOIN_ERROR("T0004","이미 가입한 회원입니다."), + DELETED_TEAM_ERROR("T0005", "삭제된 소모임입니다."), //마이페이지 관련 에러 코드 INVALID_ALARM_ERROR("MP0001","유효하지 않는 알람 입력값입니다"), From 119bc5fc2c056de82046586f013b91eaca09c26e Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 4 Jan 2024 00:26:48 +0900 Subject: [PATCH 438/619] =?UTF-8?q?fix:=20build=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/CI-dev.yml | 28 ++++++++++++++++++++++++++++ .github/workflows/CI-prod.yml | 27 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/.github/workflows/CI-dev.yml b/.github/workflows/CI-dev.yml index 5970e76f..1ef81d51 100644 --- a/.github/workflows/CI-dev.yml +++ b/.github/workflows/CI-dev.yml @@ -39,6 +39,33 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- + # 설정 파일 생성 + - run: | + mkdir ./src/main/resources + cd ./src/main/resources + touch ./application.yml + echo "${{env.APPLICATION}}" > ./application.yml + touch ./firebase-key.json + echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json + touch ./apple-key.p8 + echo "${{env.APPLE_KEY}}" > ./apple-key.p8 + + # 설정 파일을 작업공간에 저장 + - uses: actions/upload-artifact@v2 + with: + name: application.yml + path: ./src/main/resources/application.yml + + - uses: actions/upload-artifact@v2 + with: + name: firebase-key.json + path: ./src/main/resources/firebase-key.json + + - uses: actions/upload-artifact@v2 + with: + name: apple-key.p8 + path: ./src/main/resources/apple-key.p8 + # gradlew 권한 설정 - name: Grant execute permission for gradlew run: chmod +x gradlew @@ -55,3 +82,4 @@ jobs: run: | rm -f ~/.gradle/caches/modules-2/modules-2.lock rm -f ~/.gradle/caches/modules-2/gc.properties + diff --git a/.github/workflows/CI-prod.yml b/.github/workflows/CI-prod.yml index 8a4b599a..f7ed564f 100644 --- a/.github/workflows/CI-prod.yml +++ b/.github/workflows/CI-prod.yml @@ -39,6 +39,33 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- + # 설정 파일 생성 + - run: | + mkdir ./src/main/resources + cd ./src/main/resources + touch ./application.yml + echo "${{env.APPLICATION}}" > ./application.yml + touch ./firebase-key.json + echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json + touch ./apple-key.p8 + echo "${{env.APPLE_KEY}}" > ./apple-key.p8 + + # 설정 파일을 작업공간에 저장 + - uses: actions/upload-artifact@v2 + with: + name: application.yml + path: ./src/main/resources/application.yml + + - uses: actions/upload-artifact@v2 + with: + name: firebase-key.json + path: ./src/main/resources/firebase-key.json + + - uses: actions/upload-artifact@v2 + with: + name: apple-key.p8 + path: ./src/main/resources/apple-key.p8 + # gradlew 권한 설정 - name: Grant execute permission for gradlew run: chmod +x gradlew From 4aab651d357960f5e043b15db8a8c4bd7881a8d7 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 4 Jan 2024 00:42:39 +0900 Subject: [PATCH 439/619] =?UTF-8?q?refactor:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .deploy/deploy_prod.sh | 2 +- .github/workflows/ci-cd.yml | 114 ------------------------------------ Dockerfile | 16 ----- deploy.sh | 67 --------------------- 4 files changed, 1 insertion(+), 198 deletions(-) delete mode 100644 .github/workflows/ci-cd.yml delete mode 100644 Dockerfile delete mode 100644 deploy.sh diff --git a/.deploy/deploy_prod.sh b/.deploy/deploy_prod.sh index 91c86b59..cee38ea1 100644 --- a/.deploy/deploy_prod.sh +++ b/.deploy/deploy_prod.sh @@ -52,7 +52,7 @@ sleep 40 EXIST_AFTER=$(docker ps --filter name=${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} --filter status=running -q) if [ -n "$EXIST_AFTER" ]; then # nginx.config를 컨테이너에 맞게 변경해주고 reload 한다 - cp ./nginx.${AFTER_COMPOSE_COLOR}.conf /etc/nginx/nginx.conf + sudo cp ./nginx.${AFTER_COMPOSE_COLOR}.conf /etc/nginx/nginx.conf sudo nginx -s reload # 이전 컨테이너 종료 diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml deleted file mode 100644 index 38c626f3..00000000 --- a/.github/workflows/ci-cd.yml +++ /dev/null @@ -1,114 +0,0 @@ -#name: CI/CD -# -#on: -# push: -# branches: [ "main" ] -# -#permissions: -# contents: read -# -#jobs: -# build: -# runs-on: ubuntu-latest -# env: -# working-directory: ./ -# APPLICATION: ${{ secrets.APPLICATION }} -# GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }} -# APPLE_KEY: ${{ secrets.APPLE_KEY }} -# -# steps: -# # 소스 코드 체크아웃 -# - uses: actions/checkout@v2 -# -# # JDK 11 설정 -# - name: Set up JDK 11 -# uses: actions/setup-java@v2 -# with: -# java-version: '11' -# distribution: 'adopt' -# -# # Gradle 패키지 캐시 -# - name: Cache Gradle packages -# uses: actions/cache@v2 -# with: -# path: | -# ~/.gradle/caches -# ~/.gradle/wrapper -# key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} -# restore-keys: | -# ${{ runner.os }}-gradle- -# -# # 설정 파일 생성 -# - run: | -# mkdir ./src/main/resources -# cd ./src/main/resources -# touch ./application.yml -# echo "${{env.APPLICATION}}" > ./application.yml -# touch ./firebase-key.json -# echo "${{env.GOOGLE_APPLICATION_CREDENTIALS}}" | base64 --decode > ./firebase-key.json -# touch ./apple-key.p8 -# echo "${{env.APPLE_KEY}}" > ./apple-key.p8 -# -# # 설정 파일을 작업공간에 저장 -# - uses: actions/upload-artifact@v2 -# with: -# name: application.yml -# path: ./src/main/resources/application.yml -# -# - uses: actions/upload-artifact@v2 -# with: -# name: firebase-key.json -# path: ./src/main/resources/firebase-key.json -# -# - uses: actions/upload-artifact@v2 -# with: -# name: apple-key.p8 -# path: ./src/main/resources/apple-key.p8 -# -# # gradlew 권한 설정 -# - name: Grant execute permission for gradlew -# run: chmod +x gradlew -# working-directory: ${{ env.working-directory }} -# -# # Gradle로 빌드 -# - name: Build with Gradle -# run: ./gradlew build -# working-directory: ${{ env.working-directory }} -# -# # Gradle 캐시 정리 -# - name: Cleanup Gradle Cache -# if: ${{ always() }} -# run: | -# rm -f ~/.gradle/caches/modules-2/modules-2.lock -# rm -f ~/.gradle/caches/modules-2/gc.properties -# -# # Docker 이미지 빌드 및 푸시 -# - name: Docker build -# run: | -# docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} -# docker build --no-cache -t ${{ secrets.DOCKER_USERNAME }}/moing:green . -# docker build --no-cache -t ${{ secrets.DOCKER_USERNAME }}/moing:blue . -# docker push ${{ secrets.DOCKER_USERNAME }}/moing:green -# docker push ${{ secrets.DOCKER_USERNAME }}/moing:blue -# -# # EC2로 deploy.sh 전송 -# - name: Deploy deploy.sh to EC2 -# uses: appleboy/scp-action@master -# with: -# host: ${{ secrets.EC2_SERVER_HOST }} -# username: ec2-user -# key: ${{ secrets.PRIVATE_KEY }} -# source: "./deploy.sh" -# target: "/home/ec2-user/" -# -# # 배포 스크립트 실행 -# - name: Deploy on EC2 -# uses: appleboy/ssh-action@master -# with: -# host: ${{ secrets.EC2_SERVER_HOST }} -# username: ec2-user -# key: ${{ secrets.PRIVATE_KEY }} -# envs: GITHUB_SHA -# script: | -# chmod +x /home/ec2-user/deploy.sh -# /home/ec2-user/deploy.sh diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 25848cbe..00000000 --- a/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM openjdk:11-jdk - -# 타임존 설정 -ENV TZ=Asia/Seoul -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - -ARG CACHEBREAKER=1 -ARG JAR_FILE=./build/libs/backend-0.0.1-SNAPSHOT.jar -COPY ${JAR_FILE} app.jar - -# 문서를 이미지의 /static/docs 디렉토리에 복사 -COPY ./build/docs/asciidoc/*.html /static/docs/ - -# 애플리케이션 실행 시 -cp 옵션을 사용하여 /static/docs 디렉토리를 클래스패스에 추가 -ENTRYPOINT ["java","-cp",".:/static/docs","-jar","/app.jar"] - diff --git a/deploy.sh b/deploy.sh deleted file mode 100644 index 39ee49ca..00000000 --- a/deploy.sh +++ /dev/null @@ -1,67 +0,0 @@ -DOCKER_APP_NAME=meetup -DOCKER_USERNAME=modagbul - -# 최신 이미지 가져오기 -docker pull ${DOCKER_USERNAME}/moing:blue -docker pull ${DOCKER_USERNAME}/moing:green - -# 현재 실행 중인 컨테이너를 확인 (blue 또는 green) -EXIST_BLUE=$(docker ps --filter name=${DOCKER_APP_NAME}-blue --filter status=running -q) -EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --filter status=running -q) - -# 둘 다 실행 중이지 않을 경우 blue 실행 -if [ -z "$EXIST_BLUE" ] && [ -z "$EXIST_GREEN" ]; then - echo "No containers running. Starting blue up" - - # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. - if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-blue -q)" ]; then - docker rm ${DOCKER_APP_NAME}-blue - fi - - docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing:blue - BEFORE_COMPOSE_COLOR="green" - AFTER_COMPOSE_COLOR="blue" -elif [ -z "$EXIST_BLUE" ]; then - echo "blue up" - - # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. - if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-blue -q)" ]; then - docker rm ${DOCKER_APP_NAME}-blue - fi - - docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing:blue - BEFORE_COMPOSE_COLOR="green" - AFTER_COMPOSE_COLOR="blue" -else - echo "green up" - - # 만약 컨테이너가 중지된 상태로 존재하면 삭제한다. - if [ "$(docker ps -a --filter name=${DOCKER_APP_NAME}-green -q)" ]; then - docker rm ${DOCKER_APP_NAME}-green - fi - - docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing:green - BEFORE_COMPOSE_COLOR="blue" - AFTER_COMPOSE_COLOR="green" -fi - - -sleep 40 - -# 새로운 컨테이너가 제대로 실행되었는지 확인 -EXIST_AFTER=$(docker ps --filter name=${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} --filter status=running -q) -if [ -n "$EXIST_AFTER" ]; then - # nginx.config를 컨테이너에 맞게 변경해주고 reload 한다 - cp ./nginx.${AFTER_COMPOSE_COLOR}.conf /etc/nginx/nginx.conf - sudo nginx -s reload - - # 이전 컨테이너 종료 - docker stop ${DOCKER_APP_NAME}-${BEFORE_COMPOSE_COLOR} - docker rm ${DOCKER_APP_NAME}-${BEFORE_COMPOSE_COLOR} - echo "$BEFORE_COMPOSE_COLOR down" -else - # Docker logs - LOGS=$(docker logs ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} 2>&1) - echo "Error: ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} failed to start." - echo "$LOGS" -fi From 38c736dc03454f963feb3da3cfb8eecb0a048b95 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 4 Jan 2024 02:20:19 +0900 Subject: [PATCH 440/619] =?UTF-8?q?fix:=20=EC=A1=B4=EC=9E=AC=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9D=80=20=ED=8C=80=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SignInTeamUseCase.java | 2 +- .../repository/TeamCustomRepository.java | 1 + .../repository/TeamCustomRepositoryImpl.java | 21 +++++++++++++++++-- .../team/domain/service/TeamGetService.java | 4 ++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java index 0603d156..f40495f3 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/SignInTeamUseCase.java @@ -22,7 +22,7 @@ public class SignInTeamUseCase { private final TeamMemberSaveService teamMemberSaveService; public CreateTeamResponse signInTeam(String socialId, Long teamId){ Member member=memberGetService.getMemberBySocialId(socialId); - Team team=teamGetService.getTeamByTeamId(teamId); + Team team=teamGetService.getTeamIncludeDeletedByTeamId(teamId); teamMemberSaveService.addTeamMember(team, member); return new CreateTeamResponse(team.getTeamId()); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index a65e5c0a..d3f34c63 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -16,6 +16,7 @@ public interface TeamCustomRepository { GetTeamResponse findTeamByMemberId(Long memberId); Optional findTeamByTeamId(Long TeamId); + Optional findTeamIncludeDeletedByTeamId(Long teamId); List findTeamIdByMemberId(Long memberId); List findMyPageTeamByMemberId(Long memberId); List findTeamNameByTeamId(List teamId); diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index 41a03a07..5a779a5c 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -49,6 +49,13 @@ public Optional findTeamByTeamId(Long teamId) { .fetchOne()); } + @Override + public Optional findTeamIncludeDeletedByTeamId(Long teamId){ + return Optional.ofNullable(queryFactory.selectFrom(team) + .where(team.teamId.eq(teamId)) + .fetchOne()); + } + @Override public List findTeamIdByMemberId(Long memberId){ LocalDateTime threeDaysAgo = LocalDateTime.now().minusDays(3); @@ -181,7 +188,7 @@ public Page findNewTeam(String dateSort, Pageable pageable) @Override public GetTeamCountResponse findTeamCount(Long memberId, Long teamId) { LocalDateTime threeDaysAgo = LocalDateTime.now().minusDays(3); - long count=queryFactory + Long count=queryFactory .select(team.count()) // 팀의 개수를 세기 위해 수정 .from(teamMember) .innerJoin(teamMember.team, team) @@ -192,6 +199,10 @@ public GetTeamCountResponse findTeamCount(Long memberId, Long teamId) { .or(team.deletionTime.after(threeDaysAgo)))) // 강제종료된 경우 3일이 지나지 않았다면 .fetchOne(); // 단일 결과 (개수) 반환 + if (count == null) { + count = 0L; // null인 경우 0으로 처리 + } + GetTeamCountResponse response=queryFactory .select(new QGetTeamCountResponse(team.name, member.nickName)) .from(team) @@ -199,7 +210,13 @@ public GetTeamCountResponse findTeamCount(Long memberId, Long teamId) { .where(team.teamId.eq(teamId)) .fetchOne(); - response.updateCount(count); + if (response == null) { + // response가 null인 경우, 적절한 기본값 설정 또는 예외 처리 + response = new GetTeamCountResponse("기본 팀 이름", "기본 멤버 닉네임"); + response.updateCount(0L); + } else { + response.updateCount(count); + } return response; } diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index 9498ce8d..0f764ad0 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -34,6 +34,10 @@ public List getTeamIdByMemberId(Long memberId) { return teamRepository.findTeamIdByMemberId(memberId); } + public Team getTeamIncludeDeletedByTeamId(Long teamId){ + return teamRepository.findTeamIncludeDeletedByTeamId(teamId).orElseThrow(NotFoundByTeamIdException::new); + } + public Team getTeamByTeamId(Long teamId){ return teamRepository.findTeamByTeamId(teamId).orElseThrow(NotFoundByTeamIdException::new); } From 376e2bc2c4958006f915dc285a0d7032a0f8635d Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 4 Jan 2024 07:27:19 +0900 Subject: [PATCH 441/619] =?UTF-8?q?feat:=20DAU=20=EC=8A=AC=EB=9E=99=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EB=B3=B4=EB=82=B4=EA=B8=B0=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MemberCustomRepository.java | 5 +- .../MemberCustomRepositoryImpl.java | 73 +++++++++++++++++++ .../domain/repository/MemberRepository.java | 3 - .../domain/service/MemberGetService.java | 6 ++ .../application/dto/DailyStats.java | 24 ++++++ .../service/DAUScheduleUseCase.java | 56 ++++++++++++++ .../exception/ExceptionEventHandler.java | 2 +- .../config/slack/team/TeamCreateHandler.java | 7 +- .../config/slack/util/SlackAdapter.java | 27 ++++++- .../global/config/slack/util/WebhookUtil.java | 3 + 10 files changed, 194 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/statistics/application/dto/DailyStats.java create mode 100644 src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java index 3f8ab192..20217552 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java @@ -1,14 +1,15 @@ package com.moing.backend.domain.member.domain.repository; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.statistics.application.dto.DailyStats; import java.util.Optional; public interface MemberCustomRepository { - boolean checkNickname(String nickname); + boolean checkNickname(String nickname); Optional findNotDeletedBySocialId(String socialId); - Optional findNotDeletedByEmail(String email); Optional findNotDeletedByMemberId(Long id); + DailyStats getDailyStats(); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java index 9c841321..e0d45867 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java @@ -1,12 +1,18 @@ package com.moing.backend.domain.member.domain.repository; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.statistics.application.dto.DailyStats; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.Optional; import static com.moing.backend.domain.member.domain.entity.QMember.member; +import static com.moing.backend.domain.mission.domain.entity.QMission.mission; +import static com.moing.backend.domain.team.domain.entity.QTeam.team; public class MemberCustomRepositoryImpl implements MemberCustomRepository { @@ -52,4 +58,71 @@ public Optional findNotDeletedByMemberId(Long id) { .where(member.isDeleted.eq(false)) .fetchOne()); } + + @Override + public DailyStats getDailyStats() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + long todayNewMembers = queryFactory + .selectFrom(member) + .where(member.createdDate.between(startOfToday, endOfToday)) + .fetchCount(); + + long yesterdayNewMembers = queryFactory + .selectFrom(member) + .where(member.createdDate.between(startOfYesterday, startOfToday)) + .fetchCount(); + + long todayNewTeams = queryFactory + .selectFrom(team) + .where(team.createdDate.between(startOfToday, endOfToday)) + .fetchCount(); + + long yesterdayNewTeams = queryFactory + .selectFrom(team) + .where(team.createdDate.between(startOfYesterday, startOfToday)) + .fetchCount(); + + long todayRepeatMissions = queryFactory + .select(mission) + .from(mission) + .where(mission.createdDate.between(startOfToday, endOfToday) + .and(mission.type.eq(MissionType.REPEAT))) + .fetchCount(); + + long yesterdayRepeatMissions = queryFactory + .select(mission) + .from(mission) + .where(mission.createdDate.between(startOfYesterday, startOfToday) + .and(mission.type.eq(MissionType.REPEAT))) + .fetchCount(); + + long todayOnceMissions = queryFactory + .select(mission) + .from(mission) + .where(mission.createdDate.between(startOfToday, endOfToday) + .and(mission.type.eq(MissionType.ONCE))) + .fetchCount(); + + long yesterdayOnceMissions = queryFactory + .select(mission) + .from(mission) + .where(mission.createdDate.between(startOfYesterday, startOfToday) + .and(mission.type.eq(MissionType.ONCE))) + .fetchCount(); + + return new DailyStats( + todayNewMembers, + yesterdayNewMembers, + todayNewTeams, + yesterdayNewTeams, + todayRepeatMissions, + yesterdayRepeatMissions, + todayOnceMissions, + yesterdayOnceMissions); + } + } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java index 4a236a75..8bc9886c 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java @@ -2,8 +2,5 @@ import com.moing.backend.domain.member.domain.entity.Member; import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - public interface MemberRepository extends JpaRepository, MemberCustomRepository { } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java index 8c78c8b8..027eb5b4 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java @@ -3,10 +3,12 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.repository.MemberRepository; import com.moing.backend.domain.member.exception.NotFoundBySocialIdException; +import com.moing.backend.domain.statistics.application.dto.DailyStats; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import javax.transaction.Transactional; +import java.math.BigInteger; @DomainService @Transactional @@ -21,4 +23,8 @@ public Member getMemberBySocialId(String socialId){ public Member getMemberByMemberId(Long memberId) { return memberRepository.findNotDeletedByMemberId(memberId).orElseThrow(()->new NotFoundBySocialIdException()); } + + public DailyStats getDailyStats(){ + return memberRepository.getDailyStats(); + } } diff --git a/src/main/java/com/moing/backend/domain/statistics/application/dto/DailyStats.java b/src/main/java/com/moing/backend/domain/statistics/application/dto/DailyStats.java new file mode 100644 index 00000000..8c434da9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/application/dto/DailyStats.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.statistics.application.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.SqlResultSetMapping; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class DailyStats { + + private long todayNewMembers; + private long yesterdayNewMembers; + private long todayNewTeams; + private long yesterdayNewTeams; + private long todayRepeatMission; + private long yesterdayRepeatMission; + private long todayOnceMission; + private long yesterdayOnceMission; + +} + diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java new file mode 100644 index 00000000..e4189fce --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java @@ -0,0 +1,56 @@ +package com.moing.backend.domain.statistics.application.service; + +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.statistics.application.dto.DailyStats; +import com.moing.backend.global.config.slack.util.WebhookUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.LinkedHashMap; +import java.util.Map; + +@Slf4j +@Service +@Transactional +@EnableAsync +@EnableScheduling +@RequiredArgsConstructor +public class DAUScheduleUseCase { + + private final WebhookUtil webhookUtil; + private final MemberGetService memberGetService; + + public static final String DAILY_TEAM_CREATION_COUNT = "[DAU] 일일 모임 생성 수"; + public static final String DAILY_NEW_MEMBER_COUNT = "[DAU] 일일 신규 가입자 수"; + public static final String DAILY_REPEAT_MISSION_COUNT = "[DAU] 일일 반복 미션 생성 개수"; + public static final String DAILY_ONCE_MISSION_COUNT = "[DAU] 일일 한번 미션 생성 개수"; + + /* + DAU 정보 : 일일 모임 생성 수, 일일 신규 가입자 수, 일일 반복 미션 생성 수, 일일 한번 미션 생성 수 + */ + @Scheduled(cron = "0 59 23 * * *") + public void DailyTeamCreationInfoAlarm() { + Map todayStats = new LinkedHashMap<>(); + Map yesterdayStats = new LinkedHashMap<>(); + + DailyStats dailyStats = memberGetService.getDailyStats(); + todayStats.put(DAILY_TEAM_CREATION_COUNT, dailyStats.getTodayNewTeams()); + yesterdayStats.put(DAILY_TEAM_CREATION_COUNT, dailyStats.getYesterdayNewTeams()); + + todayStats.put(DAILY_NEW_MEMBER_COUNT, dailyStats.getTodayNewMembers()); + yesterdayStats.put(DAILY_NEW_MEMBER_COUNT, dailyStats.getYesterdayNewMembers()); + + todayStats.put(DAILY_REPEAT_MISSION_COUNT, dailyStats.getTodayRepeatMission()); + yesterdayStats.put(DAILY_REPEAT_MISSION_COUNT, dailyStats.getYesterdayRepeatMission()); + + todayStats.put(DAILY_ONCE_MISSION_COUNT, dailyStats.getTodayOnceMission()); + yesterdayStats.put(DAILY_ONCE_MISSION_COUNT, dailyStats.getYesterdayRepeatMission()); + webhookUtil.sendDailyStatsMessage(todayStats, yesterdayStats); + } + +} diff --git a/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java b/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java index 7466ba76..877decdc 100644 --- a/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java +++ b/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java @@ -13,7 +13,7 @@ public class ExceptionEventHandler { private final WebhookUtil webhookUtil; - @Async("asyncTaskExecutor") + @Async @EventListener public void onExceptionEvent(ExceptionEvent event) { webhookUtil.sendSlackAlertErrorLog(event.getRequest(), event.getException()); diff --git a/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java b/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java index 0985a3bc..34bcad01 100644 --- a/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java +++ b/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java @@ -3,10 +3,9 @@ import com.moing.backend.global.config.slack.team.dto.TeamCreateEvent; import com.moing.backend.global.config.slack.util.WebhookUtil; import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import org.springframework.transaction.event.TransactionPhase; -import org.springframework.transaction.event.TransactionalEventListener; @RequiredArgsConstructor @Component @@ -14,8 +13,8 @@ public class TeamCreateHandler { private final WebhookUtil webhookUtil; - @Async("asyncTaskExecutor") - @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + @Async + @EventListener public void onTeamCreateEvent(TeamCreateEvent event) { webhookUtil.sendSlackTeamCreatedMessage(event.getTeamName(), event.getLeaderId()); } diff --git a/src/main/java/com/moing/backend/global/config/slack/util/SlackAdapter.java b/src/main/java/com/moing/backend/global/config/slack/util/SlackAdapter.java index 2ce8f901..6272aeea 100644 --- a/src/main/java/com/moing/backend/global/config/slack/util/SlackAdapter.java +++ b/src/main/java/com/moing/backend/global/config/slack/util/SlackAdapter.java @@ -13,6 +13,8 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import static com.slack.api.webhook.WebhookPayloads.payload; @@ -25,7 +27,7 @@ public class SlackAdapter implements WebhookUtil { private String errorWebhookUrl; @Value("${webhook.slack.team_alarm_url}") - private String teamAlarmWebhookUrl; + private String infoWebhookUrl; private final Slack slackClient = Slack.getInstance(); @@ -51,7 +53,7 @@ public void sendSlackAlertErrorLog(HttpServletRequest request, Exception e) { public void sendSlackTeamCreatedMessage(String teamName, Long leaderId) { String message = String.format("[새로운 소모임 '%s'이(가) 생성되었습니다.]", teamName); List attachments = List.of(generateSlackTeamAttachment(teamName, leaderId)); - sendSlackMessage(teamAlarmWebhookUrl, message, attachments); + sendSlackMessage(infoWebhookUrl, message, attachments); } private Attachment generateSlackTeamAttachment(String teamName, Long leaderId) { @@ -65,6 +67,27 @@ private Attachment generateSlackTeamAttachment(String teamName, Long leaderId) { .build(); } + @Override + public void sendDailyStatsMessage(Map todayStats, Map yesterdayStats) { + String message = "[일일 통계 알림]"; + List attachments = todayStats.keySet().stream() + .map(key -> generateDailyStatsAttachment(key, todayStats.get(key), yesterdayStats.getOrDefault(key, 0L))) + .collect(Collectors.toList()); + + sendSlackMessage(infoWebhookUrl, message, attachments); + } + + private Attachment generateDailyStatsAttachment(String title, long todayCount, long yesterdayCount) { + return Attachment.builder() + .color("1A66CC") // 색상 설정 + .title(title) + .fields(List.of( + generateSlackField("Today", String.valueOf(todayCount) + " 개"), + generateSlackField("Yesterday", String.valueOf(yesterdayCount) + " 개") + )) + .build(); + } + // attachment 생성 메서드 private Attachment generateSlackErrorAttachment(Exception e, HttpServletRequest request) { String requestTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").format(LocalDateTime.now()); diff --git a/src/main/java/com/moing/backend/global/config/slack/util/WebhookUtil.java b/src/main/java/com/moing/backend/global/config/slack/util/WebhookUtil.java index 7c613543..4f010e76 100644 --- a/src/main/java/com/moing/backend/global/config/slack/util/WebhookUtil.java +++ b/src/main/java/com/moing/backend/global/config/slack/util/WebhookUtil.java @@ -1,10 +1,13 @@ package com.moing.backend.global.config.slack.util; import javax.servlet.http.HttpServletRequest; +import java.util.Map; public interface WebhookUtil { void sendSlackAlertErrorLog(HttpServletRequest request, Exception e); void sendSlackTeamCreatedMessage(String teamName, Long leaderId); + + void sendDailyStatsMessage(Map todayStats, Map yesterdayStats); } From d3e33fc4903682f52b7c6eadac1805c1fe927d59 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 4 Jan 2024 07:45:56 +0900 Subject: [PATCH 442/619] =?UTF-8?q?refactor:=20=EC=8A=A4=EC=BC=80=EC=A4=84?= =?UTF-8?q?=EB=9F=AC=20=EC=9A=B4=EC=98=81=EC=84=9C=EB=B2=84=EC=97=90?= =?UTF-8?q?=EB=A7=8C=20=EC=A0=81=EC=9A=A9=EB=90=98=EA=B2=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/history/application/service/CleanupUseCase.java | 2 ++ .../application/service/MissionStateScheduleUseCase.java | 2 ++ .../statistics/application/service/DAUScheduleUseCase.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/history/application/service/CleanupUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/CleanupUseCase.java index ed6d156c..5692f1c4 100644 --- a/src/main/java/com/moing/backend/domain/history/application/service/CleanupUseCase.java +++ b/src/main/java/com/moing/backend/domain/history/application/service/CleanupUseCase.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.history.domain.service.AlarmHistoryDeleteService; import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Profile; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -11,6 +12,7 @@ @Service @RequiredArgsConstructor +@Profile("prod") public class CleanupUseCase { private final AlarmHistoryDeleteService alarmHistoryDeleteService; diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index a094b41f..f0d3bfd3 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -11,6 +11,7 @@ import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; @@ -26,6 +27,7 @@ @EnableAsync @EnableScheduling // 스케줄링 활성화 @RequiredArgsConstructor +@Profile("prod") public class MissionStateScheduleUseCase { private final MissionStateUseCase missionStateUseCase; diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java index e4189fce..c002f123 100644 --- a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java @@ -5,6 +5,7 @@ import com.moing.backend.global.config.slack.util.WebhookUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; @@ -20,6 +21,7 @@ @EnableAsync @EnableScheduling @RequiredArgsConstructor +@Profile("prod") public class DAUScheduleUseCase { private final WebhookUtil webhookUtil; From 4a43c54905875b5b4ae4de5eb941abb728379131 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 5 Jan 2024 23:23:11 +0900 Subject: [PATCH 443/619] =?UTF-8?q?fix:=20teamMember=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B3=BC=EC=A0=95=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=8F=99=EC=8B=9C=EC=84=B1=20=EC=A0=9C=EC=96=B4=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/TeamMemberRepository.java | 5 ++++- .../domain/service/TeamMemberSaveService.java | 16 ++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java index 42d665b9..503cd5bb 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java @@ -4,13 +4,16 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Lock; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; +import javax.persistence.LockModeType; import javax.swing.text.html.Option; import java.util.Optional; public interface TeamMemberRepository extends JpaRepository, TeamMemberCustomRepository{ - Optional findTeamMemberByTeamAndMember(Team team, Member member); + @Lock(LockModeType.PESSIMISTIC_WRITE) + Optional findTeamMemberByTeamAndMember(Team team, Member member); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java index 94830dd3..a1a7090b 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java @@ -19,14 +19,14 @@ public class TeamMemberSaveService { private final TeamMemberRepository teamMemberRepository; public void addTeamMember(Team team, Member member) { - Optional teamMember = teamMemberRepository.findTeamMemberByTeamAndMember(team, member); - - checkDeletion(team); - - if (teamMember.isPresent()) { - handleExistingMember(teamMember.get()); - } else { - addNewTeamMember(team, member); + synchronized (this) { + Optional teamMember = teamMemberRepository.findTeamMemberByTeamAndMember(team, member); + checkDeletion(team); + if (teamMember.isPresent()) { + handleExistingMember(teamMember.get()); + } else { + addNewTeamMember(team, member); + } } } From 776d39954dd025da932f328a5cd169f454429f98 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 5 Jan 2024 23:23:21 +0900 Subject: [PATCH 444/619] =?UTF-8?q?fix:=20boardRead=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B3=BC=EC=A0=95=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=8F=99=EC=8B=9C=EC=84=B1=20=EC=A0=9C=EC=96=B4=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/BoardReadRepository.java | 4 ++++ .../domain/service/BoardReadSaveService.java | 15 +++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java b/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java index 0053ac5b..2be1ae98 100644 --- a/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java +++ b/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java @@ -5,10 +5,14 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Lock; +import javax.persistence.LockModeType; import java.util.List; import java.util.Optional; public interface BoardReadRepository extends JpaRepository { + + @Lock(LockModeType.PESSIMISTIC_WRITE) List findBoardReadByBoardAndMemberAndTeam(Board board, Member member, Team team); } diff --git a/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java b/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java index c15ca2c7..563cc991 100644 --- a/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java +++ b/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java @@ -16,16 +16,15 @@ public class BoardReadSaveService { private final BoardReadRepository boardReadRepository; + public void saveBoardRead(Board board, BoardRead boardRead) { - List existingBoardReads = boardReadRepository.findBoardReadByBoardAndMemberAndTeam(board, boardRead.getMember(), boardRead.getTeam()); + synchronized (this) { + List existingBoardReads = boardReadRepository.findBoardReadByBoardAndMemberAndTeam(board, boardRead.getMember(), boardRead.getTeam()); - if (existingBoardReads.size() > 1) { - // 첫 번째 엔티티를 제외하고 나머지 삭제 - List duplicates = existingBoardReads.subList(1, existingBoardReads.size()); - boardReadRepository.deleteAll(duplicates); - } else if (existingBoardReads.isEmpty()) { - boardRead.updateBoard(board); - boardReadRepository.save(boardRead); + if (existingBoardReads.isEmpty()) { + boardRead.updateBoard(board); + boardReadRepository.save(boardRead); + } } } } From 66217ffe4d58684118a2340f4cbf3bfa03a97f17 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 5 Jan 2024 23:23:40 +0900 Subject: [PATCH 445/619] =?UTF-8?q?fix:=20=EC=8A=AC=EB=9E=99=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=EC=9D=80=20=EC=9A=B4=EC=98=81=20=EC=84=9C=EB=B2=84?= =?UTF-8?q?=EC=97=90=20=EA=B4=80=ED=95=B4=EC=84=9C=EB=A7=8C=20=EA=B0=80?= =?UTF-8?q?=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/slack/exception/ExceptionEventHandler.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java b/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java index 877decdc..857523f8 100644 --- a/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java +++ b/src/main/java/com/moing/backend/global/config/slack/exception/ExceptionEventHandler.java @@ -3,12 +3,14 @@ import com.moing.backend.global.config.slack.exception.dto.ExceptionEvent; import com.moing.backend.global.config.slack.util.WebhookUtil; import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Profile; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @RequiredArgsConstructor @Component +@Profile("prod") public class ExceptionEventHandler { private final WebhookUtil webhookUtil; From 776cb09280fbd7dc6b5bf69e4e6ea27061b16922 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 5 Jan 2024 23:28:14 +0900 Subject: [PATCH 446/619] =?UTF-8?q?fix:=20dau=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A4=84=EB=9F=AC=20=EC=8B=9C=EA=B0=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/application/service/DAUScheduleUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java index c002f123..4d2ca7f7 100644 --- a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java @@ -35,7 +35,7 @@ public class DAUScheduleUseCase { /* DAU 정보 : 일일 모임 생성 수, 일일 신규 가입자 수, 일일 반복 미션 생성 수, 일일 한번 미션 생성 수 */ - @Scheduled(cron = "0 59 23 * * *") + @Scheduled(cron = "0 55 23 * * *") public void DailyTeamCreationInfoAlarm() { Map todayStats = new LinkedHashMap<>(); Map yesterdayStats = new LinkedHashMap<>(); From 13325053af25a1d0e1b25d1ac70a8d811801c97d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 6 Jan 2024 16:32:40 +0900 Subject: [PATCH 447/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A0=90=EC=88=98=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveCreateUseCase.java | 36 ++++++++++--------- .../service/MissionArchiveReadUseCase.java | 4 +-- .../service/MissionArchiveUpdateUseCase.java | 5 ++- .../MissionArchiveCustomRepository.java | 3 +- .../MissionArchiveCustomRepositoryImpl.java | 2 +- .../service/MissionArchiveQueryService.java | 22 ++---------- .../service/MissionStateUseCase.java | 35 ++++++++---------- .../MissionStateCustomRepositoryImpl.java | 4 +-- 8 files changed, 42 insertions(+), 69 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 97dc7273..2cc3df06 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -10,7 +10,6 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; @@ -21,6 +20,7 @@ import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import com.moing.backend.global.utils.BaseService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -48,15 +48,12 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss Member member = memberGetService.getMemberBySocialId(userSocialId); Long memberId = member.getMemberId(); + Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); MissionArchive newArchive = MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission); - // 단일 미션인 경우 미션 인증 시도 시 ongoing 으로 변경 - if (mission.getType() == MissionType.ONCE && mission.getStatus() == MissionStatus.WAIT) { - mission.updateStatus(MissionStatus.ONGOING); - } // 인증 완료한 미션인지 확인 if (isDoneMission(memberId,mission)) { throw new NoMoreMissionArchiveException(); @@ -66,30 +63,39 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss // 반복 미션일 경우 if (mission.getType() == MissionType.REPEAT) { - // 예정된 반복미션 접근 제한 + // 아직 열리지 않은 반복미션 접근 제한 if (mission.getStatus() == MissionStatus.WAIT) { throw new NotYetMissionArchiveException(); } + // 당일 1회 인증만 가능 - if(!missionArchiveQueryService.findDoneTodayArchive(memberId,missionId)) - newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); - else + if (missionArchiveQueryService.isAbleToArchiveToday(memberId, missionId)) { throw new NoMoreMissionArchiveException(); + } else { + newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId) + 1); + } missionStateUseCase.updateMissionState(member, mission, newArchive); missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); + } + + // 한번 미션일 경우 + else { + + // 미션 생성 후 처음 미션 인증 시도 시 ongoing 으로 변경 + if(mission.getStatus() == MissionStatus.WAIT) { + mission.updateStatus(MissionStatus.ONGOING); + } - } else { newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); missionStateUseCase.updateMissionState(member, mission, newArchive); missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); + + // 인증 후 n/n명 인증 성공 리턴값 업데이트 missionArchiveRes.updateCount(missionArchiveQueryService.findDoneSingleArchives(missionId)); } - -// missionStateUseCase.updateMissionState(member, mission, newArchive); -// missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); return missionArchiveRes; } @@ -99,8 +105,4 @@ public Boolean isDoneMission(Long memberId,Mission mission) { return missionArchiveQueryService.findMyDoneArchives(memberId, mission.getId()) >= mission.getNumber(); } - - - - } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java index 763726a7..0ac0ccf0 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveReadUseCase.java @@ -1,6 +1,5 @@ package com.moing.backend.domain.missionArchive.application.service; -import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; @@ -9,7 +8,6 @@ import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.repository.TeamRepository; import com.moing.backend.domain.team.domain.service.TeamGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -40,7 +38,7 @@ public MyMissionArchiveRes getMyArchive(String userSocialId, Long missionId) { List missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveResList(missionArchiveQueryService.findMyArchive(memberId, missionId), memberId); myMissionArchiveRes.updateArchives(missionArchiveRes); - myMissionArchiveRes.updateTodayStatus(missionArchiveQueryService.findDoneTodayArchive(memberId, missionId)); + myMissionArchiveRes.updateTodayStatus(missionArchiveQueryService.isAbleToArchiveToday(memberId, missionId)); return myMissionArchiveRes; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index 60a84e88..b306f349 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -46,7 +46,7 @@ public class MissionArchiveUpdateUseCase { private final MissionStateUseCase missionStateUseCase; - // 미션 재인증 (수정하기도 포함됨) + // 미션 재인증 (수정하기도 포함됨) -> 사용하지 않음 public MissionArchiveRes updateArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); @@ -58,13 +58,12 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(memberId, missionId)) { //s3삭제 - } MissionArchive updateArchive = missionArchiveQueryService.findMyArchive(memberId, missionId).get(0); // 단일 미션 && 미션 종료 직전인지 확인 - if (mission.getType() == MissionType.ONCE && missionStateUseCase.isAbleToEnd(missionId)) { + if (mission.getType() == MissionType.ONCE && missionStateUseCase.isAbleToEnd(mission)) { mission.updateStatus(MissionStatus.SUCCESS); // 점수 반영 로직 diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index ac242d4c..fd2ffc8d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -8,7 +8,6 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.application.dto.res.MyArchiveStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import org.springframework.stereotype.Repository; import java.util.List; @@ -22,7 +21,7 @@ public interface MissionArchiveCustomRepository { Optional> findOthersArchives(Long memberId, Long missionId) ; - Optional findDonePeopleByMissionId(Long missionId); + Optional findDonePeopleBySingleMissionId(Long missionId); Optional findDonePeopleByRepeatMissionId(Long missionId); Optional findMyDoneCountByMissionId(Long missionId,Long memberId); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 331c3f57..9c63483e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -199,7 +199,7 @@ public Optional> findOthersArchives(Long memberId, Long mis @Override - public Optional findDonePeopleByMissionId(Long missionId) { + public Optional findDonePeopleBySingleMissionId(Long missionId) { BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 2e46966e..0aa1ea1b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -31,9 +31,6 @@ public MissionArchive findByMissionArchiveId(Long missionArchiveId) { return missionArchiveRepository.findById(missionArchiveId).orElseThrow(NotFoundMissionArchiveException::new); } - public MissionArchive findArchive(Long memberId, Long missionId) { - return missionArchiveRepository.findByMissionIdAndMemberId(memberId, missionId).orElseThrow(NotFoundMissionArchiveException::new); - } public List findMyArchive(Long memberId, Long missionId) { @@ -60,9 +57,6 @@ public List findOthersArchive(Long memberId, Long missionId) { return missionArchiveRepository.findOthersArchives(memberId, missionId).orElseThrow(NotFoundMissionArchiveException::new); } - public List findArchivesByMemberId(Long memberId) { - return missionArchiveRepository.findByMemberId(memberId).orElseThrow(NotFoundMissionArchiveException::new); - } public Boolean isDone(Long memberId, Long missionId) { Optional> byMemberId = missionArchiveRepository.findArchivesByMissionIdAndMemberId(memberId, missionId); @@ -73,18 +67,6 @@ public Boolean isDone(Long memberId, Long missionId) { } } - public Boolean isTodayDone(Long memberId, Long missionId) { - Optional> byMemberId = missionArchiveRepository.findArchivesByMissionIdAndMemberId(memberId, missionId); - if (byMemberId.isPresent()) { - - return Boolean.TRUE; - } else { - return Boolean.FALSE; - } - } - - // team의 mission id 들 가져와서 나의 mission archive 리턴 - /** * mission.getTeam() 팀의 단일미션 미션 인증 보드 */ @@ -107,7 +89,7 @@ public List findMyRepeatMissionArchives(Long memberId, Lo public Long findDoneSingleArchives(Long missionId) { - return missionArchiveRepository.findDonePeopleByMissionId(missionId).orElseThrow(NotFoundMissionArchiveException::new); + return missionArchiveRepository.findDonePeopleBySingleMissionId(missionId).orElseThrow(NotFoundMissionArchiveException::new); } public Long findDoneRepeatArchives(Long missionId) { return missionArchiveRepository.findDonePeopleByRepeatMissionId(missionId).orElseThrow(NotFoundMissionArchiveException::new); @@ -126,7 +108,7 @@ public List findTop5ArchivesByTeam(List teamIds) { return missionArchiveRepository.findTop5ArchivesByTeam(teamIds).orElse(null); } - public boolean findDoneTodayArchive(Long memberId, Long missionId) { + public boolean isAbleToArchiveToday(Long memberId, Long missionId) { return missionArchiveRepository.findMyArchivesToday(memberId, missionId); } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 9c9ed7a1..e101d818 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -36,27 +36,17 @@ public class MissionStateUseCase { private final TeamScoreLogicUseCase teamScoreLogicUseCase; - public boolean isAbleToEnd(Long missionId) { + /* + 모든 모임원이 미션을 완료했는지 여부 확인 + */ + public boolean isAbleToEnd(Mission mission) { - Mission mission = missionQueryService.findMissionById(missionId); Long total = totalPeople(mission); Long done = donePeople(mission); return done >= total; } - public boolean isAbleToScoreUp(Long missionId) { - - Mission mission = missionQueryService.findMissionById(missionId); - Long total = totalPeople(mission); - Long done = donePeople(mission); - - log.info("done/total -> "+ done+ total); - - return done >= total; - - } - public Long donePeople(Mission mission) { return Long.valueOf(missionStateQueryService.stateCountByMissionId(mission.getId())); @@ -64,19 +54,22 @@ public Long donePeople(Mission mission) { public Long totalPeople(Mission mission) { return Long.valueOf(mission.getTeam().getNumOfMember()); - } public void updateMissionState(Member member, Mission mission, MissionArchive missionArchive) { - // 마지막 인증 시 - if (mission.getType().equals(MissionType.ONCE) && isAbleToEnd(mission.getId())) { - mission.updateStatus(MissionStatus.SUCCESS); - } + MissionType missionType = mission.getType(); + Long missionId = mission.getId(); + missionStateSaveService.saveMissionState(member,mission, missionArchive.getStatus()); - if (isAbleToScoreUp(mission.getId())) { - teamScoreLogicUseCase.updateTeamScore(mission.getId()); + if (missionType == MissionType.ONCE) { + + if (isAbleToEnd(mission)) { + mission.updateStatus(MissionStatus.SUCCESS); + teamScoreLogicUseCase.updateTeamScore(missionId); + } + } } diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index 10b9e4b4..15f67329 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -38,9 +38,9 @@ public int getCountsByMissionId(Long missionId) { LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); LocalDate endOfWeek = startOfWeek.plusDays(6); // 한 주의 마지막일을 일요일로 설정 - BooleanExpression repeatTypeCondition = missionState.mission.type.eq(MissionType.REPEAT) + BooleanExpression repeatTypeCondition = (missionState.mission.type.eq(MissionType.REPEAT) .and(missionState.createdDate.goe(startOfWeek.atStartOfDay())) - .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1)))).or(missionState.mission.type.eq(MissionType.ONCE)); // 기본 조건 BooleanExpression baseCondition = missionState.mission.id.eq(missionId); From f96edfde711e2e02ec3d5d31652d2d0153f9abda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 8 Jan 2024 01:57:07 +0900 Subject: [PATCH 448/619] =?UTF-8?q?feat=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=8B=9C=EC=9E=91=20=EC=95=8C=EB=A6=BC=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendMissionStartAlarmUseCase.java | 59 +++++++++++++++++++ .../service/MissionStateScheduleUseCase.java | 9 ++- 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/SendMissionStartAlarmUseCase.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionStartAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionStartAlarmUseCase.java new file mode 100644 index 00000000..be5ddebd --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionStartAlarmUseCase.java @@ -0,0 +1,59 @@ +package com.moing.backend.domain.mission.application.service; + +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.entity.PagePath; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; +import lombok.RequiredArgsConstructor; +import net.minidev.json.JSONObject; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; + +import static com.moing.backend.global.config.fcm.constant.NewMissionTitle.NEW_REPEAT_MISSION_COMING; +import static com.moing.backend.global.config.fcm.constant.NewMissionTitle.NEW_SINGLE_MISSION_COMING; + +@Service +@Transactional +@RequiredArgsConstructor +public class SendMissionStartAlarmUseCase { + + private final TeamMemberGetService teamMemberGetService; + private final ApplicationEventPublisher eventPublisher; + + public void sendRepeatMissionStartAlarm(Mission mission) { + Team team = mission.getTeam(); + String title = team.getName() + " " + NEW_REPEAT_MISSION_COMING.getTitle(); + String message = mission.getTitle(); + String type = mission.getType().toString(); + String status = mission.getStatus().toString(); + + Optional> newUploadInfos=teamMemberGetService.getNewUploadInfo(team.getTeamId(), 0L); + + Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); + Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); + // 알림 보내기 + eventPublisher.publishEvent(new MultiFcmEvent(title, message, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId(),mission.getType(),mission.getStatus()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.MISSION_PATH.getValue())); + } + + private String createIdInfo(Long teamId, Long missionId,MissionType type, MissionStatus status) { + JSONObject jo = new JSONObject(); + jo.put("isRepeated", type.equals(MissionType.REPEAT)); + jo.put("teamId", teamId); + jo.put("missionId", missionId); + jo.put("status", status.name()); + return jo.toJSONString(); + } +} + diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index f0d3bfd3..97707aaa 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.missionState.application.service; import com.moing.backend.domain.mission.application.service.MissionRemindAlarmUseCase; +import com.moing.backend.domain.mission.application.service.SendMissionStartAlarmUseCase; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.service.MissionQueryService; @@ -38,6 +39,8 @@ public class MissionStateScheduleUseCase { private final TeamScoreLogicUseCase teamScoreLogicUseCase; + private final SendMissionStartAlarmUseCase sendMissionStartAlarmUseCase; + /** * 반복미션 마감 * 일요일 마감 루틴 @@ -80,7 +83,11 @@ public void singleMissionEndRoutine() { public void RepeatMissionStart() { List startMission = missionQueryService.findRepeatMissionByStatus(MissionStatus.WAIT); startMission.forEach( - mission -> mission.updateStatus(MissionStatus.ONGOING) + mission -> { + // 미션 시작 알림 + sendMissionStartAlarmUseCase.sendRepeatMissionStartAlarm(mission); + mission.updateStatus(MissionStatus.ONGOING); + } ); } From 86162f92de7c9e130dbd2908ae0ce00ca93f164d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Jan 2024 16:59:03 +0900 Subject: [PATCH 449/619] =?UTF-8?q?fix=20:=20=ED=95=9C=EB=B2=88=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A0=90=EC=88=98=20=EB=B0=98=EC=98=81=20=EC=95=88?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionStateScheduleUseCase.java | 4 ++-- .../missionState/application/service/MissionStateUseCase.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 97707aaa..b3f0acb2 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -68,10 +68,10 @@ public void singleMissionEndRoutine() { List missionByDueTo = missionQueryService.findMissionByDueTo(); - missionByDueTo.stream().forEach(mission -> { + for (Mission mission : missionByDueTo) { mission.updateStatus(MissionStatus.END); teamScoreLogicUseCase.updateTeamScore(mission.getId()); - }); + } } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index e101d818..0e70b913 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -44,7 +44,7 @@ public boolean isAbleToEnd(Mission mission) { Long total = totalPeople(mission); Long done = donePeople(mission); - return done >= total; + return done > total; } From 21dded1600a4e9d7804ceca045b6e56da2ae5da4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Jan 2024 19:38:28 +0900 Subject: [PATCH 450/619] =?UTF-8?q?fix=20:=20=EA=B0=9C=EB=B0=9C=EC=84=9C?= =?UTF-8?q?=EB=B2=84=EC=97=90=EC=84=9C=20=EC=8A=A4=EC=BC=80=EC=A5=B4?= =?UTF-8?q?=EB=A7=81=20=EB=8F=99=EC=9E=91=20=EC=9C=84=ED=95=9C=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionStateScheduleUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index b3f0acb2..9015be45 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -28,7 +28,7 @@ @EnableAsync @EnableScheduling // 스케줄링 활성화 @RequiredArgsConstructor -@Profile("prod") +//@Profile("prod") public class MissionStateScheduleUseCase { private final MissionStateUseCase missionStateUseCase; From 9d13d5cc94b68b6ba96ddd35cc1732f91aed22e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Jan 2024 20:05:11 +0900 Subject: [PATCH 451/619] =?UTF-8?q?fix=20:=20=ED=95=9C=EB=B2=88=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EB=A7=88=EA=B0=90=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A5=B4=EB=A7=81=20=EB=B3=80=EA=B2=BD=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9C=84=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionStateScheduleUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 9015be45..c4a16531 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -63,7 +63,7 @@ public void sundayRepeatMissionRoutine() { * 해당 시간 미션 마감 * 한시간 마다 실행 */ - @Scheduled(cron = "0 1 * * * *") + @Scheduled(cron = "0 0/10 * * * *") public void singleMissionEndRoutine() { List missionByDueTo = missionQueryService.findMissionByDueTo(); From 3d9ecc3cf81ca01c36f58bb5afdb1165f57bedb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Jan 2024 20:22:28 +0900 Subject: [PATCH 452/619] =?UTF-8?q?fix=20:=20=ED=95=9C=EB=B2=88=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EB=A7=88=EA=B0=90=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EB=A1=9C=EA=B7=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionStateScheduleUseCase.java | 3 ++- .../teamScore/application/service/TeamScoreLogicUseCase.java | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index c4a16531..60c75f72 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -70,7 +70,8 @@ public void singleMissionEndRoutine() { for (Mission mission : missionByDueTo) { mission.updateStatus(MissionStatus.END); - teamScoreLogicUseCase.updateTeamScore(mission.getId()); + Long aLong = teamScoreLogicUseCase.updateTeamScore(mission.getId()); + log.info("updateTeamScoreValue" + aLong); } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index 8323c1b5..9038fa23 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -39,6 +39,7 @@ public TeamScoreRes getTeamScoreInfo(Long teamId) { } public Long updateTeamScore(Long missionId) { + log.info("updateTeamScoreStart"); Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); @@ -50,6 +51,8 @@ public Long updateTeamScore(Long missionId) { teamScoreSaveService.save(teamScore); teamSaveService.saveTeam(team); + log.info("updateTeamScoreEnd"); + return teamScore.getScore(); } From 084f53d64efce4cc7d250bb4643597cc1302ad85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Jan 2024 20:41:47 +0900 Subject: [PATCH 453/619] =?UTF-8?q?fix=20:=20=EA=B0=9C=EB=B0=9C=20?= =?UTF-8?q?=EC=84=9C=EB=B2=84=20=EC=8A=A4=EC=BC=80=EC=A5=B4=EB=A7=81=20off?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionStateScheduleUseCase.java | 4 ++-- .../teamScore/application/service/TeamScoreLogicUseCase.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 60c75f72..2b918b2d 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -28,7 +28,7 @@ @EnableAsync @EnableScheduling // 스케줄링 활성화 @RequiredArgsConstructor -//@Profile("prod") +@Profile("prod") public class MissionStateScheduleUseCase { private final MissionStateUseCase missionStateUseCase; @@ -63,7 +63,7 @@ public void sundayRepeatMissionRoutine() { * 해당 시간 미션 마감 * 한시간 마다 실행 */ - @Scheduled(cron = "0 0/10 * * * *") + @Scheduled(cron = "0 1 * * * *") public void singleMissionEndRoutine() { List missionByDueTo = missionQueryService.findMissionByDueTo(); diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index 9038fa23..ad167f4b 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -42,7 +42,6 @@ public Long updateTeamScore(Long missionId) { log.info("updateTeamScoreStart"); Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); - TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); teamScore.updateScore(getScoreByMission(mission)); @@ -69,8 +68,10 @@ public Long getScoreByMission(Mission mission) { Long done = donePeople(mission); if (done == 0) { + log.info("done"+done); return 0L; } else { + log.info("done"+(done / total * 100) / 5); return (done / total * 100) / 5 ; } From 5bb562c516959c3670b131bf2695b0b81cc0c285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Jan 2024 21:24:27 +0900 Subject: [PATCH 454/619] =?UTF-8?q?fix=20:=20=ED=8C=80=EC=8A=A4=EC=BD=94?= =?UTF-8?q?=EC=96=B4=20=EB=B0=98=EC=98=81=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionStateScheduleUseCase.java | 5 ++--- .../service/TeamScoreLogicUseCase.java | 22 ++++++------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 2b918b2d..9015be45 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -28,7 +28,7 @@ @EnableAsync @EnableScheduling // 스케줄링 활성화 @RequiredArgsConstructor -@Profile("prod") +//@Profile("prod") public class MissionStateScheduleUseCase { private final MissionStateUseCase missionStateUseCase; @@ -70,8 +70,7 @@ public void singleMissionEndRoutine() { for (Mission mission : missionByDueTo) { mission.updateStatus(MissionStatus.END); - Long aLong = teamScoreLogicUseCase.updateTeamScore(mission.getId()); - log.info("updateTeamScoreValue" + aLong); + teamScoreLogicUseCase.updateTeamScore(mission.getId()); } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index ad167f4b..eb4b5a91 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -39,7 +39,6 @@ public TeamScoreRes getTeamScoreInfo(Long teamId) { } public Long updateTeamScore(Long missionId) { - log.info("updateTeamScoreStart"); Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); @@ -50,8 +49,6 @@ public Long updateTeamScore(Long missionId) { teamScoreSaveService.save(teamScore); teamSaveService.saveTeam(team); - log.info("updateTeamScoreEnd"); - return teamScore.getScore(); } @@ -64,32 +61,27 @@ public Long getLevel(Long teamId) { } public Long getScoreByMission(Mission mission) { - Long total = totalPeople(mission); - Long done = donePeople(mission); + float total = totalPeople(mission); + float done = donePeople(mission); if (done == 0) { - log.info("done"+done); return 0L; } else { - log.info("done"+(done / total * 100) / 5); - return (done / total * 100) / 5 ; + return (long) ((done / total * 100) / 5); } } - public Long donePeople(Mission mission) { - return Long.valueOf(missionStateQueryService.stateCountByMissionId(mission.getId())); + public float donePeople(Mission mission) { + return Float.valueOf(missionStateQueryService.stateCountByMissionId(mission.getId())); } - public Long totalPeople(Mission mission) { - return Long.valueOf(mission.getTeam().getNumOfMember()); + public float totalPeople(Mission mission) { + return Float.valueOf(mission.getTeam().getNumOfMember()); } - - - } From 51f54e50b09f7a4fc5d37f98aad473644e1c4428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Jan 2024 21:35:17 +0900 Subject: [PATCH 455/619] =?UTF-8?q?fix=20:=20prod=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A5=B4=EB=A7=81=20=EC=A3=BC=EC=84=9D=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionStateScheduleUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 9015be45..b3f0acb2 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -28,7 +28,7 @@ @EnableAsync @EnableScheduling // 스케줄링 활성화 @RequiredArgsConstructor -//@Profile("prod") +@Profile("prod") public class MissionStateScheduleUseCase { private final MissionStateUseCase missionStateUseCase; From 17e5e36962e23b5a3738fc655d3c0029b85ea6ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Jan 2024 21:51:58 +0900 Subject: [PATCH 456/619] =?UTF-8?q?fix=20:=20=EB=A6=AC=EB=A7=88=EC=9D=B8?= =?UTF-8?q?=EB=93=9C=20=EC=95=8C=EB=A6=BC=20eventPublisher=20=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionRemindAlarmUseCase.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index a946a6b0..dd0a0e8f 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -99,28 +99,43 @@ public String getMessage(int num) { public Boolean sendRepeatMissionRemindOnSunday() { + String title = REMIND_ON_SUNDAY_TITLE.getMessage(); + String message = REMIND_ON_SUNDAY_MESSAGE.getMessage(); + List repeatMissionByStatus = missionQueryService.findRepeatMissionPeopleByStatus(MissionStatus.WAIT); Optional> memberIdAndTokens = mapToMemberAndToken(repeatMissionByStatus); Optional> pushMemberIdAndToken = isPushMemberIdAndToken(repeatMissionByStatus); - - eventPublisher.publishEvent(new MultiFcmEvent(REMIND_ON_SUNDAY_TITLE.getMessage(), REMIND_ON_SUNDAY_MESSAGE.getMessage(), pushMemberIdAndToken, memberIdAndTokens, - "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { + fcmService.sendMultipleDevices(new MultiRequest(pushMemberIdAndToken.get(), title,message, "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + } + if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { + saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); + } return true; - } + } public Boolean sendRepeatMissionRemindOnMonday() { + + String title = REMIND_ON_MONDAY_TITLE.getMessage(); + String message = REMIND_ON_MONDAY_MESSAGE.getMessage(); + List repeatMissionByStatus = missionQueryService.findRepeatMissionPeopleByStatus(MissionStatus.ONGOING); Optional> memberIdAndTokens = mapToMemberAndToken(repeatMissionByStatus); Optional> pushMemberIdAndToken = isPushMemberIdAndToken(repeatMissionByStatus); - eventPublisher.publishEvent(new MultiFcmEvent(REMIND_ON_MONDAY_TITLE.getMessage(), REMIND_ON_MONDAY_MESSAGE.getMessage(), pushMemberIdAndToken, memberIdAndTokens, - "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { + fcmService.sendMultipleDevices(new MultiRequest(pushMemberIdAndToken.get(), title,message, "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + } + if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { + saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); + } + return true; From 4ebf56f5329724f354d95240c331b466e46ed362 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 18 Jan 2024 11:39:49 +0900 Subject: [PATCH 457/619] =?UTF-8?q?fix:=20=ED=83=88=ED=87=B4=ED=95=9C=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/application/dto/request/CreateBoardRequest.java | 4 ++-- .../application/dto/request/CreateBoardCommentRequest.java | 3 +++ .../boardComment/application/dto/response/CommentBlocks.java | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java b/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java index b1d6209b..4aabe77e 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java @@ -15,11 +15,11 @@ @Getter public class CreateBoardRequest { @NotBlank(message = "title 을 입력해 주세요.") - @Size(min = 1, max = 15, message = "title 은 최소 1개, 최대 15개의 문자만 입력 가능합니다.") + @Size(min = 0, max = 15, message = "제목 글자수를 초과했습니다.") private String title; @NotBlank(message = "content 을 입력해 주세요.") - @Size(min = 1, max = 300, message = "content 은 최소 1개, 최대 10개의 문자만 입력 가능합니다.") + @Size(min = 0, max = 300, message = "내용 글자수를 초과했습니다.") private String content; @NotNull(message = "notice 사용 여부(isNotice) 를 입력해 주세요.") diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java index 06bd1a8b..9cc0841d 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java @@ -6,13 +6,16 @@ import lombok.NoArgsConstructor; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; @AllArgsConstructor @Builder @NoArgsConstructor @Getter public class CreateBoardCommentRequest { + @NotBlank(message = "content 을 입력해 주세요.") + @Size(min = 0, max = 300, message = "댓글 글자수를 초과했습니다.") private String content; } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java index a9cf080f..b6a5643e 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java @@ -47,7 +47,7 @@ public CommentBlocks(Long boardCommentId, String content, String writerNickName, public void deleteMember() { if (Boolean.TRUE.equals(writerIsDeleted)) { - this.makerId = null; + this.makerId = 0L; this.writerNickName = "(알 수 없음)"; this.writerProfileImage = null; } From d3b79919f7a79dcd2e729396e7b558a6956ef3fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 20 Jan 2024 01:15:02 +0900 Subject: [PATCH 458/619] =?UTF-8?q?fix=20:=20=EC=A7=80=EB=82=9C=EC=A3=BC?= =?UTF-8?q?=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=EC=99=84=EB=A3=8C=20?= =?UTF-8?q?=ED=95=9C=20=EC=9D=B8=EC=9B=90=20=EB=B6=88=EB=8D=98=EC=A7=80?= =?UTF-8?q?=EA=B8=B0=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=95=88=EB=9C=A8?= =?UTF-8?q?=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=20#204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/FireCustomRepositoryImpl.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 0383d08d..4dea8c43 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.domain.entity.Fire; import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; @@ -11,7 +12,10 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; +import java.time.DayOfWeek; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.temporal.TemporalAdjusters; import java.util.List; import java.util.Optional; @@ -52,6 +56,8 @@ public boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMembe public Optional> getFireReceivers(Long teamId, Long missionId, Long memberId) { + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + JPQLQuery missionDonePeople = select(missionArchive.member.memberId) .from(missionArchive, mission) .where(missionArchive.mission.id.eq(missionId), @@ -63,7 +69,8 @@ public Optional> getFireReceivers(Long teamId, Long mission mission.number) .having( missionArchive.mission.id.eq(missionId), - missionArchive.count.max().goe(mission.number) + missionArchive.count.max().goe(mission.number), + (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) ); LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1); // 현재 시간에서 1시간을 뺀 시간 @@ -99,4 +106,18 @@ public Optional> getFireReceivers(Long teamId, Long mission } + + private BooleanExpression createRepeatTypeConditionByArchive() { + LocalDate now = LocalDate.now(); + DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; + LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); + LocalDate endOfWeek = startOfWeek.plusDays(6); + + BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) + .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + + // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 + return dateInRange.and(dateInRange); + } + } From 734866d238642355c4350ea71c26f41f7728e343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 20 Jan 2024 02:07:59 +0900 Subject: [PATCH 459/619] =?UTF-8?q?fix=20:=20=EB=8B=A4=EC=8B=9C=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EC=95=88=EB=90=98=EB=8A=94=20=EC=9D=B4=EC=8A=88=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionStateCustomRepositoryImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java index 15f67329..93cde112 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -96,6 +96,7 @@ public Optional findMissionStateByMemberAndMission(Member member, .selectFrom(missionState) .where(missionState.mission.eq(mission), missionState.member.eq(member)) + .orderBy(missionState.createdDate.desc()) .fetchFirst()); } From c3c2fd2fe7bb1e8ef91469f418b25badbc9fe506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 20 Jan 2024 02:58:27 +0900 Subject: [PATCH 460/619] =?UTF-8?q?fix=20:=20=EC=A7=80=EB=82=9C=EC=A3=BC?= =?UTF-8?q?=EC=B0=A8=20=EB=AF=B8=EC=85=98=20=EC=99=84=EB=A3=8C=EC=9E=90=20?= =?UTF-8?q?=EB=B6=88=EB=8D=98=EC=A7=80=EA=B8=B0=20=EC=95=88=EB=B3=B4?= =?UTF-8?q?=EC=9D=B4=EB=8A=94=20=EB=B2=84=EA=B7=B8#204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fire/domain/repository/FireCustomRepositoryImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 4dea8c43..86b3b7d1 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -61,7 +61,8 @@ public Optional> getFireReceivers(Long teamId, Long mission JPQLQuery missionDonePeople = select(missionArchive.member.memberId) .from(missionArchive, mission) .where(missionArchive.mission.id.eq(missionId), - mission.id.eq(missionId) + mission.id.eq(missionId), + (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) ) .groupBy(missionArchive.member.memberId, missionArchive.mission.id, @@ -69,8 +70,7 @@ public Optional> getFireReceivers(Long teamId, Long mission mission.number) .having( missionArchive.mission.id.eq(missionId), - missionArchive.count.max().goe(mission.number), - (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) + missionArchive.count.max().goe(mission.number) ); LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1); // 현재 시간에서 1시간을 뺀 시간 From e2a324b18e96d6469094523230003a833912b14b Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Thu, 25 Jan 2024 15:44:52 +0900 Subject: [PATCH 461/619] =?UTF-8?q?deploy:=20dev=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .deploy/deploy_dev.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.deploy/deploy_dev.sh b/.deploy/deploy_dev.sh index 0c2181d8..89a7f3b9 100644 --- a/.deploy/deploy_dev.sh +++ b/.deploy/deploy_dev.sh @@ -64,4 +64,4 @@ else LOGS=$(docker logs ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} 2>&1) echo "Error: ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} failed to start." echo "$LOGS" -fi \ No newline at end of file +fi From 603b698ac6b07e469d6890eda3ed8c1cbded999c Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 26 Jan 2024 23:33:03 +0900 Subject: [PATCH 462/619] =?UTF-8?q?fix:=20=EA=B3=B5=EC=A7=80/=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EA=B8=80=20=EA=B8=80=EC=9E=90=EC=88=98=20=EC=A0=9C?= =?UTF-8?q?=ED=95=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/application/dto/request/CreateBoardRequest.java | 2 +- .../com/moing/backend/domain/board/domain/entity/Board.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java b/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java index 4aabe77e..b639ee3c 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/request/CreateBoardRequest.java @@ -15,7 +15,7 @@ @Getter public class CreateBoardRequest { @NotBlank(message = "title 을 입력해 주세요.") - @Size(min = 0, max = 15, message = "제목 글자수를 초과했습니다.") + @Size(min = 0, max = 30, message = "제목 글자수를 초과했습니다.") private String title; @NotBlank(message = "content 을 입력해 주세요.") diff --git a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java index 77b40344..7b6691ec 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java +++ b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java @@ -30,7 +30,7 @@ public class Board extends BaseTimeEntity { private boolean isLeader; /*작성자 소모임장유무*/ - @Column(nullable = false, length = 15) + @Column(nullable = false, length = 30) private String title; @Column(nullable = false, length = 300) From ab9fd41ec858e7411356a01cb04efa1c0a4b2db9 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 27 Jan 2024 23:53:00 +0900 Subject: [PATCH 463/619] =?UTF-8?q?MNG-01=20fix:=20=EC=9C=A0=EB=8B=88?= =?UTF-8?q?=ED=81=AC=20=EB=B3=B5=ED=95=A9=20=ED=82=A4=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=ED=9B=84=20=EB=9D=BD=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boardRead/domain/repository/BoardReadRepository.java | 1 - .../teamMember/domain/repository/TeamMemberRepository.java | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java b/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java index 2be1ae98..81724604 100644 --- a/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java +++ b/src/main/java/com/moing/backend/domain/boardRead/domain/repository/BoardReadRepository.java @@ -13,6 +13,5 @@ public interface BoardReadRepository extends JpaRepository { - @Lock(LockModeType.PESSIMISTIC_WRITE) List findBoardReadByBoardAndMemberAndTeam(Board board, Member member, Team team); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java index 503cd5bb..b7ab7bbe 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberRepository.java @@ -4,16 +4,14 @@ import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Lock; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; -import javax.persistence.LockModeType; import javax.swing.text.html.Option; import java.util.Optional; public interface TeamMemberRepository extends JpaRepository, TeamMemberCustomRepository{ - @Lock(LockModeType.PESSIMISTIC_WRITE) Optional findTeamMemberByTeamAndMember(Team team, Member member); + } From d4b01f52da60e40638f746484cbbd044cfa04e38 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 28 Jan 2024 03:52:01 +0900 Subject: [PATCH 464/619] =?UTF-8?q?MNG-01=20fix:=20=ED=83=88=ED=87=B4=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=95=88=EB=90=98=EA=B2=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/application/service/DisbandTeamUseCase.java | 2 +- .../team/application/service/WithdrawTeamUseCase.java | 2 +- .../teamMember/domain/service/TeamMemberGetService.java | 9 ++++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java index 5e5f29df..cf6eb651 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/DisbandTeamUseCase.java @@ -28,7 +28,7 @@ public DeleteTeamResponse disbandTeam(String socialId, Long teamId) { checkLeaderUseCase.validateTeamLeader(member, team); team.deleteTeam(); if (team.getNumOfMember() == 1) { // 1명인 경우 3일 유예기간 없음 - TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + TeamMember teamMember = teamMemberGetService.getTeamMemberNotDeleted(member, team); teamMember.deleteMember(team); } return new DeleteTeamResponse(teamId); diff --git a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUseCase.java index e4e007eb..4e69e4d7 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/WithdrawTeamUseCase.java @@ -24,7 +24,7 @@ public class WithdrawTeamUseCase { public DeleteTeamResponse withdrawTeam(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Team team = teamGetService.getTeamByTeamId(teamId); - TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + TeamMember teamMember = teamMemberGetService.getTeamMemberNotDeleted(member, team); teamMember.deleteMember(team); return new DeleteTeamResponse(teamId); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index 00d065a3..1e0a64cb 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -24,9 +24,16 @@ public List getTeamMemberIds(Long teamId){ } public TeamMember getTeamMember(Member member, Team team){ - return teamMemberRepository.findTeamMemberByTeamAndMember(team, member).orElseThrow(()-> new NotFoundByTeamIdException()); + return teamMemberRepository.findTeamMemberByTeamAndMember(team, member).orElseThrow(NotFoundByTeamIdException::new); } + public TeamMember getTeamMemberNotDeleted(Member member, Team team) { + return teamMemberRepository.findTeamMemberByTeamAndMember(team, member) + .filter(teamMember -> !teamMember.isDeleted()) + .orElseThrow(NotFoundByTeamIdException::new); + } + + public Optional> getFcmTokensExceptMe(Long teamId, Long memberId) { return teamMemberRepository.findFcmTokensByTeamIdAndMemberId(teamId, memberId); } From 19c5997a9b77a1f480e029008ff8270edb3a482d Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 28 Jan 2024 04:18:55 +0900 Subject: [PATCH 465/619] =?UTF-8?q?MNG-01=20refactor=20:=20mapper=20static?= =?UTF-8?q?=20=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/apple/AppleSignInUseCase.java | 2 +- .../service/google/GoogleSignInUseCase.java | 3 +-- .../service/kakao/KakaoSignInUseCase.java | 3 +-- .../service/BlockCreateUseCase.java | 3 --- .../service/BlockDeleteUseCase.java | 3 --- .../application/service/BlockReadUseCase.java | 16 ++++---------- .../board/application/mapper/BoardMapper.java | 6 +++--- .../service/CreateBoardUseCase.java | 3 +-- .../application/service/GetBoardUseCase.java | 3 +-- .../mapper/BoardCommentMapper.java | 2 +- .../service/CreateBoardCommentUseCase.java | 3 +-- .../application/mapper/BoardReadMapper.java | 2 +- .../service/CreateBoardReadUseCase.java | 3 +-- .../mapper/AlarmHistoryMapper.java | 4 ++-- .../service/SaveMultiAlarmHistoryUseCase.java | 3 +-- .../SaveSingleAlarmHistoryUseCase.java | 3 +-- .../application/mapper/MemberMapper.java | 21 ++++++++----------- .../application/mapper/MyPageMapper.java | 2 +- .../application/service/GetMyPageUseCase.java | 5 ++--- .../application/service/GetTeamUseCase.java | 5 ++--- .../service/ReviewTeamUseCase.java | 3 +-- 21 files changed, 35 insertions(+), 63 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUseCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUseCase.java index 6f498fb6..323ebd51 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUseCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/apple/AppleSignInUseCase.java @@ -22,6 +22,6 @@ public Member getUserData(String identityToken) { String socialId = oidcTokenJws.getBody().getSubject(); String email = (String) oidcTokenJws.getBody().get("email"); - return memberMapper.createAppleMember(socialId, email); + return MemberMapper.createAppleMember(socialId, email); } } diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUseCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUseCase.java index 5873460a..69993fd4 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUseCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/google/GoogleSignInUseCase.java @@ -16,7 +16,6 @@ @RequiredArgsConstructor public class GoogleSignInUseCase implements SignInProvider { - private final MemberMapper memberMapper; private final WebClient webClient; private final GoogleTokenUseCase googleTokenUseCase; @@ -32,7 +31,7 @@ public Member getUserData(String accessToken) { if (googleUserResponse != null) { googleTokenUseCase.verifyAccessToken(googleUserResponse.getAud()); googleUserResponse.adaptResponse(); - return memberMapper.createGoogleMember(googleUserResponse); + return MemberMapper.createGoogleMember(googleUserResponse); } throw new TokenInvalidException(); } diff --git a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUseCase.java b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUseCase.java index 9fbf06e5..7e955df4 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUseCase.java +++ b/src/main/java/com/moing/backend/domain/auth/application/service/kakao/KakaoSignInUseCase.java @@ -17,7 +17,6 @@ public class KakaoSignInUseCase implements SignInProvider { private final WebClient webClient; - private final MemberMapper memberMapper; private final KakaoTokenUseCase kakaoTokenUseCase; public Member getUserData(String accessToken) { @@ -35,6 +34,6 @@ public Member getUserData(String accessToken) { .block(); kakaoUserResponse.adaptResponse(); - return memberMapper.createKakaoMember(kakaoUserResponse); + return MemberMapper.createKakaoMember(kakaoUserResponse); } } diff --git a/src/main/java/com/moing/backend/domain/block/application/service/BlockCreateUseCase.java b/src/main/java/com/moing/backend/domain/block/application/service/BlockCreateUseCase.java index 2094c929..db8e6b25 100644 --- a/src/main/java/com/moing/backend/domain/block/application/service/BlockCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/block/application/service/BlockCreateUseCase.java @@ -17,9 +17,6 @@ public class BlockCreateUseCase { private final MemberGetService memberGetService; - private final BoardGetService boardGetService; - private final MissionArchiveQueryService missionArchiveQueryService; - private final BlockSaveService blockSaveService; diff --git a/src/main/java/com/moing/backend/domain/block/application/service/BlockDeleteUseCase.java b/src/main/java/com/moing/backend/domain/block/application/service/BlockDeleteUseCase.java index f262c244..1101ccc8 100644 --- a/src/main/java/com/moing/backend/domain/block/application/service/BlockDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/block/application/service/BlockDeleteUseCase.java @@ -17,9 +17,6 @@ public class BlockDeleteUseCase { private final MemberGetService memberGetService; - private final BoardGetService boardGetService; - private final MissionArchiveQueryService missionArchiveQueryService; - private final BlockDeleteService blockDeleteService; diff --git a/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java b/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java index c66922dd..6f108b08 100644 --- a/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/block/application/service/BlockReadUseCase.java @@ -1,12 +1,7 @@ package com.moing.backend.domain.block.application.service; -import com.moing.backend.domain.block.application.mapper.BlockMapper; -import com.moing.backend.domain.block.domain.service.BlockDeleteService; import com.moing.backend.domain.block.domain.service.BlockQueryService; -import com.moing.backend.domain.block.domain.service.BlockSaveService; -import com.moing.backend.domain.board.domain.service.BoardGetService; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.report.application.dto.BlockMemberRes; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -18,9 +13,6 @@ public class BlockReadUseCase { private final MemberGetService memberGetService; - private final BoardGetService boardGetService; - private final MissionArchiveQueryService missionArchiveQueryService; - private final BlockQueryService blockQueryService; /** @@ -31,10 +23,10 @@ public List getMyBlockList(String socialId) { return blockQueryService.getBlockLists(memberId); } - public List getMyBlockInfoList(String socialId) { - Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); + public List getMyBlockInfoList(String socialId) { + Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); - return blockQueryService.getBlockInfoLists(memberId); - } + return blockQueryService.getBlockInfoLists(memberId); + } } diff --git a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java index 9d98f4c3..eed680d5 100644 --- a/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java +++ b/src/main/java/com/moing/backend/domain/board/application/mapper/BoardMapper.java @@ -16,7 +16,7 @@ @RequiredArgsConstructor public class BoardMapper { - public Board toBoard(TeamMember teamMember, Team team, CreateBoardRequest createBoardRequest, boolean isLeader) { + public static Board toBoard(TeamMember teamMember, Team team, CreateBoardRequest createBoardRequest, boolean isLeader) { Board board = Board.builder() .title(createBoardRequest.getTitle()) .content(createBoardRequest.getContent()) @@ -31,7 +31,7 @@ public Board toBoard(TeamMember teamMember, Team team, CreateBoardRequest create return board; } - public GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter, boolean writerIsDeleted) { + public static GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter, boolean writerIsDeleted) { String nickName = writerIsDeleted ? "(알 수 없음)" : board.getTeamMember().getMember().getNickName(); String writerProfileImage = writerIsDeleted ? null : board.getTeamMember().getMember().getProfileImage(); Long writerId = writerIsDeleted ? 0L : board.getTeamMember().getMember().getMemberId(); @@ -49,7 +49,7 @@ public GetBoardDetailResponse toBoardDetail(Board board, boolean isWriter, boole .build(); } - public String getFormattedDate(LocalDateTime localDateTime) { + public static String getFormattedDate(LocalDateTime localDateTime) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"); return localDateTime.format(formatter); } diff --git a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java index 35ec9102..c7b69d31 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/CreateBoardUseCase.java @@ -27,7 +27,6 @@ public class CreateBoardUseCase { private final BoardSaveService boardSaveService; private final CheckLeaderUseCase checkLeaderUseCase; - private final BoardMapper boardMapper; private final CreateBoardReadUseCase createBoardReadUseCase; private final BaseService baseService; private final SendBoardAlarmUseCase sendBoardAlarmUseCase; @@ -39,7 +38,7 @@ public CreateBoardResponse createBoard(String socialId, Long teamId, CreateBoard //1, 게시글 생성, 저장 BaseServiceResponse data=baseService.getCommonData(socialId, teamId); boolean isLeader = checkLeaderUseCase.isTeamLeader(data.getMember(), data.getTeam()); //작성자 리더 여부 - Board board=boardSaveService.saveBoard(boardMapper.toBoard(data.getTeamMember(), data.getTeam(), createBoardRequest, isLeader)); + Board board=boardSaveService.saveBoard(BoardMapper.toBoard(data.getTeamMember(), data.getTeam(), createBoardRequest, isLeader)); //2. 읽음 처리 - 생성한 사람은 무조건 읽음 createBoardReadUseCase.createBoardRead(data.getTeam(), data.getMember(), board); diff --git a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java index ae8b14ce..5ac5e4d9 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/GetBoardUseCase.java @@ -19,7 +19,6 @@ public class GetBoardUseCase { private final BaseBoardService baseBoardService; - private final BoardMapper boardMapper; private final MemberGetService memberGetService; private final CreateBoardReadUseCase createBoardReadUseCase; private final BoardGetService boardGetService; @@ -34,7 +33,7 @@ public GetBoardDetailResponse getBoardDetail(String socialId, Long teamId, Long BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); // 2. 읽음 처리 createBoardReadUseCase.createBoardRead(data.getTeam(), data.getMember(), data.getBoard()); - return boardMapper.toBoardDetail(data.getBoard(), data.getTeamMember() == data.getBoard().getTeamMember(), data.getBoard().getTeamMember().isDeleted()); + return BoardMapper.toBoardDetail(data.getBoard(), data.getTeamMember() == data.getBoard().getTeamMember(), data.getBoard().getTeamMember().isDeleted()); } /** diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java b/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java index 8e0fe2e2..e2311e2a 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java @@ -10,7 +10,7 @@ @Component @RequiredArgsConstructor public class BoardCommentMapper { - public BoardComment toBoardComment(TeamMember teamMember, Board board, CreateBoardCommentRequest createBoardCommentRequest, boolean isLeader) { + public static BoardComment toBoardComment(TeamMember teamMember, Board board, CreateBoardCommentRequest createBoardCommentRequest, boolean isLeader) { BoardComment boardComment= BoardComment.builder() .content(createBoardCommentRequest.getContent()) .isLeader(isLeader) diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java index f51b5172..39b1f4ea 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java @@ -19,7 +19,6 @@ public class CreateBoardCommentUseCase { private final BoardCommentSaveService boardCommentSaveService; - private final BoardCommentMapper boardCommentMapper; private final BaseBoardService baseBoardService; private final CheckLeaderUseCase checkLeaderUseCase; @@ -30,7 +29,7 @@ public CreateBoardCommentResponse createBoardComment(String socialId, Long teamI // 1. 게시글 댓글 생성 BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); boolean isLeader = checkLeaderUseCase.isTeamLeader(data.getMember(), data.getTeam()); - BoardComment boardComment = boardCommentSaveService.saveBoardComment(boardCommentMapper.toBoardComment(data.getTeamMember(), data.getBoard(), createBoardCommentRequest, isLeader)); + BoardComment boardComment = boardCommentSaveService.saveBoardComment(BoardCommentMapper.toBoardComment(data.getTeamMember(), data.getBoard(), createBoardCommentRequest, isLeader)); // 2. 게시글 댓글 개수 증가 data.getBoard().incrComNum(); return new CreateBoardCommentResponse(boardComment.getBoardCommentId()); diff --git a/src/main/java/com/moing/backend/domain/boardRead/application/mapper/BoardReadMapper.java b/src/main/java/com/moing/backend/domain/boardRead/application/mapper/BoardReadMapper.java index 740e6b1a..9f58858c 100644 --- a/src/main/java/com/moing/backend/domain/boardRead/application/mapper/BoardReadMapper.java +++ b/src/main/java/com/moing/backend/domain/boardRead/application/mapper/BoardReadMapper.java @@ -8,7 +8,7 @@ @Component public class BoardReadMapper { - public BoardRead toBoardRead(Team team, Member member){ + public static BoardRead toBoardRead(Team team, Member member){ BoardRead boardRead=new BoardRead(); boardRead.updateTeam(team); boardRead.updateMember(member); diff --git a/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUseCase.java b/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUseCase.java index d1146dd9..efb39fc1 100644 --- a/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardRead/application/service/CreateBoardReadUseCase.java @@ -16,11 +16,10 @@ @RequiredArgsConstructor public class CreateBoardReadUseCase { - private final BoardReadMapper boardReadMapper; private final BoardReadSaveService boardReadSaveService; public void createBoardRead(Team team, Member member, Board board){ - BoardRead boardRead = boardReadMapper.toBoardRead(team, member); + BoardRead boardRead = BoardReadMapper.toBoardRead(team, member); boardReadSaveService.saveBoardRead(board, boardRead); } } diff --git a/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java b/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java index e00f121e..e6c2c83d 100644 --- a/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java +++ b/src/main/java/com/moing/backend/domain/history/application/mapper/AlarmHistoryMapper.java @@ -16,7 +16,7 @@ @RequiredArgsConstructor public class AlarmHistoryMapper { - public AlarmHistory toAlarmHistory(AlarmType type, String path, String idInfo, Long receiverId, String title, String body, String name){ + public static AlarmHistory toAlarmHistory(AlarmType type, String path, String idInfo, Long receiverId, String title, String body, String name){ return AlarmHistory.builder() .type(type) .path(path) @@ -50,7 +50,7 @@ public static List getMemberIds(List memberIdAndTokens) .collect(Collectors.toList()); } - public List getAlarmHistories(String idInfo, List memberIds, String title, String body, String teamName, AlarmType alarmType, String path) { + public static List getAlarmHistories(String idInfo, List memberIds, String title, String body, String teamName, AlarmType alarmType, String path) { return memberIds.stream() .map(memberId -> toAlarmHistory(alarmType, path, idInfo, memberId, title, body, teamName)) .collect(Collectors.toList()); diff --git a/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java index 0831b3b8..ab386647 100644 --- a/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java +++ b/src/main/java/com/moing/backend/domain/history/application/service/SaveMultiAlarmHistoryUseCase.java @@ -14,12 +14,11 @@ @RequiredArgsConstructor public class SaveMultiAlarmHistoryUseCase { - private final AlarmHistoryMapper alarmHistoryMapper; private final AlarmHistorySaveService alarmHistorySaveService; @Async public void saveAlarmHistories(List memberIds, String idInfo, String title, String body, String name, AlarmType alarmType, String path) { - List alarmHistories = alarmHistoryMapper.getAlarmHistories(idInfo, memberIds, title, body, name, alarmType, path); + List alarmHistories = AlarmHistoryMapper.getAlarmHistories(idInfo, memberIds, title, body, name, alarmType, path); alarmHistorySaveService.saveAlarmHistories(alarmHistories); } } diff --git a/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java index 61030af7..90f1a63d 100644 --- a/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java +++ b/src/main/java/com/moing/backend/domain/history/application/service/SaveSingleAlarmHistoryUseCase.java @@ -12,12 +12,11 @@ @RequiredArgsConstructor public class SaveSingleAlarmHistoryUseCase { - private final AlarmHistoryMapper alarmHistoryMapper; private final AlarmHistorySaveService alarmHistorySaveService; @Async public void saveAlarmHistory(Long memberId, String idInfo, String title, String body, String name, AlarmType alarmType, String path) { - AlarmHistory alarmHistory = alarmHistoryMapper.toAlarmHistory(alarmType, path, idInfo, memberId, title, body, name); + AlarmHistory alarmHistory = AlarmHistoryMapper.toAlarmHistory(alarmType, path, idInfo, memberId, title, body, name); alarmHistorySaveService.saveAlarmHistory(alarmHistory); } } diff --git a/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java b/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java index 84ceea6e..8b20e694 100644 --- a/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java +++ b/src/main/java/com/moing/backend/domain/member/application/mapper/MemberMapper.java @@ -11,39 +11,36 @@ @Component public class MemberMapper { - public Member createKakaoMember(KakaoUserResponse kakaoUserResponse) { - Member newMember = Member.builder() + public static Member createKakaoMember(KakaoUserResponse kakaoUserResponse) { + + return Member.builder() .socialId(SocialProvider.KAKAO + "@" + kakaoUserResponse.getId()) .provider(SocialProvider.KAKAO) .email(kakaoUserResponse.getKakaoAccount().getEmail()) .role(Role.USER) .registrationStatus(RegistrationStatus.UNCOMPLETED) .build(); - - return newMember; } - public Member createAppleMember(String socialId, String email) { - Member newMember = Member.builder() + public static Member createAppleMember(String socialId, String email) { + + return Member.builder() .socialId(SocialProvider.APPLE + "@" + socialId) .provider(SocialProvider.APPLE) .email(email) .role(Role.USER) .registrationStatus(RegistrationStatus.UNCOMPLETED) .build(); - - return newMember; } - public Member createGoogleMember(GoogleUserResponse googleUserResponse){ - Member newMember= Member.builder() + public static Member createGoogleMember(GoogleUserResponse googleUserResponse){ + + return Member.builder() .socialId(SocialProvider.GOOGLE + "@" + googleUserResponse.getSub()) .provider(SocialProvider.GOOGLE) .email(googleUserResponse.getEmail()) .role(Role.USER) .registrationStatus(RegistrationStatus.UNCOMPLETED) .build(); - - return newMember; } } diff --git a/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java b/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java index fd09f4ed..65fd7992 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java @@ -13,7 +13,7 @@ @RequiredArgsConstructor public class MyPageMapper { - public GetMyPageResponse toGetMyPageResponse(Member member, List categories, List blocks) { + public static GetMyPageResponse toGetMyPageResponse(Member member, List categories, List blocks) { return GetMyPageResponse.builder() .profileImage(member.getProfileImage()) .nickName(member.getNickName()) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java index 3e1db9b4..c86e9488 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java @@ -20,16 +20,15 @@ public class GetMyPageUseCase { private final MemberGetService memberGetService; private final TeamGetService teamGetService; - private final MyPageMapper myPageMapper; @Transactional(readOnly = true) public GetMyPageResponse getMyPageResponse(String socialId) { Member member = memberGetService.getMemberBySocialId(socialId); List getMyPageTeamBlocks = teamGetService.getMyPageTeamBlockByMemberId(member.getMemberId()); - return myPageMapper.toGetMyPageResponse(member, calculateCategory(getMyPageTeamBlocks), getMyPageTeamBlocks); + return MyPageMapper.toGetMyPageResponse(member, calculateCategory(getMyPageTeamBlocks), getMyPageTeamBlocks); } - private List calculateCategory(List getMyPageTeamBlocks) { + private static List calculateCategory(List getMyPageTeamBlocks) { return getMyPageTeamBlocks.stream() .map(GetMyPageTeamBlock::getCategory) .distinct() diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java index d81edcba..7d950dc7 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java @@ -24,7 +24,6 @@ public class GetTeamUseCase { private final TeamGetService teamGetService; private final BoardGetService boardGetService; private final TeamMemberGetService teamMemberGetService; - private final TeamMapper teamMapper; public GetTeamResponse getTeam(String socialId) { Member member = memberGetService.getMemberBySocialId(socialId); @@ -36,12 +35,12 @@ public GetTeamDetailResponse getTeamDetailResponse(String socialId, Long teamId) Integer boardNum = boardGetService.getUnReadBoardNum(teamId, member.getMemberId()); List teamMemberInfoList = teamMemberGetService.getTeamMemberInfo(teamId); Team team = teamGetService.getTeamByTeamId(teamId); - return teamMapper.toTeamDetailResponse(member.getMemberId(), team, boardNum, teamMemberInfoList); + return TeamMapper.toTeamDetailResponse(member.getMemberId(), team, boardNum, teamMemberInfoList); } public GetCurrentStatusResponse getCurrentStatus(Long teamId) { Team team=teamGetService.getTeamByTeamId(teamId); - return teamMapper.toCurrentStatusResponse(team); + return TeamMapper.toCurrentStatusResponse(team); } public Page getNewTeam(String dateSort, Pageable pageable) { diff --git a/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java index 7176ca7a..47d85194 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/ReviewTeamUseCase.java @@ -18,7 +18,6 @@ public class ReviewTeamUseCase { private final TeamGetService teamGetService; - private final TeamMapper teamMapper; private final MissionQueryService missionQueryService; private final CheckLeaderUseCase checkLeaderUseCase; private final MemberGetService memberGetService; @@ -27,6 +26,6 @@ public ReviewTeamResponse reviewTeam(String socialId, Long teamId){ Team team=teamGetService.getTeamByTeamId(teamId); Member member=memberGetService.getMemberBySocialId(socialId); boolean isLeader=checkLeaderUseCase.isTeamLeader(member, team); - return teamMapper.toReviewTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()),team, isLeader, member.getNickName()); + return TeamMapper.toReviewTeamResponse(missionQueryService.findMissionsCountByTeam(team.getTeamId()),team, isLeader, member.getNickName()); } } From b15ff03ffe502907d5fc16d7afa713e2efa80242 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 28 Jan 2024 04:20:25 +0900 Subject: [PATCH 466/619] =?UTF-8?q?MNG-01=20fix:=20=EC=86=8C=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=20=EC=8A=B9=EC=9D=B8=20=EC=BD=94=EB=93=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ApproveTeamUseCase.java | 37 ------------ .../presentation/AdminTeamController.java | 60 ------------------- 2 files changed, 97 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java delete mode 100644 src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java diff --git a/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java deleted file mode 100644 index 51b8a1db..00000000 --- a/src/main/java/com/moing/backend/domain/team/application/service/ApproveTeamUseCase.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.moing.backend.domain.team.application.service; - -import com.moing.backend.domain.history.domain.entity.AlarmType; -import com.moing.backend.domain.team.application.dto.response.GetLeaderInfoResponse; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.team.domain.service.TeamUpdateService; -import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; -import lombok.RequiredArgsConstructor; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; -import java.util.List; - -import static com.moing.backend.domain.history.domain.entity.PagePath.HOME_PATH; -import static com.moing.backend.global.config.fcm.constant.ApproveTeamMessage.APPROVE_TEAM_MESSAGE; - -@Service -@RequiredArgsConstructor -@Transactional -public class ApproveTeamUseCase { - - private final TeamUpdateService teamUpdateService; - private final TeamGetService teamGetService; - private final ApplicationEventPublisher eventPublisher; - - public void approveTeams(List teamIds){ - teamUpdateService.updateTeamStatus(true, teamIds); - List leaderInfos=teamGetService.getLeaderInfoResponses(teamIds); - for(GetLeaderInfoResponse info: leaderInfos){ - String title=APPROVE_TEAM_MESSAGE.title(info.getLeaderName(), info.getTeamName()); - String body= APPROVE_TEAM_MESSAGE.body(); - -// eventPublisher.publishEvent(new SingleFcmEvent(info.getLeaderFcmToken(), title, body, info.getLeaderId(), "", info.getTeamName(), AlarmType.APPROVE_TEAM, HOME_PATH.getValue())); - } - } -} diff --git a/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java deleted file mode 100644 index 79b9421a..00000000 --- a/src/main/java/com/moing/backend/domain/team/presentation/AdminTeamController.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.moing.backend.domain.team.presentation; - -import com.moing.backend.domain.team.application.dto.response.GetNewTeamResponse; -import com.moing.backend.domain.team.application.service.ApproveTeamUseCase; -import com.moing.backend.domain.team.application.service.GetTeamUseCase; -import com.moing.backend.domain.team.application.service.RejectTeamUseCase; -import com.moing.backend.global.response.SuccessResponse; -import lombok.AllArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static com.moing.backend.domain.team.presentation.constant.TeamResponseMessage.*; - -@RestController -@AllArgsConstructor -@RequestMapping("/api/admin/team") -public class AdminTeamController { - - - private final ApproveTeamUseCase approveTeamUseCase; - private final RejectTeamUseCase rejectTeamUseCase; - private final GetTeamUseCase getTeamUseCase; - - /** - * 소모임 승인 - * [POST] api/admin/team/approval??teamIds=1,2,3 - * 작성자 : 김민수 - */ - - @PostMapping("/approval") - public ResponseEntity sendApproveAlarm(@RequestParam List teamIds) { - this.approveTeamUseCase.approveTeams(teamIds); - return ResponseEntity.ok(SuccessResponse.create(SEND_APPROVAL_ALARM_SUCCESS.getMessage())); - } - - /** - * 소모임 반려 - * [POST] api/admin/team/rejection?teamIds=1,2,3 - * 작성자: 김민수 - */ - @PostMapping("/rejection") - public ResponseEntity sendRejectionAlarm(@RequestParam List teamIds) { - this.rejectTeamUseCase.rejectTeams(teamIds); - return ResponseEntity.ok(SuccessResponse.create(SEND_REJECTION_ALARM_SUCCESS.getMessage())); - } - - /** - * 소모임 전체 조회 - */ - @GetMapping - public ResponseEntity>> getNewTeam(@RequestParam(value = "dateSort", defaultValue = "asc") String dateSort, - Pageable pageable) { - return ResponseEntity.ok(SuccessResponse.create(GET_NEW_TEAM_SUCCESS.getMessage(), this.getTeamUseCase.getNewTeam(dateSort, pageable))); - } - -} From 1dbb2cea0dcb291ff4fff1329b0b83ff1d5f09cf Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 29 Jan 2024 18:11:53 +0900 Subject: [PATCH 467/619] =?UTF-8?q?MNG-01=20fix:=20synchronized=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/service/BoardReadSaveService.java | 10 ++++------ .../domain/team/application/mapper/TeamMapper.java | 10 +++++----- .../domain/service/TeamMemberSaveService.java | 14 ++++++-------- .../application/mapper/TeamScoreMapper.java | 2 +- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java b/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java index 563cc991..2ea4112e 100644 --- a/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java +++ b/src/main/java/com/moing/backend/domain/boardRead/domain/service/BoardReadSaveService.java @@ -18,13 +18,11 @@ public class BoardReadSaveService { public void saveBoardRead(Board board, BoardRead boardRead) { - synchronized (this) { - List existingBoardReads = boardReadRepository.findBoardReadByBoardAndMemberAndTeam(board, boardRead.getMember(), boardRead.getTeam()); + List existingBoardReads = boardReadRepository.findBoardReadByBoardAndMemberAndTeam(board, boardRead.getMember(), boardRead.getTeam()); - if (existingBoardReads.isEmpty()) { - boardRead.updateBoard(board); - boardReadRepository.save(boardRead); - } + if (existingBoardReads.isEmpty()) { + boardRead.updateBoard(board); + boardReadRepository.save(boardRead); } } } diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index 081a39a2..6f7a8d98 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -16,7 +16,7 @@ @Component public class TeamMapper { - public Team createTeam(CreateTeamRequest createTeamRequest, Member member) { + public static Team createTeam(CreateTeamRequest createTeamRequest, Member member) { return Team.builder() .category(Enum.valueOf(Category.class, createTeamRequest.getCategory())) .name(createTeamRequest.getName()) @@ -30,7 +30,7 @@ public Team createTeam(CreateTeamRequest createTeamRequest, Member member) { .build(); } - public GetTeamDetailResponse toTeamDetailResponse(Long memberId, Team team, Integer boardNum, List teamMemberInfoList) { + public static GetTeamDetailResponse toTeamDetailResponse(Long memberId, Team team, Integer boardNum, List teamMemberInfoList) { TeamInfo teamInfo = new TeamInfo(team.isDeleted(), team.getDeletionTime(), team.getName(), teamMemberInfoList.size(), team.getCategory(), team.getIntroduction(), memberId, teamMemberInfoList); return GetTeamDetailResponse.builder() .boardNum(boardNum) @@ -38,7 +38,7 @@ public GetTeamDetailResponse toTeamDetailResponse(Long memberId, Team team, Inte .build(); } - public ReviewTeamResponse toReviewTeamResponse(Long numOfMission, Team team, boolean isLeader, String memberName){ + public static ReviewTeamResponse toReviewTeamResponse(Long numOfMission, Team team, boolean isLeader, String memberName){ return ReviewTeamResponse .builder() .teamId(team.getTeamId()) @@ -52,7 +52,7 @@ public ReviewTeamResponse toReviewTeamResponse(Long numOfMission, Team team, boo .build(); } - public Long calculateDuration(LocalDateTime approvalTime) { + public static Long calculateDuration(LocalDateTime approvalTime) { ZoneId seoulZoneId = ZoneId.of("Asia/Seoul"); LocalDateTime currentDateTime = LocalDateTime.now(seoulZoneId); @@ -62,7 +62,7 @@ public Long calculateDuration(LocalDateTime approvalTime) { return daysBetween; } - public GetCurrentStatusResponse toCurrentStatusResponse(Team team) { + public static GetCurrentStatusResponse toCurrentStatusResponse(Team team) { return GetCurrentStatusResponse.builder() .name(team.getName()) .introduction(team.getIntroduction()) diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java index a1a7090b..8aff52e7 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberSaveService.java @@ -19,14 +19,12 @@ public class TeamMemberSaveService { private final TeamMemberRepository teamMemberRepository; public void addTeamMember(Team team, Member member) { - synchronized (this) { - Optional teamMember = teamMemberRepository.findTeamMemberByTeamAndMember(team, member); - checkDeletion(team); - if (teamMember.isPresent()) { - handleExistingMember(teamMember.get()); - } else { - addNewTeamMember(team, member); - } + Optional teamMember = teamMemberRepository.findTeamMemberByTeamAndMember(team, member); + checkDeletion(team); + if (teamMember.isPresent()) { + handleExistingMember(teamMember.get()); + } else { + addNewTeamMember(team, member); } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/mapper/TeamScoreMapper.java b/src/main/java/com/moing/backend/domain/teamScore/application/mapper/TeamScoreMapper.java index 49031bc2..7b02e363 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/mapper/TeamScoreMapper.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/mapper/TeamScoreMapper.java @@ -8,7 +8,7 @@ @Component public class TeamScoreMapper { - public TeamScore mapToTeamScore(Team team) { + public static TeamScore mapToTeamScore(Team team) { return TeamScore.builder() .score(0L) .level(1L) From 3f24ce812b97389b55c7c7194a2733fe4d6fb74a Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 29 Jan 2024 18:12:22 +0900 Subject: [PATCH 468/619] =?UTF-8?q?MNG-01=20refactor:=20=ED=8C=80=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CreateTeamUseCase.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java index 027838c4..aa8d49d4 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/CreateTeamUseCase.java @@ -25,21 +25,27 @@ public class CreateTeamUseCase { private final MemberGetService memberGetService; private final TeamSaveService teamSaveService; private final TeamMemberSaveService teamMemberSaveService; - private final TeamMapper teamMapper; private final TeamScoreSaveService teamScoreSaveService; - private final TeamScoreMapper teamScoreMapper; private final ApplicationEventPublisher eventPublisher; public CreateTeamResponse createTeam(CreateTeamRequest createTeamRequest, String socialId){ Member member = memberGetService.getMemberBySocialId(socialId); - Team team=teamMapper.createTeam(createTeamRequest, member); + Team team = createAndSaveTeam(createTeamRequest, member); + publishTeamCreateEvent(team); + return new CreateTeamResponse(team.getTeamId()); + } + + private Team createAndSaveTeam(CreateTeamRequest createTeamRequest, Member member) { + Team team = TeamMapper.createTeam(createTeamRequest, member); teamSaveService.saveTeam(team); teamMemberSaveService.addTeamMember(team, member); - //====지워야 함 (테스트 용)===== - team.approveTeam(); - //====지워야 함 (테스트 용)===== - teamScoreSaveService.save(teamScoreMapper.mapToTeamScore(team)); // 팀스코어 엔티티 생성 + team.approveTeam(); // 승인 처리 + teamScoreSaveService.save(TeamScoreMapper.mapToTeamScore(team)); + return team; + } + + private void publishTeamCreateEvent(Team team) { eventPublisher.publishEvent(new TeamCreateEvent(team.getName(), team.getLeaderId())); - return new CreateTeamResponse(team.getTeamId()); } } + From d049dc06652596c5192d7e930bbce8d055663f2d Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 29 Jan 2024 18:32:50 +0900 Subject: [PATCH 469/619] =?UTF-8?q?MNG-02=20fix:=20=ED=8C=80=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=95=8C=EB=A6=BC=20=EC=9A=B4=EC=98=81=20=EA=B3=84?= =?UTF-8?q?=EC=A0=95=EC=97=90=EC=84=9C=EB=A7=8C=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EA=B0=80=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/global/config/slack/team/TeamCreateHandler.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java b/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java index 34bcad01..0481017d 100644 --- a/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java +++ b/src/main/java/com/moing/backend/global/config/slack/team/TeamCreateHandler.java @@ -3,12 +3,14 @@ import com.moing.backend.global.config.slack.team.dto.TeamCreateEvent; import com.moing.backend.global.config.slack.util.WebhookUtil; import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Profile; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @RequiredArgsConstructor @Component +@Profile("prod") public class TeamCreateHandler { private final WebhookUtil webhookUtil; From 2671376ac70e3f77b2a0121bcfe1bf990debec97 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 29 Jan 2024 18:54:28 +0900 Subject: [PATCH 470/619] =?UTF-8?q?MNG-02=20fix:=20=EC=95=8C=EB=A6=BC?= =?UTF-8?q?=EC=84=BC=ED=84=B0=EC=97=90=EC=84=9C=20=ED=91=B8=EC=8B=9C?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=EC=9D=84=20=ED=81=B4=EB=A6=AD=ED=96=88?= =?UTF-8?q?=EC=9D=84=20=EB=95=8C=20=EC=9D=B4=EB=8F=99=ED=95=98=EA=B2=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/fcm/service/FcmService.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java index 37983a5c..16ad947e 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java +++ b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java @@ -17,7 +17,9 @@ import javax.transaction.Transactional; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Service @Transactional @@ -55,16 +57,20 @@ public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { .build()) .build(); + Map additionalData = new HashMap<>(); + additionalData.put("path", toSingleRequest.getPath()); + additionalData.put("idInfo", toSingleRequest.getIdInfo()); + Message message = Message.builder() .setToken(toSingleRequest.getRegistrationToken()) .setNotification(notification) .setAndroidConfig(androidConfig) // Applying Android configuration .setApnsConfig(apnsConfig) // Applying APNs configuration + .putAllData(additionalData) .build(); try { String response = firebaseMessaging.send(message); -// saveSingleAlarmHistoryUseCase.saveAlarmHistory(toSingleRequest.getMemberId(), toSingleRequest.getIdInfo(), toSingleRequest.getTitle(), toSingleRequest.getBody(), toSingleRequest.getName(), toSingleRequest.getAlarmType(), toSingleRequest.getPath()); return new SingleResponse(response); } catch (FirebaseMessagingException e) { throw handleException(e); @@ -103,11 +109,16 @@ public MultiResponse sendMultipleDevices(MultiRequest toMultiRequest) { .build()) .build(); + Map additionalData = new HashMap<>(); + additionalData.put("path", toMultiRequest.getPath()); + additionalData.put("idInfo", toMultiRequest.getIdInfo()); + MulticastMessage message = MulticastMessage.builder() .addAllTokens(fcmTokens) .setNotification(notification) .setAndroidConfig(androidConfig) // Applying Android configuration .setApnsConfig(apnsConfig) // Applying APNs configuration + .putAllData(additionalData) .build(); try { From fde64d0cce6e1f3b3c673030a321b98c73dee8bb Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 30 Jan 2024 11:16:51 +0900 Subject: [PATCH 471/619] =?UTF-8?q?MNG-02=20refactor:=20fcm=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=B6=94=EC=83=81=ED=99=94=EA=B2=8C=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MultiAlarmEventUseCase.java | 31 ++ .../application/SingleAlarmEventUseCase.java | 29 ++ .../service/FireThrowAlarmUseCase.java | 4 - .../service/MissionRemindAlarmUseCase.java | 14 +- .../fcm/exception/ExceptionHandler.java | 25 ++ .../global/config/fcm/service/FcmService.java | 348 +++++++++--------- .../config/fcm/service/MessageSender.java | 5 + .../fcm/service/MultiMessageSender.java | 100 +++++ .../fcm/service/SingleMessageSender.java | 73 ++++ .../config/fcm/util/FcmMessageUtil.java | 88 ++--- 10 files changed, 486 insertions(+), 231 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/alarm/application/MultiAlarmEventUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/alarm/application/SingleAlarmEventUseCase.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/exception/ExceptionHandler.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/service/MessageSender.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/service/MultiMessageSender.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/service/SingleMessageSender.java diff --git a/src/main/java/com/moing/backend/domain/alarm/application/MultiAlarmEventUseCase.java b/src/main/java/com/moing/backend/domain/alarm/application/MultiAlarmEventUseCase.java new file mode 100644 index 00000000..f9eed763 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/alarm/application/MultiAlarmEventUseCase.java @@ -0,0 +1,31 @@ +package com.moing.backend.domain.alarm.application; + +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; +import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.service.MultiMessageSender; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + + +@Component +@RequiredArgsConstructor +public class MultiAlarmEventUseCase { + + private final MultiMessageSender multiMessageSender; + private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; + + @Async + @EventListener + public void onMultiAlarmEvent(MultiFcmEvent event) { + if (event.getIdAndTokensByPush().isPresent() && !event.getIdAndTokensByPush().get().isEmpty()) { + multiMessageSender.send(new MultiRequest(event.getIdAndTokensByPush().get(), event.getTitle(), event.getBody(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); + } + if (event.getIdAndTokensBySave().isPresent() && !event.getIdAndTokensBySave().get().isEmpty()) { + saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(event.getIdAndTokensBySave().get()), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); + } + } +} diff --git a/src/main/java/com/moing/backend/domain/alarm/application/SingleAlarmEventUseCase.java b/src/main/java/com/moing/backend/domain/alarm/application/SingleAlarmEventUseCase.java new file mode 100644 index 00000000..514d64fb --- /dev/null +++ b/src/main/java/com/moing/backend/domain/alarm/application/SingleAlarmEventUseCase.java @@ -0,0 +1,29 @@ +package com.moing.backend.domain.alarm.application; + +import com.moing.backend.domain.history.application.service.SaveSingleAlarmHistoryUseCase; +import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; +import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +import com.moing.backend.global.config.fcm.service.SingleMessageSender; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + + +@Component +@RequiredArgsConstructor +public class SingleAlarmEventUseCase { + + private final SingleMessageSender singleMessageSender; + private final SaveSingleAlarmHistoryUseCase saveSingleAlarmHistoryUseCase; + + @Async + @EventListener + public void onSingleAlarmEvent(SingleFcmEvent event) { + if (event.getMember().isFirePush() && !event.getMember().isSignOut()) { //알림 on, 로그아웃 안함 + singleMessageSender.send(new SingleRequest(event.getMember().getFcmToken(), event.getTitle(), event.getBody(), event.getMember().getMemberId(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); + } + saveSingleAlarmHistoryUseCase.saveAlarmHistory(event.getMember().getMemberId(), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); + } + +} diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java index c76c180b..03b2d1bb 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -5,9 +5,7 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; -import com.moing.backend.global.config.fcm.service.FcmService; import lombok.RequiredArgsConstructor; import net.minidev.json.JSONObject; import org.springframework.context.ApplicationEventPublisher; @@ -24,9 +22,7 @@ @RequiredArgsConstructor public class FireThrowAlarmUseCase { - private final FcmService fcmService; private final ApplicationEventPublisher eventPublisher; - private final TeamMemberGetService teamMemberGetService; public void sendFireThrowAlarm(Member throwMember, Member receiveMember, Team team, Mission mission) { diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index dd0a0e8f..5bcfa309 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -6,16 +6,12 @@ import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveScheduleQueryService; -import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; -import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; import com.moing.backend.global.config.fcm.dto.request.MultiRequest; -import com.moing.backend.global.config.fcm.service.FcmService; +import com.moing.backend.global.config.fcm.service.MultiMessageSender; import lombok.RequiredArgsConstructor; -import net.minidev.json.JSONObject; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; @@ -37,7 +33,7 @@ public class MissionRemindAlarmUseCase { private final MissionQueryService missionQueryService; private final ApplicationEventPublisher eventPublisher; - private final FcmService fcmService; + private final MultiMessageSender multiMessageSender; private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; String REMIND_NAME = "미션 리마인드"; @@ -58,7 +54,7 @@ public Boolean sendRemindMissionAlarm() { // "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { - fcmService.sendMultipleDevices(new MultiRequest(pushMemberIdAndToken.get(), title,message, "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + multiMessageSender.send(new MultiRequest(pushMemberIdAndToken.get(), title, message, "", REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); } if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()),"",title,message,REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); @@ -108,7 +104,7 @@ public Boolean sendRepeatMissionRemindOnSunday() { Optional> pushMemberIdAndToken = isPushMemberIdAndToken(repeatMissionByStatus); if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { - fcmService.sendMultipleDevices(new MultiRequest(pushMemberIdAndToken.get(), title,message, "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + multiMessageSender.send(new MultiRequest(pushMemberIdAndToken.get(), title, message, "", REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); } if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); @@ -130,7 +126,7 @@ public Boolean sendRepeatMissionRemindOnMonday() { Optional> pushMemberIdAndToken = isPushMemberIdAndToken(repeatMissionByStatus); if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { - fcmService.sendMultipleDevices(new MultiRequest(pushMemberIdAndToken.get(), title,message, "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + multiMessageSender.send(new MultiRequest(pushMemberIdAndToken.get(), title, message, "", REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); } if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); diff --git a/src/main/java/com/moing/backend/global/config/fcm/exception/ExceptionHandler.java b/src/main/java/com/moing/backend/global/config/fcm/exception/ExceptionHandler.java new file mode 100644 index 00000000..b495c41a --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/exception/ExceptionHandler.java @@ -0,0 +1,25 @@ +package com.moing.backend.global.config.fcm.exception; + +import com.google.firebase.messaging.FirebaseMessagingException; + +public class ExceptionHandler { + + public static NotificationException handleFirebaseMessagingException(FirebaseMessagingException e) { + String errorCode = e.getErrorCode().name(); + String errorMessage = e.getMessage(); + + switch (errorCode) { + case "INVALID_ARGUMENT": + return new NotificationException("올바르지 않은 인자 값입니다: " + errorMessage); + case "NOT_FOUND": + return new NotificationException("등록 토큰이 유효하지 않거나, 주제(Topic)가 존재하지 않습니다: " + errorMessage); + case "UNREGISTERED": + return new NotificationException("해당 주제(Topic)의 구독이 해지되었습니다: " + errorMessage); + case "UNAVAILABLE": + return new NotificationException("서비스를 사용할 수 없습니다: " + errorMessage); + default: + return new NotificationException("메시지 전송에 실패했습니다: " + errorMessage); + } + } +} + diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java index 16ad947e..6deaf58d 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java +++ b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java @@ -1,174 +1,174 @@ -package com.moing.backend.global.config.fcm.service; - -import com.google.firebase.messaging.*; -import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; -import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; -import com.moing.backend.domain.history.application.service.SaveSingleAlarmHistoryUseCase; -import com.moing.backend.global.config.fcm.dto.request.MultiRequest; -import com.moing.backend.global.config.fcm.dto.request.SingleRequest; -import com.moing.backend.global.config.fcm.dto.response.MultiResponse; -import com.moing.backend.global.config.fcm.dto.response.SingleResponse; -import com.moing.backend.global.config.fcm.exception.NotificationException; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.retry.annotation.Backoff; -import org.springframework.retry.annotation.Retryable; -import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Service -@Transactional -@RequiredArgsConstructor -@Slf4j -public class FcmService { - - private final FirebaseMessaging firebaseMessaging; - @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) - public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { - - Notification notification = Notification.builder() - .setTitle(toSingleRequest.getTitle()) - .setBody(toSingleRequest.getBody()) - .build(); - - // Android Configuration - AndroidConfig androidConfig = AndroidConfig.builder() - .setPriority(AndroidConfig.Priority.HIGH) - .setNotification(AndroidNotification.builder() - .setChannelId("FCM_Channel") - .setTitle(toSingleRequest.getTitle()) - .setBody(toSingleRequest.getBody()) - .build()) - .build(); - - // APNs Configuration - ApnsConfig apnsConfig = ApnsConfig.builder() - .setAps(Aps.builder() - .setCategory("YOUR_CATEGORY") // Replace with your category - .setAlert(ApsAlert.builder() - .setTitle(toSingleRequest.getTitle()) - .setBody(toSingleRequest.getBody()) - .build()) - .build()) - .build(); - - Map additionalData = new HashMap<>(); - additionalData.put("path", toSingleRequest.getPath()); - additionalData.put("idInfo", toSingleRequest.getIdInfo()); - - Message message = Message.builder() - .setToken(toSingleRequest.getRegistrationToken()) - .setNotification(notification) - .setAndroidConfig(androidConfig) // Applying Android configuration - .setApnsConfig(apnsConfig) // Applying APNs configuration - .putAllData(additionalData) - .build(); - - try { - String response = firebaseMessaging.send(message); - return new SingleResponse(response); - } catch (FirebaseMessagingException e) { - throw handleException(e); - } - } - - - @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) - public MultiResponse sendMultipleDevices(MultiRequest toMultiRequest) { - - - List fcmTokens = AlarmHistoryMapper.getFcmTokens(toMultiRequest.getMemberIdAndTokens()); - Notification notification = Notification.builder() - .setTitle(toMultiRequest.getTitle()) - .setBody(toMultiRequest.getBody()) - .build(); - - // Android Configuration - AndroidConfig androidConfig = AndroidConfig.builder() - .setPriority(AndroidConfig.Priority.HIGH) - .setNotification(AndroidNotification.builder() - .setChannelId("FCM_Channel") - .setTitle(toMultiRequest.getTitle()) - .setBody(toMultiRequest.getBody()) - .build()) - .build(); - - // APNs Configuration - ApnsConfig apnsConfig = ApnsConfig.builder() - .setAps(Aps.builder() - .setCategory("YOUR_CATEGORY") // Replace with your category - .setAlert(ApsAlert.builder() - .setTitle(toMultiRequest.getTitle()) - .setBody(toMultiRequest.getBody()) - .build()) - .build()) - .build(); - - Map additionalData = new HashMap<>(); - additionalData.put("path", toMultiRequest.getPath()); - additionalData.put("idInfo", toMultiRequest.getIdInfo()); - - MulticastMessage message = MulticastMessage.builder() - .addAllTokens(fcmTokens) - .setNotification(notification) - .setAndroidConfig(androidConfig) // Applying Android configuration - .setApnsConfig(apnsConfig) // Applying APNs configuration - .putAllData(additionalData) - .build(); - - try { - BatchResponse response = firebaseMessaging.sendMulticast(message); - - - List failedTokens = new ArrayList<>(); - - if (response.getFailureCount() > 0) { - List responses = response.getResponses(); - - List memberIds = AlarmHistoryMapper.getMemberIds(toMultiRequest.getMemberIdAndTokens()); - - for (int i = 0; i < responses.size(); i++) { - if (!responses.get(i).isSuccessful()) { - // Add the failed tokens to the list - failedTokens.add(fcmTokens.get(i)); - } - } - } - - String messageString = String.format("%d messages were sent successfully.", response.getSuccessCount()); - - return new MultiResponse(messageString, failedTokens); - - } catch (FirebaseMessagingException e) { - throw handleException(e); - } - } - - - - private NotificationException handleException(FirebaseMessagingException e) { - String errorCode = e.getErrorCode().name(); - String errorMessage = e.getMessage(); - - switch (errorCode) { - case "INVALID_ARGUMENT": - return new NotificationException("올바르지 않은 인자 값입니다: " + errorMessage); - case "NOT_FOUND": - return new NotificationException("등록 토큰이 유효하지 않거나, 주제(Topic)가 존재하지 않습니다: " + errorMessage); - case "UNREGISTERED": - return new NotificationException("해당 주제(Topic)의 구독이 해지되었습니다: " + errorMessage); - case "UNAVAILABLE": - return new NotificationException("서비스를 사용할 수 없습니다: " + errorMessage); - default: - return new NotificationException("메시지 전송에 실패했습니다: " + errorMessage); - } - } - -} - - +//package com.moing.backend.global.config.fcm.service; +// +//import com.google.firebase.messaging.*; +//import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +//import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; +//import com.moing.backend.domain.history.application.service.SaveSingleAlarmHistoryUseCase; +//import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +//import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +//import com.moing.backend.global.config.fcm.dto.response.MultiResponse; +//import com.moing.backend.global.config.fcm.dto.response.SingleResponse; +//import com.moing.backend.global.config.fcm.exception.NotificationException; +//import lombok.RequiredArgsConstructor; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.retry.annotation.Backoff; +//import org.springframework.retry.annotation.Retryable; +//import org.springframework.stereotype.Service; +// +//import javax.transaction.Transactional; +//import java.util.ArrayList; +//import java.util.HashMap; +//import java.util.List; +//import java.util.Map; +// +//@Service +//@Transactional +//@RequiredArgsConstructor +//@Slf4j +//public class FcmService { +// +// private final FirebaseMessaging firebaseMessaging; +// @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) +// public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { +// +// Notification notification = Notification.builder() +// .setTitle(toSingleRequest.getTitle()) +// .setBody(toSingleRequest.getBody()) +// .build(); +// +// // Android Configuration +// AndroidConfig androidConfig = AndroidConfig.builder() +// .setPriority(AndroidConfig.Priority.HIGH) +// .setNotification(AndroidNotification.builder() +// .setChannelId("FCM_Channel") +// .setTitle(toSingleRequest.getTitle()) +// .setBody(toSingleRequest.getBody()) +// .build()) +// .build(); +// +// // APNs Configuration +// ApnsConfig apnsConfig = ApnsConfig.builder() +// .setAps(Aps.builder() +// .setCategory("YOUR_CATEGORY") // Replace with your category +// .setAlert(ApsAlert.builder() +// .setTitle(toSingleRequest.getTitle()) +// .setBody(toSingleRequest.getBody()) +// .build()) +// .build()) +// .build(); +// +// Map additionalData = new HashMap<>(); +// additionalData.put("path", toSingleRequest.getPath()); +// additionalData.put("idInfo", toSingleRequest.getIdInfo()); +// +// Message message = Message.builder() +// .setToken(toSingleRequest.getRegistrationToken()) +// .setNotification(notification) +// .setAndroidConfig(androidConfig) // Applying Android configuration +// .setApnsConfig(apnsConfig) // Applying APNs configuration +// .putAllData(additionalData) +// .build(); +// +// try { +// String response = firebaseMessaging.send(message); +// return new SingleResponse(response); +// } catch (FirebaseMessagingException e) { +// throw handleException(e); +// } +// } +// +// +// @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) +// public MultiResponse sendMultipleDevices(MultiRequest toMultiRequest) { +// +// +// List fcmTokens = AlarmHistoryMapper.getFcmTokens(toMultiRequest.getMemberIdAndTokens()); +// Notification notification = Notification.builder() +// .setTitle(toMultiRequest.getTitle()) +// .setBody(toMultiRequest.getBody()) +// .build(); +// +// // Android Configuration +// AndroidConfig androidConfig = AndroidConfig.builder() +// .setPriority(AndroidConfig.Priority.HIGH) +// .setNotification(AndroidNotification.builder() +// .setChannelId("FCM_Channel") +// .setTitle(toMultiRequest.getTitle()) +// .setBody(toMultiRequest.getBody()) +// .build()) +// .build(); +// +// // APNs Configuration +// ApnsConfig apnsConfig = ApnsConfig.builder() +// .setAps(Aps.builder() +// .setCategory("YOUR_CATEGORY") // Replace with your category +// .setAlert(ApsAlert.builder() +// .setTitle(toMultiRequest.getTitle()) +// .setBody(toMultiRequest.getBody()) +// .build()) +// .build()) +// .build(); +// +// Map additionalData = new HashMap<>(); +// additionalData.put("path", toMultiRequest.getPath()); +// additionalData.put("idInfo", toMultiRequest.getIdInfo()); +// +// MulticastMessage message = MulticastMessage.builder() +// .addAllTokens(fcmTokens) +// .setNotification(notification) +// .setAndroidConfig(androidConfig) // Applying Android configuration +// .setApnsConfig(apnsConfig) // Applying APNs configuration +// .putAllData(additionalData) +// .build(); +// +// try { +// BatchResponse response = firebaseMessaging.sendMulticast(message); +// +// +// List failedTokens = new ArrayList<>(); +// +// if (response.getFailureCount() > 0) { +// List responses = response.getResponses(); +// +// List memberIds = AlarmHistoryMapper.getMemberIds(toMultiRequest.getMemberIdAndTokens()); +// +// for (int i = 0; i < responses.size(); i++) { +// if (!responses.get(i).isSuccessful()) { +// // Add the failed tokens to the list +// failedTokens.add(fcmTokens.get(i)); +// } +// } +// } +// +// String messageString = String.format("%d messages were sent successfully.", response.getSuccessCount()); +// +// return new MultiResponse(messageString, failedTokens); +// +// } catch (FirebaseMessagingException e) { +// throw handleException(e); +// } +// } +// +// +// +// private NotificationException handleException(FirebaseMessagingException e) { +// String errorCode = e.getErrorCode().name(); +// String errorMessage = e.getMessage(); +// +// switch (errorCode) { +// case "INVALID_ARGUMENT": +// return new NotificationException("올바르지 않은 인자 값입니다: " + errorMessage); +// case "NOT_FOUND": +// return new NotificationException("등록 토큰이 유효하지 않거나, 주제(Topic)가 존재하지 않습니다: " + errorMessage); +// case "UNREGISTERED": +// return new NotificationException("해당 주제(Topic)의 구독이 해지되었습니다: " + errorMessage); +// case "UNAVAILABLE": +// return new NotificationException("서비스를 사용할 수 없습니다: " + errorMessage); +// default: +// return new NotificationException("메시지 전송에 실패했습니다: " + errorMessage); +// } +// } +// +//} +// +// diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/MessageSender.java b/src/main/java/com/moing/backend/global/config/fcm/service/MessageSender.java new file mode 100644 index 00000000..d6b73aeb --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/service/MessageSender.java @@ -0,0 +1,5 @@ +package com.moing.backend.global.config.fcm.service; + +public interface MessageSender { + void send(T request); +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/MultiMessageSender.java b/src/main/java/com/moing/backend/global/config/fcm/service/MultiMessageSender.java new file mode 100644 index 00000000..ec54e038 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/service/MultiMessageSender.java @@ -0,0 +1,100 @@ +package com.moing.backend.global.config.fcm.service; + +import com.google.firebase.messaging.*; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.dto.response.MultiResponse; +import com.moing.backend.global.config.fcm.exception.ExceptionHandler; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +@Transactional +@RequiredArgsConstructor +@Slf4j +public class MultiMessageSender implements MessageSender { + + private final FirebaseMessaging firebaseMessaging; + + @Override + @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) + public void send(MultiRequest request) { + + + List fcmTokens = AlarmHistoryMapper.getFcmTokens(request.getMemberIdAndTokens()); + Notification notification = Notification.builder() + .setTitle(request.getTitle()) + .setBody(request.getBody()) + .build(); + + // Android Configuration + AndroidConfig androidConfig = AndroidConfig.builder() + .setPriority(AndroidConfig.Priority.HIGH) + .setNotification(AndroidNotification.builder() + .setChannelId("FCM_Channel") + .setTitle(request.getTitle()) + .setBody(request.getBody()) + .build()) + .build(); + + // APNs Configuration + ApnsConfig apnsConfig = ApnsConfig.builder() + .setAps(Aps.builder() + .setCategory("YOUR_CATEGORY") // Replace with your category + .setAlert(ApsAlert.builder() + .setTitle(request.getTitle()) + .setBody(request.getBody()) + .build()) + .build()) + .build(); + + Map additionalData = new HashMap<>(); + additionalData.put("path", request.getPath()); + additionalData.put("idInfo", request.getIdInfo()); + + MulticastMessage message = MulticastMessage.builder() + .addAllTokens(fcmTokens) + .setNotification(notification) + .setAndroidConfig(androidConfig) // Applying Android configuration + .setApnsConfig(apnsConfig) // Applying APNs configuration + .putAllData(additionalData) + .build(); + + try { + BatchResponse response = firebaseMessaging.sendMulticast(message); + + + List failedTokens = new ArrayList<>(); + + if (response.getFailureCount() > 0) { + List responses = response.getResponses(); + + List memberIds = AlarmHistoryMapper.getMemberIds(request.getMemberIdAndTokens()); + + for (int i = 0; i < responses.size(); i++) { + if (!responses.get(i).isSuccessful()) { + // Add the failed tokens to the list + failedTokens.add(fcmTokens.get(i)); + } + } + } + + String messageString = String.format("%d messages were sent successfully.", response.getSuccessCount()); + + new MultiResponse(messageString, failedTokens); + + } catch (FirebaseMessagingException e) { + throw ExceptionHandler.handleFirebaseMessagingException(e); + } + } + +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/SingleMessageSender.java b/src/main/java/com/moing/backend/global/config/fcm/service/SingleMessageSender.java new file mode 100644 index 00000000..fa069c8e --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/service/SingleMessageSender.java @@ -0,0 +1,73 @@ +package com.moing.backend.global.config.fcm.service; + +import com.google.firebase.messaging.*; +import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +import com.moing.backend.global.config.fcm.dto.response.SingleResponse; +import com.moing.backend.global.config.fcm.exception.ExceptionHandler; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Retryable; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.HashMap; +import java.util.Map; + +@Service +@Transactional +@RequiredArgsConstructor +@Slf4j +public class SingleMessageSender implements MessageSender { + + private final FirebaseMessaging firebaseMessaging; + + @Override + @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) + public void send(SingleRequest request){ + Notification notification = Notification.builder() + .setTitle(request.getTitle()) + .setBody(request.getBody()) + .build(); + + // Android Configuration + AndroidConfig androidConfig = AndroidConfig.builder() + .setPriority(AndroidConfig.Priority.HIGH) + .setNotification(AndroidNotification.builder() + .setChannelId("FCM_Channel") + .setTitle(request.getTitle()) + .setBody(request.getBody()) + .build()) + .build(); + + // APNs Configuration + ApnsConfig apnsConfig = ApnsConfig.builder() + .setAps(Aps.builder() + .setCategory("YOUR_CATEGORY") // Replace with your category + .setAlert(ApsAlert.builder() + .setTitle(request.getTitle()) + .setBody(request.getBody()) + .build()) + .build()) + .build(); + + Map additionalData = new HashMap<>(); + additionalData.put("path", request.getPath()); + additionalData.put("idInfo", request.getIdInfo()); + + Message message = Message.builder() + .setToken(request.getRegistrationToken()) + .setNotification(notification) + .setAndroidConfig(androidConfig) // Applying Android configuration + .setApnsConfig(apnsConfig) // Applying APNs configuration + .putAllData(additionalData) + .build(); + + try { + String response = firebaseMessaging.send(message); + new SingleResponse(response); + } catch (FirebaseMessagingException e) { + throw ExceptionHandler.handleFirebaseMessagingException(e); + } + } +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java index 39cb3d92..7b375329 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java +++ b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java @@ -1,44 +1,44 @@ -package com.moing.backend.global.config.fcm.util; - -import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; -import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; -import com.moing.backend.domain.history.application.service.SaveSingleAlarmHistoryUseCase; -import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; -import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; -import com.moing.backend.global.config.fcm.dto.request.MultiRequest; -import com.moing.backend.global.config.fcm.dto.request.SingleRequest; -import com.moing.backend.global.config.fcm.service.FcmService; -import lombok.RequiredArgsConstructor; -import org.springframework.context.event.EventListener; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Component; - -@Component -@RequiredArgsConstructor -public class FcmMessageUtil { - - private final FcmService fcmService; - private final SaveSingleAlarmHistoryUseCase saveSingleAlarmHistoryUseCase; - private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; - - @Async - @EventListener - public void onMultiFcmEvent(MultiFcmEvent event) { - if (event.getIdAndTokensByPush().isPresent() && !event.getIdAndTokensByPush().get().isEmpty()) { - fcmService.sendMultipleDevices(new MultiRequest(event.getIdAndTokensByPush().get(), event.getTitle(), event.getBody(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); - } - if (event.getIdAndTokensBySave().isPresent() && !event.getIdAndTokensBySave().get().isEmpty()) { - saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(event.getIdAndTokensBySave().get()), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); - } - } - - @Async - @EventListener - public void onSingleFcmEvent(SingleFcmEvent event) { - if (event.getMember().isFirePush() && !event.getMember().isSignOut()) { //알림 on, 로그아웃 안함 - fcmService.sendSingleDevice(new SingleRequest(event.getMember().getFcmToken(), event.getTitle(), event.getBody(), event.getMember().getMemberId(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); - } - saveSingleAlarmHistoryUseCase.saveAlarmHistory(event.getMember().getMemberId(), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); - } -} - +//package com.moing.backend.global.config.fcm.util; +// +//import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +//import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; +//import com.moing.backend.domain.history.application.service.SaveSingleAlarmHistoryUseCase; +//import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; +//import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; +//import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +//import com.moing.backend.global.config.fcm.dto.request.SingleRequest; +//import com.moing.backend.global.config.fcm.service.FcmService; +//import lombok.RequiredArgsConstructor; +//import org.springframework.context.event.EventListener; +//import org.springframework.scheduling.annotation.Async; +//import org.springframework.stereotype.Component; +// +//@Component +//@RequiredArgsConstructor +//public class FcmMessageUtil { +// +// private final FcmService fcmService; +// private final SaveSingleAlarmHistoryUseCase saveSingleAlarmHistoryUseCase; +// private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; +// +// @Async +// @EventListener +// public void onMultiFcmEvent(MultiFcmEvent event) { +// if (event.getIdAndTokensByPush().isPresent() && !event.getIdAndTokensByPush().get().isEmpty()) { +// fcmService.sendMultipleDevices(new MultiRequest(event.getIdAndTokensByPush().get(), event.getTitle(), event.getBody(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); +// } +// if (event.getIdAndTokensBySave().isPresent() && !event.getIdAndTokensBySave().get().isEmpty()) { +// saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(event.getIdAndTokensBySave().get()), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); +// } +// } +// +// @Async +// @EventListener +// public void onSingleFcmEvent(SingleFcmEvent event) { +// if (event.getMember().isFirePush() && !event.getMember().isSignOut()) { //알림 on, 로그아웃 안함 +// fcmService.sendSingleDevice(new SingleRequest(event.getMember().getFcmToken(), event.getTitle(), event.getBody(), event.getMember().getMemberId(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); +// } +// saveSingleAlarmHistoryUseCase.saveAlarmHistory(event.getMember().getMemberId(), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); +// } +//} +// From f949262e7ae1b46f5d4850ba25bf2ca1b3c6f1cf Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 1 Feb 2024 01:17:10 +0900 Subject: [PATCH 472/619] =?UTF-8?q?MNG-05=20fix:=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A4=20=EB=95=8C=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=A7=81=EC=A0=91=20=EC=9E=85=EB=A0=A5=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EA=B2=8C=20category=20enum=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/SignUpRequest.java | 9 +++-- .../service/MissionCreateUseCase.java | 2 +- .../service/MissionReadUseCase.java | 2 +- .../dto/response/GetMyPageResponse.java | 4 +-- .../dto/response/GetMyPageTeamBlock.java | 8 +++-- .../application/mapper/MyPageMapper.java | 3 +- .../application/service/GetMyPageUseCase.java | 3 +- .../dto/request/CreateTeamRequest.java | 3 -- .../dto/response/GetNewTeamResponse.java | 3 +- .../dto/response/GetTeamDetailResponse.java | 5 --- .../application/dto/response/TeamBlock.java | 5 ++- .../application/dto/response/TeamInfo.java | 3 +- .../team/application/mapper/TeamMapper.java | 3 +- .../domain/team/domain/constant/Category.java | 36 +++++++++---------- .../domain/team/domain/entity/Team.java | 4 +-- .../presentation/MypageControllerTest.java | 7 ++-- .../team/presentation/TeamControllerTest.java | 3 +- 17 files changed, 42 insertions(+), 61 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java index 6ee3836f..426b9da5 100644 --- a/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java +++ b/src/main/java/com/moing/backend/domain/auth/application/dto/request/SignUpRequest.java @@ -1,13 +1,12 @@ package com.moing.backend.domain.auth.application.dto.request; import com.moing.backend.domain.member.domain.constant.Gender; -import com.moing.backend.domain.team.domain.constant.Category; -import com.moing.backend.global.annotation.Enum; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; @Builder diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index 6186c3a5..a20d9650 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -64,7 +64,7 @@ public MissionRecommendRes getCategoryByTeam(Long teamId) { Team team = teamGetService.getTeamByTeamId(teamId); return MissionRecommendRes.builder() - .category(team.getCategory().name()) + .category(team.getCategory()) .build(); } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java index 3379903a..a195e130 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java @@ -28,7 +28,7 @@ public MissionReadRes getMission(String userSocialId, Long missionId) { public String getTeamCategory(Long teamId) { Team team = teamGetService.getTeamByTeamId(teamId); - return team.getCategory().name(); + return team.getCategory(); } } diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageResponse.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageResponse.java index 79baebbd..f4193f11 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageResponse.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageResponse.java @@ -1,7 +1,5 @@ package com.moing.backend.domain.mypage.application.dto.response; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.team.domain.constant.Category; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -18,6 +16,6 @@ public class GetMyPageResponse { private String profileImage; private String nickName; private String introduction; - private List categories=new ArrayList<>(); + private List categories=new ArrayList<>(); private List getMyPageTeamBlocks = new ArrayList<>(); } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java index fd6f6d19..ba86cc7a 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetMyPageTeamBlock.java @@ -1,7 +1,9 @@ package com.moing.backend.domain.mypage.application.dto.response; -import com.moing.backend.domain.team.domain.constant.Category; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; @Builder @AllArgsConstructor @@ -10,6 +12,6 @@ public class GetMyPageTeamBlock { private Long teamId; private String teamName; - private Category category; + private String category; private String profileImgUrl; } diff --git a/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java b/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java index 65fd7992..e638f2f3 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/mapper/MyPageMapper.java @@ -3,7 +3,6 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageResponse; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; -import com.moing.backend.domain.team.domain.constant.Category; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -13,7 +12,7 @@ @RequiredArgsConstructor public class MyPageMapper { - public static GetMyPageResponse toGetMyPageResponse(Member member, List categories, List blocks) { + public static GetMyPageResponse toGetMyPageResponse(Member member, List categories, List blocks) { return GetMyPageResponse.builder() .profileImage(member.getProfileImage()) .nickName(member.getNickName()) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java index c86e9488..51d80c77 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/GetMyPageUseCase.java @@ -5,7 +5,6 @@ import com.moing.backend.domain.mypage.application.dto.response.GetMyPageResponse; import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.mypage.application.mapper.MyPageMapper; -import com.moing.backend.domain.team.domain.constant.Category; import com.moing.backend.domain.team.domain.service.TeamGetService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -28,7 +27,7 @@ public GetMyPageResponse getMyPageResponse(String socialId) { return MyPageMapper.toGetMyPageResponse(member, calculateCategory(getMyPageTeamBlocks), getMyPageTeamBlocks); } - private static List calculateCategory(List getMyPageTeamBlocks) { + private static List calculateCategory(List getMyPageTeamBlocks) { return getMyPageTeamBlocks.stream() .map(GetMyPageTeamBlock::getCategory) .distinct() diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/request/CreateTeamRequest.java b/src/main/java/com/moing/backend/domain/team/application/dto/request/CreateTeamRequest.java index a7f3ce33..9d4734f9 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/request/CreateTeamRequest.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/request/CreateTeamRequest.java @@ -1,7 +1,5 @@ package com.moing.backend.domain.team.application.dto.request; -import com.moing.backend.domain.team.domain.constant.Category; -import com.moing.backend.global.annotation.Enum; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -16,7 +14,6 @@ @Getter public class CreateTeamRequest { @NotBlank(message = "category 를 입력해 주세요.") - @Enum(enumClass = Category.class) private String category; @NotBlank(message = "name 을 입력해 주세요.") diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetNewTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetNewTeamResponse.java index 56f85a4b..6a741135 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetNewTeamResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetNewTeamResponse.java @@ -1,6 +1,5 @@ package com.moing.backend.domain.team.application.dto.response; -import com.moing.backend.domain.team.domain.constant.Category; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -13,7 +12,7 @@ public class GetNewTeamResponse { private String teamName; - private Category category; + private String category; private String promise; private String introduction; private String profileImgUrl; diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamDetailResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamDetailResponse.java index 63af6dcb..eb671bb4 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamDetailResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamDetailResponse.java @@ -1,14 +1,9 @@ package com.moing.backend.domain.team.application.dto.response; -import com.moing.backend.domain.team.domain.constant.Category; -import com.querydsl.core.annotations.QueryProjection; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; -import java.util.ArrayList; -import java.util.List; - @Getter @Builder @AllArgsConstructor diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java index 43c76e1c..46b78bc3 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamBlock.java @@ -1,6 +1,5 @@ package com.moing.backend.domain.team.application.dto.response; -import com.moing.backend.domain.team.domain.constant.Category; import com.querydsl.core.annotations.QueryProjection; import lombok.AllArgsConstructor; import lombok.Builder; @@ -29,13 +28,13 @@ public class TeamBlock { private String profileImgUrl; @QueryProjection - public TeamBlock(Long teamId, LocalDateTime approvalTime, Integer levelOfFire, String teamName, Integer numOfMember, Category category, LocalDateTime deletionTime, String profileImgUrl) { + public TeamBlock(Long teamId, LocalDateTime approvalTime, Integer levelOfFire, String teamName, Integer numOfMember, String category, LocalDateTime deletionTime, String profileImgUrl) { this.teamId=teamId; this.duration=calculateDuration(approvalTime); this.levelOfFire=levelOfFire; this.teamName=teamName; this.numOfMember=numOfMember; - this.category=category.getMessage(); + this.category = category; this.startDate=approvalTime.toLocalDate().format(DateTimeFormatter.ofPattern("yyyy.MM.dd")); this.deletionTime=deletionTime; this.profileImgUrl = profileImgUrl; diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java index b537a398..5fb2e67e 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/TeamInfo.java @@ -1,6 +1,5 @@ package com.moing.backend.domain.team.application.dto.response; -import com.moing.backend.domain.team.domain.constant.Category; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -17,7 +16,7 @@ public class TeamInfo { private LocalDateTime deletionTime; private String teamName; //소모임 이름 private Integer numOfMember; //소모임원 수 - private Category category; //카테고리 + private String category; //카테고리 private String introduction; //소개 private Long currentUserId; //현재 유저 아이디 private List teamMemberInfoList = new ArrayList<>(); //소모임원 정보 diff --git a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java index 6f7a8d98..a7d4cd69 100644 --- a/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java +++ b/src/main/java/com/moing/backend/domain/team/application/mapper/TeamMapper.java @@ -4,7 +4,6 @@ import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; import com.moing.backend.domain.team.application.dto.response.*; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; -import com.moing.backend.domain.team.domain.constant.Category; import com.moing.backend.domain.team.domain.entity.Team; import org.springframework.stereotype.Component; @@ -18,7 +17,7 @@ public class TeamMapper { public static Team createTeam(CreateTeamRequest createTeamRequest, Member member) { return Team.builder() - .category(Enum.valueOf(Category.class, createTeamRequest.getCategory())) + .category(createTeamRequest.getCategory()) .name(createTeamRequest.getName()) .introduction(createTeamRequest.getIntroduction()) .promise(createTeamRequest.getPromise()) diff --git a/src/main/java/com/moing/backend/domain/team/domain/constant/Category.java b/src/main/java/com/moing/backend/domain/team/domain/constant/Category.java index 79f02adb..d50e7085 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/constant/Category.java +++ b/src/main/java/com/moing/backend/domain/team/domain/constant/Category.java @@ -1,18 +1,18 @@ -package com.moing.backend.domain.team.domain.constant; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum Category{ - SPORTS("스포츠/운동"), - HABIT("생활습관 개선"), - TEST("시험/취업준비"), - STUDY("스터디/공부"), - READING("독서"), - ETC("그외 자기계발"); - - private final String message; -} - +//package com.moing.backend.domain.team.domain.constant; +// +//import lombok.Getter; +//import lombok.RequiredArgsConstructor; +// +//@Getter +//@RequiredArgsConstructor +//public enum Category{ +// SPORTS("스포츠/운동"), +// HABIT("생활습관 개선"), +// TEST("시험/취업준비"), +// STUDY("스터디/공부"), +// READING("독서"), +// ETC("그외 자기계발"); +// +// private final String message; +//} +// diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java index 29e6d530..906dd2fe 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -2,7 +2,6 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.team.domain.constant.ApprovalStatus; -import com.moing.backend.domain.team.domain.constant.Category; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; import lombok.Builder; @@ -27,9 +26,8 @@ public class Team extends BaseTimeEntity { @Column(name = "team_id") private Long teamId; - @Enumerated(EnumType.STRING) @Column(nullable = false, length = 10) - private Category category; + private String category; @Column(nullable = false, length = 10) private String name; diff --git a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java index 125aa2ea..f4d06b55 100644 --- a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java @@ -8,7 +8,6 @@ import com.moing.backend.domain.mypage.application.dto.response.GetMyPageTeamBlock; import com.moing.backend.domain.mypage.application.dto.response.GetProfileResponse; import com.moing.backend.domain.mypage.application.service.*; -import com.moing.backend.domain.team.domain.constant.Category; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -117,14 +116,14 @@ public void withdraw() throws Exception { @Test public void get_mypage() throws Exception{ //given - List categoryList=new ArrayList<>(); - categoryList.add(Category.SPORTS); + List categoryList=new ArrayList<>(); + categoryList.add("SPORTS"); List getMyPageTeamBlocks=new ArrayList<>(); GetMyPageTeamBlock blocks= GetMyPageTeamBlock.builder() .teamId(1L) .teamName("소모임이름") - .category(Category.SPORTS) + .category("SPORTS") .profileImgUrl("프로필 이미지 url") .build(); getMyPageTeamBlocks.add(blocks); diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 96b0cae6..7ccf996b 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -5,7 +5,6 @@ import com.moing.backend.domain.team.application.dto.request.UpdateTeamRequest; import com.moing.backend.domain.team.application.dto.response.*; import com.moing.backend.domain.team.application.service.*; -import com.moing.backend.domain.team.domain.constant.Category; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -195,7 +194,7 @@ public void get_team_detail() throws Exception { .deletionTime(LocalDateTime.now()) .teamName("소모임 이름") .numOfMember(1) - .category(Category.ETC) + .category("ETC") .introduction("소모임 소개글") .currentUserId(1L) .teamMemberInfoList(teamMemberInfoList).build(); From 214f8c82fdbfcc4ec598204814ac4c4b819a0355 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 1 Feb 2024 02:20:35 +0900 Subject: [PATCH 473/619] =?UTF-8?q?MNG-06=20feat:=20=EC=9C=A0=EC=A0=80?= =?UTF-8?q?=EA=B0=80=20=EC=9E=91=EC=84=B1=ED=95=9C=20=EA=B3=B5=EC=A7=80/?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=EC=97=90=20=EB=8C=93=EA=B8=80?= =?UTF-8?q?=EC=9D=B4=20=EB=8B=AC=EB=A6=AC=EB=A9=B4,=20=ED=95=B4=EB=8B=B9?= =?UTF-8?q?=20=EC=9C=A0=EC=A0=80=EC=97=90=EA=B2=8C=20=ED=91=B8=EC=8B=9C=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=EC=9D=84=20=EB=B0=9C=EC=86=A1=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CreateBoardCommentUseCase.java | 4 +- .../service/SendCommentAlarmUseCase.java | 53 +++++++++++++++++++ .../fcm/constant/NewCommentUploadMessage.java | 23 ++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java create mode 100644 src/main/java/com/moing/backend/global/config/fcm/constant/NewCommentUploadMessage.java diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java index 39b1f4ea..3530d8a5 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java @@ -21,7 +21,7 @@ public class CreateBoardCommentUseCase { private final BoardCommentSaveService boardCommentSaveService; private final BaseBoardService baseBoardService; private final CheckLeaderUseCase checkLeaderUseCase; - + private final SendCommentAlarmUseCase sendCommentAlarmUseCase; /** * 게시글 댓글 생성 */ @@ -32,6 +32,8 @@ public CreateBoardCommentResponse createBoardComment(String socialId, Long teamI BoardComment boardComment = boardCommentSaveService.saveBoardComment(BoardCommentMapper.toBoardComment(data.getTeamMember(), data.getBoard(), createBoardCommentRequest, isLeader)); // 2. 게시글 댓글 개수 증가 data.getBoard().incrComNum(); + // 3. 게시글 댓글 알림 + sendCommentAlarmUseCase.sendNewUploadAlarm(data, boardComment); return new CreateBoardCommentResponse(boardComment.getBoardCommentId()); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java new file mode 100644 index 00000000..3968c578 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java @@ -0,0 +1,53 @@ +package com.moing.backend.domain.boardComment.application.service; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.entity.PagePath; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; +import com.moing.backend.global.response.BaseBoardServiceResponse; +import lombok.RequiredArgsConstructor; +import net.minidev.json.JSONObject; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; + +import static com.moing.backend.domain.history.domain.entity.PagePath.MISSION_PATH; +import static com.moing.backend.global.config.fcm.constant.NewCommentUploadMessage.NEW_COMMENT_UPLOAD_MESSAGE; +import static com.moing.backend.global.config.fcm.constant.NewNoticeUploadMessage.NEW_NOTICE_UPLOAD_MESSAGE; + +@Service +@RequiredArgsConstructor +@Transactional +public class SendCommentAlarmUseCase { + + private final ApplicationEventPublisher eventPublisher; + + public void sendNewUploadAlarm(BaseBoardServiceResponse response, BoardComment comment) { + Member member = response.getMember(); + Team team = response.getTeam(); + Board board = response.getBoard(); + + String title = NEW_COMMENT_UPLOAD_MESSAGE.title(comment.getContent()); + String body = NEW_COMMENT_UPLOAD_MESSAGE.body(member.getNickName(),board.getTitle()); + + // 알림 보내기 + eventPublisher.publishEvent(new SingleFcmEvent(board.getTeamMember().getMember(), title, body, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); + + } + + private String createIdInfo(Long teamId, Long boardId) { + JSONObject jo = new JSONObject(); + jo.put("teamId", teamId); + jo.put("boardId", boardId); + return jo.toJSONString(); + } +} diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/NewCommentUploadMessage.java b/src/main/java/com/moing/backend/global/config/fcm/constant/NewCommentUploadMessage.java new file mode 100644 index 00000000..a71edac9 --- /dev/null +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/NewCommentUploadMessage.java @@ -0,0 +1,23 @@ +package com.moing.backend.global.config.fcm.constant; + + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum NewCommentUploadMessage { + + NEW_COMMENT_UPLOAD_MESSAGE("%s", "[%s님의 댓글] %s"); + + private final String title; + private final String body; + + public String title(String commentContent) { + return String.format(title, commentContent); + } + + public String body(String writerNickname, String boardTitle) { + return String.format(body, writerNickname, boardTitle); + } +} From 30a4a318eea67e6d0aec83c926f90350a18723e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 2 Feb 2024 17:53:00 +0900 Subject: [PATCH 474/619] chore : update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ec31b1dc..03d183bf 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ out/ ### yml ### application.yml application-local.yml +application-dev.yml .DS_Store src/main/resources/firebase-key.json From 5e82a8709053fff39669c14f8b6cfa234cda7b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 2 Feb 2024 18:05:06 +0900 Subject: [PATCH 475/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A6=89=EC=8B=9C=20=EC=8B=9C=EC=9E=91=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=A0=9C=ED=95=9C=20?= =?UTF-8?q?=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionCreateUseCase.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index a20d9650..cf6f7fde 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -15,6 +15,8 @@ import com.moing.backend.domain.mission.exception.NoMoreCreateMission; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.global.response.BaseServiceResponse; +import com.moing.backend.global.utils.BaseService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -30,26 +32,33 @@ public class MissionCreateUseCase { private final MemberGetService memberGetService; private final SendMissionCreateAlarmUseCase sendMissionCreateAlarmUseCase; + private final BaseService baseService; + public MissionCreateRes createMission(String userSocialId, Long teamId, MissionReq missionReq) { - Member member = memberGetService.getMemberBySocialId(userSocialId); - Team team = teamGetService.getTeamByTeamId(teamId); + BaseServiceResponse commonData = baseService.getCommonData(userSocialId, teamId); + Member member = commonData.getMember(); + Team team = commonData.getTeam(); - // 소모임 장 확인 + // 소모임 장 여부 확인 if (member.getMemberId().equals(team.getLeaderId())) { + Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.WAIT); - // teamRepository 변경 예정 if (mission.getType() == MissionType.REPEAT && missionQueryService.isAbleCreateRepeatMission(team.getTeamId())) { throw new NoMoreCreateMission(); } mission.setTeam(team); - missionSaveService.save(mission); - // 단일 미션 최초 1회 알림 - if (mission.getType().equals(MissionType.ONCE)) { - sendMissionCreateAlarmUseCase.sendNewMissionUploadAlarm(member, mission); + // 1. 반복미션 유예 해제 + if (mission.getType().equals(MissionType.REPEAT)) { + mission.updateStatus(MissionStatus.ONGOING); } + // 2. 미션 저장 + missionSaveService.save(mission); + + // 3. 알림 보내기 - 미션 생성 + sendMissionCreateAlarmUseCase.sendNewMissionUploadAlarm(member, mission); return MissionMapper.mapToMissionCreateRes(mission); } @@ -60,14 +69,6 @@ public MissionCreateRes createMission(String userSocialId, Long teamId, MissionR } - public MissionRecommendRes getCategoryByTeam(Long teamId) { - Team team = teamGetService.getTeamByTeamId(teamId); - - return MissionRecommendRes.builder() - .category(team.getCategory()) - .build(); - } - public Boolean getIsLeader(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); From 32915664ab884c5e3a1bcbbee90a00dfee844768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 2 Feb 2024 23:28:56 +0900 Subject: [PATCH 476/619] =?UTF-8?q?fix=20:=20=ED=95=9C=EB=B2=88=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=83=9D=EC=84=B1=20=EA=B6=8C=ED=95=9C=20=ED=95=B4?= =?UTF-8?q?=EC=A0=9C,=20=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20=EC=86=8C?= =?UTF-8?q?=EB=AA=A8=EC=9E=84=EC=9E=A5=EB=A7=8C=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EA=B0=80=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionCreateUseCase.java | 48 ++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index cf6f7fde..81d95b1b 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -28,51 +28,45 @@ public class MissionCreateUseCase { private final MissionSaveService missionSaveService; private final MissionQueryService missionQueryService; - private final TeamGetService teamGetService; - private final MemberGetService memberGetService; private final SendMissionCreateAlarmUseCase sendMissionCreateAlarmUseCase; private final BaseService baseService; - public MissionCreateRes createMission(String userSocialId, Long teamId, MissionReq missionReq) { + public MissionCreateRes createMission(String socialId, Long teamId, MissionReq missionReq) { - BaseServiceResponse commonData = baseService.getCommonData(userSocialId, teamId); + BaseServiceResponse commonData = baseService.getCommonData(socialId, teamId); Member member = commonData.getMember(); Team team = commonData.getTeam(); - // 소모임 장 여부 확인 - if (member.getMemberId().equals(team.getLeaderId())) { + Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.WAIT); + mission.setTeam(team); - Mission mission = MissionMapper.mapToMission(missionReq, member, MissionStatus.WAIT); - - if (mission.getType() == MissionType.REPEAT && missionQueryService.isAbleCreateRepeatMission(team.getTeamId())) { - throw new NoMoreCreateMission(); - } - mission.setTeam(team); - - // 1. 반복미션 유예 해제 - if (mission.getType().equals(MissionType.REPEAT)) { - mission.updateStatus(MissionStatus.ONGOING); + if (mission.getType().equals(MissionType.REPEAT)) { + // 반복 미션 생성일 경우 소모임장만 가능 + if (!(member.getMemberId().equals(team.getLeaderId()))) { + throw new NoAccessCreateMission(); + // 반복미션은 최대 2개 생성 가능 + } else if (missionQueryService.isAbleCreateRepeatMission(team.getTeamId())) { + throw new NoAccessCreateMission(); } - // 2. 미션 저장 - missionSaveService.save(mission); - - // 3. 알림 보내기 - 미션 생성 - sendMissionCreateAlarmUseCase.sendNewMissionUploadAlarm(member, mission); + // 반복미션 유예 해제 + mission.updateStatus(MissionStatus.ONGOING); - return MissionMapper.mapToMissionCreateRes(mission); - } - else{ - throw new NoAccessCreateMission(); } + // 2. 미션 저장 + missionSaveService.save(mission); + // 3. 알림 보내기 - 미션 생성 + sendMissionCreateAlarmUseCase.sendNewMissionUploadAlarm(member, mission); + return MissionMapper.mapToMissionCreateRes(mission); } public Boolean getIsLeader(String socialId, Long teamId) { - Member member = memberGetService.getMemberBySocialId(socialId); - Team team = teamGetService.getTeamByTeamId(teamId); + BaseServiceResponse commonData = baseService.getCommonData(socialId, teamId); + Member member = commonData.getMember(); + Team team = commonData.getTeam(); return member.getMemberId().equals(team.getLeaderId()); From 2dcea8cad8d28c511a15f1c456dc3de703e2d094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 2 Feb 2024 23:40:29 +0900 Subject: [PATCH 477/619] =?UTF-8?q?fix=20:=20=EC=86=8C=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=EC=9E=A5=EC=97=90=EA=B2=8C=20=EB=AF=B8=EC=85=98=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=ED=95=98=EA=B8=B0=20=EA=B6=8C=ED=95=9C=20=EB=B6=80?= =?UTF-8?q?=EC=97=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionUpdateUseCase.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index 7dc1119d..4916d151 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -11,6 +11,7 @@ import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.mission.domain.service.MissionSaveService; import com.moing.backend.domain.mission.exception.NoAccessCreateMission; +import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -43,10 +44,10 @@ public MissionReadRes updateMissionStatus(String userSocialId, Long missionId) { Member member = memberGetService.getMemberBySocialId(userSocialId); - Mission findMission = missionQueryService.findMissionById(missionId); + Team team = findMission.getTeam(); - if (findMission.getTeam().getLeaderId().equals(member.getMemberId())) { + if (team.getLeaderId().equals(member.getMemberId())) { findMission.updateStatus(MissionStatus.END); findMission.updateDueTo(LocalDateTime.now()); } else { From 4bf95aa16b59dd91be4887273caa6ed1013fbb15 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sat, 3 Feb 2024 21:25:33 +0900 Subject: [PATCH 478/619] =?UTF-8?q?MNG-06=20fix:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=95=88=EC=98=A4=EB=8A=94=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/SingleAlarmEventUseCase.java | 2 +- .../service/SendCommentAlarmUseCase.java | 19 ++++++++++--------- .../service/FireThrowAlarmUseCase.java | 2 +- .../config/fcm/dto/event/SingleFcmEvent.java | 2 ++ 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/alarm/application/SingleAlarmEventUseCase.java b/src/main/java/com/moing/backend/domain/alarm/application/SingleAlarmEventUseCase.java index 514d64fb..d2579200 100644 --- a/src/main/java/com/moing/backend/domain/alarm/application/SingleAlarmEventUseCase.java +++ b/src/main/java/com/moing/backend/domain/alarm/application/SingleAlarmEventUseCase.java @@ -20,7 +20,7 @@ public class SingleAlarmEventUseCase { @Async @EventListener public void onSingleAlarmEvent(SingleFcmEvent event) { - if (event.getMember().isFirePush() && !event.getMember().isSignOut()) { //알림 on, 로그아웃 안함 + if (event.isAlarmPush() && !event.getMember().isSignOut()) { //알림 on, 로그아웃 안함 singleMessageSender.send(new SingleRequest(event.getMember().getFcmToken(), event.getTitle(), event.getBody(), event.getMember().getMemberId(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); } saveSingleAlarmHistoryUseCase.saveAlarmHistory(event.getMember().getMemberId(), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java index 3968c578..0d8a49f9 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java @@ -2,9 +2,6 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; -import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; -import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; -import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; @@ -17,12 +14,10 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; -import java.util.List; -import java.util.Optional; -import static com.moing.backend.domain.history.domain.entity.PagePath.MISSION_PATH; +import java.util.Objects; + import static com.moing.backend.global.config.fcm.constant.NewCommentUploadMessage.NEW_COMMENT_UPLOAD_MESSAGE; -import static com.moing.backend.global.config.fcm.constant.NewNoticeUploadMessage.NEW_NOTICE_UPLOAD_MESSAGE; @Service @RequiredArgsConstructor @@ -35,13 +30,15 @@ public void sendNewUploadAlarm(BaseBoardServiceResponse response, BoardComment c Member member = response.getMember(); Team team = response.getTeam(); Board board = response.getBoard(); + Member receiver = board.getTeamMember().getMember(); String title = NEW_COMMENT_UPLOAD_MESSAGE.title(comment.getContent()); String body = NEW_COMMENT_UPLOAD_MESSAGE.body(member.getNickName(),board.getTitle()); // 알림 보내기 - eventPublisher.publishEvent(new SingleFcmEvent(board.getTeamMember().getMember(), title, body, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); - + if(checkBoardWriter(receiver, member)){ + eventPublisher.publishEvent(new SingleFcmEvent(receiver, title, body, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue(), receiver.isNewUploadPush())); + } } private String createIdInfo(Long teamId, Long boardId) { @@ -50,4 +47,8 @@ private String createIdInfo(Long teamId, Long boardId) { jo.put("boardId", boardId); return jo.toJSONString(); } + + private boolean checkBoardWriter(Member boardWriter, Member commentWriter){ + return !Objects.equals(boardWriter.getMemberId(), commentWriter.getMemberId()); + } } diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java index 03b2d1bb..ca28e88a 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -33,7 +33,7 @@ public void sendFireThrowAlarm(Member throwMember, Member receiveMember, Team te String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), randomNum); String idInfo = createIdInfo(mission.getType() == MissionType.REPEAT, mission.getTeam().getTeamId(), mission.getId()); - eventPublisher.publishEvent(new SingleFcmEvent(receiveMember, title, message, idInfo, team.getName(), AlarmType.FIRE, MISSION_PATH.getValue())); + eventPublisher.publishEvent(new SingleFcmEvent(receiveMember, title, message, idInfo, team.getName(), AlarmType.FIRE, MISSION_PATH.getValue(), receiveMember.isFirePush())); } public String getMessage(String pusher, String receiver, int num) { diff --git a/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java b/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java index 02b9ab2f..290f7e74 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java +++ b/src/main/java/com/moing/backend/global/config/fcm/dto/event/SingleFcmEvent.java @@ -19,4 +19,6 @@ public class SingleFcmEvent { private String name; private AlarmType alarmType; private String path; + private boolean isAlarmPush; + } From 0103e70b115a1984c9b373ba3baa37e333cead01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 3 Feb 2024 22:19:03 +0900 Subject: [PATCH 479/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=201=ED=9A=8C=EB=8B=B9=20=EA=B2=BD=ED=97=98?= =?UTF-8?q?=EC=B9=98=20=EC=B6=95=EC=A0=81=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EB=B3=B4=EB=84=88=EC=8A=A4=20=EC=A0=90?= =?UTF-8?q?=EC=88=98=20=EC=A0=81=EB=A6=BD=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveCreateUseCase.java | 21 ++--- .../service/MissionStateScheduleUseCase.java | 24 +---- .../service/MissionStateUseCase.java | 10 +-- .../service/TeamScoreGetUseCase.java | 46 ++++++++++ .../service/TeamScoreLogicUseCase.java | 87 ------------------ .../service/TeamScoreUpdateUseCase.java | 88 +++++++++++++++++++ .../presentation/TeamScoreController.java | 14 +-- .../presentation/TeamScoreControllerTest.java | 15 +--- 8 files changed, 155 insertions(+), 150 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java delete mode 100644 src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 2cc3df06..f79afeb1 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -19,8 +19,7 @@ import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; -import com.moing.backend.global.utils.BaseService; +import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,7 +41,7 @@ public class MissionArchiveCreateUseCase { private final MissionStateSaveService missionStateSaveService; private final MissionStateUseCase missionStateUseCase; - private final TeamScoreLogicUseCase teamScoreLogicUseCase; + private final TeamScoreUpdateUseCase teamScoreUpdateUseCase; public MissionArchiveRes createArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { @@ -50,8 +49,6 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss Long memberId = member.getMemberId(); Mission mission = missionQueryService.findMissionById(missionId); - Team team = mission.getTeam(); - MissionArchive newArchive = MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission); // 인증 완료한 미션인지 확인 @@ -63,10 +60,6 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss // 반복 미션일 경우 if (mission.getType() == MissionType.REPEAT) { - // 아직 열리지 않은 반복미션 접근 제한 - if (mission.getStatus() == MissionStatus.WAIT) { - throw new NotYetMissionArchiveException(); - } // 당일 1회 인증만 가능 if (missionArchiveQueryService.isAbleToArchiveToday(memberId, missionId)) { @@ -83,7 +76,7 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss // 한번 미션일 경우 else { - // 미션 생성 후 처음 미션 인증 시도 시 ongoing 으로 변경 + // 미션 생성 후 처음 미션 인증 시도 시 ongoing 으로 변경 -> 읽음처리 구현되면 로직 삭제 if(mission.getStatus() == MissionStatus.WAIT) { mission.updateStatus(MissionStatus.ONGOING); } @@ -94,10 +87,14 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); // 인증 후 n/n명 인증 성공 리턴값 업데이트 - missionArchiveRes.updateCount(missionArchiveQueryService.findDoneSingleArchives(missionId)); + Long doneSingleArchives = missionArchiveQueryService.findDoneSingleArchives(missionId); + missionArchiveRes.updateCount(doneSingleArchives); + } - return missionArchiveRes; + teamScoreUpdateUseCase.gainScoreByArchive(mission); + + return missionArchiveRes; } // 이 미션을 완료 했는지 diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index b3f0acb2..8322d7ec 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -5,11 +5,9 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.mission.domain.service.MissionSaveService; -import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; -import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Profile; @@ -19,7 +17,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDateTime; import java.util.List; @Slf4j @@ -37,26 +34,10 @@ public class MissionStateScheduleUseCase { private final MissionStateQueryService missionStateQueryService; private final MissionStateDeleteService missionStateDeleteService; - private final TeamScoreLogicUseCase teamScoreLogicUseCase; + private final TeamScoreUpdateUseCase teamScoreUpdateUseCase; private final SendMissionStartAlarmUseCase sendMissionStartAlarmUseCase; - /** - * 반복미션 마감 - * 일요일 마감 루틴 - */ - @Scheduled(cron = "0 59 23 * * SUN") - public void sundayRepeatMissionRoutine() { - - // 모든 진행중인 반복 미션 모아서 - List ongoingRepeatMissions = missionQueryService.findOngoingRepeatMissions(); - - // 팀 스코어 반영 ( 배치 처리 해야하는데 ) - for (Long id : ongoingRepeatMissions) { - teamScoreLogicUseCase.updateTeamScore(id); - } - } - /** * 단일 미션 마감 @@ -70,7 +51,6 @@ public void singleMissionEndRoutine() { for (Mission mission : missionByDueTo) { mission.updateStatus(MissionStatus.END); - teamScoreLogicUseCase.updateTeamScore(mission.getId()); } } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 0e70b913..9bf91010 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -6,19 +6,15 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; - @Slf4j @Service @Transactional @@ -33,7 +29,7 @@ public class MissionStateUseCase { private final MissionStateSaveService missionStateSaveService; private final MissionStateDeleteService missionStateDeleteService; - private final TeamScoreLogicUseCase teamScoreLogicUseCase; + private final TeamScoreUpdateUseCase teamScoreUpdateUseCase; /* @@ -67,7 +63,7 @@ public void updateMissionState(Member member, Mission mission, MissionArchive mi if (isAbleToEnd(mission)) { mission.updateStatus(MissionStatus.SUCCESS); - teamScoreLogicUseCase.updateTeamScore(missionId); + teamScoreUpdateUseCase.gainScoreByBonus(missionId); } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java new file mode 100644 index 00000000..83e684f8 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java @@ -0,0 +1,46 @@ +package com.moing.backend.domain.teamScore.application.service; + + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.team.domain.service.TeamSaveService; +import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; +import com.moing.backend.domain.teamScore.domain.service.TeamScoreSaveService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Service +@Transactional +@RequiredArgsConstructor +public class TeamScoreGetUseCase { + + private final TeamScoreQueryService teamScoreQueryService; + + public TeamScoreRes getTeamScoreInfo(Long teamId) { + + return TeamScoreRes.builder() + .score(getScore(teamId)) + .level(getLevel(teamId)) + .build() + ; + } + + private Long getScore(Long teamId) { + return teamScoreQueryService.findTeamScoreByTeam(teamId).getScore(); + } + + private Long getLevel(Long teamId) { + return teamScoreQueryService.findTeamScoreByTeam(teamId).getLevel(); + } + + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java deleted file mode 100644 index eb4b5a91..00000000 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.moing.backend.domain.teamScore.application.service; - - -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; -import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.team.domain.service.TeamSaveService; -import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; -import com.moing.backend.domain.teamScore.domain.entity.TeamScore; -import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; -import com.moing.backend.domain.teamScore.domain.service.TeamScoreSaveService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -@Slf4j -@Service -@Transactional -@RequiredArgsConstructor -public class TeamScoreLogicUseCase { - - private final TeamGetService teamGetService; - private final MissionQueryService missionQueryService; - private final TeamScoreQueryService teamScoreQueryService; - private final TeamScoreSaveService teamScoreSaveService; - private final MissionStateQueryService missionStateQueryService; - private final TeamSaveService teamSaveService; - - public TeamScoreRes getTeamScoreInfo(Long teamId) { - - return TeamScoreRes.builder() - .score(getScore(teamId)) - .level(getLevel(teamId)) - .build() - ; - } - - public Long updateTeamScore(Long missionId) { - Mission mission = missionQueryService.findMissionById(missionId); - Team team = mission.getTeam(); - TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); - - teamScore.updateScore(getScoreByMission(mission)); - teamScore.levelUp(); - - teamScoreSaveService.save(teamScore); - teamSaveService.saveTeam(team); - - return teamScore.getScore(); - } - - public Long getScore(Long teamId) { - return teamScoreQueryService.findTeamScoreByTeam(teamId).getScore(); - } - - public Long getLevel(Long teamId) { - return teamScoreQueryService.findTeamScoreByTeam(teamId).getLevel(); - } - - public Long getScoreByMission(Mission mission) { - float total = totalPeople(mission); - float done = donePeople(mission); - - if (done == 0) { - return 0L; - } else { - return (long) ((done / total * 100) / 5); - } - - } - - public float donePeople(Mission mission) { - return Float.valueOf(missionStateQueryService.stateCountByMissionId(mission.getId())); - } - - public float totalPeople(Mission mission) { - return Float.valueOf(mission.getTeam().getNumOfMember()); - - } - - - - -} diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java new file mode 100644 index 00000000..ba36f74a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java @@ -0,0 +1,88 @@ +package com.moing.backend.domain.teamScore.application.service; + + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.team.domain.service.TeamSaveService; +import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; +import com.moing.backend.domain.teamScore.domain.service.TeamScoreSaveService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Slf4j +@Service +@Transactional +@RequiredArgsConstructor +public class TeamScoreUpdateUseCase { + + private final MissionQueryService missionQueryService; + private final TeamScoreQueryService teamScoreQueryService; + + private final float SCORE_BASE_NUM = 10; + + private final long BONUS_SCORE_ONCE_MISSION = 1L; + private final long BONUS_SCORE_REPEAT_MISSION = 2L; + + /** + * 매번 미션 인증 시 점수 적립 + */ + public void gainScoreByArchive(Mission mission) { + + + Team team = mission.getTeam(); + TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); + + Integer numOfMember = team.getNumOfMember(); + Long gainScore = calculateScoreByArchive(numOfMember); + + teamScore.updateScore(gainScore); + + } + + private Long calculateScoreByArchive(Integer numOfMember) { + float allPeople = Float.valueOf(numOfMember); + return (long) ((SCORE_BASE_NUM/allPeople) * 2); + } + + /* + * 보너스 점수 적립 + * 한번 미션은 소모임원 마지막 인증 시 호출, 반복 미션은 각 멤버 당 마지막 인증시 호출 + */ + public void gainScoreByBonus(Long missionId) { + + Mission mission = missionQueryService.findMissionById(missionId); + Team team = mission.getTeam(); + TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); + + Integer numOfMember = team.getNumOfMember(); + + + /** + * 한번미션 일 경우 1 * 소모임원 수, 반복미션 일 경우 2점 update + * 한번 미션은 소모임원 마지막 인증 시 호출, 반복 미션은 각 멤버 당 마지막 인증시 호출 + */ + + if (mission.getType().equals(MissionType.ONCE)) { + teamScore.updateScore(BONUS_SCORE_ONCE_MISSION * numOfMember); + } else { + teamScore.updateScore(BONUS_SCORE_REPEAT_MISSION); + } + + } + + + + + + + + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java b/src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java index fe4ddf53..4fc93525 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java +++ b/src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java @@ -1,10 +1,8 @@ package com.moing.backend.domain.teamScore.presentation; -import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; -import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; -import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; -import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import com.moing.backend.domain.teamScore.application.service.TeamScoreGetUseCase; +import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -15,10 +13,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.List; - -import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_REPEAT_MISSION_SUCCESS; -import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_SINGLE_MISSION_SUCCESS; import static com.moing.backend.domain.teamScore.presentation.constant.TeamScoreResponseMessage.GET_TEAMSCORE_SUCCESS; @RestController @@ -26,7 +20,7 @@ @RequestMapping("/api/team/{teamId}") public class TeamScoreController { - private final TeamScoreLogicUseCase teamScoreLogicUseCase; + private final TeamScoreGetUseCase teamScoreGetUseCase; /** * 팀별 불 레벨/경험치 조회 @@ -36,7 +30,7 @@ public class TeamScoreController { @GetMapping("/my-fire") public ResponseEntity> getTeamScore(@PathVariable("teamId") Long teamId, @AuthenticationPrincipal User user) { - return ResponseEntity.ok(SuccessResponse.create(GET_TEAMSCORE_SUCCESS.getMessage(), this.teamScoreLogicUseCase.getTeamScoreInfo(teamId))); + return ResponseEntity.ok(SuccessResponse.create(GET_TEAMSCORE_SUCCESS.getMessage(), this.teamScoreGetUseCase.getTeamScoreInfo(teamId))); } diff --git a/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java b/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java index 1ac4977b..3766dd49 100644 --- a/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java +++ b/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java @@ -1,13 +1,8 @@ package com.moing.backend.domain.teamScore.presentation; import com.moing.backend.config.CommonControllerTest; -import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; -import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; -import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; -import com.moing.backend.domain.missionArchive.presentation.MissionGatherController; import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; -import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; -import org.assertj.core.util.Lists; +import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -16,10 +11,6 @@ import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import java.util.List; - -import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_REPEAT_MISSION_SUCCESS; -import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_SINGLE_MISSION_SUCCESS; import static com.moing.backend.domain.teamScore.presentation.constant.TeamScoreResponseMessage.GET_TEAMSCORE_SUCCESS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; @@ -33,7 +24,7 @@ public class TeamScoreControllerTest extends CommonControllerTest { @MockBean - private TeamScoreLogicUseCase teamScoreLogicUseCase; + private TeamScoreUpdateUseCase teamScoreUpdateUseCase; @Test public void 팀별_불_레벨_경험치_조회() throws Exception { @@ -44,7 +35,7 @@ public class TeamScoreControllerTest extends CommonControllerTest { .level(1L) .build(); - given(teamScoreLogicUseCase.getTeamScoreInfo(any())).willReturn(output); + given(teamScoreUpdateUseCase.getTeamScoreInfo(any())).willReturn(output); Long teamId = 1L; //when From 92f080e29a9fa955da245a5c054adfb9c291adca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 3 Feb 2024 22:25:05 +0900 Subject: [PATCH 480/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=9B=94=EC=9A=94=EC=9D=BC=20=EC=8B=9C=EC=9E=91=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionStateScheduleUseCase.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 8322d7ec..df76acdb 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -55,22 +55,6 @@ public void singleMissionEndRoutine() { } - /** - * 미션 시작 - * 월요일 아침 - */ - @Scheduled(cron = "0 0 0 * * MON") - public void RepeatMissionStart() { - List startMission = missionQueryService.findRepeatMissionByStatus(MissionStatus.WAIT); - startMission.forEach( - mission -> { - // 미션 시작 알림 - sendMissionStartAlarmUseCase.sendRepeatMissionStartAlarm(mission); - mission.updateStatus(MissionStatus.ONGOING); - } - ); - } - @Scheduled(cron = "0 0 8 * * *") public void MissionRemindAlarm() { From 5c1a0b52d22ced7598f3de5305291a61519c58b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 3 Feb 2024 22:30:10 +0900 Subject: [PATCH 481/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EB=8B=B9=20=EA=B2=BD=ED=97=98=EC=B9=98=20?= =?UTF-8?q?=EC=B6=95=EC=A0=81=20=EA=B3=84=EC=82=B0=EC=8B=9C=20=EB=B0=98?= =?UTF-8?q?=EC=98=AC=EB=A6=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamScore/application/service/TeamScoreUpdateUseCase.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java index ba36f74a..54fa84d4 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java @@ -26,7 +26,6 @@ public class TeamScoreUpdateUseCase { private final TeamScoreQueryService teamScoreQueryService; private final float SCORE_BASE_NUM = 10; - private final long BONUS_SCORE_ONCE_MISSION = 1L; private final long BONUS_SCORE_REPEAT_MISSION = 2L; @@ -48,7 +47,7 @@ public void gainScoreByArchive(Mission mission) { private Long calculateScoreByArchive(Integer numOfMember) { float allPeople = Float.valueOf(numOfMember); - return (long) ((SCORE_BASE_NUM/allPeople) * 2); + return Math.round(SCORE_BASE_NUM/allPeople) * 2L; } /* From fcec317fc78bafea2d7278689767a7965271a6ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:25:44 +0900 Subject: [PATCH 482/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=8B=9C=20=ED=95=9C=EB=B2=88/=EB=B0=98?= =?UTF-8?q?=EB=B3=B5=20=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EB=B3=B4=EB=84=88?= =?UTF-8?q?=EC=8A=A4=20=EC=A0=90=EC=88=98=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveCreateUseCase.java | 42 +++++++++++++++++-- .../service/MissionArchiveUpdateUseCase.java | 10 ++--- .../MissionArchiveCustomRepository.java | 3 ++ .../MissionArchiveCustomRepositoryImpl.java | 22 ++++++++++ .../service/MissionArchiveQueryService.java | 5 +++ .../service/MissionStateUseCase.java | 28 +------------ .../service/TeamScoreUpdateUseCase.java | 3 +- 7 files changed, 75 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index f79afeb1..f5b921f3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -64,11 +64,11 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss // 당일 1회 인증만 가능 if (missionArchiveQueryService.isAbleToArchiveToday(memberId, missionId)) { throw new NoMoreMissionArchiveException(); - } else { - newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId) + 1); } + newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId) + 1); missionStateUseCase.updateMissionState(member, mission, newArchive); + missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); } @@ -82,8 +82,8 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss } newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); - missionStateUseCase.updateMissionState(member, mission, newArchive); + missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); // 인증 후 n/n명 인증 성공 리턴값 업데이트 @@ -92,14 +92,48 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss } + gainBonusScore(mission,newArchive); teamScoreUpdateUseCase.gainScoreByArchive(mission); return missionArchiveRes; } // 이 미션을 완료 했는지 - public Boolean isDoneMission(Long memberId,Mission mission) { + private Boolean isDoneMission(Long memberId,Mission mission) { return missionArchiveQueryService.findMyDoneArchives(memberId, mission.getId()) >= mission.getNumber(); } + private void gainBonusScore(Mission mission, MissionArchive missionArchive) { + + if (mission.getType() == MissionType.ONCE) { + + if (isAbleToFinishOnceMission(mission)) { + mission.updateStatus(MissionStatus.SUCCESS); + teamScoreUpdateUseCase.gainScoreByBonus(mission); + } + + } else { + if (isAbleToFinishRepeatMission(mission, missionArchive)) { + teamScoreUpdateUseCase.gainScoreByBonus(mission); + } + + } + } + + private boolean isAbleToFinishRepeatMission(Mission mission, MissionArchive archive) { + return mission.getNumber() <= archive.getCount(); + } + + private boolean isAbleToFinishOnceMission(Mission mission) { + + Team team = mission.getTeam(); + + Integer total = team.getNumOfMember(); + Long done = missionArchiveQueryService.stateCountByMissionId(mission.getId()); + + return done > total; + + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index b306f349..4b459cd3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -63,11 +63,11 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss MissionArchive updateArchive = missionArchiveQueryService.findMyArchive(memberId, missionId).get(0); // 단일 미션 && 미션 종료 직전인지 확인 - if (mission.getType() == MissionType.ONCE && missionStateUseCase.isAbleToEnd(mission)) { - mission.updateStatus(MissionStatus.SUCCESS); - // 점수 반영 로직 - - } +// if (mission.getType() == MissionType.ONCE && missionStateUseCase.isAbleToEnd(mission)) { +// mission.updateStatus(MissionStatus.SUCCESS); +// // 점수 반영 로직 +// +// } // 반복미션의 경우 당일이 지나면 업데이트 불가능 if (!(updateArchive.getLastModifiedDate().getDayOfWeek().equals(LocalDateTime.now().getDayOfWeek()))) { throw new NoAccessMissionArchiveException(); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index fd2ffc8d..90c9a29c 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -38,4 +38,7 @@ public interface MissionArchiveCustomRepository { MyArchiveStatus findMissionStatusById(Long memberId, Long missionId, Long teamId); + Long getCountsByMissionId(Long missionId); + + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 9c63483e..02976017 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -470,6 +470,28 @@ public MyArchiveStatus findMissionStatusById(Long memberId, Long missionId, Long } + public Long getCountsByMissionId(Long missionId) { + LocalDate now = LocalDate.now(); + DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; // 한 주의 시작일을 월요일로 설정 + LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); + LocalDate endOfWeek = startOfWeek.plusDays(6); // 한 주의 마지막일을 일요일로 설정 + + BooleanExpression repeatTypeCondition = (missionArchive.mission.type.eq(MissionType.REPEAT) + .and(missionArchive.createdDate.goe(startOfWeek.atStartOfDay())) + .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1)))).or(missionArchive.mission.type.eq(MissionType.ONCE)); + + // 기본 조건 + BooleanExpression baseCondition = missionState.mission.id.eq(missionId); + // 조건 적용 + BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); + + return (long) queryFactory + .select(missionArchive) + .from(missionArchive) + .where(finalCondition) + .fetch().size(); + } + diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 0aa1ea1b..68d24a01 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -116,6 +116,11 @@ public MyArchiveStatus findMissionStatusById(Long memberId, Long missionId, Long return missionArchiveRepository.findMissionStatusById(memberId, missionId, teamId); } + public Long stateCountByMissionId(Long missionId) { + return missionArchiveRepository.getCountsByMissionId(missionId); + } + + } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 9bf91010..66615bca 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -35,40 +35,14 @@ public class MissionStateUseCase { /* 모든 모임원이 미션을 완료했는지 여부 확인 */ - public boolean isAbleToEnd(Mission mission) { - - Long total = totalPeople(mission); - Long done = donePeople(mission); - - return done > total; - - } - - public Long donePeople(Mission mission) { - return Long.valueOf(missionStateQueryService.stateCountByMissionId(mission.getId())); - } - - public Long totalPeople(Mission mission) { - return Long.valueOf(mission.getTeam().getNumOfMember()); - } public void updateMissionState(Member member, Mission mission, MissionArchive missionArchive) { - - MissionType missionType = mission.getType(); - Long missionId = mission.getId(); - missionStateSaveService.saveMissionState(member,mission, missionArchive.getStatus()); - if (missionType == MissionType.ONCE) { + } - if (isAbleToEnd(mission)) { - mission.updateStatus(MissionStatus.SUCCESS); - teamScoreUpdateUseCase.gainScoreByBonus(missionId); - } - } - } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java index 54fa84d4..08dc6bb1 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java @@ -54,9 +54,8 @@ private Long calculateScoreByArchive(Integer numOfMember) { * 보너스 점수 적립 * 한번 미션은 소모임원 마지막 인증 시 호출, 반복 미션은 각 멤버 당 마지막 인증시 호출 */ - public void gainScoreByBonus(Long missionId) { + public void gainScoreByBonus(Mission mission) { - Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); From 2121e0c2fc1e44d2b8e90204606a1535c6cd2620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 4 Feb 2024 00:33:00 +0900 Subject: [PATCH 483/619] =?UTF-8?q?fix=20:=20=ED=95=9C=EB=B2=88/=EB=B0=98?= =?UTF-8?q?=EB=B3=B5=20=EB=AF=B8=EC=85=98=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EC=A0=90=EC=88=98,=20=EC=9D=B8=EC=A6=9D=201=ED=9A=8C=EB=8B=B9?= =?UTF-8?q?=20=EC=A0=90=EC=88=98=20=EB=A1=9C=EC=A7=81=20usecase=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveCreateUseCase.java | 22 ++++++++++++------- .../MissionArchiveCustomRepositoryImpl.java | 11 ++-------- .../service/TeamScoreUpdateUseCase.java | 9 ++------ 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index f5b921f3..6ea5bda6 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -14,16 +14,16 @@ import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; -import com.moing.backend.domain.missionArchive.exception.NotYetMissionArchiveException; import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; - +@Slf4j @Service @Transactional @RequiredArgsConstructor @@ -91,9 +91,12 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss missionArchiveRes.updateCount(doneSingleArchives); } - - gainBonusScore(mission,newArchive); - teamScoreUpdateUseCase.gainScoreByArchive(mission); + // TODO : 소모임원 3명 이상일 경우 보너스 점수 + if (mission.getTeam().getNumOfMember() > 2) { + gainBonusScore(mission, newArchive); + } + // TODO : 미션 인증 1회당 점수 + teamScoreUpdateUseCase.gainScoreOfArchive(mission); return missionArchiveRes; } @@ -109,12 +112,15 @@ private void gainBonusScore(Mission mission, MissionArchive missionArchive) { if (isAbleToFinishOnceMission(mission)) { mission.updateStatus(MissionStatus.SUCCESS); - teamScoreUpdateUseCase.gainScoreByBonus(mission); + teamScoreUpdateUseCase.gainScoreOfBonus(mission); + log.info("isAbleToFinishOnceMission"); } } else { if (isAbleToFinishRepeatMission(mission, missionArchive)) { - teamScoreUpdateUseCase.gainScoreByBonus(mission); + teamScoreUpdateUseCase.gainScoreOfBonus(mission); + log.info("isAbleToFinishRepeatMission"); + } } @@ -131,7 +137,7 @@ private boolean isAbleToFinishOnceMission(Mission mission) { Integer total = team.getNumOfMember(); Long done = missionArchiveQueryService.stateCountByMissionId(mission.getId()); - return done > total; + return done >= total; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 02976017..c1712789 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -471,17 +471,10 @@ public MyArchiveStatus findMissionStatusById(Long memberId, Long missionId, Long } public Long getCountsByMissionId(Long missionId) { - LocalDate now = LocalDate.now(); - DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; // 한 주의 시작일을 월요일로 설정 - LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); - LocalDate endOfWeek = startOfWeek.plusDays(6); // 한 주의 마지막일을 일요일로 설정 - - BooleanExpression repeatTypeCondition = (missionArchive.mission.type.eq(MissionType.REPEAT) - .and(missionArchive.createdDate.goe(startOfWeek.atStartOfDay())) - .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1)))).or(missionArchive.mission.type.eq(MissionType.ONCE)); + BooleanExpression repeatTypeCondition = createRepeatTypeConditionByArchive(); // 기본 조건 - BooleanExpression baseCondition = missionState.mission.id.eq(missionId); + BooleanExpression baseCondition = missionArchive.mission.id.eq(missionId); // 조건 적용 BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java index 08dc6bb1..83646ee5 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java @@ -4,14 +4,9 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.team.domain.service.TeamSaveService; -import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; import com.moing.backend.domain.teamScore.domain.entity.TeamScore; import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; -import com.moing.backend.domain.teamScore.domain.service.TeamScoreSaveService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -32,7 +27,7 @@ public class TeamScoreUpdateUseCase { /** * 매번 미션 인증 시 점수 적립 */ - public void gainScoreByArchive(Mission mission) { + public void gainScoreOfArchive(Mission mission) { Team team = mission.getTeam(); @@ -54,7 +49,7 @@ private Long calculateScoreByArchive(Integer numOfMember) { * 보너스 점수 적립 * 한번 미션은 소모임원 마지막 인증 시 호출, 반복 미션은 각 멤버 당 마지막 인증시 호출 */ - public void gainScoreByBonus(Mission mission) { + public void gainScoreOfBonus(Mission mission) { Team team = mission.getTeam(); TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); From 679cb5ae8a910e83771a94ed00e17c556b80b8a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 4 Feb 2024 00:42:01 +0900 Subject: [PATCH 484/619] =?UTF-8?q?refactor=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=A1=B0=ED=9A=8C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/TeamScoreGetUseCase.java | 15 ++------- .../service/TeamScoreUpdateService.java | 33 ------------------- 2 files changed, 3 insertions(+), 45 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java index 83e684f8..e36247af 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java @@ -26,21 +26,12 @@ public class TeamScoreGetUseCase { public TeamScoreRes getTeamScoreInfo(Long teamId) { + TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(teamId); return TeamScoreRes.builder() - .score(getScore(teamId)) - .level(getLevel(teamId)) + .score(teamScore.getScore()) + .level(teamScore.getLevel()) .build() ; } - private Long getScore(Long teamId) { - return teamScoreQueryService.findTeamScoreByTeam(teamId).getScore(); - } - - private Long getLevel(Long teamId) { - return teamScoreQueryService.findTeamScoreByTeam(teamId).getLevel(); - } - - - } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java deleted file mode 100644 index 4ec692e1..00000000 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.moing.backend.domain.teamScore.domain.service; - -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.teamScore.domain.entity.TeamScore; -import com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; -import com.moing.backend.global.annotation.DomainService; -import lombok.RequiredArgsConstructor; -import org.springframework.transaction.annotation.Transactional; - - -@DomainService -@Transactional -@RequiredArgsConstructor -public class TeamScoreUpdateService { - - private final TeamScoreRepository teamScoreRepository; - private final TeamGetService teamGetService; - private final TeamScoreQueryService teamScoreQueryService; - - public TeamScore update(Long teamId, Long score) { - Team team = teamGetService.getTeamByTeamId(teamId); - - TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); - - teamScore.updateScore(score); - - return teamScore; - - } - - -} From 9ef96084c920f559f309821728ebe84eb0a672e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 4 Feb 2024 00:52:38 +0900 Subject: [PATCH 485/619] =?UTF-8?q?fix=20:=20=EB=B6=88=EA=BD=83=20?= =?UTF-8?q?=EB=A0=88=EB=B2=A8=EC=97=85=20=ED=94=84=EB=A1=9C=EC=84=B8?= =?UTF-8?q?=EC=8A=A4=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/TeamScoreUpdateUseCase.java | 7 ++----- .../backend/domain/teamScore/domain/entity/TeamScore.java | 6 +++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java index 83646ee5..6e54b28b 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java @@ -37,6 +37,7 @@ public void gainScoreOfArchive(Mission mission) { Long gainScore = calculateScoreByArchive(numOfMember); teamScore.updateScore(gainScore); + teamScore.updateLevel(); } @@ -67,15 +68,11 @@ public void gainScoreOfBonus(Mission mission) { } else { teamScore.updateScore(BONUS_SCORE_REPEAT_MISSION); } + teamScore.updateLevel(); } - - - - - } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index 2b19759f..55b7b008 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -37,12 +37,12 @@ public void updateScore(Long score) { this.score += score; } - public void levelUp() { - final int[] steps = {1, 2, 10, 25, 45, 100}; + public void updateLevel() { + final int[] steps = {1, 2, 25, 45, 70, 120}; for (int i = 5; i > 0; i--) { if (steps[i-1] <= this.level && this.level <= steps[i]) { - if ((20 + ((i-1) * 15)) <= score) { + if ((40 + ((i-1) * 15)) <= score) { this.level+=1; this.score -= (20 + ((i-1) * 15)); this.team.updateLevelOfFire(); From 9d761a1eedbd69eea79ffd46df7b2269812675e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 4 Feb 2024 01:09:45 +0900 Subject: [PATCH 486/619] =?UTF-8?q?fix=20:=20=EB=B6=88=EA=BD=83=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EC=84=B8=EC=8A=A4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moing/backend/domain/teamScore/domain/entity/TeamScore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index 55b7b008..62531629 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -44,7 +44,7 @@ public void updateLevel() { if (steps[i-1] <= this.level && this.level <= steps[i]) { if ((40 + ((i-1) * 15)) <= score) { this.level+=1; - this.score -= (20 + ((i-1) * 15)); + this.score -= (40 + ((i-1) * 15)); this.team.updateLevelOfFire(); return; } From 54879462c204c2382d18352c2b1250f08ce766de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 4 Feb 2024 01:11:12 +0900 Subject: [PATCH 487/619] =?UTF-8?q?fix=20:=20teamScoreUseCase=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=ED=8C=8C=EC=9D=BC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamScore/presentation/TeamScoreControllerTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java b/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java index 3766dd49..6782317e 100644 --- a/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java +++ b/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java @@ -2,6 +2,7 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; +import com.moing.backend.domain.teamScore.application.service.TeamScoreGetUseCase; import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -24,7 +25,7 @@ public class TeamScoreControllerTest extends CommonControllerTest { @MockBean - private TeamScoreUpdateUseCase teamScoreUpdateUseCase; + private TeamScoreGetUseCase teamScoreGetUseCase; @Test public void 팀별_불_레벨_경험치_조회() throws Exception { @@ -35,7 +36,7 @@ public class TeamScoreControllerTest extends CommonControllerTest { .level(1L) .build(); - given(teamScoreUpdateUseCase.getTeamScoreInfo(any())).willReturn(output); + given(teamScoreGetUseCase.getTeamScoreInfo(any())).willReturn(output); Long teamId = 1L; //when From 152b2140704ca07a43436f6e3da49f7009c09efb Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 4 Feb 2024 02:59:43 +0900 Subject: [PATCH 488/619] =?UTF-8?q?MNG-13=20feat:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=BD=EC=9D=8C=20=EC=B2=98=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/Mission-API.adoc | 9 +++- .../dto/res/GatherRepeatMissionRes.java | 1 + .../dto/res/GatherSingleMissionRes.java | 1 + .../dto/res/MissionConfirmRes.java | 12 +++++ .../dto/res/RepeatMissionBoardRes.java | 7 ++- .../dto/res/SingleMissionBoardRes.java | 1 + .../service/MissionCreateUseCase.java | 7 ++- .../service/MissionReadUseCase.java | 12 ++++- .../domain/mission/domain/entity/Mission.java | 4 ++ .../MissionCustomRepositoryImpl.java | 13 +++-- .../presentation/MissionController.java | 13 +++++ .../constant/MissionResponseMessage.java | 3 +- .../MissionArchiveCustomRepositoryImpl.java | 24 +++++++-- .../application/mapper/MissionReadMapper.java | 16 ++++++ .../service/CreateMissionReadUseCase.java | 25 +++++++++ .../domain/entity/MissionRead.java | 54 +++++++++++++++++++ .../repository/MissionReadRepository.java | 14 +++++ .../MissionReadRepositoryUtils.java | 31 +++++++++++ .../service/MissionReadSaveService.java | 28 ++++++++++ .../representation/MissionControllerTest.java | 40 ++++++++++++++ .../MissionBoardControllerTest.java | 8 ++- .../MissionGatherControllerTest.java | 28 ++++++---- 22 files changed, 326 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionConfirmRes.java create mode 100644 src/main/java/com/moing/backend/domain/missionRead/application/mapper/MissionReadMapper.java create mode 100644 src/main/java/com/moing/backend/domain/missionRead/application/service/CreateMissionReadUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionRead/domain/entity/MissionRead.java create mode 100644 src/main/java/com/moing/backend/domain/missionRead/domain/repository/MissionReadRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionRead/domain/repository/MissionReadRepositoryUtils.java create mode 100644 src/main/java/com/moing/backend/domain/missionRead/domain/service/MissionReadSaveService.java diff --git a/src/docs/asciidoc/Mission-API.adoc b/src/docs/asciidoc/Mission-API.adoc index 3cdf3e8d..48dcbaaa 100644 --- a/src/docs/asciidoc/Mission-API.adoc +++ b/src/docs/asciidoc/Mission-API.adoc @@ -29,14 +29,19 @@ operation::mission-controller-test/미션_삭제[snippets='http-request,path-par [[Mission-추천]] -=== Mission 추천 +== Mission 추천 operation::mission-controller-test/미션_추천[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- [[Mission-종료]] -=== Mission 종료 +== Mission 종료 operation::mission-controller-test/미션_종료[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] --- + +[[Mission-설명-확인]] +== Mission 설명 확인 +operation::mission-controller-test/미션_설명_확인[snippets='http-request,path-parameters,http-response,response-fields'] + diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java index 993fd70e..57fcb047 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java @@ -16,6 +16,7 @@ public class GatherRepeatMissionRes { private String totalNum; private String doneNum; private String status; + private Boolean isRead; } diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java index 0b173365..fcf90d57 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java @@ -14,6 +14,7 @@ public class GatherSingleMissionRes { private String missionTitle; private String dueTo; private String status; + private Boolean isRead; } diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionConfirmRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionConfirmRes.java new file mode 100644 index 00000000..91530ec9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/MissionConfirmRes.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mission.application.dto.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class MissionConfirmRes { + private Long missionId; +} diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java index 0caa23dc..e6ba3d27 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/RepeatMissionBoardRes.java @@ -17,9 +17,10 @@ public class RepeatMissionBoardRes { private int number; private String way; private String status; + private Boolean isRead; - public RepeatMissionBoardRes(Long missionId, String title, Long done,int number,String way,String status) { + public RepeatMissionBoardRes(Long missionId, String title, Long done,int number,String way,String status, Boolean isRead) { this.missionId = missionId; this.title = title; this.dueTo="False"; @@ -27,6 +28,7 @@ public RepeatMissionBoardRes(Long missionId, String title, Long done,int number, this.done = done; this.way = way; this.status = status; + this.isRead=isRead; } public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long done, int number,String way) { @@ -39,7 +41,7 @@ public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long do } @Builder - public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long done, int number, String way, String status) { + public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long done, int number, String way, String status, Boolean isRead) { this.missionId = missionId; this.title = title; this.dueTo = dueTo; @@ -47,5 +49,6 @@ public RepeatMissionBoardRes(Long missionId, String title, String dueTo, Long do this.number = number; this.way = way; this.status = status; + this.isRead=isRead; } } diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java index 8f4a5e9d..f5978531 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java @@ -15,5 +15,6 @@ public class SingleMissionBoardRes { private String title; private String status; private String missionType; + private Boolean isRead; } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index 81d95b1b..cf46a5a9 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -13,6 +13,7 @@ import com.moing.backend.domain.mission.domain.service.MissionSaveService; import com.moing.backend.domain.mission.exception.NoAccessCreateMission; import com.moing.backend.domain.mission.exception.NoMoreCreateMission; +import com.moing.backend.domain.missionRead.application.service.CreateMissionReadUseCase; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.global.response.BaseServiceResponse; @@ -29,6 +30,7 @@ public class MissionCreateUseCase { private final MissionSaveService missionSaveService; private final MissionQueryService missionQueryService; private final SendMissionCreateAlarmUseCase sendMissionCreateAlarmUseCase; + private final CreateMissionReadUseCase createMissionReadUseCase; private final BaseService baseService; @@ -56,7 +58,10 @@ public MissionCreateRes createMission(String socialId, Long teamId, MissionReq m // 2. 미션 저장 missionSaveService.save(mission); - // 3. 알림 보내기 - 미션 생성 + // 3. 미션 읽음 처리 + createMissionReadUseCase.createMissionRead(team,member, mission); + + // 4. 알림 보내기 - 미션 생성 sendMissionCreateAlarmUseCase.sendNewMissionUploadAlarm(member, mission); return MissionMapper.mapToMissionCreateRes(mission); diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java index a195e130..b854964a 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionReadUseCase.java @@ -2,8 +2,11 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.application.dto.res.MissionConfirmRes; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; +import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionRead.application.service.CreateMissionReadUseCase; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import lombok.RequiredArgsConstructor; @@ -17,8 +20,8 @@ public class MissionReadUseCase { private final MissionQueryService missionQueryService; private final MemberGetService memberGetService; - private final TeamGetService teamGetService; + private final CreateMissionReadUseCase createMissionReadUseCase; public MissionReadRes getMission(String userSocialId, Long missionId) { @@ -31,4 +34,11 @@ public String getTeamCategory(Long teamId) { return team.getCategory(); } + public MissionConfirmRes confirmMission(String socialId, Long missionId, Long teamId){ + Member member=memberGetService.getMemberBySocialId(socialId); + Team team=teamGetService.getTeamByTeamId(teamId); + Mission mission=missionQueryService.findMissionById(missionId); + createMissionReadUseCase.createMissionRead(team, member, mission); + return new MissionConfirmRes(mission.getId()); + } } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index 60fd58d3..937b851e 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionRead.domain.entity.MissionRead; import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.entity.BaseTimeEntity; @@ -57,6 +58,9 @@ public class Mission extends BaseTimeEntity { @OneToMany(mappedBy = "mission") List missionStateList = new ArrayList<>(); + @OneToMany(mappedBy = "mission") + List missionReads=new ArrayList<>(); + @Builder public Mission(String title, LocalDateTime dueTo, String rule, String content, int number, Team team, MissionType type, MissionStatus status, MissionWay way) { this.title = title; diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index a585c651..4efda501 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -8,6 +8,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; +import com.moing.backend.domain.missionRead.domain.repository.MissionReadRepositoryUtils; import com.moing.backend.domain.missionState.domain.entity.QMissionState; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; @@ -51,7 +52,7 @@ public Long findMissionsCountByTeam(Long teamId) { @Override public Optional> findRepeatMissionByMemberId(Long memberId,Listteams) { - + BooleanExpression isReadExpression = MissionReadRepositoryUtils.isMissionReadByMemberIdAndTeamIds(memberId, teams); BooleanExpression dateInRange = createRepeatTypeConditionByState(); return Optional.ofNullable(queryFactory @@ -62,8 +63,8 @@ public Optional> findRepeatMissionByMemberId(Long m mission.title, mission.number.stringValue(), missionState.count().stringValue(), - mission.status.stringValue() - + mission.status.stringValue(), + isReadExpression.as("isRead") )) .from(mission) .leftJoin(missionState) @@ -140,6 +141,9 @@ public Optional> findRepeatMissionByStatus(MissionStatus missionSt @Override public Optional> findSingleMissionByMemberId(Long memberId, List teams) { + BooleanExpression isReadExpression = MissionReadRepositoryUtils.isMissionReadByMemberIdAndTeamIds(memberId, teams); + + return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherSingleMissionRes.class, mission.id, @@ -147,7 +151,8 @@ public Optional> findSingleMissionByMemberId(Long m mission.team.name, mission.title, mission.dueTo.stringValue(), - mission.status.stringValue() + mission.status.stringValue(), + isReadExpression.as("isRead") )) .from(mission) .leftJoin(missionState).on( diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 35c456fe..bf1f6939 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.mission.application.dto.req.MissionReq; import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; +import com.moing.backend.domain.mission.application.dto.res.MissionConfirmRes; import com.moing.backend.domain.mission.application.service.*; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; @@ -107,6 +108,18 @@ public ResponseEntity> isLeader(@AuthenticationPrincipa // return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionRemindAlarmUseCase.sendRepeatMissionRemind())); // } + /** + * 미션 설명 확인 (미션 읽음 처리) + * [GET] {teamId}/missions/{missionId}/read + * 작성자 : 김민수 + */ + @GetMapping("/{missionId}/confirm") + public ResponseEntity> confirmMissionExplanation(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long missionId){ + return ResponseEntity.ok(SuccessResponse.create(CONFIRM_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.confirmMission(user.getSocialId(), missionId, teamId))); + + } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java b/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java index 1adb30cf..14eec075 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/constant/MissionResponseMessage.java @@ -11,7 +11,8 @@ public enum MissionResponseMessage { UPDATE_MISSION_SUCCESS("미션 수정을 완료 했습니다"), END_MISSION_SUCCESS("미션 종료를 완료 했습니다"), DELETE_MISSION_SUCCESS("미션 삭제를 완료 했습니다"), - RECOMMEND_MISSION_SUCCESS("미션 추천을 위한 팀 카테고리를 조회 했습니다"); + RECOMMEND_MISSION_SUCCESS("미션 추천을 위한 팀 카테고리를 조회 했습니다"), + CONFIRM_MISSION_SUCCESS("미션 설명을 확인했습니다."); private final String message; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 9c63483e..90e99c89 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.domain.repository; +import com.moing.backend.domain.board.application.dto.response.BoardBlocks; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; @@ -13,6 +14,8 @@ import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; +import com.moing.backend.domain.missionRead.domain.entity.QMissionRead; +import com.moing.backend.domain.missionRead.domain.repository.MissionReadRepositoryUtils; import com.moing.backend.domain.team.domain.entity.QTeam; import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; import com.querydsl.core.Tuple; @@ -40,8 +43,12 @@ import java.util.List; import java.util.Optional; +import static com.moing.backend.domain.board.domain.entity.QBoard.board; +import static com.moing.backend.domain.boardRead.domain.entity.QBoardRead.boardRead; +import static com.moing.backend.domain.member.domain.entity.QMember.member; import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; +import static com.moing.backend.domain.missionRead.domain.entity.QMissionRead.missionRead; import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; import static com.moing.backend.domain.team.domain.entity.QTeam.team; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; @@ -61,6 +68,9 @@ public MissionArchiveCustomRepositoryImpl(EntityManager em) { @Override public Optional> findSingleMissionInComplete(Long memberId, Long teamId, MissionStatus status, OrderCondition orderCondition) { + + BooleanExpression isReadExpression = MissionReadRepositoryUtils.isMissionReadByMemberIdAndTeamId(memberId, teamId); + OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); return Optional.ofNullable(queryFactory .select(Projections.constructor(SingleMissionBoardRes.class, @@ -68,7 +78,8 @@ public Optional> findSingleMissionInComplete(Long me mission.dueTo.stringValue(), mission.title, mission.status.stringValue(), - mission.type.stringValue() + mission.type.stringValue(), + isReadExpression.as("isRead") )) .from(mission) .where(mission.notIn @@ -92,6 +103,8 @@ public Optional> findSingleMissionInComplete(Long me @Override public Optional> findSingleMissionComplete(Long memberId, Long teamId, MissionStatus status, OrderCondition orderCondition) { + BooleanExpression isReadExpression = MissionReadRepositoryUtils.isMissionReadByMemberIdAndTeamId(memberId, teamId); + OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); return Optional.ofNullable(queryFactory .select(Projections.constructor(SingleMissionBoardRes.class, @@ -99,7 +112,8 @@ public Optional> findSingleMissionComplete(Long memb mission.dueTo.stringValue(), mission.title, missionArchive.status.stringValue(), - mission.type.stringValue() + mission.type.stringValue(), + isReadExpression.as("isRead") )) .from(mission) .join(mission.missionArchiveList,missionArchive) @@ -259,6 +273,9 @@ public Optional findMyDoneCountByMissionId(Long missionId, Long memberId) @Override public Optional> findRepeatMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status) { + BooleanExpression isReadExpression = MissionReadRepositoryUtils.isMissionReadByMemberIdAndTeamId(memberId, teamId); + + BooleanExpression dateInRange = createRepeatTypeConditionByState(); return Optional.ofNullable(queryFactory .select(Projections.constructor(RepeatMissionBoardRes.class, @@ -268,7 +285,8 @@ public Optional> findRepeatMissionArchivesByMemberId missionState.count(), mission.number, mission.way.stringValue(), - mission.status.stringValue() + mission.status.stringValue(), + isReadExpression.as("isRead") )) .from(mission) .leftJoin(missionState) diff --git a/src/main/java/com/moing/backend/domain/missionRead/application/mapper/MissionReadMapper.java b/src/main/java/com/moing/backend/domain/missionRead/application/mapper/MissionReadMapper.java new file mode 100644 index 00000000..3059d832 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionRead/application/mapper/MissionReadMapper.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.missionRead.application.mapper; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.missionRead.domain.entity.MissionRead; +import com.moing.backend.domain.team.domain.entity.Team; +import org.springframework.stereotype.Component; + +@Component +public class MissionReadMapper { + public static MissionRead toMissionRead(Team team, Member member){ + MissionRead missionRead=new MissionRead(); + missionRead.updateTeam(team); + missionRead.updateMember(member); + return missionRead; + } +} diff --git a/src/main/java/com/moing/backend/domain/missionRead/application/service/CreateMissionReadUseCase.java b/src/main/java/com/moing/backend/domain/missionRead/application/service/CreateMissionReadUseCase.java new file mode 100644 index 00000000..1989d180 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionRead/application/service/CreateMissionReadUseCase.java @@ -0,0 +1,25 @@ +package com.moing.backend.domain.missionRead.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.missionRead.application.mapper.MissionReadMapper; +import com.moing.backend.domain.missionRead.domain.entity.MissionRead; +import com.moing.backend.domain.missionRead.domain.service.MissionReadSaveService; +import com.moing.backend.domain.team.domain.entity.Team; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class CreateMissionReadUseCase { + + private final MissionReadSaveService missionReadSaveService; + + public void createMissionRead(Team team, Member member, Mission mission) { + MissionRead missionRead = MissionReadMapper.toMissionRead(team, member); + missionReadSaveService.saveMissionRead(mission, missionRead); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionRead/domain/entity/MissionRead.java b/src/main/java/com/moing/backend/domain/missionRead/domain/entity/MissionRead.java new file mode 100644 index 00000000..f00939f5 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionRead/domain/entity/MissionRead.java @@ -0,0 +1,54 @@ +package com.moing.backend.domain.missionRead.domain.entity; + +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class MissionRead extends BaseTimeEntity{ + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "mission_read_id") + private Long missionReadId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "mission_id") + private Mission mission; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team__id") + private Team team; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "Member_id") + private Member member; + + + /** + * 연관관계 매핑 + */ + public void updateMission(Mission mission) { + this.mission=mission; + } + + public void updateTeam(Team team) { + this.team = team; + } + + public void updateMember(Member member) { + this.member = member; + } +} diff --git a/src/main/java/com/moing/backend/domain/missionRead/domain/repository/MissionReadRepository.java b/src/main/java/com/moing/backend/domain/missionRead/domain/repository/MissionReadRepository.java new file mode 100644 index 00000000..64baf36f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionRead/domain/repository/MissionReadRepository.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.missionRead.domain.repository; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.missionRead.domain.entity.MissionRead; +import com.moing.backend.domain.team.domain.entity.Team; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface MissionReadRepository extends JpaRepository { + + List findMissionReadByMissionAndMemberAndTeam(Mission mission, Member member, Team team); +} diff --git a/src/main/java/com/moing/backend/domain/missionRead/domain/repository/MissionReadRepositoryUtils.java b/src/main/java/com/moing/backend/domain/missionRead/domain/repository/MissionReadRepositoryUtils.java new file mode 100644 index 00000000..d3d715ca --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionRead/domain/repository/MissionReadRepositoryUtils.java @@ -0,0 +1,31 @@ +package com.moing.backend.domain.missionRead.domain.repository; + +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.JPAExpressions; + +import java.util.List; + +import static com.moing.backend.domain.mission.domain.entity.QMission.mission; +import static com.moing.backend.domain.missionRead.domain.entity.QMissionRead.missionRead; + +public class MissionReadRepositoryUtils { + public static BooleanExpression isMissionReadByMemberIdAndTeamId(Long memberId, Long teamId) { + return JPAExpressions + .select(missionRead.missionReadId) + .from(missionRead) + .where(missionRead.member.memberId.eq(memberId), + missionRead.mission.team.teamId.eq(teamId), + missionRead.mission.id.eq(mission.id)) + .exists(); + } + + public static BooleanExpression isMissionReadByMemberIdAndTeamIds(Long memberId, List teamIds){ + return JPAExpressions + .select(missionRead.missionReadId) + .from(missionRead) + .where(missionRead.member.memberId.eq(memberId), + missionRead.mission.team.teamId.in(teamIds), + missionRead.mission.id.eq(mission.id)) + .exists(); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionRead/domain/service/MissionReadSaveService.java b/src/main/java/com/moing/backend/domain/missionRead/domain/service/MissionReadSaveService.java new file mode 100644 index 00000000..8dc37ac2 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionRead/domain/service/MissionReadSaveService.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.missionRead.domain.service; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.missionRead.domain.entity.MissionRead; +import com.moing.backend.domain.missionRead.domain.repository.MissionReadRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; +import java.util.List; + +@DomainService +@RequiredArgsConstructor +@Transactional +public class MissionReadSaveService { + + private final MissionReadRepository missionReadRepository; + + + public void saveMissionRead(Mission mission, MissionRead missionRead) { + List existingMissionReads = missionReadRepository.findMissionReadByMissionAndMemberAndTeam(mission, missionRead.getMember(), missionRead.getTeam()); + + if (existingMissionReads.isEmpty()) { + missionRead.updateMission(mission); + missionReadRepository.save(missionRead); + } + } +} diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index e1736dfd..27a63d54 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -2,6 +2,7 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.mission.application.dto.req.MissionReq; +import com.moing.backend.domain.mission.application.dto.res.MissionConfirmRes; import com.moing.backend.domain.mission.application.dto.res.MissionCreateRes; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; import com.moing.backend.domain.mission.application.service.MissionCreateUseCase; @@ -23,6 +24,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.CONFIRM_MISSION_SUCCESS; import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.RECOMMEND_MISSION_SUCCESS; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; @@ -407,4 +409,42 @@ public class MissionControllerTest extends CommonControllerTest { } + @Test + public void 미션_설명_확인() throws Exception { + //given + Long teamId = 2L; + Long missionId = 1L; + MissionConfirmRes output=new MissionConfirmRes(missionId); + + given(missionReadUseCase.confirmMission(any(),any(),any())).willReturn(output); + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/{teamId}/missions/{missionId}/confirm",teamId,missionId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionId").description("확인 미션 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(CONFIRM_MISSION_SUCCESS.getMessage()), + fieldWithPath("data.missionId").description("확인한 미션의 아이디") + ) + ) + ) + .andReturn(); + } + } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java index 5065dcac..69039960 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java @@ -44,6 +44,7 @@ public class MissionBoardControllerTest extends CommonControllerTest { .title("Mission title") .status("WAIT/ONGOING/SKIP/COMPLETE") .missionType("ONCE/REPEAT") + .isRead(true) .build()); given(missionArchiveBoardUseCase.getActiveSingleMissions(any(),any())).willReturn(output); @@ -75,7 +76,8 @@ public class MissionBoardControllerTest extends CommonControllerTest { fieldWithPath("data[].dueTo").description("미션 마감 시각"), fieldWithPath("data[].title").description("미션 제목"), fieldWithPath("data[].status").description("미션 인증 상태"), - fieldWithPath("data[].missionType").description("미션 타입") + fieldWithPath("data[].missionType").description("미션 타입"), + fieldWithPath("data[].isRead").description("미션 읽음 여부") ) ) @@ -96,6 +98,7 @@ public class MissionBoardControllerTest extends CommonControllerTest { .number(3) .way("TEXT/PHOTO/LINK") .status("WAIT/ONGOING/SKIP/COMPLETE") + .isRead(true) .build()); given(missionArchiveBoardUseCase.getActiveRepeatMissions(any(),any())).willReturn(output); @@ -129,7 +132,8 @@ public class MissionBoardControllerTest extends CommonControllerTest { fieldWithPath("data[].number").description("전체 횟수"), fieldWithPath("data[].done").description("인증한 횟수"), fieldWithPath("data[].way").description("인증 방법"), - fieldWithPath("data[].status").description("인증 상태") + fieldWithPath("data[].status").description("인증 상태"), + fieldWithPath("data[].isRead").description("미션 읽음 여부") ) ) diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index eb414ec2..628302f0 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -1,11 +1,11 @@ package com.moing.backend.domain.missionArchive.representation; import com.moing.backend.config.CommonControllerTest; -import com.moing.backend.domain.mission.application.dto.res.*; +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; -import com.moing.backend.domain.missionArchive.application.service.MissionArchiveReadUseCase; import com.moing.backend.domain.missionArchive.presentation.MissionGatherController; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; @@ -24,9 +24,8 @@ import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; -import static org.springframework.restdocs.payload.PayloadDocumentation.*; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; @WebMvcTest(MissionGatherController.class) public class MissionGatherControllerTest extends CommonControllerTest { @@ -46,6 +45,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .teamName("team name") .missionTitle("mission title") .status("WAIT/ONGOING/END/FAIL/SUCCESS") + .isRead(true) .build()); given(missionGatherBoardUseCase.getAllActiveSingleMissions(any())).willReturn(output); @@ -75,7 +75,9 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].dueTo").description("미션 마감 시각"), fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목"), - fieldWithPath("data[].status").description("미션 상태") + fieldWithPath("data[].status").description("미션 상태"), + fieldWithPath("data[].isRead").description("미션 읽음 여부") + ) ) @@ -96,6 +98,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .doneNum("0") .totalNum("0") .status("WAIT/ONGOING/END/FAIL/SUCCESS") + .isRead(true) .build()); given(missionGatherBoardUseCase.getAllActiveRepeatMissions(any())).willReturn(output); @@ -126,7 +129,8 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].missionTitle").description("미션 제목"), fieldWithPath("data[].doneNum").description("완료한 횟수"), fieldWithPath("data[].totalNum").description("전체 횟수"), - fieldWithPath("data[].status").description("미션 상태") + fieldWithPath("data[].status").description("미션 상태"), + fieldWithPath("data[].isRead").description("미션 읽음 여부") ) @@ -147,6 +151,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .teamName("team name") .missionTitle("mission title") .status("WAIT/ONGOING/END/FAIL/SUCCESS") + .isRead(true) .build()); given(missionGatherBoardUseCase.getTeamActiveSingleMissions(any(),any())).willReturn(output); @@ -177,7 +182,9 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].dueTo").description("미션 마감 시각"), fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목"), - fieldWithPath("data[].status").description("미션 상태") + fieldWithPath("data[].status").description("미션 상태"), + fieldWithPath("data[].isRead").description("미션 읽음 여부") + ) ) @@ -198,6 +205,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .doneNum("0") .totalNum("0") .status("WAIT/ONGOING/END/FAIL/SUCCESS") + .isRead(true) .build()); given(missionGatherBoardUseCase.getTeamActiveRepeatMissions(any(),any())).willReturn(output); @@ -229,7 +237,9 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].missionTitle").description("미션 제목"), fieldWithPath("data[].doneNum").description("완료한 횟수"), fieldWithPath("data[].totalNum").description("전체 횟수"), - fieldWithPath("data[].status").description("미션 상태") + fieldWithPath("data[].status").description("미션 상태"), + fieldWithPath("data[].isRead").description("미션 읽음 여부") + ) From 865ead56bce5464c97f496781f06bd7b7044134e Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 4 Feb 2024 03:00:23 +0900 Subject: [PATCH 489/619] =?UTF-8?q?MNG-13=20fix:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EB=95=8C=20=EC=9D=BD?= =?UTF-8?q?=EC=9D=8C=20=EA=B4=80=EB=A0=A8=ED=95=B4=20=EC=BF=BC=EB=A6=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/BoardCustomRepositoryImpl.java | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index 3d357803..c051b9fe 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -3,9 +3,13 @@ import com.moing.backend.domain.board.application.dto.response.BoardBlocks; import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; import com.moing.backend.domain.board.application.dto.response.QBoardBlocks; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -23,9 +27,16 @@ public BoardCustomRepositoryImpl(EntityManager em) { @Override public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { - // 전체 게시글 보기 + BooleanExpression isReadExpression = JPAExpressions + .select(boardRead.board.boardId) + .from(boardRead) + .where(boardRead.member.memberId.eq(memberId), + boardRead.board.team.teamId.eq(teamId), + boardRead.board.boardId.eq(board.boardId)) + .exists(); + List allBoardBlocks = queryFactory - .select(new QBoardBlocks( + .select(Projections.constructor(BoardBlocks.class, board.boardId, board.teamMember.member.nickName.coalesce("알수없음"), board.isLeader, @@ -33,10 +44,10 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { board.title, board.content, board.commentNum, + isReadExpression.as("isRead"), // 읽음 여부 board.teamMember.isDeleted, board.isNotice, - board.teamMember.member.memberId.coalesce(0L) - )) + board.teamMember.member.memberId.coalesce(0L))) .from(board) .leftJoin(board.teamMember, teamMember) .leftJoin(board.teamMember.member, member) @@ -44,29 +55,17 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { .orderBy(board.createdDate.desc()) .fetch(); - // 읽은 게시글 목록 조회 - List readBoardIds = queryFactory - .select(boardRead.board.boardId) - .from(boardRead) - .where(boardRead.member.memberId.eq(memberId)) - .where(boardRead.board.team.teamId.eq(teamId)) - .fetch(); - - // 읽은 게시글 표시 - allBoardBlocks.forEach(boardBlock -> { - if (readBoardIds.contains(boardBlock.getBoardId())) { - boardBlock.readBoard(); + // 공지와 일반 게시글로 나누기 및 읽음 여부 적용 + List noticeBlocks = new ArrayList<>(); + List regularBlocks = new ArrayList<>(); + allBoardBlocks.forEach(block -> { + if (block.isNotice()) { + noticeBlocks.add(block); + } else { + regularBlocks.add(block); } }); - // 공지와 일반 게시글로 나누기 - List noticeBlocks = allBoardBlocks.stream() - .filter(BoardBlocks::isNotice) - .collect(Collectors.toList()); - List regularBlocks = allBoardBlocks.stream() - .filter(b -> !b.isNotice()) - .collect(Collectors.toList()); - return new GetAllBoardResponse(noticeBlocks.size(), noticeBlocks, regularBlocks.size(), regularBlocks); } From ad97104c0d80bd181fa1b63ae692365ff519a6eb Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 4 Feb 2024 16:02:16 +0900 Subject: [PATCH 490/619] =?UTF-8?q?MNG-13=20fix:=20=EC=A7=84=ED=96=89=20?= =?UTF-8?q?=EC=A4=91=20=EB=AF=B8=EC=85=98=EC=97=90=EC=84=9C=EB=8A=94=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=9D=BD=EC=9D=8C=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=A0=9C=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/GatherRepeatMissionRes.java | 1 - .../dto/res/GatherSingleMissionRes.java | 1 - .../repository/MissionCustomRepositoryImpl.java | 9 ++------- .../MissionGatherControllerTest.java | 17 ++++------------- 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java index 57fcb047..993fd70e 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java @@ -16,7 +16,6 @@ public class GatherRepeatMissionRes { private String totalNum; private String doneNum; private String status; - private Boolean isRead; } diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java index fcf90d57..0b173365 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java @@ -14,7 +14,6 @@ public class GatherSingleMissionRes { private String missionTitle; private String dueTo; private String status; - private Boolean isRead; } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 4efda501..f96ecad7 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -52,7 +52,6 @@ public Long findMissionsCountByTeam(Long teamId) { @Override public Optional> findRepeatMissionByMemberId(Long memberId,Listteams) { - BooleanExpression isReadExpression = MissionReadRepositoryUtils.isMissionReadByMemberIdAndTeamIds(memberId, teams); BooleanExpression dateInRange = createRepeatTypeConditionByState(); return Optional.ofNullable(queryFactory @@ -63,8 +62,7 @@ public Optional> findRepeatMissionByMemberId(Long m mission.title, mission.number.stringValue(), missionState.count().stringValue(), - mission.status.stringValue(), - isReadExpression.as("isRead") + mission.status.stringValue() )) .from(mission) .leftJoin(missionState) @@ -141,8 +139,6 @@ public Optional> findRepeatMissionByStatus(MissionStatus missionSt @Override public Optional> findSingleMissionByMemberId(Long memberId, List teams) { - BooleanExpression isReadExpression = MissionReadRepositoryUtils.isMissionReadByMemberIdAndTeamIds(memberId, teams); - return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherSingleMissionRes.class, @@ -151,8 +147,7 @@ public Optional> findSingleMissionByMemberId(Long m mission.team.name, mission.title, mission.dueTo.stringValue(), - mission.status.stringValue(), - isReadExpression.as("isRead") + mission.status.stringValue() )) .from(mission) .leftJoin(missionState).on( diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index 628302f0..410eafee 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -45,7 +45,6 @@ public class MissionGatherControllerTest extends CommonControllerTest { .teamName("team name") .missionTitle("mission title") .status("WAIT/ONGOING/END/FAIL/SUCCESS") - .isRead(true) .build()); given(missionGatherBoardUseCase.getAllActiveSingleMissions(any())).willReturn(output); @@ -75,8 +74,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].dueTo").description("미션 마감 시각"), fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목"), - fieldWithPath("data[].status").description("미션 상태"), - fieldWithPath("data[].isRead").description("미션 읽음 여부") + fieldWithPath("data[].status").description("미션 상태") ) @@ -98,7 +96,6 @@ public class MissionGatherControllerTest extends CommonControllerTest { .doneNum("0") .totalNum("0") .status("WAIT/ONGOING/END/FAIL/SUCCESS") - .isRead(true) .build()); given(missionGatherBoardUseCase.getAllActiveRepeatMissions(any())).willReturn(output); @@ -129,8 +126,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].missionTitle").description("미션 제목"), fieldWithPath("data[].doneNum").description("완료한 횟수"), fieldWithPath("data[].totalNum").description("전체 횟수"), - fieldWithPath("data[].status").description("미션 상태"), - fieldWithPath("data[].isRead").description("미션 읽음 여부") + fieldWithPath("data[].status").description("미션 상태") ) @@ -151,7 +147,6 @@ public class MissionGatherControllerTest extends CommonControllerTest { .teamName("team name") .missionTitle("mission title") .status("WAIT/ONGOING/END/FAIL/SUCCESS") - .isRead(true) .build()); given(missionGatherBoardUseCase.getTeamActiveSingleMissions(any(),any())).willReturn(output); @@ -182,8 +177,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].dueTo").description("미션 마감 시각"), fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목"), - fieldWithPath("data[].status").description("미션 상태"), - fieldWithPath("data[].isRead").description("미션 읽음 여부") + fieldWithPath("data[].status").description("미션 상태") ) @@ -205,7 +199,6 @@ public class MissionGatherControllerTest extends CommonControllerTest { .doneNum("0") .totalNum("0") .status("WAIT/ONGOING/END/FAIL/SUCCESS") - .isRead(true) .build()); given(missionGatherBoardUseCase.getTeamActiveRepeatMissions(any(),any())).willReturn(output); @@ -237,9 +230,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].missionTitle").description("미션 제목"), fieldWithPath("data[].doneNum").description("완료한 횟수"), fieldWithPath("data[].totalNum").description("전체 횟수"), - fieldWithPath("data[].status").description("미션 상태"), - fieldWithPath("data[].isRead").description("미션 읽음 여부") - + fieldWithPath("data[].status").description("미션 상태") ) From c8c5a2a899e8850675083ad7a96271e14711cf5d Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 5 Feb 2024 14:34:45 +0900 Subject: [PATCH 491/619] =?UTF-8?q?MNG-13=20fix:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=84=A4=EB=AA=85=20=ED=99=95=EC=9D=B8=20API=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/presentation/MissionController.java | 15 +++++++++++++-- .../representation/MissionControllerTest.java | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index bf1f6939..4845baee 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -110,10 +110,10 @@ public ResponseEntity> isLeader(@AuthenticationPrincipa /** * 미션 설명 확인 (미션 읽음 처리) - * [GET] {teamId}/missions/{missionId}/read + * [POST] {teamId}/missions/{missionId}/read * 작성자 : 김민수 */ - @GetMapping("/{missionId}/confirm") + @PostMapping("/{missionId}/confirm") public ResponseEntity> confirmMissionExplanation(@AuthenticationPrincipal User user, @PathVariable Long teamId, @PathVariable Long missionId){ @@ -122,6 +122,17 @@ public ResponseEntity> confirmMissionExplanat } +// @PostMapping("/test") +// public void test() { +// Thread thread1 = new Thread(() -> { +// this.missionReadUseCase.confirmMission("KAKAO@tester01", 1L,1L); +// }); +// Thread thread2 = new Thread(() -> { +// this.missionReadUseCase.confirmMission("KAKAO@tester01", 1L,1L); +// }); +// thread1.start(); +// thread2.start(); +// } } diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index 27a63d54..93be9324 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -419,7 +419,7 @@ public class MissionControllerTest extends CommonControllerTest { given(missionReadUseCase.confirmMission(any(),any(),any())).willReturn(output); //when ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. - get("/api/team/{teamId}/missions/{missionId}/confirm",teamId,missionId) + post("/api/team/{teamId}/missions/{missionId}/confirm",teamId,missionId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) ); From c17899603879627cc76a0956672dbe2eab44f05b Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 5 Feb 2024 14:40:00 +0900 Subject: [PATCH 492/619] =?UTF-8?q?MNG=2013=20refactor:=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=EC=B2=98=EB=A6=AC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/MissionController.java | 12 +- .../global/config/fcm/service/FcmService.java | 174 ------------------ .../config/fcm/util/FcmMessageUtil.java | 44 ----- 3 files changed, 1 insertion(+), 229 deletions(-) delete mode 100644 src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java delete mode 100644 src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index 4845baee..f041b45b 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -122,17 +122,7 @@ public ResponseEntity> confirmMissionExplanat } -// @PostMapping("/test") -// public void test() { -// Thread thread1 = new Thread(() -> { -// this.missionReadUseCase.confirmMission("KAKAO@tester01", 1L,1L); -// }); -// Thread thread2 = new Thread(() -> { -// this.missionReadUseCase.confirmMission("KAKAO@tester01", 1L,1L); -// }); -// thread1.start(); -// thread2.start(); -// } + } diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java b/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java deleted file mode 100644 index 6deaf58d..00000000 --- a/src/main/java/com/moing/backend/global/config/fcm/service/FcmService.java +++ /dev/null @@ -1,174 +0,0 @@ -//package com.moing.backend.global.config.fcm.service; -// -//import com.google.firebase.messaging.*; -//import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; -//import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; -//import com.moing.backend.domain.history.application.service.SaveSingleAlarmHistoryUseCase; -//import com.moing.backend.global.config.fcm.dto.request.MultiRequest; -//import com.moing.backend.global.config.fcm.dto.request.SingleRequest; -//import com.moing.backend.global.config.fcm.dto.response.MultiResponse; -//import com.moing.backend.global.config.fcm.dto.response.SingleResponse; -//import com.moing.backend.global.config.fcm.exception.NotificationException; -//import lombok.RequiredArgsConstructor; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.retry.annotation.Backoff; -//import org.springframework.retry.annotation.Retryable; -//import org.springframework.stereotype.Service; -// -//import javax.transaction.Transactional; -//import java.util.ArrayList; -//import java.util.HashMap; -//import java.util.List; -//import java.util.Map; -// -//@Service -//@Transactional -//@RequiredArgsConstructor -//@Slf4j -//public class FcmService { -// -// private final FirebaseMessaging firebaseMessaging; -// @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) -// public SingleResponse sendSingleDevice(SingleRequest toSingleRequest) { -// -// Notification notification = Notification.builder() -// .setTitle(toSingleRequest.getTitle()) -// .setBody(toSingleRequest.getBody()) -// .build(); -// -// // Android Configuration -// AndroidConfig androidConfig = AndroidConfig.builder() -// .setPriority(AndroidConfig.Priority.HIGH) -// .setNotification(AndroidNotification.builder() -// .setChannelId("FCM_Channel") -// .setTitle(toSingleRequest.getTitle()) -// .setBody(toSingleRequest.getBody()) -// .build()) -// .build(); -// -// // APNs Configuration -// ApnsConfig apnsConfig = ApnsConfig.builder() -// .setAps(Aps.builder() -// .setCategory("YOUR_CATEGORY") // Replace with your category -// .setAlert(ApsAlert.builder() -// .setTitle(toSingleRequest.getTitle()) -// .setBody(toSingleRequest.getBody()) -// .build()) -// .build()) -// .build(); -// -// Map additionalData = new HashMap<>(); -// additionalData.put("path", toSingleRequest.getPath()); -// additionalData.put("idInfo", toSingleRequest.getIdInfo()); -// -// Message message = Message.builder() -// .setToken(toSingleRequest.getRegistrationToken()) -// .setNotification(notification) -// .setAndroidConfig(androidConfig) // Applying Android configuration -// .setApnsConfig(apnsConfig) // Applying APNs configuration -// .putAllData(additionalData) -// .build(); -// -// try { -// String response = firebaseMessaging.send(message); -// return new SingleResponse(response); -// } catch (FirebaseMessagingException e) { -// throw handleException(e); -// } -// } -// -// -// @Retryable(value = FirebaseMessagingException.class, maxAttempts = 3, backoff = @Backoff(delay = 1000)) -// public MultiResponse sendMultipleDevices(MultiRequest toMultiRequest) { -// -// -// List fcmTokens = AlarmHistoryMapper.getFcmTokens(toMultiRequest.getMemberIdAndTokens()); -// Notification notification = Notification.builder() -// .setTitle(toMultiRequest.getTitle()) -// .setBody(toMultiRequest.getBody()) -// .build(); -// -// // Android Configuration -// AndroidConfig androidConfig = AndroidConfig.builder() -// .setPriority(AndroidConfig.Priority.HIGH) -// .setNotification(AndroidNotification.builder() -// .setChannelId("FCM_Channel") -// .setTitle(toMultiRequest.getTitle()) -// .setBody(toMultiRequest.getBody()) -// .build()) -// .build(); -// -// // APNs Configuration -// ApnsConfig apnsConfig = ApnsConfig.builder() -// .setAps(Aps.builder() -// .setCategory("YOUR_CATEGORY") // Replace with your category -// .setAlert(ApsAlert.builder() -// .setTitle(toMultiRequest.getTitle()) -// .setBody(toMultiRequest.getBody()) -// .build()) -// .build()) -// .build(); -// -// Map additionalData = new HashMap<>(); -// additionalData.put("path", toMultiRequest.getPath()); -// additionalData.put("idInfo", toMultiRequest.getIdInfo()); -// -// MulticastMessage message = MulticastMessage.builder() -// .addAllTokens(fcmTokens) -// .setNotification(notification) -// .setAndroidConfig(androidConfig) // Applying Android configuration -// .setApnsConfig(apnsConfig) // Applying APNs configuration -// .putAllData(additionalData) -// .build(); -// -// try { -// BatchResponse response = firebaseMessaging.sendMulticast(message); -// -// -// List failedTokens = new ArrayList<>(); -// -// if (response.getFailureCount() > 0) { -// List responses = response.getResponses(); -// -// List memberIds = AlarmHistoryMapper.getMemberIds(toMultiRequest.getMemberIdAndTokens()); -// -// for (int i = 0; i < responses.size(); i++) { -// if (!responses.get(i).isSuccessful()) { -// // Add the failed tokens to the list -// failedTokens.add(fcmTokens.get(i)); -// } -// } -// } -// -// String messageString = String.format("%d messages were sent successfully.", response.getSuccessCount()); -// -// return new MultiResponse(messageString, failedTokens); -// -// } catch (FirebaseMessagingException e) { -// throw handleException(e); -// } -// } -// -// -// -// private NotificationException handleException(FirebaseMessagingException e) { -// String errorCode = e.getErrorCode().name(); -// String errorMessage = e.getMessage(); -// -// switch (errorCode) { -// case "INVALID_ARGUMENT": -// return new NotificationException("올바르지 않은 인자 값입니다: " + errorMessage); -// case "NOT_FOUND": -// return new NotificationException("등록 토큰이 유효하지 않거나, 주제(Topic)가 존재하지 않습니다: " + errorMessage); -// case "UNREGISTERED": -// return new NotificationException("해당 주제(Topic)의 구독이 해지되었습니다: " + errorMessage); -// case "UNAVAILABLE": -// return new NotificationException("서비스를 사용할 수 없습니다: " + errorMessage); -// default: -// return new NotificationException("메시지 전송에 실패했습니다: " + errorMessage); -// } -// } -// -//} -// -// diff --git a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java b/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java deleted file mode 100644 index 7b375329..00000000 --- a/src/main/java/com/moing/backend/global/config/fcm/util/FcmMessageUtil.java +++ /dev/null @@ -1,44 +0,0 @@ -//package com.moing.backend.global.config.fcm.util; -// -//import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; -//import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; -//import com.moing.backend.domain.history.application.service.SaveSingleAlarmHistoryUseCase; -//import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; -//import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; -//import com.moing.backend.global.config.fcm.dto.request.MultiRequest; -//import com.moing.backend.global.config.fcm.dto.request.SingleRequest; -//import com.moing.backend.global.config.fcm.service.FcmService; -//import lombok.RequiredArgsConstructor; -//import org.springframework.context.event.EventListener; -//import org.springframework.scheduling.annotation.Async; -//import org.springframework.stereotype.Component; -// -//@Component -//@RequiredArgsConstructor -//public class FcmMessageUtil { -// -// private final FcmService fcmService; -// private final SaveSingleAlarmHistoryUseCase saveSingleAlarmHistoryUseCase; -// private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; -// -// @Async -// @EventListener -// public void onMultiFcmEvent(MultiFcmEvent event) { -// if (event.getIdAndTokensByPush().isPresent() && !event.getIdAndTokensByPush().get().isEmpty()) { -// fcmService.sendMultipleDevices(new MultiRequest(event.getIdAndTokensByPush().get(), event.getTitle(), event.getBody(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); -// } -// if (event.getIdAndTokensBySave().isPresent() && !event.getIdAndTokensBySave().get().isEmpty()) { -// saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(event.getIdAndTokensBySave().get()), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); -// } -// } -// -// @Async -// @EventListener -// public void onSingleFcmEvent(SingleFcmEvent event) { -// if (event.getMember().isFirePush() && !event.getMember().isSignOut()) { //알림 on, 로그아웃 안함 -// fcmService.sendSingleDevice(new SingleRequest(event.getMember().getFcmToken(), event.getTitle(), event.getBody(), event.getMember().getMemberId(), event.getIdInfo(), event.getName(), event.getAlarmType(), event.getPath())); -// } -// saveSingleAlarmHistoryUseCase.saveAlarmHistory(event.getMember().getMemberId(), event.getIdInfo(), event.getTitle(), event.getBody(), event.getName(), event.getAlarmType(), event.getPath()); -// } -//} -// From a989fc12ebde635fe7e707e0c587fc20479773b1 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 5 Feb 2024 16:51:59 +0900 Subject: [PATCH 493/619] =?UTF-8?q?MNG-13=20fix:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EB=95=8C=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=ED=95=9C=20=EC=9C=A0=EC=A0=80=20=EB=8B=89=EB=84=A4?= =?UTF-8?q?=EC=9E=84,=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EB=B3=B4=EC=9D=B4=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/board/application/dto/response/BoardBlocks.java | 5 ++--- .../board/domain/repository/BoardCustomRepositoryImpl.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java index a33dcc21..544a626a 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java @@ -7,7 +7,6 @@ @Getter @Builder -@AllArgsConstructor public class BoardBlocks { private Long boardId; @@ -34,7 +33,7 @@ public class BoardBlocks { @QueryProjection - public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, String writerProfileImage, String title, String content, Integer commentNum, Boolean writerIsDeleted, boolean isNotice, Long makerId) { + public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, String writerProfileImage, String title, String content, Integer commentNum, Boolean isRead, Boolean writerIsDeleted, boolean isNotice, Long makerId) { this.boardId = boardId; this.writerNickName = writerNickName; this.writerIsLeader = writerIsLeader; @@ -42,7 +41,7 @@ public BoardBlocks(Long boardId, String writerNickName, Boolean writerIsLeader, this.title = title; this.content = content; this.commentNum = commentNum; - this.isRead = false; + this.isRead = isRead; this.writerIsDeleted=writerIsDeleted; this.isNotice=isNotice; this.makerId = makerId; diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index c051b9fe..1a2771a8 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -36,7 +36,7 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { .exists(); List allBoardBlocks = queryFactory - .select(Projections.constructor(BoardBlocks.class, + .select(new QBoardBlocks( board.boardId, board.teamMember.member.nickName.coalesce("알수없음"), board.isLeader, From 1657749e6c3dca11e44bdd6e5b92c3ceaf5470ae Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 6 Feb 2024 02:24:28 +0900 Subject: [PATCH 494/619] =?UTF-8?q?MNG-13=20test:=20=EA=B0=9C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=A1=B0=ED=9A=8C=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamMember/domain/entity/TeamMember.java | 2 +- .../board/domain/BoardRepositoryTest.java | 128 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java index 5cf9ffea..9d7aa88e 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java @@ -18,7 +18,7 @@ public class TeamMember extends BaseTimeEntity { @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="team_member_id") private Long teamMemberId; diff --git a/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java b/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java new file mode 100644 index 00000000..0bf41f9c --- /dev/null +++ b/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java @@ -0,0 +1,128 @@ +package com.moing.backend.domain.board.domain; + +import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; +import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; +import com.moing.backend.domain.board.application.mapper.BoardMapper; +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.repository.BoardRepository; +import com.moing.backend.domain.boardRead.domain.entity.BoardRead; +import com.moing.backend.domain.boardRead.domain.repository.BoardReadRepository; +import com.moing.backend.domain.member.domain.constant.Gender; +import com.moing.backend.domain.member.domain.constant.RegistrationStatus; +import com.moing.backend.domain.member.domain.constant.Role; +import com.moing.backend.domain.member.domain.constant.SocialProvider; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.repository.MemberRepository; +import com.moing.backend.domain.team.domain.constant.ApprovalStatus; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.repository.TeamRepository; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; +import org.junit.jupiter.api.BeforeEach; +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.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + + +@SpringBootTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ActiveProfiles("dev") +@Transactional +public class BoardRepositoryTest { + + @Autowired + MemberRepository memberRepository; + + @Autowired + TeamMemberRepository teamMemberRepository; + + @Autowired + TeamRepository teamRepository; + + @Autowired + BoardRepository boardRepository; + + @Autowired + BoardReadRepository boardReadRepository; + + private Member minsu, seungyeon; + + private Team team; + private TeamMember deletedTM, validTM; + private CreateBoardRequest createBoardRequest; + + @BeforeEach + void setUp() { + //given + minsu = memberRepository.save(new Member(null, "minsu@naver.com", "undef", Gender.WOMAN, null, "민수", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@minsu")); + seungyeon = memberRepository.save(new Member(null, "seungyeon@naver.com", "undef", Gender.WOMAN, null, "승연", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@seungyeon")); + + team = teamRepository.save(Team.builder() + .category("ETC") + .name("소모임 이름") + .introduction("소모임 소개") + .promise("소모임 각오") + .profileImgUrl("소모임 프로필 이미지 url") + .approvalStatus(ApprovalStatus.APPROVAL) + .leaderId(1L) + .numOfMember(2) + .levelOfFire(1) + .build()); + + validTM=teamMemberRepository.save(TeamMember.builder().team(team).member(minsu).isDeleted(false).build()); + deletedTM=teamMemberRepository.save(TeamMember.builder().team(team).member(seungyeon).isDeleted(true).build()); + + createBoardRequest = CreateBoardRequest.builder() + .title("게시글 제목") + .content("게시글 내용") + .isNotice(false) + .build(); + } + + @Test + @DisplayName("게시글을 읽은 경우") + void whenBoardIsRead_thenMarkAsRead() { + //given + Board board = boardRepository.save(BoardMapper.toBoard(validTM, team, createBoardRequest, false)); + + boardReadRepository.save(new BoardRead(null, board, team, minsu)); + + //when + GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), minsu.getMemberId()); + + //then + assertThat(response.getNotNoticeBlocks().get(0).getIsRead()).isTrue(); + } + + @Test + @DisplayName("게시글을 읽지 않은 경우") + void whenBoardIsNotRead_thenMarkAsUnread() { + //given + Board board = boardRepository.save(BoardMapper.toBoard(validTM, team, createBoardRequest, false)); + + //when + GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), minsu.getMemberId()); + + //then + assertThat(response.getNotNoticeBlocks().get(0).getIsRead()).isFalse(); + } + @Test + @DisplayName("작성자가 삭제된 경우") + void 게시글_작성자가_탈퇴하지_않은_경우_게시글_전체_조회() { + //given + Board board = boardRepository.save(BoardMapper.toBoard(deletedTM, team, createBoardRequest, false)); //작성자 탈퇴한 경우 + + //when + GetAllBoardResponse response=boardRepository.findBoardAll(team.getTeamId(),minsu.getMemberId()); + + //then + assertThat(response.getNotNoticeBlocks().get(0).getWriterNickName()).isEqualTo("(알 수 없음)"); + } +} From 0e3bb00a04e04dfbe3ca00341d7ae29d545fc764 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 6 Feb 2024 02:38:59 +0900 Subject: [PATCH 495/619] =?UTF-8?q?MNG-13=20fix:=20gradle=20test=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionStateQueryServiceTest.java | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java b/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java index 91a716c3..3e8be90c 100644 --- a/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java +++ b/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java @@ -1,35 +1,35 @@ -package com.moing.backend.domain.missionState.domain.service; - -import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; -import com.moing.backend.domain.missionState.domain.repository.MissionStateCustomRepository; -import com.moing.backend.domain.missionState.domain.repository.MissionStateCustomRepositoryImpl; -import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; - -import javax.persistence.EntityManager; - -import static org.junit.jupiter.api.Assertions.*; - -@SpringBootTest -class MissionStateQueryServiceTest { - - - @MockBean - MissionStateQueryService missionStateQueryService ; - @MockBean - MissionStateCustomRepositoryImpl missionStateCustomRepository ; - - - @Test - public void missionDonePeople() { - System.out.println(missionStateQueryService.stateCountByMissionId(4L)); - } - - - - - -} \ No newline at end of file +//package com.moing.backend.domain.missionState.domain.service; +// +//import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +//import com.moing.backend.domain.missionState.domain.repository.MissionStateCustomRepository; +//import com.moing.backend.domain.missionState.domain.repository.MissionStateCustomRepositoryImpl; +//import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; +//import org.junit.jupiter.api.Test; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.boot.test.mock.mockito.MockBean; +// +//import javax.persistence.EntityManager; +// +//import static org.junit.jupiter.api.Assertions.*; +// +//@SpringBootTest +//class MissionStateQueryServiceTest { +// +// +// @MockBean +// MissionStateQueryService missionStateQueryService ; +// @MockBean +// MissionStateCustomRepositoryImpl missionStateCustomRepository ; +// +// +// @Test +// public void missionDonePeople() { +// System.out.println(missionStateQueryService.stateCountByMissionId(4L)); +// } +// +// +// +// +// +//} \ No newline at end of file From 0484ee641912fec587b4c9ec77638a29d61837c5 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 6 Feb 2024 14:31:33 +0900 Subject: [PATCH 496/619] =?UTF-8?q?MNG-14=20fix:=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=ED=9E=88=EC=8A=A4=ED=86=A0=EB=A6=AC=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=A0=20=EB=95=8C=20=EB=AA=A8=EB=91=90=20?= =?UTF-8?q?=EC=9D=BD=EC=9D=8C=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/GetAlarmHistoryUseCase.java | 2 +- .../AlarmHistoryCustomRepositoryImpl.java | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java b/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java index b0eba8af..612c0eae 100644 --- a/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java +++ b/src/main/java/com/moing/backend/domain/history/application/service/GetAlarmHistoryUseCase.java @@ -21,7 +21,7 @@ public class GetAlarmHistoryUseCase { /** * 알림 히스토리 조회 */ - @Transactional(readOnly = true) + @Transactional public List getAllAlarmHistories(String socialId) { Member member = memberGetService.getMemberBySocialId(socialId); return alarmHistoryGetService.getAlarmHistories(member.getMemberId()); diff --git a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java index b7c816b4..2176d113 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/history/domain/repository/AlarmHistoryCustomRepositoryImpl.java @@ -3,23 +3,28 @@ import com.moing.backend.domain.history.application.dto.response.GetAlarmHistoryResponse; import com.moing.backend.domain.history.application.dto.response.QGetAlarmHistoryResponse; import com.querydsl.jpa.impl.JPAQueryFactory; +import com.querydsl.jpa.impl.JPAUpdateClause; import javax.persistence.EntityManager; import java.util.List; import static com.moing.backend.domain.history.domain.entity.QAlarmHistory.alarmHistory; +import static com.moing.backend.domain.team.domain.entity.QTeam.team; public class AlarmHistoryCustomRepositoryImpl implements AlarmHistoryCustomRepository { private final JPAQueryFactory queryFactory; + private final EntityManager em; + public AlarmHistoryCustomRepositoryImpl(EntityManager em) { this.queryFactory = new JPAQueryFactory(em); + this.em = em; } @Override public List findAlarmHistoriesByMemberId(Long memberId) { - return queryFactory.select(new QGetAlarmHistoryResponse(alarmHistory.id, + List response= queryFactory.select(new QGetAlarmHistoryResponse(alarmHistory.id, alarmHistory.type, alarmHistory.path, alarmHistory.idInfo, @@ -32,8 +37,21 @@ public List findAlarmHistoriesByMemberId(Long memberId) .where(alarmHistory.receiverId.eq(memberId)) .orderBy(alarmHistory.createdDate.desc()) .fetch(); + + readAlarmHistory(memberId); + return response; } + private void readAlarmHistory(Long memberId){ + queryFactory + .update(alarmHistory) + .set(alarmHistory.isRead, true) + .where(alarmHistory.receiverId.eq(memberId)) + .execute(); + + em.flush(); + em.clear(); + } @Override public String findUnreadAlarmCount(Long memberId) { Long count = queryFactory.select(alarmHistory.count()) From 553379bde77cf1b79a9498f1e926590c7243e3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 6 Feb 2024 23:09:46 +0900 Subject: [PATCH 497/619] =?UTF-8?q?MNG-10=20fix=20:=20=EB=8B=B9=EC=9D=BC?= =?UTF-8?q?=EC=97=90=20=EC=9D=B8=EC=A6=9D=EC=9D=84=20=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EC=9D=80=20=EB=AA=A8=EC=9E=84=EC=9B=90=EB=A7=8C=20?= =?UTF-8?q?=EB=B6=88=EB=8D=98=EC=A7=80=EA=B8=B0=EC=97=90=20=EB=9D=84?= =?UTF-8?q?=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/FireCustomRepositoryImpl.java | 99 ++++++++++--------- 1 file changed, 52 insertions(+), 47 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 4dea8c43..78a51b2a 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -1,13 +1,9 @@ package com.moing.backend.domain.fire.domain.repository; import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; -import com.moing.backend.domain.fire.domain.entity.Fire; -import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -20,12 +16,9 @@ import java.util.Optional; import static com.moing.backend.domain.fire.domain.entity.QFire.fire; -import static com.moing.backend.domain.member.domain.entity.QMember.member; import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; -import static com.moing.backend.domain.team.domain.entity.QTeam.team; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; -import static com.querydsl.jpa.JPAExpressions.max; import static com.querydsl.jpa.JPAExpressions.select; public class FireCustomRepositoryImpl implements FireCustomRepository { @@ -53,53 +46,24 @@ public boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMembe return count <= 0; // 1시간 이내에 생성된 데이터가 존재하면 true를 반환, 그렇지 않으면 false 반환 } - public Optional> getFireReceivers(Long teamId, Long missionId, Long memberId) { - BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); - - JPQLQuery missionDonePeople = select(missionArchive.member.memberId) - .from(missionArchive, mission) - .where(missionArchive.mission.id.eq(missionId), - mission.id.eq(missionId) - ) - .groupBy(missionArchive.member.memberId, - missionArchive.mission.id, - missionArchive.count, - mission.number) - .having( - missionArchive.mission.id.eq(missionId), - missionArchive.count.max().goe(mission.number), - (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) - ); - - LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1); // 현재 시간에서 1시간을 뺀 시간 - - BooleanExpression oneHourStatus = JPAExpressions - .select() - .from(fire) - .where( - fire.throwMemberId.eq(memberId), - fire.receiveMemberId.notIn(missionDonePeople), - fire.createdDate.after(oneHourAgo) // createdDate가 oneHourAgo 이후인 데이터 - ) - - .exists(); + JPQLQuery todayCompletedMemberOfRepeat = todayRepeatMissionDone(missionId); + JPQLQuery completedMembersOfAll = allMissionDone(missionId); return Optional.ofNullable(queryFactory .select(Projections.constructor(FireReceiveRes.class, - teamMember.member.memberId, - teamMember.member.nickName, - teamMember.member.profileImage -// oneHourStatus.stringValue() -// teamMember.member.nickName - )) + teamMember.member.memberId, + teamMember.member.nickName, + teamMember.member.profileImage + )) .from(teamMember) .where( teamMember.team.teamId.eq(teamId), teamMember.member.memberId.ne(memberId), - teamMember.member.memberId.notIn(missionDonePeople), + teamMember.member.memberId.notIn(completedMembersOfAll) + .and(teamMember.member.memberId.notIn(todayCompletedMemberOfRepeat)), teamMember.isDeleted.ne(Boolean.TRUE) ) .fetch()); @@ -113,11 +77,52 @@ private BooleanExpression createRepeatTypeConditionByArchive() { LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); LocalDate endOfWeek = startOfWeek.plusDays(6); - BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) + return missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + } - // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 - return dateInRange.and(dateInRange); + private JPQLQuery todayRepeatMissionDone(Long missionId) { + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + + return + select(missionArchive.member.memberId) + .from(missionArchive, mission) + .where(missionArchive.mission.id.eq(missionId), + mission.id.eq(missionId), + (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) + ) + .groupBy(missionArchive.member.memberId, + missionArchive.mission.id, + missionArchive.count, + mission.number, + missionArchive.mission.type, + missionArchive.createdDate) + .having( + missionArchive.mission.id.eq(missionId), + (missionArchive.mission.type.eq(MissionType.REPEAT)).or(missionArchive.mission.type.eq(MissionType.ONCE)) + ); } + private JPQLQuery allMissionDone(Long missionId) { + + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + + return + select(missionArchive.member.memberId) + .from(missionArchive, mission) + .where(missionArchive.mission.id.eq(missionId), + mission.id.eq(missionId), + (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) + ) + .groupBy(missionArchive.member.memberId, + missionArchive.mission.id, + missionArchive.count, + mission.number) + .having( + missionArchive.mission.id.eq(missionId), + missionArchive.count.max().goe(mission.number) + ); + } + + } From c1d4ed91260afdc3348cd8113c76949f3cf10c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 7 Feb 2024 00:20:16 +0900 Subject: [PATCH 498/619] =?UTF-8?q?MNG-12=20fix=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EB=A6=AC=ED=84=B4=EA=B0=92=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20+=20=EB=AF=B8=EC=85=98=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9E=90=20=EC=9D=B4=EC=99=B8=20=EC=88=98=EC=A0=95/?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EB=B6=88=EA=B0=80=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/mapper/MissionMapper.java | 4 +- .../service/MissionDeleteUseCase.java | 16 ++++ .../MissionStateTerminateBatchConfig.java | 96 ------------------- .../service/MissionTerminateConfig.java | 94 ------------------ .../service/MissionUpdateUseCase.java | 20 ++-- .../application/service/RepeatMissionEnd.java | 94 ------------------ .../domain/mission/domain/entity/Mission.java | 5 +- .../MissionCustomRepositoryImpl.java | 3 +- .../exception/NoAccessDeleteMission.java | 12 +++ .../exception/NoAccessUpdateMission.java | 12 +++ .../backend/global/response/ErrorCode.java | 2 + .../representation/MissionControllerTest.java | 9 +- 12 files changed, 68 insertions(+), 299 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionStateTerminateBatchConfig.java delete mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminateConfig.java delete mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java create mode 100644 src/main/java/com/moing/backend/domain/mission/exception/NoAccessDeleteMission.java create mode 100644 src/main/java/com/moing/backend/domain/mission/exception/NoAccessUpdateMission.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java index 01da4b6b..5d0f10a2 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java +++ b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java @@ -30,6 +30,7 @@ public static Mission mapToMission(MissionReq missionReq, Member member, Mission .type(MissionType.valueOf(missionReq.getType())) .number(missionReq.getNumber()) .status(status) + .makerId(member.getMemberId()) .build(); } @@ -47,7 +48,7 @@ public static MissionCreateRes mapToMissionCreateRes(Mission mission) { .type(mission.getType().name()) .status(mission.getStatus().name()) .number(mission.getNumber()) - .isLeader(Boolean.TRUE) + .isLeader(mission.getTeam().getLeaderId().equals(mission.getMakerId())) .build(); } @@ -60,6 +61,7 @@ public static MissionReadRes mapToMissionReadRes(Mission mission) { .way(mission.getWay().name()) .content(mission.getContent()) .type(mission.getType().name()) + .isLeader(mission.getTeam().getLeaderId().equals(mission.getMakerId())) .build(); } } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java index b68bf10d..9902c639 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java @@ -2,8 +2,15 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.mission.domain.service.MissionDeleteService; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.mission.exception.NoAccessCreateMission; +import com.moing.backend.domain.mission.exception.NoAccessDeleteMission; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.global.response.BaseServiceResponse; +import com.moing.backend.global.utils.BaseService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -16,10 +23,19 @@ public class MissionDeleteUseCase { private final MissionDeleteService missionDeleteService; private final MemberGetService memberGetService; + private final BaseService baseService; + private final MissionQueryService missionQueryService; + public Long deleteMission(String userSocialId,Long missionId) { + Member member = memberGetService.getMemberBySocialId(userSocialId); + Mission mission = missionQueryService.findMissionById(missionId); + + if (!member.getMemberId().equals(mission.getMakerId())) { + throw new NoAccessDeleteMission(); + } return missionDeleteService.deleteMission(missionId); } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionStateTerminateBatchConfig.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionStateTerminateBatchConfig.java deleted file mode 100644 index 4e4885e2..00000000 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionStateTerminateBatchConfig.java +++ /dev/null @@ -1,96 +0,0 @@ -//package com.moing.backend.domain.mission.application.service; -// -//import com.moing.backend.domain.mission.domain.entity.Mission; -//import com.moing.backend.domain.missionState.domain.entity.MissionState; -//import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; -//import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; -//import lombok.RequiredArgsConstructor; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.batch.core.Job; -//import org.springframework.batch.core.Step; -//import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -//import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -//import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; -//import org.springframework.batch.core.configuration.annotation.StepScope; -//import org.springframework.batch.item.ItemProcessor; -//import org.springframework.batch.item.database.JpaItemWriter; -//import org.springframework.batch.item.database.JpaPagingItemReader; -//import org.springframework.batch.item.database.builder.JpaItemWriterBuilder; -//import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -// -//import javax.persistence.EntityManagerFactory; -//import java.util.HashMap; -//import java.util.Map; -// -//@Slf4j -//@Configuration -//@EnableBatchProcessing -//@RequiredArgsConstructor -//public class MissionStateTerminateBatchConfig { -// -// private final JobBuilderFactory jobBuilderFactory; -// private final StepBuilderFactory stepBuilderFactory; -// private final EntityManagerFactory entityManagerFactory; -// -// private final TeamScoreLogicUseCase teamScoreLogicUseCase; -// private final MissionStateDeleteService missionStateDeleteService; -// -// @Bean -// public Job missionTerminateJob() { -// return jobBuilderFactory.get("missionTerminateJob") -// .start(missionTerminateStep()) -// .build(); -// } -// -// @Bean -// public Step missionTerminateStep() { -// return stepBuilderFactory.get("missionTerminateStep") -// .chunk(10) -// .reader(missionReader()) -// .processor(missionProcessor()) -// .writer(missionWriter()) -// .reader(missionStateReader()) -// .processor(missionStateProcessor()) -// .writer(missionStateWriter()) -// .build(); -// } -// -// @Bean -// @StepScope -// public JpaPagingItemReader missionStateReader() { -// -// Map parameterValues = new HashMap<>(); -// parameterValues.put("missionId", 10000); -// -// .parameterValues(parameterValues) // 쿼리 파라미터 설정 -// -// return new JpaPagingItemReaderBuilder() -// .name("missionStateReader") -// .entityManagerFactory(entityManagerFactory) -// .queryString("SELECT m FROM MissionState m WHERE m.mission_id = :missionId") -// .pageSize(10) -// .build(); -// } -// -// @Bean -// public ItemProcessor missionStateProcessor() { -// return mission -> { -// teamScoreLogicUseCase.updateTeamScore(mission.getId()); -// return mission; -// }; -// } -// -// -// -// @Bean -// public JpaItemWriter missionStateWriter() { -// return new JpaItemWriterBuilder() -// .entityManagerFactory(entityManagerFactory) -// .build(); -// } -// -// -// -//} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminateConfig.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminateConfig.java deleted file mode 100644 index 836a5aff..00000000 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminateConfig.java +++ /dev/null @@ -1,94 +0,0 @@ -//package com.moing.backend.domain.mission.application.service; -// -//import com.moing.backend.domain.mission.domain.entity.Mission; -//import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -//import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -//import com.moing.backend.domain.missionState.application.service.MissionStateScheduleUseCase; -//import com.moing.backend.domain.missionState.domain.entity.MissionState; -//import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; -//import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; -//import lombok.RequiredArgsConstructor; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.batch.core.Job; -//import org.springframework.batch.core.Step; -//import org.springframework.batch.core.configuration.annotation.*; -//import org.springframework.batch.item.ItemProcessor; -//import org.springframework.batch.item.database.JpaItemWriter; -//import org.springframework.batch.item.database.JpaPagingItemReader; -//import org.springframework.batch.item.database.builder.JpaItemWriterBuilder; -//import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -// -//import javax.persistence.EntityManagerFactory; -//import java.util.HashMap; -//import java.util.Map; -//import java.util.Optional; -// -//import static com.moing.backend.domain.mission.domain.entity.QMission.mission; -// -//@Slf4j -//@Configuration -//@EnableBatchProcessing -//@RequiredArgsConstructor -//public class MissionTerminateBatchConfig { -// -// private final JobBuilderFactory jobBuilderFactory; -// private final StepBuilderFactory stepBuilderFactory; -// private final EntityManagerFactory entityManagerFactory; -// -// private final TeamScoreLogicUseCase teamScoreLogicUseCase; -// private final MissionStateDeleteService missionStateDeleteService; -// private final MissionStateScheduleUseCase missionStateScheduleUseCase; -// -// @Bean -// public Job missionTerminateJob() { -// return jobBuilderFactory.get("missionTerminateJob") -// .start(missionTerminateStep()) -// .build(); -// } -// -// @Bean -// public Step missionTerminateStep() { -// return stepBuilderFactory.get("missionTerminateStep") -// .chunk(10) -// .reader(missionReader()) -// .processor(missionProcessor()) -// .writer(missionWriter()) -// .build(); -// } -// -// @Bean -// @StepScope -// public JpaPagingItemReader missionReader() { -// return new JpaPagingItemReaderBuilder() -// .name("missionReader") -// .entityManagerFactory(entityManagerFactory) -// .queryString("SELECT m FROM Mission m WHERE m.status = 'ONGOING' AND m.type = 'REPEAT'") -// .pageSize(10) -// .build(); -// } -// -// @Bean -// public ItemProcessor missionProcessor() { -// return mission -> { -// teamScoreLogicUseCase.updateTeamScore(mission.getId()); -// return mission; -// }; -// } -// -// -// -// @Bean -// public JpaItemWriter teamScoreWriter() { -// missionStateScheduleUseCase.missionStateReset(); -// return new JpaItemWriterBuilder() -// .entityManagerFactory(entityManagerFactory) -// .build(); -// } -// -// -// -// -// -//} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index 4916d151..d64b1773 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -11,6 +11,8 @@ import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.mission.domain.service.MissionSaveService; import com.moing.backend.domain.mission.exception.NoAccessCreateMission; +import com.moing.backend.domain.mission.exception.NoAccessDeleteMission; +import com.moing.backend.domain.mission.exception.NoAccessUpdateMission; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -31,12 +33,18 @@ public MissionCreateRes updateMission(String userSocialId, Long missionId, Missi Member member = memberGetService.getMemberBySocialId(userSocialId); + Mission mission = missionQueryService.findMissionById(missionId); - // 소모임장 확인 로직 추가 - Mission findMission = missionQueryService.findMissionById(missionId); - findMission.updateMission(missionReq); + /** + * 미션 생성자 확인 + */ + + if (!member.getMemberId().equals(mission.getMakerId())) { + throw new NoAccessUpdateMission(); + } + mission.updateMission(missionReq); - return MissionMapper.mapToMissionCreateRes(findMission); + return MissionMapper.mapToMissionCreateRes(mission); } @@ -47,11 +55,11 @@ public MissionReadRes updateMissionStatus(String userSocialId, Long missionId) { Mission findMission = missionQueryService.findMissionById(missionId); Team team = findMission.getTeam(); - if (team.getLeaderId().equals(member.getMemberId())) { + if (findMission.getMakerId().equals(member.getMemberId())) { findMission.updateStatus(MissionStatus.END); findMission.updateDueTo(LocalDateTime.now()); } else { - throw new NoAccessCreateMission(); + throw new NoAccessUpdateMission(); } return MissionMapper.mapToMissionReadRes(findMission); diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java b/src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java deleted file mode 100644 index 114a2e95..00000000 --- a/src/main/java/com/moing/backend/domain/mission/application/service/RepeatMissionEnd.java +++ /dev/null @@ -1,94 +0,0 @@ -//package com.moing.backend.domain.mission.application.service; -// -//import com.moing.backend.domain.mission.domain.entity.Mission; -//import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; -//import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; -//import lombok.RequiredArgsConstructor; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.batch.core.Job; -//import org.springframework.batch.core.Step; -//import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -//import org.springframework.batch.core.configuration.annotation.JobScope; -//import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; -//import org.springframework.batch.core.configuration.annotation.StepScope; -//import org.springframework.batch.item.ItemProcessor; -//import org.springframework.batch.item.database.JpaItemWriter; -//import org.springframework.batch.item.database.JpaPagingItemReader; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -// -//import javax.persistence.EntityManagerFactory; -// -//@Slf4j -//@RequiredArgsConstructor -//@Configuration -//public class RepeatMissionEnd { -// -// public static final String JOB_NAME = "makeMissionEnd"; -// -// private final EntityManagerFactory entityManagerFactory; -// private final StepBuilderFactory stepBuilderFactory; -// private final JobBuilderFactory jobBuilderFactory; -// -// private final MissionStateUseCase missionStateUseCase; -// private final TeamScoreLogicUseCase teamScoreLogicUseCase; -// -// private final int chunkSize = 10; -// -// @Bean -// public Job payPagingJob() { -// return jobBuilderFactory.get(JOB_NAME) -// .start(payPagingStep()) -// .build(); -// } -// -// @Bean -// @JobScope -// public Step payPagingStep() { -// return stepBuilderFactory.get("makeMissionEndStep") -// .chunk(chunkSize) -// .reader(payPagingReader()) -// .processor(payPagingProcessor()) -// .writer(writer()) -// .build(); -// } -// -// @Bean -// @StepScope -// public JpaPagingItemReader payPagingReader() { -// -// JpaPagingItemReader reader = new JpaPagingItemReader() { -// @Override -// public int getPage() { -// return 0; -// } -// }; -// -// reader.setQueryString("SELECT m FROM Mission m WHERE m.status = 'ONGOING' AND m.type = 'REPEAT'"); -// reader.setPageSize(chunkSize); -// reader.setEntityManagerFactory(entityManagerFactory); -// reader.setName("payPagingReader"); -// -// return reader; -// } -// -// // sundayRepeatMissionRoutine() -// @Bean -// @StepScope -// public ItemProcessor payPagingProcessor() { -// return mission -> { -// teamScoreLogicUseCase.updateTeamScore(mission.getId()); -// missionStateUseCase.deleteAllMissionState(mission.getId()); -// mission.makeEnd(); -// return mission; -// }; -// } -// -// @Bean -// @StepScope -// public JpaItemWriter writer() { -// JpaItemWriter writer = new JpaItemWriter<>(); -// writer.setEntityManagerFactory(entityManagerFactory); -// return writer; -// } -//} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index 60fd58d3..8a346a05 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -38,6 +38,8 @@ public class Mission extends BaseTimeEntity { private int number; + private Long makerId; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_id") private Team team; @@ -58,7 +60,7 @@ public class Mission extends BaseTimeEntity { List missionStateList = new ArrayList<>(); @Builder - public Mission(String title, LocalDateTime dueTo, String rule, String content, int number, Team team, MissionType type, MissionStatus status, MissionWay way) { + public Mission(String title, LocalDateTime dueTo, String rule, String content, int number, Team team, MissionType type, MissionStatus status, MissionWay way,Long makerId) { this.title = title; this.dueTo = dueTo; this.rule = rule; @@ -68,6 +70,7 @@ public Mission(String title, LocalDateTime dueTo, String rule, String content, i this.type = type; this.status = status; this.way = way; + this.makerId = makerId; } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index a585c651..884aabee 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -178,8 +178,7 @@ public boolean findRepeatMissionsByTeamId(Long teamId) { @Override public Optional findByIds(Long memberId, Long missionId) { - - BooleanExpression isLeader = mission.team.leaderId.eq(memberId); + BooleanExpression isLeader = mission.makerId.eq(memberId); return Optional.ofNullable(queryFactory .select(Projections.constructor(MissionReadRes.class, diff --git a/src/main/java/com/moing/backend/domain/mission/exception/NoAccessDeleteMission.java b/src/main/java/com/moing/backend/domain/mission/exception/NoAccessDeleteMission.java new file mode 100644 index 00000000..5265c4c7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/exception/NoAccessDeleteMission.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mission.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NoAccessDeleteMission extends MissionException { + + public NoAccessDeleteMission() { + super(ErrorCode.NO_ACCESS_DELETE_MISSION, + HttpStatus.UNAUTHORIZED); + } +} diff --git a/src/main/java/com/moing/backend/domain/mission/exception/NoAccessUpdateMission.java b/src/main/java/com/moing/backend/domain/mission/exception/NoAccessUpdateMission.java new file mode 100644 index 00000000..e1a5045b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/exception/NoAccessUpdateMission.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mission.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NoAccessUpdateMission extends MissionException { + + public NoAccessUpdateMission() { + super(ErrorCode.NO_ACCESS_UPDATE_MISSION, + HttpStatus.UNAUTHORIZED); + } +} diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index d5aa9c43..86c82168 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -27,6 +27,8 @@ public enum ErrorCode { //미션 관련 에러코드 NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), + NO_ACCESS_UPDATE_MISSION("M0001", "미션 생성자만 미션을 수정할 수 있습니다."), + NO_ACCESS_DELETE_MISSION("M0001", "미션 생성자만 미션을 삭제할 수 있습니다."), NOT_FOUND_MISSION("M0002", "미션을 찾을 수 없습니다."), NOT_FOUND_END_MISSION("M0003", "기한이 지난 미션을 찾을 수 없습니다."), NO_MORE_CREATE_MISSION("M0004", "반복미션은 2개까지 생성할 수 있습니다."), diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index e1736dfd..192d803d 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -126,7 +126,7 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.type").description("미션 유형(단일/반복)"), fieldWithPath("data.way").description("미션 진행 방법(사진/글/링크)"), fieldWithPath("data.status").description("미션 진행 상태"), - fieldWithPath("data.isLeader").description("소모임장 여부") + fieldWithPath("data.isLeader").description("미션 생성자 여부") ) ) ) @@ -207,7 +207,7 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.type").description("미션 유형(ONCE/REPEAT)"), fieldWithPath("data.way").description("미션 진행 방법(TEXT/PHOTO/LINK)"), fieldWithPath("data.status").description("미션 진행 상태(END/ONGOING/SUCCESS/FAIL)"), - fieldWithPath("data.isLeader").description("소모임장 여부") + fieldWithPath("data.isLeader").description("미션 생성자 여부") ) ) @@ -264,7 +264,7 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.content").description("미션 내용"), fieldWithPath("data.way").description("미션 진행 방법(TEXT/PHOTO/LINK)"), fieldWithPath("data.type").description("미션 유형(ONCE/REPEAT)"), - fieldWithPath("data.isLeader").description("소모임장인지 여부") + fieldWithPath("data.isLeader").description("미션 생성자 여부") ) @@ -278,7 +278,6 @@ public class MissionControllerTest extends CommonControllerTest { public void 미션_삭제() throws Exception { //given - Long teamId = 2L; Long missionId = 1L; //when @@ -398,7 +397,7 @@ public class MissionControllerTest extends CommonControllerTest { fieldWithPath("data.content").description("미션 내용"), fieldWithPath("data.way").description("미션 진행 방법(TEXT/PHOTO/LINK)"), fieldWithPath("data.type").description("미션 유형(ONCE/REPEAT)"), - fieldWithPath("data.isLeader").description("소모임장 여부") + fieldWithPath("data.isLeader").description("미션 생성자 여부") ) ) From d321bdc5dfbd811c4a010d0491404f635bde4338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 8 Feb 2024 00:24:46 +0900 Subject: [PATCH 499/619] =?UTF-8?q?MNG-12=20fix=20:=20=EC=86=8C=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=EC=9E=A5=EC=97=90=EA=B2=8C=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EA=B6=8C=ED=95=9C=20=EB=B6=80=EC=97=AC=20?= =?UTF-8?q?(isLeader=20=EA=B0=92)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mission/application/mapper/MissionMapper.java | 8 ++++---- .../mission/application/service/MissionCreateUseCase.java | 2 +- .../mission/application/service/MissionUpdateUseCase.java | 4 ++-- .../domain/repository/MissionCustomRepositoryImpl.java | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java index 5d0f10a2..a6ca5266 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java +++ b/src/main/java/com/moing/backend/domain/mission/application/mapper/MissionMapper.java @@ -35,7 +35,7 @@ public static Mission mapToMission(MissionReq missionReq, Member member, Mission } - public static MissionCreateRes mapToMissionCreateRes(Mission mission) { + public static MissionCreateRes mapToMissionCreateRes(Mission mission,Member member) { return MissionCreateRes.builder() @@ -48,11 +48,11 @@ public static MissionCreateRes mapToMissionCreateRes(Mission mission) { .type(mission.getType().name()) .status(mission.getStatus().name()) .number(mission.getNumber()) - .isLeader(mission.getTeam().getLeaderId().equals(mission.getMakerId())) + .isLeader( mission.getMakerId().equals(member.getMemberId()) || mission.getTeam().getLeaderId().equals(member.getMemberId())) .build(); } - public static MissionReadRes mapToMissionReadRes(Mission mission) { + public static MissionReadRes mapToMissionReadRes(Mission mission,Member member) { return MissionReadRes.builder() .title(mission.getTitle()) @@ -61,7 +61,7 @@ public static MissionReadRes mapToMissionReadRes(Mission mission) { .way(mission.getWay().name()) .content(mission.getContent()) .type(mission.getType().name()) - .isLeader(mission.getTeam().getLeaderId().equals(mission.getMakerId())) + .isLeader( mission.getMakerId().equals(member.getMemberId()) || mission.getTeam().getLeaderId().equals(member.getMemberId())) .build(); } } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index 81d95b1b..c287e3f6 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -59,7 +59,7 @@ public MissionCreateRes createMission(String socialId, Long teamId, MissionReq m // 3. 알림 보내기 - 미션 생성 sendMissionCreateAlarmUseCase.sendNewMissionUploadAlarm(member, mission); - return MissionMapper.mapToMissionCreateRes(mission); + return MissionMapper.mapToMissionCreateRes(mission,member); } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index d64b1773..e6f6408a 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -44,7 +44,7 @@ public MissionCreateRes updateMission(String userSocialId, Long missionId, Missi } mission.updateMission(missionReq); - return MissionMapper.mapToMissionCreateRes(mission); + return MissionMapper.mapToMissionCreateRes(mission,member); } @@ -62,7 +62,7 @@ public MissionReadRes updateMissionStatus(String userSocialId, Long missionId) { throw new NoAccessUpdateMission(); } - return MissionMapper.mapToMissionReadRes(findMission); + return MissionMapper.mapToMissionReadRes(findMission,member); } } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 884aabee..d65a05a2 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -178,7 +178,7 @@ public boolean findRepeatMissionsByTeamId(Long teamId) { @Override public Optional findByIds(Long memberId, Long missionId) { - BooleanExpression isLeader = mission.makerId.eq(memberId); + BooleanExpression isLeader = mission.makerId.eq(memberId).or(mission.team.leaderId.eq(memberId)); return Optional.ofNullable(queryFactory .select(Projections.constructor(MissionReadRes.class, From e80f5f53140b9df3155ef09de41a9d33ff6ac4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 8 Feb 2024 00:29:01 +0900 Subject: [PATCH 500/619] =?UTF-8?q?MNG-12=20fix=20:=20=EC=86=8C=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=EC=9E=A5=20=EC=88=98=EC=A0=95/=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionDeleteUseCase.java | 6 ++++-- .../mission/application/service/MissionUpdateUseCase.java | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java index 9902c639..2a6479f6 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionDeleteUseCase.java @@ -30,10 +30,12 @@ public Long deleteMission(String userSocialId,Long missionId) { Member member = memberGetService.getMemberBySocialId(userSocialId); - Mission mission = missionQueryService.findMissionById(missionId); + Team team = mission.getTeam(); + + Long memberId = member.getMemberId(); - if (!member.getMemberId().equals(mission.getMakerId())) { + if (!memberId.equals(mission.getMakerId()) || memberId.equals(team.getLeaderId())) { throw new NoAccessDeleteMission(); } return missionDeleteService.deleteMission(missionId); diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index e6f6408a..c6dfb752 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -34,12 +34,15 @@ public MissionCreateRes updateMission(String userSocialId, Long missionId, Missi Member member = memberGetService.getMemberBySocialId(userSocialId); Mission mission = missionQueryService.findMissionById(missionId); + Team team = mission.getTeam(); + + Long memberId = member.getMemberId(); /** * 미션 생성자 확인 */ - if (!member.getMemberId().equals(mission.getMakerId())) { + if (!memberId.equals(mission.getMakerId()) || memberId.equals(team.getLeaderId())) { throw new NoAccessUpdateMission(); } mission.updateMission(missionReq); From 571befff3f4018be0d353b58d2466b30e04690f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 8 Feb 2024 01:14:46 +0900 Subject: [PATCH 501/619] =?UTF-8?q?MNG-12=20fix=20:=20=EC=86=8C=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=EC=9E=A5=20=EC=88=98=EC=A0=95=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EA=B6=8C=ED=95=9C=20=EB=B6=80=EC=97=AC=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?customImpl=20=EC=97=90=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionCustomRepositoryImpl.java | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index d65a05a2..1527cfe9 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.QMission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; @@ -24,6 +25,7 @@ import java.util.List; import java.util.Optional; +import static com.moing.backend.domain.mission.domain.entity.QMission.*; import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; @@ -178,21 +180,28 @@ public boolean findRepeatMissionsByTeamId(Long teamId) { @Override public Optional findByIds(Long memberId, Long missionId) { - BooleanExpression isLeader = mission.makerId.eq(memberId).or(mission.team.leaderId.eq(memberId)); - - return Optional.ofNullable(queryFactory - .select(Projections.constructor(MissionReadRes.class, - mission.title, - mission.dueTo.stringValue(), - mission.rule, - mission.content, - mission.type.stringValue(), - mission.way.stringValue(), - isLeader)) - .from(mission) - .where(mission.id.eq(missionId)) - .fetchOne() + Mission mission = queryFactory + .selectFrom(QMission.mission) + .where(QMission.mission.id.eq(missionId)) + .fetchOne(); + + if (mission == null) { + return Optional.empty(); + } + + boolean isLeader = mission.getMakerId().equals(memberId) || mission.getTeam().getLeaderId().equals(memberId); + + MissionReadRes result = new MissionReadRes( + mission.getTitle(), + mission.getDueTo().toString(), + mission.getRule(), + mission.getContent(), + mission.getType().toString(), + mission.getWay().toString(), + isLeader ); + + return Optional.of(result); } From bd7df6856e2025792b41380a56e8d9f2fcec4bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 8 Feb 2024 18:46:03 +0900 Subject: [PATCH 502/619] =?UTF-8?q?MNG-10=20fix=20:=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=20=EB=8B=B9=EC=9D=BC=20=EC=9E=90=EC=A0=95=EC=9D=B4=20=EC=A7=80?= =?UTF-8?q?=EB=82=98=EB=A9=B4=20=EB=8B=A4=EC=8B=9C=20=EB=B6=88=EB=8D=98?= =?UTF-8?q?=EC=A7=80=EA=B8=B0=EC=97=90=20=EB=9C=A8=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/FireCustomRepositoryImpl.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 78a51b2a..84ec1109 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -80,16 +80,24 @@ private BooleanExpression createRepeatTypeConditionByArchive() { return missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); } + private BooleanExpression hasAlreadyVerifiedToday() { + LocalDateTime today = LocalDateTime.now(); + LocalDateTime startOfToday = today.withHour(0).withMinute(0).withSecond(0).withNano(0); + LocalDateTime endOfToday = today.withHour(23).withMinute(59).withSecond(59).withNano(999999999); + + return missionArchive.createdDate.between(startOfToday, endOfToday); + } private JPQLQuery todayRepeatMissionDone(Long missionId) { BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + BooleanExpression hasAlreadyVerifiedToday = hasAlreadyVerifiedToday(); return select(missionArchive.member.memberId) .from(missionArchive, mission) .where(missionArchive.mission.id.eq(missionId), mission.id.eq(missionId), - (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) + (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange).and(hasAlreadyVerifiedToday)).or(missionArchive.mission.type.eq(MissionType.ONCE)) ) .groupBy(missionArchive.member.memberId, missionArchive.mission.id, From 3eefb7d36eb86afe147c34f7e351c43476a2d462 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 8 Feb 2024 18:58:07 +0900 Subject: [PATCH 503/619] =?UTF-8?q?MNG-15=20feat:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=ED=95=A0=20?= =?UTF-8?q?=EB=95=8C=20=EC=B0=A8=EB=8B=A8=20=EB=A9=A4=EB=B2=84=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/block/domain/entity/Block.java | 4 ++++ .../application/dto/response/BoardBlocks.java | 1 - .../repository/BoardCustomRepositoryImpl.java | 16 +++++++++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/block/domain/entity/Block.java b/src/main/java/com/moing/backend/domain/block/domain/entity/Block.java index 853c3eb3..2f2f22a7 100644 --- a/src/main/java/com/moing/backend/domain/block/domain/entity/Block.java +++ b/src/main/java/com/moing/backend/domain/block/domain/entity/Block.java @@ -24,4 +24,8 @@ public class Block extends BaseTimeEntity { private Long blockMemberId; private Long targetId; + public Block(Long blockMemberId, Long targetId) { + this.blockMemberId=blockMemberId; + this.targetId=targetId; + } } diff --git a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java index 544a626a..6deb3f17 100644 --- a/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java +++ b/src/main/java/com/moing/backend/domain/board/application/dto/response/BoardBlocks.java @@ -60,7 +60,6 @@ public void deleteMember() { if(Boolean.TRUE.equals(writerIsDeleted)) { this.writerNickName = "(알 수 없음)"; this.writerProfileImage = null; - this.makerId = 0L; } } } diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index 1a2771a8..1abd67e2 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.board.domain.repository; +import com.moing.backend.domain.block.domain.entity.QBlock; import com.moing.backend.domain.board.application.dto.response.BoardBlocks; import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; import com.moing.backend.domain.board.application.dto.response.QBoardBlocks; @@ -13,6 +14,7 @@ import java.util.List; import java.util.stream.Collectors; +import static com.moing.backend.domain.block.domain.entity.QBlock.block; import static com.moing.backend.domain.board.domain.entity.QBoard.board; import static com.moing.backend.domain.boardRead.domain.entity.QBoardRead.boardRead; import static com.moing.backend.domain.member.domain.entity.QMember.member; @@ -35,6 +37,13 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { boardRead.board.boardId.eq(board.boardId)) .exists(); + BooleanExpression blockCondition = JPAExpressions + .select(block.id) + .from(block) + .where(block.blockMemberId.eq(memberId), + block.targetId.eq(board.teamMember.member.memberId)) + .notExists(); + List allBoardBlocks = queryFactory .select(new QBoardBlocks( board.boardId, @@ -44,14 +53,15 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { board.title, board.content, board.commentNum, - isReadExpression.as("isRead"), // 읽음 여부 + isReadExpression.as("isRead"), board.teamMember.isDeleted, board.isNotice, - board.teamMember.member.memberId.coalesce(0L))) + board.teamMember.member.memberId)) .from(board) .leftJoin(board.teamMember, teamMember) .leftJoin(board.teamMember.member, member) - .where(board.team.teamId.eq(teamId)) + .where(board.team.teamId.eq(teamId) + .and(blockCondition)) .orderBy(board.createdDate.desc()) .fetch(); From b3e7efe19ab063dc3ff016317a1da777afc1d0ef Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 8 Feb 2024 18:58:45 +0900 Subject: [PATCH 504/619] =?UTF-8?q?MNG-15=20feat:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EB=8C=93=EA=B8=80=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=A0=20=EB=95=8C=20=EC=B0=A8=EB=8B=A8=20=EB=A9=A4?= =?UTF-8?q?=EB=B2=84=20=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/response/CommentBlocks.java | 1 - .../BoardCommentCustomRepositoryImpl.java | 14 +++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java index b6a5643e..af02defe 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java @@ -47,7 +47,6 @@ public CommentBlocks(Long boardCommentId, String content, String writerNickName, public void deleteMember() { if (Boolean.TRUE.equals(writerIsDeleted)) { - this.makerId = 0L; this.writerNickName = "(알 수 없음)"; this.writerProfileImage = null; } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index 56b3b862..047a0e5c 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -6,12 +6,15 @@ import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.querydsl.core.types.ExpressionUtils; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; import java.util.List; +import static com.moing.backend.domain.block.domain.entity.QBlock.block; +import static com.moing.backend.domain.board.domain.entity.QBoard.board; import static com.moing.backend.domain.boardComment.domain.entity.QBoardComment.boardComment; import static com.moing.backend.domain.member.domain.entity.QMember.member; @@ -26,6 +29,14 @@ public BoardCommentCustomRepositoryImpl(EntityManager em) { @Override public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember teamMember) { + + BooleanExpression blockCondition = JPAExpressions + .select(block.id) + .from(block) + .where(block.blockMemberId.eq(teamMember.getMember().getMemberId()), + block.targetId.eq(boardComment.teamMember.member.memberId)) + .notExists(); + List commentBlocks = queryFactory .select(new QCommentBlocks( boardComment.boardCommentId, @@ -45,7 +56,8 @@ public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember team .from(boardComment) .leftJoin(boardComment.teamMember, QTeamMember.teamMember) .leftJoin(boardComment.teamMember.member, member) - .where(boardComment.board.boardId.eq(boardId)) + .where(boardComment.board.boardId.eq(boardId) + .and(blockCondition)) .orderBy(boardComment.createdDate.asc()) .fetch(); From 1fb58ae62342e244498d9005e1bf7649ab529217 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 8 Feb 2024 20:47:47 +0900 Subject: [PATCH 505/619] =?UTF-8?q?MNG-15=20refactor:=20=EC=B0=A8=EB=8B=A8?= =?UTF-8?q?=ED=95=A8=20=EB=A9=A4=EB=B2=84=20=EA=B4=80=EB=A6=AC=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B3=B5=ED=86=B5=20=ED=95=A8=EC=88=98=EB=A1=9C=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/BlockRepositoryUtils.java | 18 +++++ .../repository/BoardCustomRepositoryImpl.java | 31 ++++----- .../BoardCommentCustomRepositoryImpl.java | 10 +-- .../board/domain/BoardRepositoryTest.java | 66 ++++++++++++++----- 4 files changed, 84 insertions(+), 41 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepositoryUtils.java diff --git a/src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepositoryUtils.java b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepositoryUtils.java new file mode 100644 index 00000000..e6062054 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepositoryUtils.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.block.domain.repository; + +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.NumberPath; +import com.querydsl.jpa.JPAExpressions; + +import static com.moing.backend.domain.block.domain.entity.QBlock.block; + +public class BlockRepositoryUtils { + public static BooleanExpression blockCondition(Long memberId, NumberPath targetMemberId) { + return JPAExpressions + .select(block.id) + .from(block) + .where(block.blockMemberId.eq(memberId), + block.targetId.eq(targetMemberId)) + .notExists(); + } +} diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index 1abd67e2..208de1af 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -1,10 +1,9 @@ package com.moing.backend.domain.board.domain.repository; -import com.moing.backend.domain.block.domain.entity.QBlock; +import com.moing.backend.domain.block.domain.repository.BlockRepositoryUtils; import com.moing.backend.domain.board.application.dto.response.BoardBlocks; import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; import com.moing.backend.domain.board.application.dto.response.QBoardBlocks; -import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -12,9 +11,7 @@ import javax.persistence.EntityManager; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; -import static com.moing.backend.domain.block.domain.entity.QBlock.block; import static com.moing.backend.domain.board.domain.entity.QBoard.board; import static com.moing.backend.domain.boardRead.domain.entity.QBoardRead.boardRead; import static com.moing.backend.domain.member.domain.entity.QMember.member; @@ -29,20 +26,8 @@ public BoardCustomRepositoryImpl(EntityManager em) { @Override public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { - BooleanExpression isReadExpression = JPAExpressions - .select(boardRead.board.boardId) - .from(boardRead) - .where(boardRead.member.memberId.eq(memberId), - boardRead.board.team.teamId.eq(teamId), - boardRead.board.boardId.eq(board.boardId)) - .exists(); - BooleanExpression blockCondition = JPAExpressions - .select(block.id) - .from(block) - .where(block.blockMemberId.eq(memberId), - block.targetId.eq(board.teamMember.member.memberId)) - .notExists(); + BooleanExpression blockCondition = BlockRepositoryUtils.blockCondition(memberId, board.teamMember.member.memberId); List allBoardBlocks = queryFactory .select(new QBoardBlocks( @@ -53,7 +38,7 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { board.title, board.content, board.commentNum, - isReadExpression.as("isRead"), + isReadExpression(memberId, teamId).as("isRead"), board.teamMember.isDeleted, board.isNotice, board.teamMember.member.memberId)) @@ -99,4 +84,14 @@ public Integer findUnReadBoardNum(Long teamId, Long memberId) { return Math.toIntExact(allBoards - readBoards); } + + private BooleanExpression isReadExpression(Long memberId, Long teamId) { + return JPAExpressions + .select(boardRead.board.boardId) + .from(boardRead) + .where(boardRead.member.memberId.eq(memberId), + boardRead.board.team.teamId.eq(teamId), + boardRead.board.boardId.eq(board.boardId)) + .exists(); + } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index 047a0e5c..894c82ea 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.boardComment.domain.repository; +import com.moing.backend.domain.block.domain.repository.BlockRepositoryUtils; import com.moing.backend.domain.boardComment.application.dto.response.CommentBlocks; import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; import com.moing.backend.domain.boardComment.application.dto.response.QCommentBlocks; @@ -13,8 +14,6 @@ import javax.persistence.EntityManager; import java.util.List; -import static com.moing.backend.domain.block.domain.entity.QBlock.block; -import static com.moing.backend.domain.board.domain.entity.QBoard.board; import static com.moing.backend.domain.boardComment.domain.entity.QBoardComment.boardComment; import static com.moing.backend.domain.member.domain.entity.QMember.member; @@ -30,12 +29,7 @@ public BoardCommentCustomRepositoryImpl(EntityManager em) { @Override public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember teamMember) { - BooleanExpression blockCondition = JPAExpressions - .select(block.id) - .from(block) - .where(block.blockMemberId.eq(teamMember.getMember().getMemberId()), - block.targetId.eq(boardComment.teamMember.member.memberId)) - .notExists(); + BooleanExpression blockCondition = BlockRepositoryUtils.blockCondition(teamMember.getTeamMemberId(), boardComment.teamMember.member.memberId); List commentBlocks = queryFactory .select(new QCommentBlocks( diff --git a/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java b/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java index 0bf41f9c..35152a71 100644 --- a/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java +++ b/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java @@ -1,5 +1,7 @@ package com.moing.backend.domain.board.domain; +import com.moing.backend.domain.block.domain.entity.Block; +import com.moing.backend.domain.block.domain.repository.BlockRepository; import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; import com.moing.backend.domain.board.application.mapper.BoardMapper; @@ -23,7 +25,6 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Transactional; @@ -52,17 +53,21 @@ public class BoardRepositoryTest { @Autowired BoardReadRepository boardReadRepository; - private Member minsu, seungyeon; + @Autowired + BlockRepository blockRepository; + + private Member checkingMember, member1, member2; private Team team; - private TeamMember deletedTM, validTM; + private TeamMember checkingTM, tm1Deleted, tm2NotDeleted; private CreateBoardRequest createBoardRequest; @BeforeEach void setUp() { //given - minsu = memberRepository.save(new Member(null, "minsu@naver.com", "undef", Gender.WOMAN, null, "민수", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@minsu")); - seungyeon = memberRepository.save(new Member(null, "seungyeon@naver.com", "undef", Gender.WOMAN, null, "승연", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@seungyeon")); + checkingMember = memberRepository.save(new Member(null, "alstn@naver.com", "undef", Gender.WOMAN, null, "민수", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@alstn")); + member1 = memberRepository.save(new Member(null, "tmddus@naver.com", "undef", Gender.WOMAN, null, "승연", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tmddus")); + member2 = memberRepository.save(new Member(null, "codud@naver.com", "undef", Gender.WOMAN, null, "채영", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@codud")); team = teamRepository.save(Team.builder() .category("ETC") @@ -76,8 +81,9 @@ void setUp() { .levelOfFire(1) .build()); - validTM=teamMemberRepository.save(TeamMember.builder().team(team).member(minsu).isDeleted(false).build()); - deletedTM=teamMemberRepository.save(TeamMember.builder().team(team).member(seungyeon).isDeleted(true).build()); + checkingTM = teamMemberRepository.save(TeamMember.builder().team(team).member(checkingMember).isDeleted(false).build()); + tm1Deleted = teamMemberRepository.save(TeamMember.builder().team(team).member(member1).isDeleted(true).build()); + tm2NotDeleted = teamMemberRepository.save(TeamMember.builder().team(team).member(member2).isDeleted(true).build()); createBoardRequest = CreateBoardRequest.builder() .title("게시글 제목") @@ -90,12 +96,12 @@ void setUp() { @DisplayName("게시글을 읽은 경우") void whenBoardIsRead_thenMarkAsRead() { //given - Board board = boardRepository.save(BoardMapper.toBoard(validTM, team, createBoardRequest, false)); + Board board = boardRepository.save(BoardMapper.toBoard(checkingTM, team, createBoardRequest, false)); - boardReadRepository.save(new BoardRead(null, board, team, minsu)); + boardReadRepository.save(new BoardRead(null, board, team, checkingMember)); //when - GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), minsu.getMemberId()); + GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); //then assertThat(response.getNotNoticeBlocks().get(0).getIsRead()).isTrue(); @@ -105,10 +111,10 @@ void whenBoardIsRead_thenMarkAsRead() { @DisplayName("게시글을 읽지 않은 경우") void whenBoardIsNotRead_thenMarkAsUnread() { //given - Board board = boardRepository.save(BoardMapper.toBoard(validTM, team, createBoardRequest, false)); - + Board board = boardRepository.save(BoardMapper.toBoard(checkingTM, team, createBoardRequest, false)); + //when - GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), minsu.getMemberId()); + GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); //then assertThat(response.getNotNoticeBlocks().get(0).getIsRead()).isFalse(); @@ -117,12 +123,42 @@ void whenBoardIsNotRead_thenMarkAsUnread() { @DisplayName("작성자가 삭제된 경우") void 게시글_작성자가_탈퇴하지_않은_경우_게시글_전체_조회() { //given - Board board = boardRepository.save(BoardMapper.toBoard(deletedTM, team, createBoardRequest, false)); //작성자 탈퇴한 경우 + Board board = boardRepository.save(BoardMapper.toBoard(tm1Deleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 //when - GetAllBoardResponse response=boardRepository.findBoardAll(team.getTeamId(),minsu.getMemberId()); + GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); //then assertThat(response.getNotNoticeBlocks().get(0).getWriterNickName()).isEqualTo("(알 수 없음)"); } + + @Test + @DisplayName("유저 차단 경우 작성자 탈퇴 아님") + void 유저_탈퇴안했을때_차단_조회() { + //given + Board board = boardRepository.save(BoardMapper.toBoard(tm2NotDeleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 + Block block = blockRepository.save(new Block(checkingMember.getMemberId(), member2.getMemberId())); + + //when + GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); + + //then + assertThat(response.getNotNoticeBlocks().size()).isEqualTo(0); + + } + + @Test + @DisplayName("유저 차단 경우 작성자 탈퇴") + void 유저_탈퇴했을때_차단_조회() { + //given + Board board = boardRepository.save(BoardMapper.toBoard(tm1Deleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 + Block block = blockRepository.save(new Block(checkingMember.getMemberId(), member1.getMemberId())); + + //when + GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); + + //then + assertThat(response.getNotNoticeBlocks().size()).isEqualTo(0); + + } } From 74dc1bba17af248290ec38c2c897bbe80d79f38a Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 8 Feb 2024 21:20:22 +0900 Subject: [PATCH 506/619] =?UTF-8?q?MNG-15=20fix:=20=EC=B0=A8=EB=8B=A8?= =?UTF-8?q?=ED=95=9C=20=EB=A9=A4=EB=B2=84=EA=B0=80=20=EC=9E=91=EC=84=B1?= =?UTF-8?q?=ED=95=9C=20=EA=B3=B5=EC=A7=80,=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=EC=9D=80=20=EB=AA=A9=ED=91=9C=EB=B3=B4=EB=93=9C=EC=97=90=20?= =?UTF-8?q?=EC=A0=9C=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/BlockRepositoryUtils.java | 9 ++++++ .../repository/BoardCustomRepositoryImpl.java | 28 +++++++++---------- .../board/domain/BoardRepositoryTest.java | 14 ++++++++++ 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepositoryUtils.java b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepositoryUtils.java index e6062054..a3ccffd1 100644 --- a/src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepositoryUtils.java +++ b/src/main/java/com/moing/backend/domain/block/domain/repository/BlockRepositoryUtils.java @@ -15,4 +15,13 @@ public static BooleanExpression blockCondition(Long memberId, NumberPath t block.targetId.eq(targetMemberId)) .notExists(); } + + public static BooleanExpression blockCondition(NumberPath memberId, Long targetMemberId) { + return JPAExpressions + .select(block.id) + .from(block) + .where(block.blockMemberId.eq(memberId), + block.targetId.eq(targetMemberId)) + .notExists(); + } } diff --git a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java index 208de1af..c0b9c927 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/board/domain/repository/BoardCustomRepositoryImpl.java @@ -66,25 +66,25 @@ public GetAllBoardResponse findBoardAll(Long teamId, Long memberId) { @Override public Integer findUnReadBoardNum(Long teamId, Long memberId) { - // 전체 게시글 수 - Long allBoards = queryFactory + BooleanExpression isNotReadExpression = isReadExpression(memberId, teamId).not(); + + BooleanExpression blockCondition = BlockRepositoryUtils.blockCondition(memberId, board.teamMember.member.memberId); + + Long unReadBoardsCount = queryFactory .select(board.count()) .from(board) - .where(board.team.teamId.eq(teamId)) - .fetchFirst(); - - // 멤버가 읽은 게시글 수 - Long readBoards = queryFactory - .select(boardRead.board.boardId) - .distinct() - .from(boardRead) - .where(boardRead.member.memberId.eq(memberId)) - .where(boardRead.board.team.teamId.eq(teamId)) - .stream().count(); + .leftJoin(boardRead) + .on(board.boardId.eq(boardRead.board.boardId) + .and(boardRead.member.memberId.eq(memberId))) + .where(board.team.teamId.eq(teamId) + .and(isNotReadExpression) + .and(blockCondition)) + .fetchOne(); - return Math.toIntExact(allBoards - readBoards); + return Math.toIntExact(unReadBoardsCount != null ? unReadBoardsCount : 0); } + private BooleanExpression isReadExpression(Long memberId, Long teamId) { return JPAExpressions .select(boardRead.board.boardId) diff --git a/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java b/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java index 35152a71..564016f2 100644 --- a/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java +++ b/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java @@ -159,6 +159,20 @@ void whenBoardIsNotRead_thenMarkAsUnread() { //then assertThat(response.getNotNoticeBlocks().size()).isEqualTo(0); + } + + @Test + @DisplayName("유저 차단 경우 목표보드 게시글 개수") + void 유저_차단_게시글_조회(){ + //given + Board board = boardRepository.save(BoardMapper.toBoard(tm2NotDeleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 + Block block = blockRepository.save(new Block(checkingMember.getMemberId(), member2.getMemberId())); + + //when + Integer unReadBoardNum= boardRepository.findUnReadBoardNum(team.getTeamId(), checkingMember.getMemberId()); + //then + assertThat(unReadBoardNum).isEqualTo(0); } + } From 480edd6a3560707706eb29405220838adcb87183 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 8 Feb 2024 21:21:02 +0900 Subject: [PATCH 507/619] =?UTF-8?q?MNG-15=20fix:=20=EC=B0=A8=EB=8B=A8?= =?UTF-8?q?=ED=95=9C=20=EB=A9=A4=EB=B2=84=EA=B0=80=20=EC=83=88=EB=A1=9C=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A0=20=EB=AF=B8=EC=85=98,=20=EA=B3=B5=EC=A7=80/?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=EC=9D=80=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=95=88=EC=98=A4=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TeamMemberCustomRepository.java | 6 --- .../TeamMemberCustomRepositoryImpl.java | 40 +++---------------- .../domain/service/TeamMemberGetService.java | 13 ------ 3 files changed, 6 insertions(+), 53 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index b321c2cf..fd3c9574 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -1,18 +1,12 @@ package com.moing.backend.domain.teamMember.domain.repository; -import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; -import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import java.util.List; import java.util.Optional; public interface TeamMemberCustomRepository { - List findMemberIdsByTeamId(Long teamId); Optional> findNewUploadInfo(Long teamId, Long memberId); - Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId); List findTeamMemberInfoByTeamId(Long teamId); - List findTeamMemberByMemberId(Long memberId); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index dcc7f39b..535c8de0 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -1,11 +1,11 @@ package com.moing.backend.domain.teamMember.domain.repository; -import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.block.domain.repository.BlockRepositoryUtils; import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.team.application.dto.response.QTeamMemberInfo; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -22,18 +22,10 @@ public TeamMemberCustomRepositoryImpl(EntityManager em) { this.queryFactory = new JPAQueryFactory(em); } - @Override - public List findMemberIdsByTeamId(Long teamId) { - return queryFactory - .select(teamMember.member.memberId) - .from(teamMember) - .where(teamMember.team.teamId.eq(teamId) - .and(teamMember.team.isDeleted.eq(false))) - .fetch(); - } - @Override public Optional> findNewUploadInfo(Long teamId, Long memberId) { + BooleanExpression blockCondition= BlockRepositoryUtils.blockCondition(teamMember.member.memberId, memberId); + List result = queryFactory.select(Projections.constructor(NewUploadInfo.class, teamMember.member.fcmToken, teamMember.member.memberId, @@ -42,21 +34,8 @@ public Optional> findNewUploadInfo(Long teamId, Long memberI .from(teamMember) .where(teamMember.team.teamId.eq(teamId) .and(teamMember.member.memberId.ne(memberId)) - .and(teamMember.isDeleted.eq(false))) - .fetch(); - - return result.isEmpty() ? Optional.empty() : Optional.of(result); - } - - @Override - public Optional> findFcmTokensByTeamIdAndMemberId(Long teamId, Long memberId) { - List result = queryFactory.select(teamMember.member.fcmToken) - .from(teamMember) - .where(teamMember.team.teamId.eq(teamId) - .and(teamMember.member.isNewUploadPush.eq(true)) - .and(teamMember.member.isSignOut.eq(false)) - .and(teamMember.member.memberId.ne(memberId)) - .and(teamMember.isDeleted.eq(false))) + .and(teamMember.isDeleted.eq(false) + .and(blockCondition))) .fetch(); return result.isEmpty() ? Optional.empty() : Optional.of(result); @@ -79,11 +58,4 @@ public List findTeamMemberInfoByTeamId(Long teamId){ .fetch(); } - @Override - public List findTeamMemberByMemberId(Long memberId) { - return queryFactory.selectFrom(teamMember) - .where(teamMember.member.memberId.eq(memberId) - .and(teamMember.isDeleted.eq(false))) - .fetch(); - } } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index 1e0a64cb..5c03d599 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -1,6 +1,5 @@ package com.moing.backend.domain.teamMember.domain.service; -import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.application.dto.response.TeamMemberInfo; @@ -19,10 +18,6 @@ public class TeamMemberGetService { private final TeamMemberRepository teamMemberRepository; - public List getTeamMemberIds(Long teamId){ - return teamMemberRepository.findMemberIdsByTeamId(teamId); - } - public TeamMember getTeamMember(Member member, Team team){ return teamMemberRepository.findTeamMemberByTeamAndMember(team, member).orElseThrow(NotFoundByTeamIdException::new); } @@ -34,18 +29,10 @@ public TeamMember getTeamMemberNotDeleted(Member member, Team team) { } - public Optional> getFcmTokensExceptMe(Long teamId, Long memberId) { - return teamMemberRepository.findFcmTokensByTeamIdAndMemberId(teamId, memberId); - } - public List getTeamMemberInfo(Long teamId){ return teamMemberRepository.findTeamMemberInfoByTeamId(teamId); } - public List getNotDeletedTeamMember(Long memberId){ - return teamMemberRepository.findTeamMemberByMemberId(memberId); - } - public Optional> getNewUploadInfo(Long teamId, Long memberId) { return teamMemberRepository.findNewUploadInfo(teamId, memberId); } From 1e54f2b3ac8af33cd429f62ade9082d1712c9779 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 9 Feb 2024 23:27:04 +0900 Subject: [PATCH 508/619] =?UTF-8?q?MNG-17=20feat:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=EC=9E=90=EC=97=90=EA=B2=8C=EB=8F=84=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EA=B0=80=EA=B2=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendCommentAlarmUseCase.java | 32 ++++++++++++++++--- .../BoardCommentCustomRepository.java | 6 ++++ .../BoardCommentCustomRepositoryImpl.java | 26 +++++++++++++++ .../service/BoardCommentGetService.java | 7 ++++ 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java index 0d8a49f9..12e4ca96 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java @@ -2,10 +2,15 @@ import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; import com.moing.backend.global.response.BaseBoardServiceResponse; import lombok.RequiredArgsConstructor; @@ -14,8 +19,9 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; - +import java.util.List; import java.util.Objects; +import java.util.Optional; import static com.moing.backend.global.config.fcm.constant.NewCommentUploadMessage.NEW_COMMENT_UPLOAD_MESSAGE; @@ -25,22 +31,36 @@ public class SendCommentAlarmUseCase { private final ApplicationEventPublisher eventPublisher; + private final BoardCommentGetService boardCommentGetService; public void sendNewUploadAlarm(BaseBoardServiceResponse response, BoardComment comment) { Member member = response.getMember(); Team team = response.getTeam(); Board board = response.getBoard(); - Member receiver = board.getTeamMember().getMember(); String title = NEW_COMMENT_UPLOAD_MESSAGE.title(comment.getContent()); String body = NEW_COMMENT_UPLOAD_MESSAGE.body(member.getNickName(),board.getTitle()); - // 알림 보내기 - if(checkBoardWriter(receiver, member)){ + sendBoardWriter(board, member, title, body, team); + sendBoardCommentWriter(board, member, title, body, team); + } + + private void sendBoardWriter(Board board, Member member, String title, String body, Team team) { + Member receiver = board.getTeamMember().getMember(); + + if (checkBoardWriter(receiver, member)) { eventPublisher.publishEvent(new SingleFcmEvent(receiver, title, body, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue(), receiver.isNewUploadPush())); } } + private void sendBoardCommentWriter(Board board, Member member, String title, String body, Team team) { + Optional> newUploadInfos = boardCommentGetService.getNewUploadInfo(member.getMemberId(), board.getBoardId()); + Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); + Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); + + eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); + } + private String createIdInfo(Long teamId, Long boardId) { JSONObject jo = new JSONObject(); jo.put("teamId", teamId); @@ -48,7 +68,9 @@ private String createIdInfo(Long teamId, Long boardId) { return jo.toJSONString(); } - private boolean checkBoardWriter(Member boardWriter, Member commentWriter){ + private boolean checkBoardWriter(Member boardWriter, Member commentWriter) { //댓글 작성자와 게시글 작성자가 동일한 경우 return !Objects.equals(boardWriter.getMemberId(), commentWriter.getMemberId()); } + + } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java index f5e48759..25a70306 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java @@ -1,8 +1,14 @@ package com.moing.backend.domain.boardComment.domain.repository; import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import java.util.List; +import java.util.Optional; + public interface BoardCommentCustomRepository { GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember teamMember); + + Optional> findNewUploadInfo(Long memberId, Long boardId); } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index 894c82ea..5bcbb722 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -4,18 +4,22 @@ import com.moing.backend.domain.boardComment.application.dto.response.CommentBlocks; import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; import com.moing.backend.domain.boardComment.application.dto.response.QCommentBlocks; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.querydsl.core.types.ExpressionUtils; +import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; import java.util.List; +import java.util.Optional; import static com.moing.backend.domain.boardComment.domain.entity.QBoardComment.boardComment; import static com.moing.backend.domain.member.domain.entity.QMember.member; +import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; public class BoardCommentCustomRepositoryImpl implements BoardCommentCustomRepository{ @@ -57,4 +61,26 @@ public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember team return new GetBoardCommentResponse(commentBlocks); } + + @Override + public Optional> findNewUploadInfo(Long memberId, Long boardId) { + BooleanExpression blockCondition= BlockRepositoryUtils.blockCondition(boardComment.teamMember.member.memberId, memberId); + + List result = queryFactory.select(Projections.constructor(NewUploadInfo.class, + boardComment.teamMember.member.fcmToken, + boardComment.teamMember.member.memberId, + boardComment.teamMember.member.isNewUploadPush, + boardComment.teamMember.member.isSignOut)) + .distinct() + .from(teamMember) + .leftJoin(boardComment.teamMember, QTeamMember.teamMember) + .leftJoin(boardComment.teamMember.member, member) + .where(boardComment.board.boardId.eq(boardId) //게시글의 댓글인데 + .and(boardComment.teamMember.member.memberId.ne(memberId)) //나는 포함 안하고 + .and(boardComment.teamMember.isDeleted.eq(false)) //탈퇴한 사람도 포함 안함 + .and(blockCondition)) + .fetch(); + + return result.isEmpty() ? Optional.empty() : Optional.of(result); + } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java index 005c10a4..28023ab0 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java @@ -4,11 +4,14 @@ import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; import com.moing.backend.domain.boardComment.exception.NotFoundByBoardCommentIdException; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; @DomainService @Transactional @@ -24,4 +27,8 @@ public BoardComment getBoardComment(Long boardCommentId){ public GetBoardCommentResponse getBoardCommentAll(Long boardId, TeamMember teamMember){ return boardCommentRepository.findBoardCommentAll(boardId, teamMember); } + + public Optional> getNewUploadInfo(Long memberId, Long boardId) { + return boardCommentRepository.findNewUploadInfo(memberId, boardId); + } } From 3c2d01c4e5ad97ee0e04c3d2e2329d0690c41ef0 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 9 Feb 2024 23:40:47 +0900 Subject: [PATCH 509/619] =?UTF-8?q?MNG-17=20fix:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EA=B8=80=20=EC=9E=91=EC=84=B1=EC=9E=90=EC=99=80=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EC=9E=91=EC=84=B1=EC=9E=90=EA=B0=80=20=EB=8F=99?= =?UTF-8?q?=EC=9D=BC=ED=95=9C=20=EA=B2=BD=EC=9A=B0=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EB=B0=A9=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendCommentAlarmUseCase.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java index 12e4ca96..84d1078a 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java @@ -38,23 +38,23 @@ public void sendNewUploadAlarm(BaseBoardServiceResponse response, BoardComment c Team team = response.getTeam(); Board board = response.getBoard(); + Optional> newUploadInfos = boardCommentGetService.getNewUploadInfo(member.getMemberId(), board.getBoardId()); String title = NEW_COMMENT_UPLOAD_MESSAGE.title(comment.getContent()); String body = NEW_COMMENT_UPLOAD_MESSAGE.body(member.getNickName(),board.getTitle()); - sendBoardWriter(board, member, title, body, team); - sendBoardCommentWriter(board, member, title, body, team); + sendBoardCommentWriter(board, member, title, body, team, newUploadInfos); + sendBoardWriter(board, member, title, body, team, newUploadInfos); } - private void sendBoardWriter(Board board, Member member, String title, String body, Team team) { + private void sendBoardWriter(Board board, Member member, String title, String body, Team team, Optional> newUploadInfos) { Member receiver = board.getTeamMember().getMember(); - if (checkBoardWriter(receiver, member)) { + if (checkBoardWriter(receiver, member, newUploadInfos)) { eventPublisher.publishEvent(new SingleFcmEvent(receiver, title, body, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue(), receiver.isNewUploadPush())); } } - private void sendBoardCommentWriter(Board board, Member member, String title, String body, Team team) { - Optional> newUploadInfos = boardCommentGetService.getNewUploadInfo(member.getMemberId(), board.getBoardId()); + private void sendBoardCommentWriter(Board board, Member member, String title, String body, Team team, Optional> newUploadInfos) { Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); @@ -68,8 +68,17 @@ private String createIdInfo(Long teamId, Long boardId) { return jo.toJSONString(); } - private boolean checkBoardWriter(Member boardWriter, Member commentWriter) { //댓글 작성자와 게시글 작성자가 동일한 경우 - return !Objects.equals(boardWriter.getMemberId(), commentWriter.getMemberId()); + private boolean checkBoardWriter(Member boardWriter, Member commentWriter, Optional> newUploadInfos) { + // 댓글 작성자와 게시글 작성자가 동일한 경우 알림을 보내지 않는다. + if (Objects.equals(boardWriter.getMemberId(), commentWriter.getMemberId())) { + return false; + } + + // newUploadInfos 리스트에 boardWriter의 memberId가 없는 경우만 알림을 보낸다. + // 리스트가 비어있거나, boardWriter의 memberId가 리스트에 없으면 true를 반환. + return newUploadInfos + .map(infos -> infos.stream().noneMatch(info -> info.getMemberId().equals(boardWriter.getMemberId()))) + .orElse(true); } From 38a394fad0d09a56e46a3341025621da55da4faa Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 11 Feb 2024 01:24:11 +0900 Subject: [PATCH 510/619] =?UTF-8?q?MNG-17=20hotfix:=20=EC=BF=BC=EB=A6=AC?= =?UTF-8?q?=20from=20=EC=A0=88=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/BoardCommentCustomRepositoryImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index 5bcbb722..048fa21f 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -72,8 +72,8 @@ public Optional> findNewUploadInfo(Long memberId, Long board boardComment.teamMember.member.isNewUploadPush, boardComment.teamMember.member.isSignOut)) .distinct() - .from(teamMember) - .leftJoin(boardComment.teamMember, QTeamMember.teamMember) + .from(boardComment) + .leftJoin(boardComment.teamMember, teamMember) .leftJoin(boardComment.teamMember.member, member) .where(boardComment.board.boardId.eq(boardId) //게시글의 댓글인데 .and(boardComment.teamMember.member.memberId.ne(memberId)) //나는 포함 안하고 From 5ae5909bc21bf9471fa1fcd965e562b6e00148f7 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 11 Feb 2024 11:42:41 +0900 Subject: [PATCH 511/619] =?UTF-8?q?MNG-17=20delete:=20=EB=A0=88=ED=8F=AC?= =?UTF-8?q?=EC=A7=80=ED=86=A0=EB=A6=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A3=BC=EC=84=9D=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/domain/BoardRepositoryTest.java | 356 +++++++++--------- 1 file changed, 178 insertions(+), 178 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java b/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java index 564016f2..9ccb1d77 100644 --- a/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java +++ b/src/test/java/com/moing/backend/domain/board/domain/BoardRepositoryTest.java @@ -1,178 +1,178 @@ -package com.moing.backend.domain.board.domain; - -import com.moing.backend.domain.block.domain.entity.Block; -import com.moing.backend.domain.block.domain.repository.BlockRepository; -import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; -import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; -import com.moing.backend.domain.board.application.mapper.BoardMapper; -import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.board.domain.repository.BoardRepository; -import com.moing.backend.domain.boardRead.domain.entity.BoardRead; -import com.moing.backend.domain.boardRead.domain.repository.BoardReadRepository; -import com.moing.backend.domain.member.domain.constant.Gender; -import com.moing.backend.domain.member.domain.constant.RegistrationStatus; -import com.moing.backend.domain.member.domain.constant.Role; -import com.moing.backend.domain.member.domain.constant.SocialProvider; -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.member.domain.repository.MemberRepository; -import com.moing.backend.domain.team.domain.constant.ApprovalStatus; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.repository.TeamRepository; -import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; -import org.junit.jupiter.api.BeforeEach; -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.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.transaction.annotation.Transactional; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - - -@SpringBootTest -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -@ActiveProfiles("dev") -@Transactional -public class BoardRepositoryTest { - - @Autowired - MemberRepository memberRepository; - - @Autowired - TeamMemberRepository teamMemberRepository; - - @Autowired - TeamRepository teamRepository; - - @Autowired - BoardRepository boardRepository; - - @Autowired - BoardReadRepository boardReadRepository; - - @Autowired - BlockRepository blockRepository; - - private Member checkingMember, member1, member2; - - private Team team; - private TeamMember checkingTM, tm1Deleted, tm2NotDeleted; - private CreateBoardRequest createBoardRequest; - - @BeforeEach - void setUp() { - //given - checkingMember = memberRepository.save(new Member(null, "alstn@naver.com", "undef", Gender.WOMAN, null, "민수", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@alstn")); - member1 = memberRepository.save(new Member(null, "tmddus@naver.com", "undef", Gender.WOMAN, null, "승연", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tmddus")); - member2 = memberRepository.save(new Member(null, "codud@naver.com", "undef", Gender.WOMAN, null, "채영", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@codud")); - - team = teamRepository.save(Team.builder() - .category("ETC") - .name("소모임 이름") - .introduction("소모임 소개") - .promise("소모임 각오") - .profileImgUrl("소모임 프로필 이미지 url") - .approvalStatus(ApprovalStatus.APPROVAL) - .leaderId(1L) - .numOfMember(2) - .levelOfFire(1) - .build()); - - checkingTM = teamMemberRepository.save(TeamMember.builder().team(team).member(checkingMember).isDeleted(false).build()); - tm1Deleted = teamMemberRepository.save(TeamMember.builder().team(team).member(member1).isDeleted(true).build()); - tm2NotDeleted = teamMemberRepository.save(TeamMember.builder().team(team).member(member2).isDeleted(true).build()); - - createBoardRequest = CreateBoardRequest.builder() - .title("게시글 제목") - .content("게시글 내용") - .isNotice(false) - .build(); - } - - @Test - @DisplayName("게시글을 읽은 경우") - void whenBoardIsRead_thenMarkAsRead() { - //given - Board board = boardRepository.save(BoardMapper.toBoard(checkingTM, team, createBoardRequest, false)); - - boardReadRepository.save(new BoardRead(null, board, team, checkingMember)); - - //when - GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); - - //then - assertThat(response.getNotNoticeBlocks().get(0).getIsRead()).isTrue(); - } - - @Test - @DisplayName("게시글을 읽지 않은 경우") - void whenBoardIsNotRead_thenMarkAsUnread() { - //given - Board board = boardRepository.save(BoardMapper.toBoard(checkingTM, team, createBoardRequest, false)); - - //when - GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); - - //then - assertThat(response.getNotNoticeBlocks().get(0).getIsRead()).isFalse(); - } - @Test - @DisplayName("작성자가 삭제된 경우") - void 게시글_작성자가_탈퇴하지_않은_경우_게시글_전체_조회() { - //given - Board board = boardRepository.save(BoardMapper.toBoard(tm1Deleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 - - //when - GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); - - //then - assertThat(response.getNotNoticeBlocks().get(0).getWriterNickName()).isEqualTo("(알 수 없음)"); - } - - @Test - @DisplayName("유저 차단 경우 작성자 탈퇴 아님") - void 유저_탈퇴안했을때_차단_조회() { - //given - Board board = boardRepository.save(BoardMapper.toBoard(tm2NotDeleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 - Block block = blockRepository.save(new Block(checkingMember.getMemberId(), member2.getMemberId())); - - //when - GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); - - //then - assertThat(response.getNotNoticeBlocks().size()).isEqualTo(0); - - } - - @Test - @DisplayName("유저 차단 경우 작성자 탈퇴") - void 유저_탈퇴했을때_차단_조회() { - //given - Board board = boardRepository.save(BoardMapper.toBoard(tm1Deleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 - Block block = blockRepository.save(new Block(checkingMember.getMemberId(), member1.getMemberId())); - - //when - GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); - - //then - assertThat(response.getNotNoticeBlocks().size()).isEqualTo(0); - } - - @Test - @DisplayName("유저 차단 경우 목표보드 게시글 개수") - void 유저_차단_게시글_조회(){ - //given - Board board = boardRepository.save(BoardMapper.toBoard(tm2NotDeleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 - Block block = blockRepository.save(new Block(checkingMember.getMemberId(), member2.getMemberId())); - - //when - Integer unReadBoardNum= boardRepository.findUnReadBoardNum(team.getTeamId(), checkingMember.getMemberId()); - - //then - assertThat(unReadBoardNum).isEqualTo(0); - } - -} +//package com.moing.backend.domain.board.domain; +// +//import com.moing.backend.domain.block.domain.entity.Block; +//import com.moing.backend.domain.block.domain.repository.BlockRepository; +//import com.moing.backend.domain.board.application.dto.request.CreateBoardRequest; +//import com.moing.backend.domain.board.application.dto.response.GetAllBoardResponse; +//import com.moing.backend.domain.board.application.mapper.BoardMapper; +//import com.moing.backend.domain.board.domain.entity.Board; +//import com.moing.backend.domain.board.domain.repository.BoardRepository; +//import com.moing.backend.domain.boardRead.domain.entity.BoardRead; +//import com.moing.backend.domain.boardRead.domain.repository.BoardReadRepository; +//import com.moing.backend.domain.member.domain.constant.Gender; +//import com.moing.backend.domain.member.domain.constant.RegistrationStatus; +//import com.moing.backend.domain.member.domain.constant.Role; +//import com.moing.backend.domain.member.domain.constant.SocialProvider; +//import com.moing.backend.domain.member.domain.entity.Member; +//import com.moing.backend.domain.member.domain.repository.MemberRepository; +//import com.moing.backend.domain.team.domain.constant.ApprovalStatus; +//import com.moing.backend.domain.team.domain.entity.Team; +//import com.moing.backend.domain.team.domain.repository.TeamRepository; +//import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +//import com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; +//import org.junit.jupiter.api.BeforeEach; +//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.jdbc.AutoConfigureTestDatabase; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.test.context.ActiveProfiles; +//import org.springframework.transaction.annotation.Transactional; +// +//import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +// +// +//@SpringBootTest +//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +//@ActiveProfiles("local") +//@Transactional +//public class BoardRepositoryTest { +// +// @Autowired +// MemberRepository memberRepository; +// +// @Autowired +// TeamMemberRepository teamMemberRepository; +// +// @Autowired +// TeamRepository teamRepository; +// +// @Autowired +// BoardRepository boardRepository; +// +// @Autowired +// BoardReadRepository boardReadRepository; +// +// @Autowired +// BlockRepository blockRepository; +// +// private Member checkingMember, member1, member2; +// +// private Team team; +// private TeamMember checkingTM, tm1Deleted, tm2NotDeleted; +// private CreateBoardRequest createBoardRequest; +// +// @BeforeEach +// void setUp() { +// //given +// checkingMember = memberRepository.save(new Member(null, "alstn@naver.com", "undef", Gender.WOMAN, null, "민수", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@alstn")); +// member1 = memberRepository.save(new Member(null, "tmddus@naver.com", "undef", Gender.WOMAN, null, "승연", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@tmddus")); +// member2 = memberRepository.save(new Member(null, "codud@naver.com", "undef", Gender.WOMAN, null, "채영", null, SocialProvider.KAKAO, RegistrationStatus.COMPLETED, Role.USER, "KAKAO@codud")); +// +// team = teamRepository.save(Team.builder() +// .category("ETC") +// .name("소모임 이름") +// .introduction("소모임 소개") +// .promise("소모임 각오") +// .profileImgUrl("소모임 프로필 이미지 url") +// .approvalStatus(ApprovalStatus.APPROVAL) +// .leaderId(1L) +// .numOfMember(2) +// .levelOfFire(1) +// .build()); +// +// checkingTM = teamMemberRepository.save(TeamMember.builder().team(team).member(checkingMember).isDeleted(false).build()); +// tm1Deleted = teamMemberRepository.save(TeamMember.builder().team(team).member(member1).isDeleted(true).build()); +// tm2NotDeleted = teamMemberRepository.save(TeamMember.builder().team(team).member(member2).isDeleted(true).build()); +// +// createBoardRequest = CreateBoardRequest.builder() +// .title("게시글 제목") +// .content("게시글 내용") +// .isNotice(false) +// .build(); +// } +// +// @Test +// @DisplayName("게시글을 읽은 경우") +// void whenBoardIsRead_thenMarkAsRead() { +// //given +// Board board = boardRepository.save(BoardMapper.toBoard(checkingTM, team, createBoardRequest, false)); +// +// boardReadRepository.save(new BoardRead(null, board, team, checkingMember)); +// +// //when +// GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); +// +// //then +// assertThat(response.getNotNoticeBlocks().get(0).getIsRead()).isTrue(); +// } +// +// @Test +// @DisplayName("게시글을 읽지 않은 경우") +// void whenBoardIsNotRead_thenMarkAsUnread() { +// //given +// Board board = boardRepository.save(BoardMapper.toBoard(checkingTM, team, createBoardRequest, false)); +// +// //when +// GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); +// +// //then +// assertThat(response.getNotNoticeBlocks().get(0).getIsRead()).isFalse(); +// } +// @Test +// @DisplayName("작성자가 삭제된 경우") +// void 게시글_작성자가_탈퇴하지_않은_경우_게시글_전체_조회() { +// //given +// Board board = boardRepository.save(BoardMapper.toBoard(tm1Deleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 +// +// //when +// GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); +// +// //then +// assertThat(response.getNotNoticeBlocks().get(0).getWriterNickName()).isEqualTo("(알 수 없음)"); +// } +// +// @Test +// @DisplayName("유저 차단 경우 작성자 탈퇴 아님") +// void 유저_탈퇴안했을때_차단_조회() { +// //given +// Board board = boardRepository.save(BoardMapper.toBoard(tm2NotDeleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 +// Block block = blockRepository.save(new Block(checkingMember.getMemberId(), member2.getMemberId())); +// +// //when +// GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); +// +// //then +// assertThat(response.getNotNoticeBlocks().size()).isEqualTo(0); +// +// } +// +// @Test +// @DisplayName("유저 차단 경우 작성자 탈퇴") +// void 유저_탈퇴했을때_차단_조회() { +// //given +// Board board = boardRepository.save(BoardMapper.toBoard(tm1Deleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 +// Block block = blockRepository.save(new Block(checkingMember.getMemberId(), member1.getMemberId())); +// +// //when +// GetAllBoardResponse response = boardRepository.findBoardAll(team.getTeamId(), checkingMember.getMemberId()); +// +// //then +// assertThat(response.getNotNoticeBlocks().size()).isEqualTo(0); +// } +// +// @Test +// @DisplayName("유저 차단 경우 목표보드 게시글 개수") +// void 유저_차단_게시글_조회(){ +// //given +// Board board = boardRepository.save(BoardMapper.toBoard(tm2NotDeleted, team, createBoardRequest, false)); //작성자 탈퇴한 경우 +// Block block = blockRepository.save(new Block(checkingMember.getMemberId(), member2.getMemberId())); +// +// //when +// Integer unReadBoardNum= boardRepository.findUnReadBoardNum(team.getTeamId(), checkingMember.getMemberId()); +// +// //then +// assertThat(unReadBoardNum).isEqualTo(0); +// } +// +//} From 210eb46bece33877ac4211da6741aa1fd1fc3ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sun, 11 Feb 2024 11:51:36 +0900 Subject: [PATCH 512/619] =?UTF-8?q?MNG-12=20fix=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20=EC=86=8C=EB=AA=A8=EC=9E=84=EC=9E=A5/?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=EA=B6=8C=ED=95=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B2=84=EA=B7=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionUpdateUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index c6dfb752..bd10ef8e 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -42,7 +42,7 @@ public MissionCreateRes updateMission(String userSocialId, Long missionId, Missi * 미션 생성자 확인 */ - if (!memberId.equals(mission.getMakerId()) || memberId.equals(team.getLeaderId())) { + if (!(memberId.equals(mission.getMakerId()) || memberId.equals(team.getLeaderId()))) { throw new NoAccessUpdateMission(); } mission.updateMission(missionReq); From a964dc059594b5735d3ca8bf8165c67bf8162cca Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 12 Feb 2024 22:10:48 +0900 Subject: [PATCH 513/619] =?UTF-8?q?MNG-15=20fix:=20=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=EC=9B=90=20=EC=86=8C=EA=B0=9C=EC=97=90=EC=84=9C=20=EC=B0=A8?= =?UTF-8?q?=EB=8B=A8=20=EB=A9=A4=EB=B2=84=20=EA=B4=80=EB=A6=AC=20=EC=95=88?= =?UTF-8?q?=EB=B3=B4=EC=9D=B4=EA=B2=8C=20=ED=95=98=EB=8A=94=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/team/application/service/GetTeamUseCase.java | 2 +- .../domain/repository/TeamMemberCustomRepository.java | 2 +- .../repository/TeamMemberCustomRepositoryImpl.java | 9 +++++++-- .../teamMember/domain/service/TeamMemberGetService.java | 4 ++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java index 7d950dc7..3562ae11 100644 --- a/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java +++ b/src/main/java/com/moing/backend/domain/team/application/service/GetTeamUseCase.java @@ -33,7 +33,7 @@ public GetTeamResponse getTeam(String socialId) { public GetTeamDetailResponse getTeamDetailResponse(String socialId, Long teamId) { Member member = memberGetService.getMemberBySocialId(socialId); Integer boardNum = boardGetService.getUnReadBoardNum(teamId, member.getMemberId()); - List teamMemberInfoList = teamMemberGetService.getTeamMemberInfo(teamId); + List teamMemberInfoList = teamMemberGetService.getTeamMemberInfo(member.getMemberId(), teamId); Team team = teamGetService.getTeamByTeamId(teamId); return TeamMapper.toTeamDetailResponse(member.getMemberId(), team, boardNum, teamMemberInfoList); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java index fd3c9574..54efa9db 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepository.java @@ -8,5 +8,5 @@ public interface TeamMemberCustomRepository { Optional> findNewUploadInfo(Long teamId, Long memberId); - List findTeamMemberInfoByTeamId(Long teamId); + List findTeamMemberInfoByTeamId(Long memberId, Long teamId); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java index 535c8de0..bc789a1a 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/repository/TeamMemberCustomRepositoryImpl.java @@ -42,7 +42,11 @@ public Optional> findNewUploadInfo(Long teamId, Long memberI } @Override - public List findTeamMemberInfoByTeamId(Long teamId){ + public List findTeamMemberInfoByTeamId(Long memberId, Long teamId){ + + BooleanExpression blockCondition= BlockRepositoryUtils.blockCondition(memberId, teamMember.member.memberId); + + return queryFactory .select(new QTeamMemberInfo( teamMember.member.memberId, @@ -53,7 +57,8 @@ public List findTeamMemberInfoByTeamId(Long teamId){ .from(teamMember) .innerJoin(teamMember.team, team) // innerJoin을 사용하여 최적화 .where(teamMember.team.teamId.eq(teamId) // where 절을 하나로 합침 - .and(teamMember.isDeleted.eq(false))) + .and(teamMember.isDeleted.eq(false)) + .and(blockCondition)) .groupBy(teamMember.member.memberId) .fetch(); } diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java index 5c03d599..5c3122db 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/service/TeamMemberGetService.java @@ -29,8 +29,8 @@ public TeamMember getTeamMemberNotDeleted(Member member, Team team) { } - public List getTeamMemberInfo(Long teamId){ - return teamMemberRepository.findTeamMemberInfoByTeamId(teamId); + public List getTeamMemberInfo(Long memberId, Long teamId){ + return teamMemberRepository.findTeamMemberInfoByTeamId(memberId, teamId); } public Optional> getNewUploadInfo(Long teamId, Long memberId) { From 12674f1d9295251aa49aa8e970957be401f43727 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 12 Feb 2024 22:15:47 +0900 Subject: [PATCH 514/619] =?UTF-8?q?MNG-15=20fix:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=B0=A8=EB=8B=A8=20=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=EC=95=88=EB=B3=B4=EC=9D=B4=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveCustomRepositoryImpl.java | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 5e3ad422..5203f83f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -1,11 +1,10 @@ package com.moing.backend.domain.missionArchive.domain.repository; -import com.moing.backend.domain.board.application.dto.response.BoardBlocks; +import com.moing.backend.domain.block.domain.repository.BlockRepositoryUtils; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; -import com.moing.backend.domain.mission.domain.entity.QMission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; @@ -13,11 +12,7 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MyArchiveStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; -import com.moing.backend.domain.missionRead.domain.entity.QMissionRead; import com.moing.backend.domain.missionRead.domain.repository.MissionReadRepositoryUtils; -import com.moing.backend.domain.team.domain.entity.QTeam; -import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; import com.querydsl.core.Tuple; import com.querydsl.core.types.Expression; import com.querydsl.core.types.Order; @@ -27,14 +22,10 @@ import com.querydsl.core.types.dsl.CaseBuilder; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; -import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; -import feign.Param; import lombok.extern.slf4j.Slf4j; -import org.springframework.data.jpa.repository.Query; import javax.persistence.EntityManager; -import javax.swing.text.html.Option; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; @@ -43,18 +34,10 @@ import java.util.List; import java.util.Optional; -import static com.moing.backend.domain.board.domain.entity.QBoard.board; -import static com.moing.backend.domain.boardRead.domain.entity.QBoardRead.boardRead; -import static com.moing.backend.domain.member.domain.entity.QMember.member; import static com.moing.backend.domain.mission.domain.entity.QMission.mission; -import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; -import static com.moing.backend.domain.missionRead.domain.entity.QMissionRead.missionRead; +import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; -import static com.moing.backend.domain.team.domain.entity.QTeam.team; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; -import static javax.swing.Spring.constant; -import static org.springframework.data.jpa.domain.Specification.not; -import static org.springframework.data.jpa.domain.Specification.where; @Slf4j public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { @@ -192,6 +175,8 @@ public Optional> findOthersArchives(Long memberId, Long mis BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + BooleanExpression blockCondition= BlockRepositoryUtils.blockCondition(memberId, missionArchive.member.memberId); + return Optional.ofNullable(queryFactory .select(missionArchive) .from(missionArchive) @@ -200,7 +185,7 @@ public Optional> findOthersArchives(Long memberId, Long mis missionArchive.member.memberId.ne(memberId), missionArchive.status.eq(MissionArchiveStatus.COMPLETE).or(missionArchive.status.eq(MissionArchiveStatus.SKIP)), (missionArchive.mission.type.eq(MissionType.REPEAT) - .and(missionArchive.mission.status.eq(MissionStatus.ONGOING)).and(dateInRange)) + .and(missionArchive.mission.status.eq(MissionStatus.ONGOING)).and(dateInRange)).and(blockCondition) .or(missionArchive.mission.type.eq(MissionType.REPEAT) .and(missionArchive.mission.status.eq(MissionStatus.END))) .or(missionArchive.mission.type.eq(MissionType.ONCE)) From d8677a293018b85371dc5b41e6312ef41db172a5 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 12 Feb 2024 22:21:37 +0900 Subject: [PATCH 515/619] =?UTF-8?q?MNG-15=20fix:=20=EB=B6=88=20=EB=8D=98?= =?UTF-8?q?=EC=A7=80=EA=B8=B0=EC=97=90=EC=84=9C=20=EC=B0=A8=EB=8B=A8=20?= =?UTF-8?q?=EB=A9=A4=EB=B2=84=20=EC=95=88=20=EB=B3=B4=EC=9D=B4=EA=B2=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fire/domain/repository/FireCustomRepositoryImpl.java | 6 +++++- .../repository/MissionArchiveCustomRepositoryImpl.java | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index 84ec1109..ececacb0 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.fire.domain.repository; +import com.moing.backend.domain.block.domain.repository.BlockRepositoryUtils; import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.querydsl.core.types.Projections; @@ -52,6 +53,8 @@ public Optional> getFireReceivers(Long teamId, Long mission JPQLQuery completedMembersOfAll = allMissionDone(missionId); + BooleanExpression blockCondition= BlockRepositoryUtils.blockCondition(memberId, teamMember.member.memberId); + return Optional.ofNullable(queryFactory .select(Projections.constructor(FireReceiveRes.class, teamMember.member.memberId, @@ -64,7 +67,8 @@ public Optional> getFireReceivers(Long teamId, Long mission teamMember.member.memberId.ne(memberId), teamMember.member.memberId.notIn(completedMembersOfAll) .and(teamMember.member.memberId.notIn(todayCompletedMemberOfRepeat)), - teamMember.isDeleted.ne(Boolean.TRUE) + teamMember.isDeleted.ne(Boolean.TRUE), + blockCondition ) .fetch()); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 5203f83f..c0326012 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -184,8 +184,9 @@ public Optional> findOthersArchives(Long memberId, Long mis missionArchive.mission.id.eq(missionId), missionArchive.member.memberId.ne(memberId), missionArchive.status.eq(MissionArchiveStatus.COMPLETE).or(missionArchive.status.eq(MissionArchiveStatus.SKIP)), + blockCondition, (missionArchive.mission.type.eq(MissionType.REPEAT) - .and(missionArchive.mission.status.eq(MissionStatus.ONGOING)).and(dateInRange)).and(blockCondition) + .and(missionArchive.mission.status.eq(MissionStatus.ONGOING)).and(dateInRange)) .or(missionArchive.mission.type.eq(MissionType.REPEAT) .and(missionArchive.mission.status.eq(MissionStatus.END))) .or(missionArchive.mission.type.eq(MissionType.ONCE)) From 1dd87866059f21c0275c14e6c82b1bcae19cf9e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 13 Feb 2024 19:04:29 +0900 Subject: [PATCH 516/619] =?UTF-8?q?MNG-18=20fix=20:=20=EC=8A=A4=EC=BD=94?= =?UTF-8?q?=EC=96=B4=20=EC=A0=90=EC=88=98=20=EC=B0=A8=EA=B0=90=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveCreateUseCase.java | 5 ++--- .../application/service/TeamScoreUpdateUseCase.java | 5 +++-- .../domain/teamScore/domain/entity/ScoreStatus.java | 11 +++++++++++ 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/teamScore/domain/entity/ScoreStatus.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 6ea5bda6..caed6cc3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -19,6 +19,7 @@ import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; +import com.moing.backend.domain.teamScore.domain.entity.ScoreStatus; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -96,7 +97,7 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss gainBonusScore(mission, newArchive); } // TODO : 미션 인증 1회당 점수 - teamScoreUpdateUseCase.gainScoreOfArchive(mission); + teamScoreUpdateUseCase.gainScoreOfArchive(mission, ScoreStatus.PLUS); return missionArchiveRes; } @@ -113,13 +114,11 @@ private void gainBonusScore(Mission mission, MissionArchive missionArchive) { if (isAbleToFinishOnceMission(mission)) { mission.updateStatus(MissionStatus.SUCCESS); teamScoreUpdateUseCase.gainScoreOfBonus(mission); - log.info("isAbleToFinishOnceMission"); } } else { if (isAbleToFinishRepeatMission(mission, missionArchive)) { teamScoreUpdateUseCase.gainScoreOfBonus(mission); - log.info("isAbleToFinishRepeatMission"); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java index 6e54b28b..b9be5788 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamScore.domain.entity.ScoreStatus; import com.moing.backend.domain.teamScore.domain.entity.TeamScore; import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; import lombok.RequiredArgsConstructor; @@ -27,7 +28,7 @@ public class TeamScoreUpdateUseCase { /** * 매번 미션 인증 시 점수 적립 */ - public void gainScoreOfArchive(Mission mission) { + public void gainScoreOfArchive(Mission mission, ScoreStatus scoreStatus) { Team team = mission.getTeam(); @@ -36,7 +37,7 @@ public void gainScoreOfArchive(Mission mission) { Integer numOfMember = team.getNumOfMember(); Long gainScore = calculateScoreByArchive(numOfMember); - teamScore.updateScore(gainScore); + teamScore.updateScore(gainScore * scoreStatus.getValue()); teamScore.updateLevel(); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/ScoreStatus.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/ScoreStatus.java new file mode 100644 index 00000000..3471cae4 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/ScoreStatus.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.teamScore.domain.entity; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum ScoreStatus { + PLUS(1L), MINUS(-1L); + private final Long value; +} From 176b3151d63927feb36f2b01007bafd0891c703e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 13 Feb 2024 19:06:09 +0900 Subject: [PATCH 517/619] =?UTF-8?q?MNG-18=20fix=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EB=B3=80=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionArchiveCreateUseCase.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index caed6cc3..4d4ba925 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -32,14 +32,10 @@ public class MissionArchiveCreateUseCase { private final MissionArchiveSaveService missionArchiveSaveService; private final MissionArchiveQueryService missionArchiveQueryService; - private final MissionArchiveDeleteService missionArchiveDeleteService; - - private final MissionHeartQueryService missionHeartQueryService; private final MissionQueryService missionQueryService; private final MemberGetService memberGetService; - private final MissionStateSaveService missionStateSaveService; private final MissionStateUseCase missionStateUseCase; private final TeamScoreUpdateUseCase teamScoreUpdateUseCase; From f68d0bec55eff18f0e52541d71b8a09a3eed68e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 15 Feb 2024 00:54:47 +0900 Subject: [PATCH 518/619] =?UTF-8?q?MNG-18=20fix=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EC=9D=B8=EC=A6=9D=20=EC=B7=A8=EC=86=8C=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=EC=97=90=20=EB=AF=B8=EC=85=98=20=EC=A0=90?= =?UTF-8?q?=EC=88=98=20=EC=B0=A8=EA=B0=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveDeleteUseCase.java | 9 +++- .../service/TeamScoreUpdateUseCase.java | 2 - .../teamScore/domain/entity/TeamScore.java | 44 ++++++++++++++++--- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java index a66bc217..cb577f8a 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java @@ -23,6 +23,8 @@ import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; +import com.moing.backend.domain.teamScore.domain.entity.ScoreStatus; import com.moing.backend.global.utils.UpdateUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -47,6 +49,8 @@ public class MissionArchiveDeleteUseCase { private final MissionStateDeleteService missionStateDeleteService; private final MissionStateQueryService missionStateQueryService; + private final TeamScoreUpdateUseCase teamScoreUpdateUseCase; + private final UpdateUtils updateUtils; @@ -55,10 +59,11 @@ public Long deleteArchive(String userSocialId, Long missionId,Long count) { Member member = memberGetService.getMemberBySocialId(userSocialId); Long memberId = member.getMemberId(); + Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); - MissionArchive deleteArchive = missionArchiveQueryService.findOneMyArchive(memberId, missionId,count).get(0); + MissionArchive deleteArchive = missionArchiveQueryService.findOneMyArchive(memberId, missionId,count); MissionState missionState = missionStateQueryService.findMissionState(member, mission); LocalDateTime createdDate = deleteArchive.getCreatedDate(); @@ -77,6 +82,8 @@ public Long deleteArchive(String userSocialId, Long missionId,Long count) { missionArchiveDeleteService.deleteMissionArchive(deleteArchive); missionStateDeleteService.deleteMissionState(missionState); + teamScoreUpdateUseCase.gainScoreOfArchive(mission, ScoreStatus.MINUS); + return deleteArchive.getId(); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java index b9be5788..04c88904 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java @@ -38,7 +38,6 @@ public void gainScoreOfArchive(Mission mission, ScoreStatus scoreStatus) { Long gainScore = calculateScoreByArchive(numOfMember); teamScore.updateScore(gainScore * scoreStatus.getValue()); - teamScore.updateLevel(); } @@ -69,7 +68,6 @@ public void gainScoreOfBonus(Mission mission) { } else { teamScore.updateScore(BONUS_SCORE_REPEAT_MISSION); } - teamScore.updateLevel(); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index 62531629..d0a4395d 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -34,17 +34,51 @@ public TeamScore(Team team, Long score,Long level) { } public void updateScore(Long score) { + + int newStep = getStep(this.level, this.score + score); + this.score += score; + + if (this.score < 0) { // 점수 차감 / score down + level down + this.updateLevel(ScoreStatus.MINUS); + } + else { // 점수 획득. score up / score down + level up + + if ((40 + (newStep * 15L) <= this.score)) { // score down + level up + this.updateLevel(ScoreStatus.PLUS); + + } else { // score up +// this.score += score; + } + } + + } - public void updateLevel() { - final int[] steps = {1, 2, 25, 45, 70, 120}; + public int getStep(Long level, Long score) { + final int[] steps = {1, 2, 26, 46, 71, 121}; + + int index = 0; + for (int i = 5; i > 0; i--) { + if (steps[i-1] <= this.level && this.level < steps[i]) { + index=i-1; + break; + + } + } + return index; + + } + + public void updateLevel(ScoreStatus sign) { + final int[] steps = {1, 2, 26, 46, 71, 121}; + + this.level += sign.getValue(); for (int i = 5; i > 0; i--) { if (steps[i-1] <= this.level && this.level <= steps[i]) { - if ((40 + ((i-1) * 15)) <= score) { - this.level+=1; - this.score -= (40 + ((i-1) * 15)); + if ((40 + ((i-1) * 20)) <= score || score < 0) { + this.score -= sign.getValue() * (40 + ((i-1) * 20)); this.team.updateLevelOfFire(); return; } From 3f621a902d0cfbe6ab2b72c1293240355f987e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 15 Feb 2024 00:55:33 +0900 Subject: [PATCH 519/619] =?UTF-8?q?MNG-18=20fix=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EC=9D=B8=EC=A6=9D=20=EC=B7=A8=EC=86=8C=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EC=95=88=EB=90=90=EB=8D=98=20=EB=B2=84=EA=B7=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/service/MissionArchiveQueryService.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 68d24a01..700897c5 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionArchive.domain.service; +import com.moing.backend.domain.member.domain.repository.MemberRepository; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; @@ -26,6 +27,7 @@ public class MissionArchiveQueryService { private final MissionRepository missionRepository; private final MissionArchiveRepository missionArchiveRepository; private final TeamMemberRepository teamMemberRepository; + private final MemberRepository memberRepository; public MissionArchive findByMissionArchiveId(Long missionArchiveId) { return missionArchiveRepository.findById(missionArchiveId).orElseThrow(NotFoundMissionArchiveException::new); @@ -42,15 +44,11 @@ public List findMyArchive(Long memberId, Long missionId) { return optional.get(); } } - public List findOneMyArchive(Long memberId, Long missionId, Long count) { + public MissionArchive findOneMyArchive(Long memberId, Long missionId, Long count) { - Optional> optional = missionArchiveRepository.findMyArchives(memberId, missionId); + List missionArchives = missionArchiveRepository.findMyArchives(memberId, missionId).orElseThrow(NotFoundMissionArchiveException::new); + return missionArchives.stream().filter( m -> m.getCount().equals(count)).findFirst().orElseThrow(NotFoundMissionArchiveException::new); - if (optional.isPresent() && optional.get().size() == 0) { - return new ArrayList<>(); - } else { - return optional.get(); - } } public List findOthersArchive(Long memberId, Long missionId) { From d93d539fa17762618f3a4f3a59c46fdcd831e442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 15 Feb 2024 01:20:41 +0900 Subject: [PATCH 520/619] =?UTF-8?q?MNG-16=20fix=20:=20=EC=86=8C=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=EC=9E=A5=20=EB=AA=A8=EB=93=A0=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=20=EA=B6=8C=ED=95=9C=20=EB=B6=80=EC=97=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionUpdateUseCase.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index bd10ef8e..37a42829 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -42,7 +42,7 @@ public MissionCreateRes updateMission(String userSocialId, Long missionId, Missi * 미션 생성자 확인 */ - if (!(memberId.equals(mission.getMakerId()) || memberId.equals(team.getLeaderId()))) { + if (!((memberId.equals(mission.getMakerId())) || memberId.equals(team.getLeaderId())) ) { throw new NoAccessUpdateMission(); } mission.updateMission(missionReq); @@ -55,10 +55,11 @@ public MissionReadRes updateMissionStatus(String userSocialId, Long missionId) { Member member = memberGetService.getMemberBySocialId(userSocialId); + Long memberId = member.getMemberId(); Mission findMission = missionQueryService.findMissionById(missionId); Team team = findMission.getTeam(); - if (findMission.getMakerId().equals(member.getMemberId())) { + if ((memberId.equals(findMission.getMakerId())) || memberId.equals(team.getLeaderId()) ) { findMission.updateStatus(MissionStatus.END); findMission.updateDueTo(LocalDateTime.now()); } else { From 1c12c73876c0276df55fd6e813d4024a99785beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 15 Feb 2024 01:21:04 +0900 Subject: [PATCH 521/619] =?UTF-8?q?MNG-16=20fix=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95/=EC=A2=85=EB=A3=8C=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/moing/backend/global/response/ErrorCode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 86c82168..4478309a 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -27,8 +27,8 @@ public enum ErrorCode { //미션 관련 에러코드 NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), - NO_ACCESS_UPDATE_MISSION("M0001", "미션 생성자만 미션을 수정할 수 있습니다."), - NO_ACCESS_DELETE_MISSION("M0001", "미션 생성자만 미션을 삭제할 수 있습니다."), + NO_ACCESS_UPDATE_MISSION("M0001", "미션 생성자 또는 소모임장만 미션을 수정할 수 있습니다."), + NO_ACCESS_DELETE_MISSION("M0001", "미션 생성자 또는 소모임장만 미션을 삭제할 수 있습니다."), NOT_FOUND_MISSION("M0002", "미션을 찾을 수 없습니다."), NOT_FOUND_END_MISSION("M0003", "기한이 지난 미션을 찾을 수 없습니다."), NO_MORE_CREATE_MISSION("M0004", "반복미션은 2개까지 생성할 수 있습니다."), From 9ee35d25e1324f34f8f581420db93f4d9a7fb7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 16 Feb 2024 00:37:44 +0900 Subject: [PATCH 522/619] =?UTF-8?q?MNG-16=20fix=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EA=B1=B4=EB=84=88=EB=9B=B0=EA=B8=B0=20=EC=B7=A8=EC=86=8C=20?= =?UTF-8?q?=EC=95=88=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionArchiveDeleteUseCase.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java index cb577f8a..58ebc08d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java @@ -12,6 +12,7 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; @@ -74,7 +75,7 @@ public Long deleteArchive(String userSocialId, Long missionId,Long count) { throw new NoAccessMissionArchiveException(); } - if (mission.getWay().equals(MissionWay.PHOTO)) { + if (deleteArchive.getStatus().equals(MissionArchiveStatus.COMPLETE) && mission.getWay().equals(MissionWay.PHOTO)) { String archive = deleteArchive.getArchive(); updateUtils.deleteImgUrl(archive); } From 03ed130741a901f9cb023d7c060132d31de18a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 20 Feb 2024 23:16:09 +0900 Subject: [PATCH 523/619] =?UTF-8?q?MNG-18=20fix=20:=20=EB=AA=A9=ED=91=9C?= =?UTF-8?q?=EB=B3=B4=EB=93=9C=20=EB=A0=88=EB=B2=A8=EA=B3=BC=20=EB=AF=B8?= =?UTF-8?q?=EC=85=98=EB=B3=B4=EB=93=9C=20=EB=A0=88=EB=B2=A8=EC=9D=B4=20?= =?UTF-8?q?=EB=8B=A4=EB=A5=B8=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moing/backend/domain/team/domain/entity/Team.java | 4 ++-- .../backend/domain/teamScore/domain/entity/TeamScore.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java index 906dd2fe..cb348a9c 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java +++ b/src/main/java/com/moing/backend/domain/team/domain/entity/Team.java @@ -90,7 +90,7 @@ public void deleteTeamMember(){ numOfMember--; } - public void updateLevelOfFire() { - levelOfFire++; + public void updateLevelOfFire(Integer level) { + this.levelOfFire = level; } } diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java index d0a4395d..061a5100 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -74,12 +74,12 @@ public void updateLevel(ScoreStatus sign) { final int[] steps = {1, 2, 26, 46, 71, 121}; this.level += sign.getValue(); + this.team.updateLevelOfFire(this.level.intValue()); for (int i = 5; i > 0; i--) { if (steps[i-1] <= this.level && this.level <= steps[i]) { if ((40 + ((i-1) * 20)) <= score || score < 0) { this.score -= sign.getValue() * (40 + ((i-1) * 20)); - this.team.updateLevelOfFire(); return; } } From 51556b7855585f8b360c21d65c270a06f0bb8018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Sat, 24 Feb 2024 21:32:44 +0900 Subject: [PATCH 524/619] =?UTF-8?q?MNG-19=20fix=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EC=9D=BC/=EC=9B=94=20?= =?UTF-8?q?=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionStateScheduleUseCase.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index df76acdb..23e1fcf8 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -56,17 +56,9 @@ public void singleMissionEndRoutine() { } - @Scheduled(cron = "0 0 8 * * *") + @Scheduled(cron = "0 0 20 * * *") public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } - @Scheduled(cron = "0 1 20 * * 0") - public void RepeatMissionRemindAlarmOnSunday() { - missionRemindAlarmUseCase.sendRepeatMissionRemindOnSunday(); - } - @Scheduled(cron = "0 1 20 * * 1") - public void RepeatMissionRemindAlarmOnMonday() { - missionRemindAlarmUseCase.sendRepeatMissionRemindOnMonday(); - } } From 397993136f27a6eba5b3def0609fab548829e760 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Tue, 27 Feb 2024 02:53:46 +0900 Subject: [PATCH 525/619] deploy: test deploy --- .deploy/deploy_prod.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.deploy/deploy_prod.sh b/.deploy/deploy_prod.sh index cee38ea1..f2612515 100644 --- a/.deploy/deploy_prod.sh +++ b/.deploy/deploy_prod.sh @@ -64,4 +64,4 @@ else LOGS=$(docker logs ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} 2>&1) echo "Error: ${DOCKER_APP_NAME}-${AFTER_COMPOSE_COLOR} failed to start." echo "$LOGS" -fi \ No newline at end of file +fi From e5c5bfb28f58d9d5016677df0ad9e95b34c01e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 29 Feb 2024 12:35:40 +0900 Subject: [PATCH 526/619] =?UTF-8?q?hotfix=20fix=20:=20=EB=A6=AC=EB=A7=88?= =?UTF-8?q?=EC=9D=B8=EB=93=9C=20=ED=91=B8=EC=8B=9C=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=AC=B8=EA=B5=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/global/config/fcm/constant/RemindMissionTitle.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java index 7abd7a5d..95ee96f4 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/RemindMissionTitle.java @@ -9,7 +9,7 @@ public enum RemindMissionTitle { REMIND_MISSION_TITLE1("오늘도 좋은 하루 보내세요!"), REMIND_MISSION_TITLE2("혹시 ... 잊으신 건 아니죠?\uD83D\uDC40"), - REMIND_MISSION_TITLE3("좋은 아침이에요! ☀\uFE0F"), + REMIND_MISSION_TITLE3("아직 인증하지 않은 미션이 있어요!"), REMIND_MISSION_TITLE4("오늘의 열정이 타오르불\uD83D\uDD25"), From e87fc16f68978ddf98190379baf4b58284207154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 29 Feb 2024 13:05:51 +0900 Subject: [PATCH 527/619] =?UTF-8?q?hotfix=20feat=20:=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=ED=91=B8=EC=8B=9C=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=8A=A4=EC=BC=80=EC=A5=B4=EB=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(=EC=98=A4=ED=9B=845=EC=8B=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/UpdateRemindAlarmUseCase.java | 86 +++++++++++++++++++ .../repository/MemberCustomRepository.java | 3 + .../MemberCustomRepositoryImpl.java | 15 ++++ .../domain/service/MemberGetService.java | 6 ++ .../NotFoundRemindAlarmException.java | 11 +++ .../service/MissionStateScheduleUseCase.java | 12 ++- .../backend/global/response/ErrorCode.java | 1 + 7 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/member/exception/NotFoundRemindAlarmException.java diff --git a/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java new file mode 100644 index 00000000..1355e921 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java @@ -0,0 +1,86 @@ +package com.moing.backend.domain.member.application.service; + +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.application.service.SaveMultiAlarmHistoryUseCase; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.entity.PagePath; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.application.service.SendMissionStartAlarmUseCase; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.global.config.fcm.dto.request.MultiRequest; +import com.moing.backend.global.config.fcm.service.FcmService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.moing.backend.global.config.fcm.constant.RemindMissionTitle.REMIND_ON_MONDAY_MESSAGE; +import static com.moing.backend.global.config.fcm.constant.RemindMissionTitle.REMIND_ON_MONDAY_TITLE; +@Service +@Transactional +@RequiredArgsConstructor +public class UpdateRemindAlarmUseCase { + + private final MemberGetService memberGetService; + private final FcmService fcmService; + private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; + + String REMIND_NAME = "미션 리마인드"; + + + public Boolean sendUpdateAppPushAlarm() { + + String title = "MOING 업데이트 소식"; + String message = "이제 누구나 미션을 만들 수 있어요. 지금 업데이트하고 다른 소식도 확인해보세요!"; + + List allMemberOfPushAlarm = memberGetService.getAllMemberOfPushAlarm(); + + Optional> memberIdAndTokens = mapToMemberAndToken(allMemberOfPushAlarm); + Optional> pushMemberIdAndToken = isPushMemberIdAndToken(allMemberOfPushAlarm); + + if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { + fcmService.sendMultipleDevices(new MultiRequest(pushMemberIdAndToken.get(), title,message, "",REMIND_NAME, AlarmType.REMIND, PagePath.HOME_PATH.getValue())); + } + if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { + saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.HOME_PATH.getValue()); + } + + return true; + + + } + + public Optional> mapToMemberAndToken(List members) { + return Optional.of(members.stream() + .map(member -> MemberIdAndToken.builder() + .fcmToken(member.getFcmToken()) + .memberId(member.getMemberId()) + .build()) + .collect(Collectors.toList())); + } + public Optional> isPushMemberIdAndToken(List members) { + return Optional.of(members.stream() + .map(member -> { + if (member.isRemindPush() && !member.isSignOut()) { + return MemberIdAndToken.builder() + .fcmToken(member.getFcmToken()) + .memberId(member.getMemberId()) + .build(); + } + return null; + }) + .filter(Objects::nonNull) + .collect(Collectors.toList())); + } + +} diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java index 20217552..fc4474da 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.statistics.application.dto.DailyStats; +import java.util.List; import java.util.Optional; public interface MemberCustomRepository { @@ -12,4 +13,6 @@ public interface MemberCustomRepository { Optional findNotDeletedByEmail(String email); Optional findNotDeletedByMemberId(Long id); DailyStats getDailyStats(); + + Optional> findAllMemberOnPushAlarm(); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java index e0d45867..233e6001 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java @@ -8,6 +8,7 @@ import javax.persistence.EntityManager; import java.time.LocalDateTime; import java.time.ZoneId; +import java.util.List; import java.util.Optional; import static com.moing.backend.domain.member.domain.entity.QMember.member; @@ -125,4 +126,18 @@ public DailyStats getDailyStats() { yesterdayOnceMissions); } + @Override + public Optional> findAllMemberOnPushAlarm() { + return Optional.ofNullable( + queryFactory.selectFrom(member) + .where( + member.isDeleted.eq(false), + member.isRemindPush.eq(true), + member.isSignOut.eq(false) + ) + .fetch() + ); + } + + } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java index 027eb5b4..dbaa3737 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java @@ -3,12 +3,14 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.repository.MemberRepository; import com.moing.backend.domain.member.exception.NotFoundBySocialIdException; +import com.moing.backend.domain.member.exception.NotFoundRemindAlarmException; import com.moing.backend.domain.statistics.application.dto.DailyStats; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import javax.transaction.Transactional; import java.math.BigInteger; +import java.util.List; @DomainService @Transactional @@ -27,4 +29,8 @@ public Member getMemberByMemberId(Long memberId) { public DailyStats getDailyStats(){ return memberRepository.getDailyStats(); } + + public List getAllMemberOfPushAlarm() { + return memberRepository.findAllMemberOnPushAlarm().orElseThrow(NotFoundRemindAlarmException::new); + } } diff --git a/src/main/java/com/moing/backend/domain/member/exception/NotFoundRemindAlarmException.java b/src/main/java/com/moing/backend/domain/member/exception/NotFoundRemindAlarmException.java new file mode 100644 index 00000000..679e8d2f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/exception/NotFoundRemindAlarmException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.member.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundRemindAlarmException extends MemberException { + public NotFoundRemindAlarmException() { + super(ErrorCode.NOT_FOUND_ALL_MEMBER, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index b3f0acb2..371f5f03 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.missionState.application.service; +import com.moing.backend.domain.member.application.service.UpdateRemindAlarmUseCase; import com.moing.backend.domain.mission.application.service.MissionRemindAlarmUseCase; import com.moing.backend.domain.mission.application.service.SendMissionStartAlarmUseCase; import com.moing.backend.domain.mission.domain.entity.Mission; @@ -34,13 +35,13 @@ public class MissionStateScheduleUseCase { private final MissionStateUseCase missionStateUseCase; private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; private final MissionQueryService missionQueryService; - private final MissionStateQueryService missionStateQueryService; - private final MissionStateDeleteService missionStateDeleteService; + private final UpdateRemindAlarmUseCase updateRemindAlarmUseCase; private final TeamScoreLogicUseCase teamScoreLogicUseCase; private final SendMissionStartAlarmUseCase sendMissionStartAlarmUseCase; + /** * 반복미션 마감 * 일요일 마감 루틴 @@ -105,4 +106,11 @@ public void RepeatMissionRemindAlarmOnSunday() { public void RepeatMissionRemindAlarmOnMonday() { missionRemindAlarmUseCase.sendRepeatMissionRemindOnMonday(); } + + @Scheduled(cron = "0 0 17 * * *") + public void UpdatePushAlarm() { + updateRemindAlarmUseCase.sendUpdateAppPushAlarm(); + } + + } diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index d5aa9c43..b3e202af 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -24,6 +24,7 @@ public enum ErrorCode { TOKEN_INVALID_ERROR("AU0002", "입력 토큰이 유효하지 않습니다."), APPID_INVALID_ERROR("AU0003", "appId가 유효하지 않습니다"), NICKNAME_DUPLICATION_ERROR("AU0004", "닉네임이 중복됩니다."), + NOT_FOUND_ALL_MEMBER("AU0005","푸시 알림을 위한 모든 멤버를 불러오는데 실패했습니다."), //미션 관련 에러코드 NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), From 71631ad0c3b57671e92381195951590e3961c170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 29 Feb 2024 13:07:06 +0900 Subject: [PATCH 528/619] =?UTF-8?q?hotfix=20feat=20:=20=EB=A6=AC=EB=A7=88?= =?UTF-8?q?=EC=9D=B8=EB=93=9C=20=ED=91=B8=EC=8B=9C=EC=95=8C=EB=A6=BC=20on?= =?UTF-8?q?=20=ED=95=B4=EB=91=94=20=EC=9C=A0=EC=A0=80=20=EA=B0=80=EC=A0=B8?= =?UTF-8?q?=EC=98=A4=EA=B8=B0=20testcode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MemberCustomRepositoryTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/test/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryTest.java diff --git a/src/test/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryTest.java b/src/test/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryTest.java new file mode 100644 index 00000000..ea725f82 --- /dev/null +++ b/src/test/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryTest.java @@ -0,0 +1,35 @@ +//package com.moing.backend.domain.member.domain.repository; +// +//import com.moing.backend.domain.member.domain.entity.Member; +//import org.junit.jupiter.api.Test; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.test.context.ActiveProfiles; +//import org.springframework.transaction.annotation.Transactional; +// +//import javax.persistence.EntityManager; +// +//import java.util.List; +// +//import static org.junit.jupiter.api.Assertions.*; +//@SpringBootTest +//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +//@ActiveProfiles("dev") +//@Transactional +//class MemberCustomRepositoryTest { +// +// @Autowired +// EntityManager em; +// +// @Autowired +// private MemberRepository memberRepository; +// @Test +// void findAllMemberOnPushAlarm() { +// List members = memberRepository.findAllMemberOnPushAlarm().orElseThrow(); +// for (Member member : members) { +// System.out.println(member.getNickName()); +// } +// +// } +//} \ No newline at end of file From b8f56e9bea3ea2afe6fe0a7168bf13c8426d208b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 29 Feb 2024 15:22:13 +0900 Subject: [PATCH 529/619] =?UTF-8?q?hotfix=20fix=20:=20fcmService=20?= =?UTF-8?q?=EB=8C=80=EC=8B=A0=20multiMessageSender=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/UpdateRemindAlarmUseCase.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java index 1355e921..0f535603 100644 --- a/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java @@ -10,7 +10,7 @@ import com.moing.backend.domain.mission.application.service.SendMissionStartAlarmUseCase; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.global.config.fcm.dto.request.MultiRequest; -import com.moing.backend.global.config.fcm.service.FcmService; +import com.moing.backend.global.config.fcm.service.MultiMessageSender; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Profile; @@ -32,8 +32,8 @@ public class UpdateRemindAlarmUseCase { private final MemberGetService memberGetService; - private final FcmService fcmService; private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; + private final MultiMessageSender multiMessageSender; String REMIND_NAME = "미션 리마인드"; @@ -49,12 +49,11 @@ public Boolean sendUpdateAppPushAlarm() { Optional> pushMemberIdAndToken = isPushMemberIdAndToken(allMemberOfPushAlarm); if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { - fcmService.sendMultipleDevices(new MultiRequest(pushMemberIdAndToken.get(), title,message, "",REMIND_NAME, AlarmType.REMIND, PagePath.HOME_PATH.getValue())); + multiMessageSender.send(new MultiRequest(pushMemberIdAndToken.get(), title, message, "", REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); } if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { - saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.HOME_PATH.getValue()); + saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); } - return true; From 022b7873d1240fd0cf6c79699ecc1a040c1f7780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Thu, 29 Feb 2024 19:53:41 +0900 Subject: [PATCH 530/619] =?UTF-8?q?hotfix=20fix=20:=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EB=8F=85=EB=A0=A4=20=ED=91=B8=EC=8B=9C?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=8A=A4=EC=BC=80=EC=A5=B4=EB=A7=81=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionStateScheduleUseCase.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index 82c34bf2..025f790c 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -61,9 +61,9 @@ public void MissionRemindAlarm() { } - @Scheduled(cron = "0 0 17 * * *") - public void UpdatePushAlarm() { - updateRemindAlarmUseCase.sendUpdateAppPushAlarm(); - } +// @Scheduled(cron = "0 0 17 * * *") +// public void UpdatePushAlarm() { +// updateRemindAlarmUseCase.sendUpdateAppPushAlarm(); +// } } From 5a312ac26508693c688da6570b18ada016780864 Mon Sep 17 00:00:00 2001 From: Minsu Kim <86006389+minsu20@users.noreply.github.com> Date: Tue, 5 Mar 2024 01:17:35 +0900 Subject: [PATCH 531/619] =?UTF-8?q?deploy=20:=20secret=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 4d0d9fd7e697e0e53cbd6c5903d8d9d1d6dbaaf4 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 5 Mar 2024 03:01:47 +0900 Subject: [PATCH 532/619] =?UTF-8?q?deploy:=20=ED=94=84=EB=A1=9C=ED=95=84?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .deploy/{Dockerfile => dev_dockerfile} | 2 +- .deploy/prod_dockerfile | 16 ++++++++++++++++ .github/workflows/CD-dev.yml | 4 ++-- .github/workflows/CD-prod.yml | 4 ++-- 4 files changed, 21 insertions(+), 5 deletions(-) rename .deploy/{Dockerfile => dev_dockerfile} (83%) create mode 100644 .deploy/prod_dockerfile diff --git a/.deploy/Dockerfile b/.deploy/dev_dockerfile similarity index 83% rename from .deploy/Dockerfile rename to .deploy/dev_dockerfile index 25848cbe..3abad45c 100644 --- a/.deploy/Dockerfile +++ b/.deploy/dev_dockerfile @@ -12,5 +12,5 @@ COPY ${JAR_FILE} app.jar COPY ./build/docs/asciidoc/*.html /static/docs/ # 애플리케이션 실행 시 -cp 옵션을 사용하여 /static/docs 디렉토리를 클래스패스에 추가 -ENTRYPOINT ["java","-cp",".:/static/docs","-jar","/app.jar"] +ENTRYPOINT ["java","-cp",".:/static/docs","-Dspring.profiles.active=dev","-jar","/app.jar"] diff --git a/.deploy/prod_dockerfile b/.deploy/prod_dockerfile new file mode 100644 index 00000000..bff7338e --- /dev/null +++ b/.deploy/prod_dockerfile @@ -0,0 +1,16 @@ +FROM openjdk:11-jdk + +# 타임존 설정 +ENV TZ=Asia/Seoul +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +ARG CACHEBREAKER=1 +ARG JAR_FILE=./build/libs/backend-0.0.1-SNAPSHOT.jar +COPY ${JAR_FILE} app.jar + +# 문서를 이미지의 /static/docs 디렉토리에 복사 +COPY ./build/docs/asciidoc/*.html /static/docs/ + +# 애플리케이션 실행 시 -cp 옵션을 사용하여 /static/docs 디렉토리를 클래스패스에 추가 +ENTRYPOINT ["java","-cp",".:/static/docs","-Dspring.profiles.active=prod","-jar","/app.jar"] + diff --git a/.github/workflows/CD-dev.yml b/.github/workflows/CD-dev.yml index 40cd9a33..92a3178b 100644 --- a/.github/workflows/CD-dev.yml +++ b/.github/workflows/CD-dev.yml @@ -85,8 +85,8 @@ jobs: # Docker 이미지 빌드 및 푸시 - name: Docker build run: | - docker build --no-cache -f ./.deploy/Dockerfile -t ${{ secrets.DOCKER_USERNAME_DEV }}/moing_dev:green . - docker build --no-cache -f ./.deploy/Dockerfile -t ${{ secrets.DOCKER_USERNAME_DEV }}/moing_dev:blue . + docker build --no-cache -f ./.deploy/dev_dockerfile -t ${{ secrets.DOCKER_USERNAME_DEV }}/moing_dev:green . + docker build --no-cache -f ./.deploy/dev_dockerfile -t ${{ secrets.DOCKER_USERNAME_DEV }}/moing_dev:blue . - name: Docker Hub Login diff --git a/.github/workflows/CD-prod.yml b/.github/workflows/CD-prod.yml index 2c132f0c..4f211ba4 100644 --- a/.github/workflows/CD-prod.yml +++ b/.github/workflows/CD-prod.yml @@ -85,8 +85,8 @@ jobs: # Docker 이미지 빌드 및 푸시 - name: Docker build run: | - docker build --no-cache -f ./.deploy/Dockerfile -t ${{ secrets.DOCKER_USERNAME_PROD }}/moing_prod:green . - docker build --no-cache -f ./.deploy/Dockerfile -t ${{ secrets.DOCKER_USERNAME_PROD }}/moing_prod:blue . + docker build --no-cache -f ./.deploy/prod_dockerfile -t ${{ secrets.DOCKER_USERNAME_PROD }}/moing_prod:green . + docker build --no-cache -f ./.deploy/prod_dockerfile -t ${{ secrets.DOCKER_USERNAME_PROD }}/moing_prod:blue . - name: Docker Hub Login From 5f240b4d7af20a5e6b8e997ffcacf89fa2a1227a Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 5 Mar 2024 17:04:02 +0900 Subject: [PATCH 533/619] =?UTF-8?q?deploy:=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=88=ED=84=B0=EB=A7=81=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20gradle=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build.gradle b/build.gradle index e9a7af8c..c33ae8ce 100644 --- a/build.gradle +++ b/build.gradle @@ -97,6 +97,13 @@ dependencies { //json implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.3' + //log + implementation 'org.springframework.boot:spring-boot-starter-logging' + + implementation("org.springframework.boot:spring-boot-starter-actuator") + implementation("io.micrometer:micrometer-registry-prometheus") // 프로메테우스 마이크로미터 + + } tasks.named('test') { From 258d2ab8c3b789fd470bca67535f1db9fb6fe085 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 5 Mar 2024 17:11:27 +0900 Subject: [PATCH 534/619] =?UTF-8?q?deploy:=20=EB=A1=9C=EA=B7=B8=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=88=ED=84=B0=EB=A7=81=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20security=20=ED=97=88=EC=9A=A9=EB=B2=94=EC=9C=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moing/backend/global/config/security/SecurityConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java index e4b390f3..76259ea4 100644 --- a/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java +++ b/src/main/java/com/moing/backend/global/config/security/SecurityConfig.java @@ -52,7 +52,7 @@ protected void configure(HttpSecurity http) throws Exception { .antMatchers("/swagger-ui/**").permitAll() .antMatchers("/webjars/**").permitAll() .antMatchers("/v3/api-docs").permitAll() - .antMatchers("/api/auth/**", "/docs/**", "/api/image/**").permitAll() + .antMatchers("/api/auth/**", "/docs/**", "/api/image/**", "/actuator", "/actuator/*").permitAll() .anyRequest().authenticated() .and() .apply(new JwtSecurityConfig(tokenUtil, memberQueryService)); From 9a2c92ff8f15983688004c753e705c475cf3049f Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 8 Mar 2024 03:30:22 +0900 Subject: [PATCH 535/619] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=83=9D=EC=84=B1=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?logback-spring.xml=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- logs/error-log-2024-03-08.0.log | 170 ++++++++++++++++++++++++++ logs/error.log | 1 + logs/info-log-2024-03-08.0.log | 57 +++++++++ logs/info.log | 58 +++++++++ src/main/resources/logback-spring.xml | 26 ++++ 5 files changed, 312 insertions(+) create mode 100644 logs/error-log-2024-03-08.0.log create mode 100644 logs/error.log create mode 100644 logs/info-log-2024-03-08.0.log create mode 100644 logs/info.log create mode 100644 src/main/resources/logback-spring.xml diff --git a/logs/error-log-2024-03-08.0.log b/logs/error-log-2024-03-08.0.log new file mode 100644 index 00000000..0690a9c2 --- /dev/null +++ b/logs/error-log-2024-03-08.0.log @@ -0,0 +1,170 @@ +2024-03-08 03:20:37 [ERROR] Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. Check whether you have a dependency on 'io.netty:netty-resolver-dns-native-macos' +java.lang.reflect.InvocationTargetException: null + at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) + at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) + at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) + at io.netty.resolver.dns.DnsServerAddressStreamProviders.(DnsServerAddressStreamProviders.java:64) + at io.netty.resolver.dns.DnsNameResolverBuilder.(DnsNameResolverBuilder.java:66) + at io.lettuce.core.resource.AddressResolverGroupProvider$DefaultDnsAddressResolverGroupWrapper.(AddressResolverGroupProvider.java:56) + at io.lettuce.core.resource.AddressResolverGroupProvider.(AddressResolverGroupProvider.java:35) + at io.lettuce.core.resource.DefaultClientResources.(DefaultClientResources.java:112) + at io.lettuce.core.AbstractRedisClient.(AbstractRedisClient.java:123) + at io.lettuce.core.RedisClient.(RedisClient.java:99) + at io.lettuce.core.RedisClient.create(RedisClient.java:136) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.lambda$createClient$7(LettuceConnectionFactory.java:1216) + at java.base/java.util.Optional.orElseGet(Optional.java:369) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.createClient(LettuceConnectionFactory.java:1216) + at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.afterPropertiesSet(LettuceConnectionFactory.java:338) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.resolveBeanReference(ConfigurationClassEnhancer.java:362) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:334) + at com.moing.backend.global.config.redis.RedisConfig$$EnhancerBySpringCGLIB$$d14604b9.redisConnectionFactory() + at com.moing.backend.global.config.redis.RedisConfig.redisTemplate(RedisConfig.java:37) + at com.moing.backend.global.config.redis.RedisConfig$$EnhancerBySpringCGLIB$$d14604b9.CGLIB$redisTemplate$0() + at com.moing.backend.global.config.redis.RedisConfig$$EnhancerBySpringCGLIB$$d14604b9$$FastClassBySpringCGLIB$$3fb0050f.invoke() + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) + at com.moing.backend.global.config.redis.RedisConfig$$EnhancerBySpringCGLIB$$d14604b9.redisTemplate() + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) + at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) + at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) + at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) + at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) + at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) + at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) + at com.moing.backend.BackendApplication.main(BackendApplication.java:16) +Caused by: java.lang.UnsatisfiedLinkError: failed to load the required native library + at io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.ensureAvailability(MacOSDnsServerAddressStreamProvider.java:110) + at io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.(MacOSDnsServerAddressStreamProvider.java:120) + ... 100 common frames omitted +Caused by: java.lang.UnsatisfiedLinkError: could not load a native library: netty_resolver_dns_native_macos_aarch_64 + at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:239) + at io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.loadNativeLibrary(MacOSDnsServerAddressStreamProvider.java:92) + at io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.(MacOSDnsServerAddressStreamProvider.java:77) + at java.base/java.lang.Class.forName0(Native Method) + at java.base/java.lang.Class.forName(Class.java:398) + at io.netty.resolver.dns.DnsServerAddressStreamProviders$1.run(DnsServerAddressStreamProviders.java:50) + at java.base/java.security.AccessController.doPrivileged(Native Method) + at io.netty.resolver.dns.DnsServerAddressStreamProviders.(DnsServerAddressStreamProviders.java:46) + ... 95 common frames omitted + Suppressed: java.lang.UnsatisfiedLinkError: could not load a native library: netty_resolver_dns_native_macos + at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:239) + at io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.loadNativeLibrary(MacOSDnsServerAddressStreamProvider.java:95) + ... 101 common frames omitted + Caused by: java.io.FileNotFoundException: META-INF/native/libnetty_resolver_dns_native_macos.jnilib + at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:181) + ... 102 common frames omitted + Suppressed: java.lang.UnsatisfiedLinkError: no netty_resolver_dns_native_macos in java.library.path: [/Users/minsu/Library/Java/Extensions, /Library/Java/Extensions, /Network/Library/Java/Extensions, /System/Library/Java/Extensions, /usr/lib/java, .] + at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2662) + at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:827) + at java.base/java.lang.System.loadLibrary(System.java:1871) + at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:38) + at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:396) + at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:161) + ... 102 common frames omitted + Suppressed: java.lang.UnsatisfiedLinkError: no netty_resolver_dns_native_macos in java.library.path: [/Users/minsu/Library/Java/Extensions, /Library/Java/Extensions, /Network/Library/Java/Extensions, /System/Library/Java/Extensions, /usr/lib/java, .] + at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2662) + at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:827) + at java.base/java.lang.System.loadLibrary(System.java:1871) + at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:38) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at io.netty.util.internal.NativeLibraryLoader$1.run(NativeLibraryLoader.java:430) + at java.base/java.security.AccessController.doPrivileged(Native Method) + at io.netty.util.internal.NativeLibraryLoader.loadLibraryByHelper(NativeLibraryLoader.java:422) + at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:388) + ... 103 common frames omitted +Caused by: java.io.FileNotFoundException: META-INF/native/libnetty_resolver_dns_native_macos_aarch_64.jnilib + at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:181) + ... 102 common frames omitted + Suppressed: java.lang.UnsatisfiedLinkError: no netty_resolver_dns_native_macos_aarch_64 in java.library.path: [/Users/minsu/Library/Java/Extensions, /Library/Java/Extensions, /Network/Library/Java/Extensions, /System/Library/Java/Extensions, /usr/lib/java, .] + at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2662) + at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:827) + at java.base/java.lang.System.loadLibrary(System.java:1871) + at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:38) + at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:396) + at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:161) + ... 102 common frames omitted + Suppressed: java.lang.UnsatisfiedLinkError: no netty_resolver_dns_native_macos_aarch_64 in java.library.path: [/Users/minsu/Library/Java/Extensions, /Library/Java/Extensions, /Network/Library/Java/Extensions, /System/Library/Java/Extensions, /usr/lib/java, .] + at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2662) + at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:827) + at java.base/java.lang.System.loadLibrary(System.java:1871) + at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:38) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:566) + at io.netty.util.internal.NativeLibraryLoader$1.run(NativeLibraryLoader.java:430) + at java.base/java.security.AccessController.doPrivileged(Native Method) + at io.netty.util.internal.NativeLibraryLoader.loadLibraryByHelper(NativeLibraryLoader.java:422) + at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:388) + ... 103 common frames omitted diff --git a/logs/error.log b/logs/error.log new file mode 100644 index 00000000..33d71ffb --- /dev/null +++ b/logs/error.log @@ -0,0 +1 @@ +[2024-03-08 02:56:20:11127] [main] [ERROR] i.n.r.d.DnsServerAddressStreamProviders - Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. Check whether you have a dependency on 'io.netty:netty-resolver-dns-native-macos'. Use DEBUG level to see the full stack: java.lang.UnsatisfiedLinkError: failed to load the required native library diff --git a/logs/info-log-2024-03-08.0.log b/logs/info-log-2024-03-08.0.log new file mode 100644 index 00000000..435bff5f --- /dev/null +++ b/logs/info-log-2024-03-08.0.log @@ -0,0 +1,57 @@ +2024-03-08 03:20:25 [ INFO] Starting BackendApplication using Java 11.0.18 on minsuui-MacBookPro.local with PID 30517 (/Users/minsu/Documents/GitHub/backend/build/classes/java/main started by minsu in /Users/minsu/Documents/GitHub/backend) +2024-03-08 03:20:25 [ INFO] The following 1 profile is active: "dev" +2024-03-08 03:20:25 [ INFO] HV000001: Hibernate Validator 6.2.5.Final +2024-03-08 03:20:26 [ INFO] Multiple Spring Data modules found, entering strict repository configuration mode +2024-03-08 03:20:26 [ INFO] Bootstrapping Spring Data JPA repositories in DEFAULT mode. +2024-03-08 03:20:26 [ INFO] Finished Spring Data repository scanning in 103 ms. Found 16 JPA repository interfaces. +2024-03-08 03:20:26 [ INFO] Multiple Spring Data modules found, entering strict repository configuration mode +2024-03-08 03:20:26 [ INFO] Bootstrapping Spring Data Redis repositories in DEFAULT mode. +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.block.domain.repository.BlockRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.board.domain.repository.BoardRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.boardRead.domain.repository.BoardReadRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.fire.domain.repository.FireRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.history.domain.repository.AlarmHistoryRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.member.domain.repository.MemberRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.mission.domain.repository.MissionRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionHeart.domain.repository.MissionHeartRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.mypage.domain.repository.FeedbackRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.report.domain.repository.ReportRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.team.domain.repository.TeamRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +2024-03-08 03:20:26 [ INFO] Finished Spring Data repository scanning in 22 ms. Found 0 Redis repository interfaces. +2024-03-08 03:20:34 [ INFO] BeanFactory id=1c0a394d-13be-381f-a1f6-d0c02e8550cb +2024-03-08 03:20:34 [ INFO] Bean '(inner bean)#53d30d23' of type [com.amazonaws.auth.BasicAWSCredentials] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-03-08 03:20:34 [ INFO] Bean '(inner bean)#424f02b8' of type [com.amazonaws.auth.AWSStaticCredentialsProvider] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-03-08 03:20:34 [ INFO] Bean '(inner bean)#589fb74d' of type [com.amazonaws.auth.profile.ProfileCredentialsProvider] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-03-08 03:20:34 [ INFO] Bean 'credentialsProvider' of type [org.springframework.cloud.aws.core.credentials.CredentialsProviderFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-03-08 03:20:34 [ INFO] Bean 'credentialsProvider' of type [com.amazonaws.auth.AWSCredentialsProviderChain] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-03-08 03:20:34 [ INFO] Tomcat initialized with port(s): 8080 (http) +2024-03-08 03:20:34 [ INFO] Initializing ProtocolHandler ["http-nio-8080"] +2024-03-08 03:20:34 [ INFO] Starting service [Tomcat] +2024-03-08 03:20:34 [ INFO] Starting Servlet engine: [Apache Tomcat/9.0.78] +2024-03-08 03:20:35 [ INFO] Initializing Spring embedded WebApplicationContext +2024-03-08 03:20:35 [ INFO] Root WebApplicationContext: initialization completed in 9175 ms +2024-03-08 03:20:35 [ INFO] HHH000412: Hibernate ORM core version 5.6.15.Final +2024-03-08 03:20:35 [ INFO] HCANN000001: Hibernate Commons Annotations {5.1.2.Final} +2024-03-08 03:20:35 [ INFO] jpa-hikari-pool - Starting... +2024-03-08 03:20:35 [ INFO] jpa-hikari-pool - Start completed. +2024-03-08 03:20:35 [ INFO] HHH000400: Using dialect: org.hibernate.dialect.MySQL57Dialect +2024-03-08 03:20:36 [ INFO] HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] +2024-03-08 03:20:36 [ INFO] Initialized JPA EntityManagerFactory for persistence unit 'default' +2024-03-08 03:20:38 [ INFO] Will not secure Ant [pattern='/resource/**'] +2024-03-08 03:20:38 [ INFO] Will not secure Ant [pattern='/css/**'] +2024-03-08 03:20:38 [ INFO] Will not secure Ant [pattern='/js/**'] +2024-03-08 03:20:38 [ INFO] Will not secure Ant [pattern='/img/**'] +2024-03-08 03:20:38 [ INFO] Will not secure Ant [pattern='/lib/**'] +2024-03-08 03:20:38 [ INFO] Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@79715834, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4d94b0af, org.springframework.security.web.context.SecurityContextPersistenceFilter@6c92af74, org.springframework.security.web.header.HeaderWriterFilter@c39ebcf, org.springframework.security.web.authentication.logout.LogoutFilter@32317a37, com.moing.backend.global.config.security.filter.JwtAuthFilter@72a80668, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@7f8bc54e, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@31f151ff, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@42cb8174, org.springframework.security.web.session.SessionManagementFilter@1be7b7de, org.springframework.security.web.access.ExceptionTranslationFilter@35cf5d9, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@314e2b4b] +2024-03-08 03:20:39 [ INFO] Exposing 16 endpoint(s) beneath base path '/actuator' +2024-03-08 03:20:39 [ INFO] Starting ProtocolHandler ["http-nio-8080"] +2024-03-08 03:20:39 [ INFO] Tomcat started on port(s): 8080 (http) with context path '' +2024-03-08 03:20:39 [ INFO] Started BackendApplication in 14.149 seconds (JVM running for 14.713) +2024-03-08 03:23:23 [ INFO] Closing JPA EntityManagerFactory for persistence unit 'default' +2024-03-08 03:23:23 [ INFO] jpa-hikari-pool - Shutdown initiated... +2024-03-08 03:23:23 [ INFO] jpa-hikari-pool - Shutdown completed. diff --git a/logs/info.log b/logs/info.log new file mode 100644 index 00000000..4d30242f --- /dev/null +++ b/logs/info.log @@ -0,0 +1,58 @@ +[2024-03-08 02:56:09:555] [main] [INFO] com.moing.backend.BackendApplication - Starting BackendApplication using Java 11.0.18 on minsuui-MacBookPro.local with PID 30145 (/Users/minsu/Documents/GitHub/backend/build/classes/java/main started by minsu in /Users/minsu/Documents/GitHub/backend) +[2024-03-08 02:56:09:559] [main] [INFO] com.moing.backend.BackendApplication - The following 1 profile is active: "dev" +[2024-03-08 02:56:09:561] [background-preinit] [INFO] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 6.2.5.Final +[2024-03-08 02:56:10:1509] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +[2024-03-08 02:56:10:1510] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode. +[2024-03-08 02:56:10:1605] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 92 ms. Found 16 JPA repository interfaces. +[2024-03-08 02:56:10:1614] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode +[2024-03-08 02:56:10:1614] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +[2024-03-08 02:56:10:1636] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.block.domain.repository.BlockRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1636] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.board.domain.repository.BoardRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1636] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1636] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.boardRead.domain.repository.BoardReadRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1637] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.fire.domain.repository.FireRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1637] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.history.domain.repository.AlarmHistoryRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1638] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.member.domain.repository.MemberRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1638] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.mission.domain.repository.MissionRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1638] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1638] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionHeart.domain.repository.MissionHeartRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1639] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1639] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.mypage.domain.repository.FeedbackRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1639] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.report.domain.repository.ReportRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1639] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.team.domain.repository.TeamRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1640] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1640] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository +[2024-03-08 02:56:10:1640] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 22 ms. Found 0 Redis repository interfaces. +[2024-03-08 02:56:17:8373] [main] [INFO] o.s.cloud.context.scope.GenericScope - BeanFactory id=1c0a394d-13be-381f-a1f6-d0c02e8550cb +[2024-03-08 02:56:17:8454] [main] [INFO] o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean '(inner bean)#1471b98d' of type [com.amazonaws.auth.BasicAWSCredentials] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +[2024-03-08 02:56:17:8454] [main] [INFO] o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean '(inner bean)#1510b9a2' of type [com.amazonaws.auth.AWSStaticCredentialsProvider] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +[2024-03-08 02:56:17:8458] [main] [INFO] o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean '(inner bean)#23b1aa9' of type [com.amazonaws.auth.profile.ProfileCredentialsProvider] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +[2024-03-08 02:56:17:8459] [main] [INFO] o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'credentialsProvider' of type [org.springframework.cloud.aws.core.credentials.CredentialsProviderFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +[2024-03-08 02:56:17:8459] [main] [INFO] o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'credentialsProvider' of type [com.amazonaws.auth.AWSCredentialsProviderChain] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +[2024-03-08 02:56:17:8660] [main] [INFO] o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http) +[2024-03-08 02:56:17:8664] [main] [INFO] o.a.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"] +[2024-03-08 02:56:17:8665] [main] [INFO] o.a.catalina.core.StandardService - Starting service [Tomcat] +[2024-03-08 02:56:17:8665] [main] [INFO] o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.78] +[2024-03-08 02:56:18:8758] [main] [INFO] o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext +[2024-03-08 02:56:18:8758] [main] [INFO] o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 8151 ms +[2024-03-08 02:56:18:8977] [main] [INFO] o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default] +[2024-03-08 02:56:18:8998] [main] [INFO] org.hibernate.Version - HHH000412: Hibernate ORM core version 5.6.15.Final +[2024-03-08 02:56:18:9061] [main] [INFO] o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {5.1.2.Final} +[2024-03-08 02:56:18:9104] [main] [INFO] com.zaxxer.hikari.HikariDataSource - jpa-hikari-pool - Starting... +[2024-03-08 02:56:18:9505] [main] [INFO] com.zaxxer.hikari.HikariDataSource - jpa-hikari-pool - Start completed. +[2024-03-08 02:56:18:9512] [main] [INFO] org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.MySQL57Dialect +[2024-03-08 02:56:20:10691] [main] [INFO] o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] +[2024-03-08 02:56:20:10704] [main] [INFO] o.s.o.j.LocalContainerEntityManagerFactoryBean - Initialized JPA EntityManagerFactory for persistence unit 'default' +[2024-03-08 02:56:21:12399] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will not secure Ant [pattern='/resource/**'] +[2024-03-08 02:56:21:12399] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will not secure Ant [pattern='/css/**'] +[2024-03-08 02:56:21:12399] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will not secure Ant [pattern='/js/**'] +[2024-03-08 02:56:21:12399] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will not secure Ant [pattern='/img/**'] +[2024-03-08 02:56:21:12400] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will not secure Ant [pattern='/lib/**'] +[2024-03-08 02:56:21:12434] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@7c63146c, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@5b2235a5, org.springframework.security.web.context.SecurityContextPersistenceFilter@12bff19d, org.springframework.security.web.header.HeaderWriterFilter@4cc40892, org.springframework.security.web.authentication.logout.LogoutFilter@793942d9, com.moing.backend.global.config.security.filter.JwtAuthFilter@5af6378e, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@64ce7e6f, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5d7d2cb5, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@205b3a1a, org.springframework.security.web.session.SessionManagementFilter@62edf11e, org.springframework.security.web.access.ExceptionTranslationFilter@6ed1fdb7, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@5064988] +[2024-03-08 02:56:22:13050] [main] [INFO] o.s.b.a.e.web.EndpointLinksResolver - Exposing 16 endpoint(s) beneath base path '/actuator' +[2024-03-08 02:56:22:13155] [main] [INFO] o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"] +[2024-03-08 02:56:22:13166] [main] [INFO] o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path '' +[2024-03-08 02:56:22:13181] [main] [INFO] com.moing.backend.BackendApplication - Started BackendApplication in 13.07 seconds (JVM running for 13.671) +[2024-03-08 02:56:44:35239] [SpringApplicationShutdownHook] [INFO] o.s.o.j.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default' +[2024-03-08 02:56:44:35242] [SpringApplicationShutdownHook] [INFO] com.zaxxer.hikari.HikariDataSource - jpa-hikari-pool - Shutdown initiated... +[2024-03-08 02:56:44:35289] [SpringApplicationShutdownHook] [INFO] com.zaxxer.hikari.HikariDataSource - jpa-hikari-pool - Shutdown completed. diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..fb6ab4bc --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,26 @@ + + + + + + + .\logs\logback\logback-%d{yyyy-MM-dd}_%i.log + + 50MB + + + + ${SAVE_LOG_PATTERN} + + + + + ${LOG_PATTERN} + + + + + + + + \ No newline at end of file From 638eff10c2834f3904c08c5396143a495b1a7d7e Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Mar 2024 21:22:48 +0900 Subject: [PATCH 536/619] =?UTF-8?q?MNG-11=20feat:=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=B0=8F=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20?= =?UTF-8?q?=EA=B3=84=EC=B8=B5=EC=97=90=20AOP=20=EB=A1=9C=EA=B9=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../backend/global/log/aop/LogAspect.java | 42 ++++++++++++ .../backend/global/log/aop/LogFormat.java | 52 +++++++++++++++ .../backend/global/log/aop/LogTrace.java | 64 +++++++++++++++++++ .../backend/global/log/aop/Pointcuts.java | 17 +++++ .../backend/global/log/aop/TraceStatus.java | 15 +++++ .../log/filter/LogThreadIdHandleFilter.java | 51 +++++++++++++++ .../global/log/filter/RequestInfoFormat.java | 18 ++++++ 8 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/global/log/aop/LogAspect.java create mode 100644 src/main/java/com/moing/backend/global/log/aop/LogFormat.java create mode 100644 src/main/java/com/moing/backend/global/log/aop/LogTrace.java create mode 100644 src/main/java/com/moing/backend/global/log/aop/Pointcuts.java create mode 100644 src/main/java/com/moing/backend/global/log/aop/TraceStatus.java create mode 100644 src/main/java/com/moing/backend/global/log/filter/LogThreadIdHandleFilter.java create mode 100644 src/main/java/com/moing/backend/global/log/filter/RequestInfoFormat.java diff --git a/build.gradle b/build.gradle index c33ae8ce..4ca667bb 100644 --- a/build.gradle +++ b/build.gradle @@ -99,7 +99,7 @@ dependencies { //log implementation 'org.springframework.boot:spring-boot-starter-logging' - + implementation 'org.springframework.boot:spring-boot-starter-aop' implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("io.micrometer:micrometer-registry-prometheus") // 프로메테우스 마이크로미터 diff --git a/src/main/java/com/moing/backend/global/log/aop/LogAspect.java b/src/main/java/com/moing/backend/global/log/aop/LogAspect.java new file mode 100644 index 00000000..ccaab9a7 --- /dev/null +++ b/src/main/java/com/moing/backend/global/log/aop/LogAspect.java @@ -0,0 +1,42 @@ +package com.moing.backend.global.log.aop; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +@Slf4j +@Aspect +@Component +@RequiredArgsConstructor +public class LogAspect { + + private final LogTrace logTrace; + + @Around("com.moing.backend.global.log.aop.Pointcuts.allService()") + public Object serviceLog(ProceedingJoinPoint joinPoint) throws Throwable { + return getObject(joinPoint); + } + + @Around("com.moing.backend.global.log.aop.Pointcuts.allService()") + public Object controllerLog(ProceedingJoinPoint joinPoint) throws Throwable { + return getObject(joinPoint); + } + + private Object getObject(ProceedingJoinPoint joinPoint) throws Throwable { + TraceStatus traceStatus = null; + try { + traceStatus = logTrace.start(joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()); + Object result = joinPoint.proceed(); + logTrace.end(traceStatus); + return result; + }catch (Exception e) { + if (traceStatus != null) { + logTrace.exception(e, traceStatus); + } + throw e; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/log/aop/LogFormat.java b/src/main/java/com/moing/backend/global/log/aop/LogFormat.java new file mode 100644 index 00000000..9ca8ccc0 --- /dev/null +++ b/src/main/java/com/moing/backend/global/log/aop/LogFormat.java @@ -0,0 +1,52 @@ +package com.moing.backend.global.log.aop; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.moing.backend.global.exception.ApplicationException; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class LogFormat { + private final String threadId; + private final String className; + private final String methodName; + private final Long executeTime; + private final String errorCode; + private final String errorMessage; + private final Class errorClass; + private final StackTraceElement[] errorStackTrace; + + public static LogFormat createLogFormat(TraceStatus traceStatus) { + return LogFormat.builder() + .threadId(traceStatus.getThreadId()) + .className(traceStatus.getClassName()) + .methodName(traceStatus.getMethodName()) + .executeTime(System.currentTimeMillis() - traceStatus.getStartTime()) + .build(); + } + + public static LogFormat createErrorLogFormat(TraceStatus traceStatus, Exception exception) { + LogFormat.LogFormatBuilder logFormatBuilder = LogFormat.builder() + .threadId(traceStatus.getThreadId()) + .className(traceStatus.getClassName()) + .methodName(traceStatus.getMethodName()); + if (exception instanceof ApplicationException) { + ApplicationException ae = (ApplicationException) exception; + return logFormatBuilder + .errorCode(ae.getErrorCode().getErrorCode()) + .errorMessage(ae.getErrorCode().getMessage()) + .build(); + } else { + return logFormatBuilder + .errorClass(exception.getClass()) + .errorMessage(exception.getMessage()) + .errorStackTrace(exception.getStackTrace()) + .build(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/log/aop/LogTrace.java b/src/main/java/com/moing/backend/global/log/aop/LogTrace.java new file mode 100644 index 00000000..e16b3653 --- /dev/null +++ b/src/main/java/com/moing/backend/global/log/aop/LogTrace.java @@ -0,0 +1,64 @@ +package com.moing.backend.global.log.aop; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.UUID; + +@Slf4j +@Component +@RequiredArgsConstructor +public class LogTrace { + + private static final ThreadLocal threadId = new ThreadLocal<>(); + private static final Integer WARN_REQUEST_TIME = 1000; + + private final ObjectMapper objectMapper; + + + public TraceStatus start(String fullClassName, String method) { + String id = threadId.get(); + long startTime = System.currentTimeMillis(); + int lastDotIndex = fullClassName.lastIndexOf("."); + String className = fullClassName.substring(lastDotIndex + 1); + return new TraceStatus(id, startTime, className, method); + } + + @SneakyThrows + public void end(TraceStatus traceStatus) { + final LogFormat logFormat = LogFormat.createLogFormat(traceStatus); + final String logMessage = objectMapper.writeValueAsString(logFormat); + if (logFormat.getExecuteTime() >= WARN_REQUEST_TIME) { + log.warn(logMessage); + } else { + log.info(logMessage); + } + } + + @SneakyThrows + public void exception(Exception exception, TraceStatus traceStatus){ + final LogFormat errorLogFormat = LogFormat.createErrorLogFormat(traceStatus, exception); + final String errorLog = objectMapper.writeValueAsString(errorLogFormat); + log.error(errorLog); + } + + public void configThreadId() { + threadId.set(createThreadId()); + } + + public void clearTheadId() { + threadId.remove(); + } + + public String getThreadId() { + return threadId.get(); + } + + private String createThreadId() { + return UUID.randomUUID().toString().substring(0, 8); + } + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/log/aop/Pointcuts.java b/src/main/java/com/moing/backend/global/log/aop/Pointcuts.java new file mode 100644 index 00000000..3dd7887c --- /dev/null +++ b/src/main/java/com/moing/backend/global/log/aop/Pointcuts.java @@ -0,0 +1,17 @@ +package com.moing.backend.global.log.aop; + +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; + +@Aspect +public class Pointcuts { + + + @Pointcut("execution(* com.moing.backend.*presentation.*Controller.*(..))") + public void allController() {} + + @Pointcut("execution(* com.moing.backend..service..*.*(..))") + public void allService() { + } + +} diff --git a/src/main/java/com/moing/backend/global/log/aop/TraceStatus.java b/src/main/java/com/moing/backend/global/log/aop/TraceStatus.java new file mode 100644 index 00000000..b7d98520 --- /dev/null +++ b/src/main/java/com/moing/backend/global/log/aop/TraceStatus.java @@ -0,0 +1,15 @@ +package com.moing.backend.global.log.aop; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +@AllArgsConstructor +public class TraceStatus { + private String threadId; + private Long startTime; + private String className; + private String methodName; +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/log/filter/LogThreadIdHandleFilter.java b/src/main/java/com/moing/backend/global/log/filter/LogThreadIdHandleFilter.java new file mode 100644 index 00000000..ad8873d4 --- /dev/null +++ b/src/main/java/com/moing/backend/global/log/filter/LogThreadIdHandleFilter.java @@ -0,0 +1,51 @@ +package com.moing.backend.global.log.filter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.moing.backend.global.log.aop.LogTrace; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + + +@Slf4j +@Order(Integer.MIN_VALUE) +@Component +@RequiredArgsConstructor +public class LogThreadIdHandleFilter implements Filter { + + private final ObjectMapper objectMapper; + private final LogTrace logTrace; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + Filter.super.init(filterConfig); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + logTrace.configThreadId(); + log.info(buildRequestInfoMessage((HttpServletRequest) request)); + chain.doFilter(request, response); + logTrace.clearTheadId(); + } + + private String buildRequestInfoMessage(HttpServletRequest request) throws JsonProcessingException { + final RequestInfoFormat requestInfoFormat = RequestInfoFormat.builder() + .threadId(logTrace.getThreadId()) + .url(request.getRequestURI()) + .method(request.getMethod()) + .build(); + return objectMapper.writeValueAsString(requestInfoFormat); + } + + @Override + public void destroy() { + Filter.super.destroy(); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/global/log/filter/RequestInfoFormat.java b/src/main/java/com/moing/backend/global/log/filter/RequestInfoFormat.java new file mode 100644 index 00000000..030eb2fc --- /dev/null +++ b/src/main/java/com/moing/backend/global/log/filter/RequestInfoFormat.java @@ -0,0 +1,18 @@ +package com.moing.backend.global.log.filter; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class RequestInfoFormat { + private final String threadId; + private final String url; + private final String method; + private final String ip; +} \ No newline at end of file From e384d198c207702c8092d786578853636a777971 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Mar 2024 23:34:02 +0900 Subject: [PATCH 537/619] =?UTF-8?q?MNG-19=20refactor:=20DAU=20=EC=A0=84?= =?UTF-8?q?=EB=9E=B5=ED=8C=A8=ED=84=B4=20=EC=9D=B4=EC=9A=A9=ED=95=B4=20OCP?= =?UTF-8?q?=20=EC=A4=80=EC=88=98=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MemberCustomRepository.java | 5 +- .../MemberCustomRepositoryImpl.java | 65 +++------------ .../domain/service/MemberGetService.java | 11 ++- .../repository/MissionCustomRepository.java | 13 ++- .../MissionCustomRepositoryImpl.java | 79 +++++++++++++++++-- .../domain/service/MissionQueryService.java | 22 +++++- .../application/service/DAUManager.java | 38 +++++++++ .../application/service/DAUMember.java | 28 +++++++ .../application/service/DAUOnceMission.java | 27 +++++++ .../application/service/DAUProvider.java | 9 +++ .../application/service/DAURepeatMission.java | 27 +++++++ .../service/DAUScheduleUseCase.java | 28 +++---- .../application/service/DAUTeam.java | 28 +++++++ .../domain/constant/DAUStatusType.java | 16 ++++ .../repository/TeamCustomRepository.java | 2 + .../repository/TeamCustomRepositoryImpl.java | 31 ++++++++ .../team/domain/service/TeamGetService.java | 7 ++ 17 files changed, 344 insertions(+), 92 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/statistics/application/service/DAUManager.java create mode 100644 src/main/java/com/moing/backend/domain/statistics/application/service/DAUMember.java create mode 100644 src/main/java/com/moing/backend/domain/statistics/application/service/DAUOnceMission.java create mode 100644 src/main/java/com/moing/backend/domain/statistics/application/service/DAUProvider.java create mode 100644 src/main/java/com/moing/backend/domain/statistics/application/service/DAURepeatMission.java create mode 100644 src/main/java/com/moing/backend/domain/statistics/application/service/DAUTeam.java create mode 100644 src/main/java/com/moing/backend/domain/statistics/domain/constant/DAUStatusType.java diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java index fc4474da..4133dba8 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java @@ -1,7 +1,6 @@ package com.moing.backend.domain.member.domain.repository; import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.statistics.application.dto.DailyStats; import java.util.List; import java.util.Optional; @@ -12,7 +11,7 @@ public interface MemberCustomRepository { Optional findNotDeletedBySocialId(String socialId); Optional findNotDeletedByEmail(String email); Optional findNotDeletedByMemberId(Long id); - DailyStats getDailyStats(); - + Long getTodayNewMembers(); + Long getYesterdayNewMembers(); Optional> findAllMemberOnPushAlarm(); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java index 233e6001..f5a2a5bd 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java @@ -1,8 +1,6 @@ package com.moing.backend.domain.member.domain.repository; import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -import com.moing.backend.domain.statistics.application.dto.DailyStats; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -12,8 +10,6 @@ import java.util.Optional; import static com.moing.backend.domain.member.domain.entity.QMember.member; -import static com.moing.backend.domain.mission.domain.entity.QMission.mission; -import static com.moing.backend.domain.team.domain.entity.QTeam.team; public class MemberCustomRepositoryImpl implements MemberCustomRepository { @@ -61,7 +57,7 @@ public Optional findNotDeletedByMemberId(Long id) { } @Override - public DailyStats getDailyStats() { + public Long getTodayNewMembers() { LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); LocalDateTime endOfToday = startOfToday.plusDays(1); @@ -72,58 +68,23 @@ public DailyStats getDailyStats() { .where(member.createdDate.between(startOfToday, endOfToday)) .fetchCount(); - long yesterdayNewMembers = queryFactory - .selectFrom(member) - .where(member.createdDate.between(startOfYesterday, startOfToday)) - .fetchCount(); - - long todayNewTeams = queryFactory - .selectFrom(team) - .where(team.createdDate.between(startOfToday, endOfToday)) - .fetchCount(); - - long yesterdayNewTeams = queryFactory - .selectFrom(team) - .where(team.createdDate.between(startOfYesterday, startOfToday)) - .fetchCount(); - - long todayRepeatMissions = queryFactory - .select(mission) - .from(mission) - .where(mission.createdDate.between(startOfToday, endOfToday) - .and(mission.type.eq(MissionType.REPEAT))) - .fetchCount(); + return todayNewMembers; + } - long yesterdayRepeatMissions = queryFactory - .select(mission) - .from(mission) - .where(mission.createdDate.between(startOfYesterday, startOfToday) - .and(mission.type.eq(MissionType.REPEAT))) - .fetchCount(); + @Override + public Long getYesterdayNewMembers() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); - long todayOnceMissions = queryFactory - .select(mission) - .from(mission) - .where(mission.createdDate.between(startOfToday, endOfToday) - .and(mission.type.eq(MissionType.ONCE))) - .fetchCount(); - long yesterdayOnceMissions = queryFactory - .select(mission) - .from(mission) - .where(mission.createdDate.between(startOfYesterday, startOfToday) - .and(mission.type.eq(MissionType.ONCE))) + long yesterdayNewMembers = queryFactory + .selectFrom(member) + .where(member.createdDate.between(startOfYesterday, startOfToday)) .fetchCount(); - return new DailyStats( - todayNewMembers, - yesterdayNewMembers, - todayNewTeams, - yesterdayNewTeams, - todayRepeatMissions, - yesterdayRepeatMissions, - todayOnceMissions, - yesterdayOnceMissions); + return yesterdayNewMembers; } @Override diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java index dbaa3737..85153003 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java @@ -4,12 +4,10 @@ import com.moing.backend.domain.member.domain.repository.MemberRepository; import com.moing.backend.domain.member.exception.NotFoundBySocialIdException; import com.moing.backend.domain.member.exception.NotFoundRemindAlarmException; -import com.moing.backend.domain.statistics.application.dto.DailyStats; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import javax.transaction.Transactional; -import java.math.BigInteger; import java.util.List; @DomainService @@ -26,10 +24,15 @@ public Member getMemberByMemberId(Long memberId) { return memberRepository.findNotDeletedByMemberId(memberId).orElseThrow(()->new NotFoundBySocialIdException()); } - public DailyStats getDailyStats(){ - return memberRepository.getDailyStats(); + public Long getTodayNewMembers(){ + return memberRepository.getTodayNewMembers(); } + public Long getYesterdayNewMembers(){ + return memberRepository.getYesterdayNewMembers(); + } + + public List getAllMemberOfPushAlarm() { return memberRepository.findAllMemberOnPushAlarm().orElseThrow(NotFoundRemindAlarmException::new); } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index ee3cd340..63dbd117 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -17,7 +17,7 @@ public interface MissionCustomRepository { Optional> findSingleMissionByMemberId(Long memberId, List teams); - Optional> findRepeatMissionByMemberId(Long memberId, Listteams); + Optional> findRepeatMissionByMemberId(Long memberId, List teams); Optional> findMissionByDueTo(); @@ -27,10 +27,15 @@ public interface MissionCustomRepository { Optional> findRepeatMissionPeopleByStatus(MissionStatus missionStatus); - - boolean findRepeatMissionsByTeamId(Long teamId); + boolean findRepeatMissionsByTeamId(Long teamId); Optional findByIds(Long memberId, Long missionId); + Long getTodayOnceMissions(); + + Long getYesterdayOnceMissions(); + + Long getTodayRepeatMissions(); - } \ No newline at end of file + Long getYesterdayRepeatMissions(); +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 9c346297..cf525072 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -8,25 +8,19 @@ import com.moing.backend.domain.mission.domain.entity.QMission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; -import com.moing.backend.domain.missionRead.domain.repository.MissionReadRepositoryUtils; -import com.moing.backend.domain.missionState.domain.entity.QMissionState; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.jpa.JPAExpressions; -import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; - import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.temporal.TemporalAdjusters; import java.util.List; import java.util.Optional; -import static com.moing.backend.domain.mission.domain.entity.QMission.*; import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; @@ -204,6 +198,77 @@ public Optional findByIds(Long memberId, Long missionId) { return Optional.of(result); } + @Override + public Long getTodayOnceMissions() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + + long todayOnceMissions = queryFactory + .select(mission) + .from(mission) + .where(mission.createdDate.between(startOfToday, endOfToday) + .and(mission.type.eq(MissionType.ONCE))) + .fetchCount(); + + return todayOnceMissions; + + } + + @Override + public Long getYesterdayOnceMissions() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + long yesterdayOnceMissions = queryFactory + .select(mission) + .from(mission) + .where(mission.createdDate.between(startOfYesterday, startOfToday) + .and(mission.type.eq(MissionType.ONCE))) + .fetchCount(); + + return yesterdayOnceMissions; + } + + @Override + public Long getTodayRepeatMissions() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + long todayRepeatMissions = queryFactory + .select(mission) + .from(mission) + .where(mission.createdDate.between(startOfToday, endOfToday) + .and(mission.type.eq(MissionType.REPEAT))) + .fetchCount(); + + return todayRepeatMissions; + } + + @Override + public Long getYesterdayRepeatMissions() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + long yesterdayRepeatMissions = queryFactory + .select(mission) + .from(mission) + .where(mission.createdDate.between(startOfYesterday, startOfToday) + .and(mission.type.eq(MissionType.REPEAT))) + .fetchCount(); + + + return yesterdayRepeatMissions; + } + private BooleanExpression createRepeatTypeConditionByArchive() { LocalDate now = LocalDate.now(); diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 324540ad..a1f9178f 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -6,10 +6,10 @@ import com.moing.backend.domain.mission.application.dto.res.MissionReadRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -import com.moing.backend.domain.mission.exception.*; -import com.moing.backend.domain.mission.exception.NotFoundMissionException; import com.moing.backend.domain.mission.domain.repository.MissionRepository; -import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; +import com.moing.backend.domain.mission.exception.NotFoundEndMissionException; +import com.moing.backend.domain.mission.exception.NotFoundMissionException; +import com.moing.backend.domain.mission.exception.NotFoundOngoingMissionException; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; @@ -83,4 +83,20 @@ public List findRepeatMissionByStatus(MissionStatus missionStatus) { return missionRepository.findRepeatMissionByStatus(missionStatus).orElseThrow(NotFoundMissionException::new ); } + + public Long getTodayOnceMissions(){ + return missionRepository.getTodayOnceMissions(); + } + + public Long getYesterdayOnceMissions(){ + return missionRepository.getYesterdayOnceMissions(); + } + + public Long getTodayRepeatMissions(){ + return missionRepository.getTodayRepeatMissions(); + } + + public Long getYesterdayRepeatMissions(){ + return missionRepository.getYesterdayRepeatMissions(); + } } diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUManager.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUManager.java new file mode 100644 index 00000000..c40b7655 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUManager.java @@ -0,0 +1,38 @@ +package com.moing.backend.domain.statistics.application.service; + +import com.moing.backend.domain.statistics.domain.constant.DAUStatusType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +@Component +public class DAUManager { + + private final Map serviceMap = new EnumMap<>(DAUStatusType.class); + + @Autowired + public DAUManager(List services) { + for (DAUProvider service : services) { + serviceMap.put(service.getSupportedType(), service); + } + } + + public Long getTodayStats(DAUStatusType type) { + DAUProvider service = serviceMap.get(type); + if (service != null) { + return service.getTodayStats(); + } + throw new IllegalArgumentException("Unsupported DAUStatusType: " + type); + } + + public Long getYesterdayStats(DAUStatusType type) { + DAUProvider service = serviceMap.get(type); + if (service != null) { + return service.getYesterdayStats(); + } + throw new IllegalArgumentException("Unsupported DAUStatusType: " + type); + } +} diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUMember.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUMember.java new file mode 100644 index 00000000..d0908092 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUMember.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.statistics.application.service; + +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.statistics.domain.constant.DAUStatusType; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class DAUMember implements DAUProvider { + + private final MemberGetService memberGetService; + + @Override + public Long getTodayStats() { + return memberGetService.getTodayNewMembers(); + } + + @Override + public Long getYesterdayStats() { + return memberGetService.getYesterdayNewMembers(); + } + + @Override + public DAUStatusType getSupportedType() { + return DAUStatusType.DAILY_MEMBER_COUNT; + } +} diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUOnceMission.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUOnceMission.java new file mode 100644 index 00000000..ac8bb719 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUOnceMission.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.statistics.application.service; + +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.statistics.domain.constant.DAUStatusType; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class DAUOnceMission implements DAUProvider { + private final MissionQueryService missionQueryService; + + @Override + public Long getTodayStats() { + return missionQueryService.getTodayOnceMissions(); + } + + @Override + public Long getYesterdayStats() { + return missionQueryService.getYesterdayOnceMissions(); + } + + @Override + public DAUStatusType getSupportedType() { + return DAUStatusType.DAILY_ONCE_MISSION_COUNT; + } +} diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUProvider.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUProvider.java new file mode 100644 index 00000000..9af66f78 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUProvider.java @@ -0,0 +1,9 @@ +package com.moing.backend.domain.statistics.application.service; + +import com.moing.backend.domain.statistics.domain.constant.DAUStatusType; + +public interface DAUProvider { + Long getTodayStats(); + Long getYesterdayStats(); + DAUStatusType getSupportedType(); +} diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAURepeatMission.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAURepeatMission.java new file mode 100644 index 00000000..cc48fd79 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAURepeatMission.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.statistics.application.service; + +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.statistics.domain.constant.DAUStatusType; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class DAURepeatMission implements DAUProvider { + private final MissionQueryService missionQueryService; + + @Override + public Long getTodayStats() { + return missionQueryService.getTodayRepeatMissions(); + } + + @Override + public Long getYesterdayStats() { + return missionQueryService.getYesterdayRepeatMissions(); + } + + @Override + public DAUStatusType getSupportedType() { + return DAUStatusType.DAILY_REPEAT_MISSION_COUNT; + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java index 4d2ca7f7..a79dd59b 100644 --- a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUScheduleUseCase.java @@ -1,7 +1,6 @@ package com.moing.backend.domain.statistics.application.service; -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.statistics.application.dto.DailyStats; +import com.moing.backend.domain.statistics.domain.constant.DAUStatusType; import com.moing.backend.global.config.slack.util.WebhookUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -25,33 +24,24 @@ public class DAUScheduleUseCase { private final WebhookUtil webhookUtil; - private final MemberGetService memberGetService; - - public static final String DAILY_TEAM_CREATION_COUNT = "[DAU] 일일 모임 생성 수"; - public static final String DAILY_NEW_MEMBER_COUNT = "[DAU] 일일 신규 가입자 수"; - public static final String DAILY_REPEAT_MISSION_COUNT = "[DAU] 일일 반복 미션 생성 개수"; - public static final String DAILY_ONCE_MISSION_COUNT = "[DAU] 일일 한번 미션 생성 개수"; + private final DAUManager dauManager; /* - DAU 정보 : 일일 모임 생성 수, 일일 신규 가입자 수, 일일 반복 미션 생성 수, 일일 한번 미션 생성 수 + DAU 정보 : 일일 모임 생성 수, 일일 신규 가입자 수, 일일 반복 미션 생성 수, 일일 한번 미션 생성 수, 일일 미션 인증 수, 일일 불 던지기 생성 */ @Scheduled(cron = "0 55 23 * * *") - public void DailyTeamCreationInfoAlarm() { + public void DailyInfoAlarm() { Map todayStats = new LinkedHashMap<>(); Map yesterdayStats = new LinkedHashMap<>(); - DailyStats dailyStats = memberGetService.getDailyStats(); - todayStats.put(DAILY_TEAM_CREATION_COUNT, dailyStats.getTodayNewTeams()); - yesterdayStats.put(DAILY_TEAM_CREATION_COUNT, dailyStats.getYesterdayNewTeams()); - todayStats.put(DAILY_NEW_MEMBER_COUNT, dailyStats.getTodayNewMembers()); - yesterdayStats.put(DAILY_NEW_MEMBER_COUNT, dailyStats.getYesterdayNewMembers()); + for (DAUStatusType type : DAUStatusType.values()) { + + todayStats.put(type.getMessage(), dauManager.getTodayStats(type)); + yesterdayStats.put(type.getMessage(), dauManager.getYesterdayStats(type)); - todayStats.put(DAILY_REPEAT_MISSION_COUNT, dailyStats.getTodayRepeatMission()); - yesterdayStats.put(DAILY_REPEAT_MISSION_COUNT, dailyStats.getYesterdayRepeatMission()); + } - todayStats.put(DAILY_ONCE_MISSION_COUNT, dailyStats.getTodayOnceMission()); - yesterdayStats.put(DAILY_ONCE_MISSION_COUNT, dailyStats.getYesterdayRepeatMission()); webhookUtil.sendDailyStatsMessage(todayStats, yesterdayStats); } diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUTeam.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUTeam.java new file mode 100644 index 00000000..5eb38f5f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUTeam.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.statistics.application.service; + +import com.moing.backend.domain.statistics.domain.constant.DAUStatusType; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class DAUTeam implements DAUProvider { + + private final TeamGetService teamGetService; + + @Override + public Long getTodayStats() { + return teamGetService.getTodayNewTeams(); + } + + @Override + public Long getYesterdayStats() { + return teamGetService.getYesterdayNewTeams(); + } + + @Override + public DAUStatusType getSupportedType() { + return DAUStatusType.DAILY_TEAM_COUNT; + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/statistics/domain/constant/DAUStatusType.java b/src/main/java/com/moing/backend/domain/statistics/domain/constant/DAUStatusType.java new file mode 100644 index 00000000..939304e1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/domain/constant/DAUStatusType.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.statistics.domain.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum DAUStatusType { + DAILY_TEAM_COUNT("[DAU] 일일 모임 생성 수"), + DAILY_MEMBER_COUNT("[DAU] 일일 신규 가입자 수"), + DAILY_REPEAT_MISSION_COUNT("[DAU] 일일 반복 미션 생성 개수"), + DAILY_ONCE_MISSION_COUNT("[DAU] 일일 한번 미션 생성 개수"), + DAILY_MISSION_ARCHIVE_COUNT("[DAU] 일일 미션 인증 개수"), + DAILY_FIRE_COUNT("[DAU] 일일 불 던지기 생성 개수"); + private final String message; +} diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java index d3f34c63..6d3f3ba3 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepository.java @@ -24,4 +24,6 @@ public interface TeamCustomRepository { List findLeaderInfoByTeamIds(List teamIds); Page findNewTeam(String dateSort, Pageable pageable); GetTeamCountResponse findTeamCount(Long memberId, Long teamId); + Long getTodayNewTeams(); + Long getYesterdayNewTeams(); } diff --git a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java index 5a779a5c..21cfeeb5 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/team/domain/repository/TeamCustomRepositoryImpl.java @@ -15,6 +15,7 @@ import javax.persistence.EntityManager; import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.List; import java.util.Optional; @@ -221,5 +222,35 @@ public GetTeamCountResponse findTeamCount(Long memberId, Long teamId) { return response; } + @Override + public Long getTodayNewTeams() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + long todayNewTeams = queryFactory + .selectFrom(team) + .where(team.createdDate.between(startOfToday, endOfToday)) + .fetchCount(); + return todayNewTeams; + + } + + @Override + public Long getYesterdayNewTeams() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + long yesterdayNewTeams = queryFactory + .selectFrom(team) + .where(team.createdDate.between(startOfYesterday, startOfToday)) + .fetchCount(); + + return yesterdayNewTeams; + } + } diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index 0f764ad0..360190f4 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -65,4 +65,11 @@ public GetTeamCountResponse getTeamCountAndName(Long teamId, Long memberId) { return teamRepository.findTeamCount(memberId, teamId); } + public Long getTodayNewTeams(){ + return teamRepository.getTodayNewTeams(); + } + + public Long getYesterdayNewTeams(){ + return teamRepository.getYesterdayNewTeams(); + } } From 0e83a461d5d230ae20cb272d2f81f89f3ac16c5a Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Mar 2024 23:34:42 +0900 Subject: [PATCH 538/619] =?UTF-8?q?MNG-19=20feat:=20DAU=EC=97=90=20?= =?UTF-8?q?=EC=9D=BC=EC=9D=BC=20=EB=B6=88=20=EB=8D=98=EC=A7=80=EA=B8=B0=20?= =?UTF-8?q?=ED=9A=9F=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/FireCustomRepository.java | 8 ++--- .../repository/FireCustomRepositoryImpl.java | 32 +++++++++++++++++++ .../fire/domain/service/FireQueryService.java | 10 +++--- .../application/service/DAUFire.java | 28 ++++++++++++++++ 4 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/statistics/application/service/DAUFire.java diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java index 12470073..1f6304ec 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepository.java @@ -2,9 +2,6 @@ import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; -import com.moing.backend.domain.fire.domain.entity.Fire; -import com.moing.backend.domain.member.domain.entity.Member; -import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; import java.util.Optional; @@ -13,5 +10,6 @@ public interface FireCustomRepository { boolean hasFireCreatedWithinOneHour(Long throwMemberId, Long receiveMemberId); Optional> getFireReceivers(Long teamId, Long missionId, Long memberId); - - } + Long getTodayFires(); + Long getYesterdayFires(); +} diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index ececacb0..5c5d3e30 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -12,6 +12,7 @@ import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.temporal.TemporalAdjusters; import java.util.List; import java.util.Optional; @@ -74,6 +75,36 @@ public Optional> getFireReceivers(Long teamId, Long mission } + @Override + public Long getTodayFires() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + long todayFires = queryFactory + .selectFrom(fire) + .where(fire.createdDate.between(startOfToday, endOfToday)) + .fetchCount(); + + return todayFires; + } + + @Override + public Long getYesterdayFires(){ + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + long yesterdayFires = queryFactory + .selectFrom(fire) + .where(fire.createdDate.between(startOfYesterday, startOfToday)) + .fetchCount(); + + return yesterdayFires; + } + private BooleanExpression createRepeatTypeConditionByArchive() { LocalDate now = LocalDate.now(); @@ -84,6 +115,7 @@ private BooleanExpression createRepeatTypeConditionByArchive() { return missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); } + private BooleanExpression hasAlreadyVerifiedToday() { LocalDateTime today = LocalDateTime.now(); LocalDateTime startOfToday = today.withHour(0).withMinute(0).withSecond(0).withNano(0); diff --git a/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java b/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java index 2bcaef0c..1635607d 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/service/FireQueryService.java @@ -1,12 +1,8 @@ package com.moing.backend.domain.fire.domain.service; import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; -import com.moing.backend.domain.fire.domain.entity.Fire; -import com.moing.backend.domain.fire.domain.repository.FireCustomRepository; import com.moing.backend.domain.fire.domain.repository.FireRepository; -import com.moing.backend.domain.fire.exception.NotFoundFireException; import com.moing.backend.domain.fire.exception.NotFoundFireReceiversException; -import com.moing.backend.domain.member.domain.entity.Member; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -26,4 +22,10 @@ public List getNotYetMissionMember(Long teamId, Long missionId, return fireRepository.getFireReceivers(teamId, missionId,memberId).orElseThrow(NotFoundFireReceiversException::new); } + public Long getTodayFires(){ + return fireRepository.getTodayFires(); + } + public Long getYesterdayFires(){ + return fireRepository.getYesterdayFires(); + } } diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUFire.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUFire.java new file mode 100644 index 00000000..526e1366 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUFire.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.statistics.application.service; + +import com.moing.backend.domain.fire.domain.service.FireQueryService; +import com.moing.backend.domain.statistics.domain.constant.DAUStatusType; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class DAUFire implements DAUProvider { + + private final FireQueryService fireQueryService; + + @Override + public Long getTodayStats() { + return fireQueryService.getTodayFires(); + } + + @Override + public Long getYesterdayStats() { + return fireQueryService.getYesterdayFires(); + } + + @Override + public DAUStatusType getSupportedType() { + return DAUStatusType.DAILY_FIRE_COUNT; + } +} \ No newline at end of file From 6f9312fd195c28f698eca2020741f834368e5f27 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Mar 2024 23:35:07 +0900 Subject: [PATCH 539/619] =?UTF-8?q?MNG-19=20feat:=20DAU=EC=97=90=20?= =?UTF-8?q?=EC=9D=BC=EC=9D=BC=20=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=ED=9A=9F=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveCustomRepository.java | 5 ++-- .../MissionArchiveCustomRepositoryImpl.java | 29 +++++++++++++++++++ .../service/MissionArchiveQueryService.java | 9 ++++-- .../service/DAUMissionArchive.java | 28 ++++++++++++++++++ 4 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/statistics/application/service/DAUMissionArchive.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index 90c9a29c..81de1683 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -40,5 +40,6 @@ public interface MissionArchiveCustomRepository { Long getCountsByMissionId(Long missionId); - - } + Long getTodayMissionArchives(); + Long getYesterdayMissionArchives(); +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index c0326012..9e016dfe 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -29,6 +29,7 @@ import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.List; @@ -489,7 +490,35 @@ public Long getCountsByMissionId(Long missionId) { .fetch().size(); } + @Override + public Long getTodayMissionArchives() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + long todayMissionArchives = queryFactory + .selectFrom(missionArchive) + .where(missionArchive.createdDate.between(startOfToday, endOfToday)) + .fetchCount(); + + return todayMissionArchives; + } + @Override + public Long getYesterdayMissionArchives() { + LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Seoul")); + LocalDateTime startOfToday = now.toLocalDate().atStartOfDay(); + LocalDateTime endOfToday = startOfToday.plusDays(1); + LocalDateTime startOfYesterday = startOfToday.minusDays(1); + + long yesterdayMissionArchives = queryFactory + .selectFrom(missionArchive) + .where(missionArchive.createdDate.between(startOfYesterday, startOfToday)) + .fetchCount(); + + return yesterdayMissionArchives; + } } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 700897c5..e5edfa07 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -118,7 +118,10 @@ public Long stateCountByMissionId(Long missionId) { return missionArchiveRepository.getCountsByMissionId(missionId); } - - - + public Long getTodayMissionArchives(){ + return missionArchiveRepository.getTodayMissionArchives(); + } + public Long getYesterdayMissionArchives(){ + return missionArchiveRepository.getYesterdayMissionArchives(); + } } diff --git a/src/main/java/com/moing/backend/domain/statistics/application/service/DAUMissionArchive.java b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUMissionArchive.java new file mode 100644 index 00000000..b2ce9698 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/statistics/application/service/DAUMissionArchive.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.statistics.application.service; + +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.statistics.domain.constant.DAUStatusType; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class DAUMissionArchive implements DAUProvider { + + private final MissionArchiveQueryService missionArchiveQueryService; + + @Override + public Long getTodayStats() { + return missionArchiveQueryService.getTodayMissionArchives(); + } + + @Override + public Long getYesterdayStats() { + return missionArchiveQueryService.getYesterdayMissionArchives(); + } + + @Override + public DAUStatusType getSupportedType() { + return DAUStatusType.DAILY_MISSION_ARCHIVE_COUNT; + } +} From 411b96afa9f3cfed756a8e4027a31a361f44fc63 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Mar 2024 23:35:39 +0900 Subject: [PATCH 540/619] =?UTF-8?q?MNG-11=20fix:=20around=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=ED=98=B8=EC=B6=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/moing/backend/global/log/aop/LogAspect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/global/log/aop/LogAspect.java b/src/main/java/com/moing/backend/global/log/aop/LogAspect.java index ccaab9a7..b7b6d636 100644 --- a/src/main/java/com/moing/backend/global/log/aop/LogAspect.java +++ b/src/main/java/com/moing/backend/global/log/aop/LogAspect.java @@ -20,7 +20,7 @@ public Object serviceLog(ProceedingJoinPoint joinPoint) throws Throwable { return getObject(joinPoint); } - @Around("com.moing.backend.global.log.aop.Pointcuts.allService()") + @Around("com.moing.backend.global.log.aop.Pointcuts.allController()") public Object controllerLog(ProceedingJoinPoint joinPoint) throws Throwable { return getObject(joinPoint); } From b61c6877bd26dead1ce6c903e65a722be64c7252 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 10 Mar 2024 23:53:06 +0900 Subject: [PATCH 541/619] =?UTF-8?q?MNG-11=20fix:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- logs/error-log-2024-03-08.0.log | 170 ------------------ logs/error.log | 1 - logs/info-log-2024-03-08.0.log | 57 ------ logs/info.log | 58 ------ .../{logback-spring.xml => logback.xml} | 0 5 files changed, 286 deletions(-) delete mode 100644 logs/error-log-2024-03-08.0.log delete mode 100644 logs/error.log delete mode 100644 logs/info-log-2024-03-08.0.log delete mode 100644 logs/info.log rename src/main/resources/{logback-spring.xml => logback.xml} (100%) diff --git a/logs/error-log-2024-03-08.0.log b/logs/error-log-2024-03-08.0.log deleted file mode 100644 index 0690a9c2..00000000 --- a/logs/error-log-2024-03-08.0.log +++ /dev/null @@ -1,170 +0,0 @@ -2024-03-08 03:20:37 [ERROR] Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. Check whether you have a dependency on 'io.netty:netty-resolver-dns-native-macos' -java.lang.reflect.InvocationTargetException: null - at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) - at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) - at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) - at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) - at io.netty.resolver.dns.DnsServerAddressStreamProviders.(DnsServerAddressStreamProviders.java:64) - at io.netty.resolver.dns.DnsNameResolverBuilder.(DnsNameResolverBuilder.java:66) - at io.lettuce.core.resource.AddressResolverGroupProvider$DefaultDnsAddressResolverGroupWrapper.(AddressResolverGroupProvider.java:56) - at io.lettuce.core.resource.AddressResolverGroupProvider.(AddressResolverGroupProvider.java:35) - at io.lettuce.core.resource.DefaultClientResources.(DefaultClientResources.java:112) - at io.lettuce.core.AbstractRedisClient.(AbstractRedisClient.java:123) - at io.lettuce.core.RedisClient.(RedisClient.java:99) - at io.lettuce.core.RedisClient.create(RedisClient.java:136) - at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.lambda$createClient$7(LettuceConnectionFactory.java:1216) - at java.base/java.util.Optional.orElseGet(Optional.java:369) - at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.createClient(LettuceConnectionFactory.java:1216) - at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.afterPropertiesSet(LettuceConnectionFactory.java:338) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) - at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) - at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) - at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) - at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) - at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.resolveBeanReference(ConfigurationClassEnhancer.java:362) - at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:334) - at com.moing.backend.global.config.redis.RedisConfig$$EnhancerBySpringCGLIB$$d14604b9.redisConnectionFactory() - at com.moing.backend.global.config.redis.RedisConfig.redisTemplate(RedisConfig.java:37) - at com.moing.backend.global.config.redis.RedisConfig$$EnhancerBySpringCGLIB$$d14604b9.CGLIB$redisTemplate$0() - at com.moing.backend.global.config.redis.RedisConfig$$EnhancerBySpringCGLIB$$d14604b9$$FastClassBySpringCGLIB$$3fb0050f.invoke() - at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) - at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) - at com.moing.backend.global.config.redis.RedisConfig$$EnhancerBySpringCGLIB$$d14604b9.redisTemplate() - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.base/java.lang.reflect.Method.invoke(Method.java:566) - at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) - at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) - at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) - at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) - at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) - at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) - at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) - at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) - at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) - at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) - at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) - at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) - at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) - at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) - at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) - at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) - at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) - at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) - at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) - at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) - at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) - at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) - at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) - at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) - at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) - at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) - at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) - at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) - at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) - at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) - at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) - at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) - at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) - at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) - at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) - at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) - at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) - at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) - at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) - at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) - at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) - at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) - at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) - at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) - at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) - at com.moing.backend.BackendApplication.main(BackendApplication.java:16) -Caused by: java.lang.UnsatisfiedLinkError: failed to load the required native library - at io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.ensureAvailability(MacOSDnsServerAddressStreamProvider.java:110) - at io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.(MacOSDnsServerAddressStreamProvider.java:120) - ... 100 common frames omitted -Caused by: java.lang.UnsatisfiedLinkError: could not load a native library: netty_resolver_dns_native_macos_aarch_64 - at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:239) - at io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.loadNativeLibrary(MacOSDnsServerAddressStreamProvider.java:92) - at io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.(MacOSDnsServerAddressStreamProvider.java:77) - at java.base/java.lang.Class.forName0(Native Method) - at java.base/java.lang.Class.forName(Class.java:398) - at io.netty.resolver.dns.DnsServerAddressStreamProviders$1.run(DnsServerAddressStreamProviders.java:50) - at java.base/java.security.AccessController.doPrivileged(Native Method) - at io.netty.resolver.dns.DnsServerAddressStreamProviders.(DnsServerAddressStreamProviders.java:46) - ... 95 common frames omitted - Suppressed: java.lang.UnsatisfiedLinkError: could not load a native library: netty_resolver_dns_native_macos - at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:239) - at io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider.loadNativeLibrary(MacOSDnsServerAddressStreamProvider.java:95) - ... 101 common frames omitted - Caused by: java.io.FileNotFoundException: META-INF/native/libnetty_resolver_dns_native_macos.jnilib - at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:181) - ... 102 common frames omitted - Suppressed: java.lang.UnsatisfiedLinkError: no netty_resolver_dns_native_macos in java.library.path: [/Users/minsu/Library/Java/Extensions, /Library/Java/Extensions, /Network/Library/Java/Extensions, /System/Library/Java/Extensions, /usr/lib/java, .] - at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2662) - at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:827) - at java.base/java.lang.System.loadLibrary(System.java:1871) - at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:38) - at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:396) - at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:161) - ... 102 common frames omitted - Suppressed: java.lang.UnsatisfiedLinkError: no netty_resolver_dns_native_macos in java.library.path: [/Users/minsu/Library/Java/Extensions, /Library/Java/Extensions, /Network/Library/Java/Extensions, /System/Library/Java/Extensions, /usr/lib/java, .] - at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2662) - at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:827) - at java.base/java.lang.System.loadLibrary(System.java:1871) - at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:38) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.base/java.lang.reflect.Method.invoke(Method.java:566) - at io.netty.util.internal.NativeLibraryLoader$1.run(NativeLibraryLoader.java:430) - at java.base/java.security.AccessController.doPrivileged(Native Method) - at io.netty.util.internal.NativeLibraryLoader.loadLibraryByHelper(NativeLibraryLoader.java:422) - at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:388) - ... 103 common frames omitted -Caused by: java.io.FileNotFoundException: META-INF/native/libnetty_resolver_dns_native_macos_aarch_64.jnilib - at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:181) - ... 102 common frames omitted - Suppressed: java.lang.UnsatisfiedLinkError: no netty_resolver_dns_native_macos_aarch_64 in java.library.path: [/Users/minsu/Library/Java/Extensions, /Library/Java/Extensions, /Network/Library/Java/Extensions, /System/Library/Java/Extensions, /usr/lib/java, .] - at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2662) - at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:827) - at java.base/java.lang.System.loadLibrary(System.java:1871) - at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:38) - at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:396) - at io.netty.util.internal.NativeLibraryLoader.load(NativeLibraryLoader.java:161) - ... 102 common frames omitted - Suppressed: java.lang.UnsatisfiedLinkError: no netty_resolver_dns_native_macos_aarch_64 in java.library.path: [/Users/minsu/Library/Java/Extensions, /Library/Java/Extensions, /Network/Library/Java/Extensions, /System/Library/Java/Extensions, /usr/lib/java, .] - at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2662) - at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:827) - at java.base/java.lang.System.loadLibrary(System.java:1871) - at io.netty.util.internal.NativeLibraryUtil.loadLibrary(NativeLibraryUtil.java:38) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) - at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.base/java.lang.reflect.Method.invoke(Method.java:566) - at io.netty.util.internal.NativeLibraryLoader$1.run(NativeLibraryLoader.java:430) - at java.base/java.security.AccessController.doPrivileged(Native Method) - at io.netty.util.internal.NativeLibraryLoader.loadLibraryByHelper(NativeLibraryLoader.java:422) - at io.netty.util.internal.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:388) - ... 103 common frames omitted diff --git a/logs/error.log b/logs/error.log deleted file mode 100644 index 33d71ffb..00000000 --- a/logs/error.log +++ /dev/null @@ -1 +0,0 @@ -[2024-03-08 02:56:20:11127] [main] [ERROR] i.n.r.d.DnsServerAddressStreamProviders - Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. Check whether you have a dependency on 'io.netty:netty-resolver-dns-native-macos'. Use DEBUG level to see the full stack: java.lang.UnsatisfiedLinkError: failed to load the required native library diff --git a/logs/info-log-2024-03-08.0.log b/logs/info-log-2024-03-08.0.log deleted file mode 100644 index 435bff5f..00000000 --- a/logs/info-log-2024-03-08.0.log +++ /dev/null @@ -1,57 +0,0 @@ -2024-03-08 03:20:25 [ INFO] Starting BackendApplication using Java 11.0.18 on minsuui-MacBookPro.local with PID 30517 (/Users/minsu/Documents/GitHub/backend/build/classes/java/main started by minsu in /Users/minsu/Documents/GitHub/backend) -2024-03-08 03:20:25 [ INFO] The following 1 profile is active: "dev" -2024-03-08 03:20:25 [ INFO] HV000001: Hibernate Validator 6.2.5.Final -2024-03-08 03:20:26 [ INFO] Multiple Spring Data modules found, entering strict repository configuration mode -2024-03-08 03:20:26 [ INFO] Bootstrapping Spring Data JPA repositories in DEFAULT mode. -2024-03-08 03:20:26 [ INFO] Finished Spring Data repository scanning in 103 ms. Found 16 JPA repository interfaces. -2024-03-08 03:20:26 [ INFO] Multiple Spring Data modules found, entering strict repository configuration mode -2024-03-08 03:20:26 [ INFO] Bootstrapping Spring Data Redis repositories in DEFAULT mode. -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.block.domain.repository.BlockRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.board.domain.repository.BoardRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.boardRead.domain.repository.BoardReadRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.fire.domain.repository.FireRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.history.domain.repository.AlarmHistoryRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.member.domain.repository.MemberRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.mission.domain.repository.MissionRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionHeart.domain.repository.MissionHeartRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.mypage.domain.repository.FeedbackRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.report.domain.repository.ReportRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.team.domain.repository.TeamRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -2024-03-08 03:20:26 [ INFO] Finished Spring Data repository scanning in 22 ms. Found 0 Redis repository interfaces. -2024-03-08 03:20:34 [ INFO] BeanFactory id=1c0a394d-13be-381f-a1f6-d0c02e8550cb -2024-03-08 03:20:34 [ INFO] Bean '(inner bean)#53d30d23' of type [com.amazonaws.auth.BasicAWSCredentials] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) -2024-03-08 03:20:34 [ INFO] Bean '(inner bean)#424f02b8' of type [com.amazonaws.auth.AWSStaticCredentialsProvider] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) -2024-03-08 03:20:34 [ INFO] Bean '(inner bean)#589fb74d' of type [com.amazonaws.auth.profile.ProfileCredentialsProvider] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) -2024-03-08 03:20:34 [ INFO] Bean 'credentialsProvider' of type [org.springframework.cloud.aws.core.credentials.CredentialsProviderFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) -2024-03-08 03:20:34 [ INFO] Bean 'credentialsProvider' of type [com.amazonaws.auth.AWSCredentialsProviderChain] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) -2024-03-08 03:20:34 [ INFO] Tomcat initialized with port(s): 8080 (http) -2024-03-08 03:20:34 [ INFO] Initializing ProtocolHandler ["http-nio-8080"] -2024-03-08 03:20:34 [ INFO] Starting service [Tomcat] -2024-03-08 03:20:34 [ INFO] Starting Servlet engine: [Apache Tomcat/9.0.78] -2024-03-08 03:20:35 [ INFO] Initializing Spring embedded WebApplicationContext -2024-03-08 03:20:35 [ INFO] Root WebApplicationContext: initialization completed in 9175 ms -2024-03-08 03:20:35 [ INFO] HHH000412: Hibernate ORM core version 5.6.15.Final -2024-03-08 03:20:35 [ INFO] HCANN000001: Hibernate Commons Annotations {5.1.2.Final} -2024-03-08 03:20:35 [ INFO] jpa-hikari-pool - Starting... -2024-03-08 03:20:35 [ INFO] jpa-hikari-pool - Start completed. -2024-03-08 03:20:35 [ INFO] HHH000400: Using dialect: org.hibernate.dialect.MySQL57Dialect -2024-03-08 03:20:36 [ INFO] HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] -2024-03-08 03:20:36 [ INFO] Initialized JPA EntityManagerFactory for persistence unit 'default' -2024-03-08 03:20:38 [ INFO] Will not secure Ant [pattern='/resource/**'] -2024-03-08 03:20:38 [ INFO] Will not secure Ant [pattern='/css/**'] -2024-03-08 03:20:38 [ INFO] Will not secure Ant [pattern='/js/**'] -2024-03-08 03:20:38 [ INFO] Will not secure Ant [pattern='/img/**'] -2024-03-08 03:20:38 [ INFO] Will not secure Ant [pattern='/lib/**'] -2024-03-08 03:20:38 [ INFO] Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@79715834, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4d94b0af, org.springframework.security.web.context.SecurityContextPersistenceFilter@6c92af74, org.springframework.security.web.header.HeaderWriterFilter@c39ebcf, org.springframework.security.web.authentication.logout.LogoutFilter@32317a37, com.moing.backend.global.config.security.filter.JwtAuthFilter@72a80668, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@7f8bc54e, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@31f151ff, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@42cb8174, org.springframework.security.web.session.SessionManagementFilter@1be7b7de, org.springframework.security.web.access.ExceptionTranslationFilter@35cf5d9, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@314e2b4b] -2024-03-08 03:20:39 [ INFO] Exposing 16 endpoint(s) beneath base path '/actuator' -2024-03-08 03:20:39 [ INFO] Starting ProtocolHandler ["http-nio-8080"] -2024-03-08 03:20:39 [ INFO] Tomcat started on port(s): 8080 (http) with context path '' -2024-03-08 03:20:39 [ INFO] Started BackendApplication in 14.149 seconds (JVM running for 14.713) -2024-03-08 03:23:23 [ INFO] Closing JPA EntityManagerFactory for persistence unit 'default' -2024-03-08 03:23:23 [ INFO] jpa-hikari-pool - Shutdown initiated... -2024-03-08 03:23:23 [ INFO] jpa-hikari-pool - Shutdown completed. diff --git a/logs/info.log b/logs/info.log deleted file mode 100644 index 4d30242f..00000000 --- a/logs/info.log +++ /dev/null @@ -1,58 +0,0 @@ -[2024-03-08 02:56:09:555] [main] [INFO] com.moing.backend.BackendApplication - Starting BackendApplication using Java 11.0.18 on minsuui-MacBookPro.local with PID 30145 (/Users/minsu/Documents/GitHub/backend/build/classes/java/main started by minsu in /Users/minsu/Documents/GitHub/backend) -[2024-03-08 02:56:09:559] [main] [INFO] com.moing.backend.BackendApplication - The following 1 profile is active: "dev" -[2024-03-08 02:56:09:561] [background-preinit] [INFO] o.h.validator.internal.util.Version - HV000001: Hibernate Validator 6.2.5.Final -[2024-03-08 02:56:10:1509] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode -[2024-03-08 02:56:10:1510] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data JPA repositories in DEFAULT mode. -[2024-03-08 02:56:10:1605] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 92 ms. Found 16 JPA repository interfaces. -[2024-03-08 02:56:10:1614] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode -[2024-03-08 02:56:10:1614] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. -[2024-03-08 02:56:10:1636] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.block.domain.repository.BlockRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1636] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.board.domain.repository.BoardRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1636] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1636] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.boardRead.domain.repository.BoardReadRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1637] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.fire.domain.repository.FireRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1637] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.history.domain.repository.AlarmHistoryRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1638] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.member.domain.repository.MemberRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1638] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.mission.domain.repository.MissionRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1638] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1638] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionHeart.domain.repository.MissionHeartRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1639] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1639] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.mypage.domain.repository.FeedbackRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1639] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.report.domain.repository.ReportRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1639] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.team.domain.repository.TeamRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1640] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.teamMember.domain.repository.TeamMemberRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1640] [main] [INFO] o.s.d.r.c.RepositoryConfigurationExtensionSupport - Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository -[2024-03-08 02:56:10:1640] [main] [INFO] o.s.d.r.c.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 22 ms. Found 0 Redis repository interfaces. -[2024-03-08 02:56:17:8373] [main] [INFO] o.s.cloud.context.scope.GenericScope - BeanFactory id=1c0a394d-13be-381f-a1f6-d0c02e8550cb -[2024-03-08 02:56:17:8454] [main] [INFO] o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean '(inner bean)#1471b98d' of type [com.amazonaws.auth.BasicAWSCredentials] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) -[2024-03-08 02:56:17:8454] [main] [INFO] o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean '(inner bean)#1510b9a2' of type [com.amazonaws.auth.AWSStaticCredentialsProvider] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) -[2024-03-08 02:56:17:8458] [main] [INFO] o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean '(inner bean)#23b1aa9' of type [com.amazonaws.auth.profile.ProfileCredentialsProvider] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) -[2024-03-08 02:56:17:8459] [main] [INFO] o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'credentialsProvider' of type [org.springframework.cloud.aws.core.credentials.CredentialsProviderFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) -[2024-03-08 02:56:17:8459] [main] [INFO] o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'credentialsProvider' of type [com.amazonaws.auth.AWSCredentialsProviderChain] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) -[2024-03-08 02:56:17:8660] [main] [INFO] o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http) -[2024-03-08 02:56:17:8664] [main] [INFO] o.a.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"] -[2024-03-08 02:56:17:8665] [main] [INFO] o.a.catalina.core.StandardService - Starting service [Tomcat] -[2024-03-08 02:56:17:8665] [main] [INFO] o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.78] -[2024-03-08 02:56:18:8758] [main] [INFO] o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext -[2024-03-08 02:56:18:8758] [main] [INFO] o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 8151 ms -[2024-03-08 02:56:18:8977] [main] [INFO] o.h.jpa.internal.util.LogHelper - HHH000204: Processing PersistenceUnitInfo [name: default] -[2024-03-08 02:56:18:8998] [main] [INFO] org.hibernate.Version - HHH000412: Hibernate ORM core version 5.6.15.Final -[2024-03-08 02:56:18:9061] [main] [INFO] o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {5.1.2.Final} -[2024-03-08 02:56:18:9104] [main] [INFO] com.zaxxer.hikari.HikariDataSource - jpa-hikari-pool - Starting... -[2024-03-08 02:56:18:9505] [main] [INFO] com.zaxxer.hikari.HikariDataSource - jpa-hikari-pool - Start completed. -[2024-03-08 02:56:18:9512] [main] [INFO] org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.MySQL57Dialect -[2024-03-08 02:56:20:10691] [main] [INFO] o.h.e.t.j.p.i.JtaPlatformInitiator - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] -[2024-03-08 02:56:20:10704] [main] [INFO] o.s.o.j.LocalContainerEntityManagerFactoryBean - Initialized JPA EntityManagerFactory for persistence unit 'default' -[2024-03-08 02:56:21:12399] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will not secure Ant [pattern='/resource/**'] -[2024-03-08 02:56:21:12399] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will not secure Ant [pattern='/css/**'] -[2024-03-08 02:56:21:12399] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will not secure Ant [pattern='/js/**'] -[2024-03-08 02:56:21:12399] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will not secure Ant [pattern='/img/**'] -[2024-03-08 02:56:21:12400] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will not secure Ant [pattern='/lib/**'] -[2024-03-08 02:56:21:12434] [main] [INFO] o.s.s.web.DefaultSecurityFilterChain - Will secure any request with [org.springframework.security.web.session.DisableEncodeUrlFilter@7c63146c, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@5b2235a5, org.springframework.security.web.context.SecurityContextPersistenceFilter@12bff19d, org.springframework.security.web.header.HeaderWriterFilter@4cc40892, org.springframework.security.web.authentication.logout.LogoutFilter@793942d9, com.moing.backend.global.config.security.filter.JwtAuthFilter@5af6378e, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@64ce7e6f, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5d7d2cb5, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@205b3a1a, org.springframework.security.web.session.SessionManagementFilter@62edf11e, org.springframework.security.web.access.ExceptionTranslationFilter@6ed1fdb7, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@5064988] -[2024-03-08 02:56:22:13050] [main] [INFO] o.s.b.a.e.web.EndpointLinksResolver - Exposing 16 endpoint(s) beneath base path '/actuator' -[2024-03-08 02:56:22:13155] [main] [INFO] o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"] -[2024-03-08 02:56:22:13166] [main] [INFO] o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path '' -[2024-03-08 02:56:22:13181] [main] [INFO] com.moing.backend.BackendApplication - Started BackendApplication in 13.07 seconds (JVM running for 13.671) -[2024-03-08 02:56:44:35239] [SpringApplicationShutdownHook] [INFO] o.s.o.j.LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'default' -[2024-03-08 02:56:44:35242] [SpringApplicationShutdownHook] [INFO] com.zaxxer.hikari.HikariDataSource - jpa-hikari-pool - Shutdown initiated... -[2024-03-08 02:56:44:35289] [SpringApplicationShutdownHook] [INFO] com.zaxxer.hikari.HikariDataSource - jpa-hikari-pool - Shutdown completed. diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback.xml similarity index 100% rename from src/main/resources/logback-spring.xml rename to src/main/resources/logback.xml From 36190e2aa77fc2997e2909b8b95715b3add7119c Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 11 Mar 2024 00:05:46 +0900 Subject: [PATCH 542/619] =?UTF-8?q?MNG-11=20fix:=20resources=20=EB=94=94?= =?UTF-8?q?=EB=A0=89=ED=86=A0=EB=A6=AC=20=EC=83=9D=EC=84=B1=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/CD-dev.yml | 1 - .github/workflows/CD-prod.yml | 1 - .github/workflows/CI-dev.yml | 1 - .github/workflows/CI-prod.yml | 1 - 4 files changed, 4 deletions(-) diff --git a/.github/workflows/CD-dev.yml b/.github/workflows/CD-dev.yml index 92a3178b..581fe8c0 100644 --- a/.github/workflows/CD-dev.yml +++ b/.github/workflows/CD-dev.yml @@ -40,7 +40,6 @@ jobs: # 설정 파일 생성 - run: | - mkdir ./src/main/resources cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml diff --git a/.github/workflows/CD-prod.yml b/.github/workflows/CD-prod.yml index 4f211ba4..4a541082 100644 --- a/.github/workflows/CD-prod.yml +++ b/.github/workflows/CD-prod.yml @@ -40,7 +40,6 @@ jobs: # 설정 파일 생성 - run: | - mkdir ./src/main/resources cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml diff --git a/.github/workflows/CI-dev.yml b/.github/workflows/CI-dev.yml index 1ef81d51..caeb3688 100644 --- a/.github/workflows/CI-dev.yml +++ b/.github/workflows/CI-dev.yml @@ -41,7 +41,6 @@ jobs: # 설정 파일 생성 - run: | - mkdir ./src/main/resources cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml diff --git a/.github/workflows/CI-prod.yml b/.github/workflows/CI-prod.yml index f7ed564f..ee7e333c 100644 --- a/.github/workflows/CI-prod.yml +++ b/.github/workflows/CI-prod.yml @@ -41,7 +41,6 @@ jobs: # 설정 파일 생성 - run: | - mkdir ./src/main/resources cd ./src/main/resources touch ./application.yml echo "${{env.APPLICATION}}" > ./application.yml From def56f8fa1fe4be06f58202552b2127be2e26835 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 11 Mar 2024 01:18:10 +0900 Subject: [PATCH 543/619] =?UTF-8?q?MNG-11=20fix:=20LogTrace=20MockBean=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/moing/backend/config/CommonControllerTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/com/moing/backend/config/CommonControllerTest.java b/src/test/java/com/moing/backend/config/CommonControllerTest.java index 50f698fa..9710cdb2 100644 --- a/src/test/java/com/moing/backend/config/CommonControllerTest.java +++ b/src/test/java/com/moing/backend/config/CommonControllerTest.java @@ -8,6 +8,7 @@ import com.moing.backend.global.config.security.filter.JwtAuthenticationEntryPoint; import com.moing.backend.global.config.security.jwt.TokenUtil; import com.moing.backend.global.config.security.util.AuthenticationUtil; +import com.moing.backend.global.log.aop.LogTrace; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -57,6 +58,9 @@ public class CommonControllerTest { @MockBean public MemberGetService memberQueryService; + @MockBean + public LogTrace logTrace; + @BeforeEach public void setUp(final WebApplicationContext context, final RestDocumentationContextProvider provider) throws Exception { From d5e02b865d69bfe9b56bbe4a99defecd32ceb35f Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 11 Mar 2024 01:56:27 +0900 Subject: [PATCH 544/619] =?UTF-8?q?MNG-11=20fix:=20=20deploy=ED=95=A0=20?= =?UTF-8?q?=EB=95=8C=20=EB=A1=9C=EA=B7=B8=20=ED=8C=8C=EC=9D=BC=20docker=20?= =?UTF-8?q?volume=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .deploy/deploy_dev.sh | 16 ++++++++++++---- .deploy/deploy_prod.sh | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/.deploy/deploy_dev.sh b/.deploy/deploy_dev.sh index 89a7f3b9..740b82ee 100644 --- a/.deploy/deploy_dev.sh +++ b/.deploy/deploy_dev.sh @@ -1,3 +1,5 @@ +#!/bin/bash + DOCKER_APP_NAME=meetup DOCKER_USERNAME=modagbul @@ -5,6 +7,10 @@ DOCKER_USERNAME=modagbul docker pull ${DOCKER_USERNAME}/moing_dev:blue docker pull ${DOCKER_USERNAME}/moing_dev:green +# 로그 디렉토리 설정 +LOG_DIR=$(pwd)/logs/logback +mkdir -p $LOG_DIR + # 현재 실행 중인 컨테이너를 확인 (blue 또는 green) EXIST_BLUE=$(docker ps --filter name=${DOCKER_APP_NAME}-blue --filter status=running -q) EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --filter status=running -q) @@ -18,7 +24,8 @@ if [ -z "$EXIST_BLUE" ] && [ -z "$EXIST_GREEN" ]; then docker rm ${DOCKER_APP_NAME}-blue fi - docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_dev:blue + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul \ + -v $LOG_DIR:/logs/logback ${DOCKER_USERNAME}/moing_dev:blue BEFORE_COMPOSE_COLOR="green" AFTER_COMPOSE_COLOR="blue" elif [ -z "$EXIST_BLUE" ]; then @@ -29,7 +36,8 @@ elif [ -z "$EXIST_BLUE" ]; then docker rm ${DOCKER_APP_NAME}-blue fi - docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_dev:blue + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul \ + -v $LOG_DIR:/logs/logback ${DOCKER_USERNAME}/moing_dev:blue BEFORE_COMPOSE_COLOR="green" AFTER_COMPOSE_COLOR="blue" else @@ -40,12 +48,12 @@ else docker rm ${DOCKER_APP_NAME}-green fi - docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_dev:green + docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 -e TZ=Asia/Seoul \ + -v $LOG_DIR:/logs/logback ${DOCKER_USERNAME}/moing_dev:green BEFORE_COMPOSE_COLOR="blue" AFTER_COMPOSE_COLOR="green" fi - sleep 40 # 새로운 컨테이너가 제대로 실행되었는지 확인 diff --git a/.deploy/deploy_prod.sh b/.deploy/deploy_prod.sh index f2612515..d5ae4e4b 100644 --- a/.deploy/deploy_prod.sh +++ b/.deploy/deploy_prod.sh @@ -1,3 +1,5 @@ +#!/bin/bash + DOCKER_APP_NAME=meetup DOCKER_USERNAME=modagbul @@ -5,6 +7,10 @@ DOCKER_USERNAME=modagbul docker pull ${DOCKER_USERNAME}/moing_prod:blue docker pull ${DOCKER_USERNAME}/moing_prod:green +# 로그 디렉토리 설정 +LOG_DIR=$(pwd)/logs/logback +mkdir -p $LOG_DIR + # 현재 실행 중인 컨테이너를 확인 (blue 또는 green) EXIST_BLUE=$(docker ps --filter name=${DOCKER_APP_NAME}-blue --filter status=running -q) EXIST_GREEN=$(docker ps --filter name=${DOCKER_APP_NAME}-green --filter status=running -q) @@ -18,7 +24,8 @@ if [ -z "$EXIST_BLUE" ] && [ -z "$EXIST_GREEN" ]; then docker rm ${DOCKER_APP_NAME}-blue fi - docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_prod:blue + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul \ + -v $LOG_DIR:/logs/logback ${DOCKER_USERNAME}/moing_prod:blue BEFORE_COMPOSE_COLOR="green" AFTER_COMPOSE_COLOR="blue" elif [ -z "$EXIST_BLUE" ]; then @@ -29,7 +36,8 @@ elif [ -z "$EXIST_BLUE" ]; then docker rm ${DOCKER_APP_NAME}-blue fi - docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_prod:blue + docker run -d --name ${DOCKER_APP_NAME}-blue -p 8081:8080 -e TZ=Asia/Seoul \ + -v $LOG_DIR:/logs/logback ${DOCKER_USERNAME}/moing_prod:blue BEFORE_COMPOSE_COLOR="green" AFTER_COMPOSE_COLOR="blue" else @@ -40,12 +48,12 @@ else docker rm ${DOCKER_APP_NAME}-green fi - docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 -e TZ=Asia/Seoul ${DOCKER_USERNAME}/moing_prod:green + docker run -d --name ${DOCKER_APP_NAME}-green -p 8082:8080 -e TZ=Asia/Seoul \ + -v $LOG_DIR:/logs/logback ${DOCKER_USERNAME}/moing_prod:green BEFORE_COMPOSE_COLOR="blue" AFTER_COMPOSE_COLOR="green" fi - sleep 40 # 새로운 컨테이너가 제대로 실행되었는지 확인 From 8251211fc68babf167ee9a6935f38cfd2fb8cf73 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 15 Mar 2024 15:41:34 +0900 Subject: [PATCH 545/619] =?UTF-8?q?fix=20:=20=EB=A0=88=EB=B2=A8=2070=20?= =?UTF-8?q?=EC=9D=B4=EC=83=81=20=EC=9D=BC=20=EB=95=8C=20score=EA=B0=80=201?= =?UTF-8?q?00=20=EB=84=98=EA=B8=B0=EC=97=90=20=EB=A0=88=EB=B2=A8=2070=20?= =?UTF-8?q?=EC=9D=B4=EC=83=81=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/TeamScoreGetUseCase.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java index e36247af..a51f4026 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java @@ -27,11 +27,19 @@ public class TeamScoreGetUseCase { public TeamScoreRes getTeamScoreInfo(Long teamId) { TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(teamId); + Long level = teamScore.getLevel(); + Long score = teamScore.getScore(); + + // 70 레벨 이상은 경험치 120 되어야 레벨업 가능. level을 각 레벨 별 필요한 경험치 수에 따르 퍼센트로 계산 + if (level > 70) { + score = ( score / 120 ) * 100; + } + return TeamScoreRes.builder() - .score(teamScore.getScore()) - .level(teamScore.getLevel()) - .build() - ; + .score(score) + .level(level) + .build(); + } } From 91f6f205f65cccfaad15bb58f45480dc3ce40226 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Fri, 15 Mar 2024 15:41:34 +0900 Subject: [PATCH 546/619] =?UTF-8?q?fix=20:=20=EB=A0=88=EB=B2=A8=2070=20?= =?UTF-8?q?=EC=9D=B4=EC=83=81=20=EC=9D=BC=20=EB=95=8C=20score=EA=B0=80=201?= =?UTF-8?q?00=20=EB=84=98=EA=B8=B0=EC=97=90=20=EB=A0=88=EB=B2=A8=2070=20?= =?UTF-8?q?=EC=9D=B4=EC=83=81=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/TeamScoreGetUseCase.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java index e36247af..a51f4026 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java @@ -27,11 +27,19 @@ public class TeamScoreGetUseCase { public TeamScoreRes getTeamScoreInfo(Long teamId) { TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(teamId); + Long level = teamScore.getLevel(); + Long score = teamScore.getScore(); + + // 70 레벨 이상은 경험치 120 되어야 레벨업 가능. level을 각 레벨 별 필요한 경험치 수에 따르 퍼센트로 계산 + if (level > 70) { + score = ( score / 120 ) * 100; + } + return TeamScoreRes.builder() - .score(teamScore.getScore()) - .level(teamScore.getLevel()) - .build() - ; + .score(score) + .level(level) + .build(); + } } From 2ffa113be946868e10aee03ee0a983fa48395efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Apr 2024 08:35:19 +0900 Subject: [PATCH 547/619] =?UTF-8?q?refactor=20:=20missionState=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionStateCustomRepository.java | 25 ----- .../MissionStateCustomRepositoryImpl.java | 103 ------------------ .../repository/MissionStateRepository.java | 9 -- .../service/MissionStateDeleteService.java | 32 ------ .../service/MissionStateSaveService.java | 31 ------ .../service/MissionStateQueryServiceTest.java | 35 ------ 6 files changed, 235 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java delete mode 100644 src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java deleted file mode 100644 index 01166d64..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.moing.backend.domain.missionState.domain.repository; - -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.missionState.domain.entity.MissionState; -import org.springframework.stereotype.Repository; - -import java.util.List; -import java.util.Optional; - -@Repository -public interface MissionStateCustomRepository { - - int getCountsByMissionId(Long missionId) ; - - List findByMissionId(List missionId); - List findByMissionId(Long missionId); - - Optional> findFinishMission(); - - Optional findMissionStateByMemberAndMission(Member member, Mission mission); - - - -} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java deleted file mode 100644 index 93cde112..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.moing.backend.domain.missionState.domain.repository; - -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.domain.missionState.domain.entity.MissionState; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.jpa.impl.JPAQueryFactory; - -import javax.persistence.EntityManager; - - -import java.time.DayOfWeek; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.temporal.TemporalAdjusters; -import java.util.List; -import java.util.Optional; - -import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; - -public class MissionStateCustomRepositoryImpl implements MissionStateCustomRepository { - - private final JPAQueryFactory queryFactory; - - public MissionStateCustomRepositoryImpl(EntityManager entityManager) { - this.queryFactory = new JPAQueryFactory(entityManager); - } - - - @Override - public int getCountsByMissionId(Long missionId) { - - LocalDate now = LocalDate.now(); - DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; // 한 주의 시작일을 월요일로 설정 - LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); - LocalDate endOfWeek = startOfWeek.plusDays(6); // 한 주의 마지막일을 일요일로 설정 - - BooleanExpression repeatTypeCondition = (missionState.mission.type.eq(MissionType.REPEAT) - .and(missionState.createdDate.goe(startOfWeek.atStartOfDay())) - .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1)))).or(missionState.mission.type.eq(MissionType.ONCE)); - - // 기본 조건 - BooleanExpression baseCondition = missionState.mission.id.eq(missionId); - // 조건 적용 - BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); - - - return queryFactory - .select(missionState) - .from(missionState) - .where(finalCondition) - .fetch().size(); - } - - @Override - public List findByMissionId(List missionId) { - - return queryFactory - .select(missionState) - .from(missionState) - .where( - missionState.mission.id.in(missionId) - ).fetch(); - - } - @Override - public List findByMissionId(Long missionId) { - - return queryFactory - .select(missionState) - .from(missionState) - .where( - missionState.mission.id.in(missionId) - ).fetch(); - - } - - @Override - public Optional> findFinishMission() { - return Optional.ofNullable(queryFactory - .select(missionState) - .from(missionState) - .where( - missionState.mission.dueTo.ne(LocalDateTime.now()), - missionState.mission.status.eq(MissionStatus.ONGOING) - - ).fetch() - ); - } - - public Optional findMissionStateByMemberAndMission(Member member, Mission mission) { - return Optional.ofNullable(queryFactory - .selectFrom(missionState) - .where(missionState.mission.eq(mission), - missionState.member.eq(member)) - .orderBy(missionState.createdDate.desc()) - .fetchFirst()); - } - -} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java deleted file mode 100644 index 32d06a99..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.moing.backend.domain.missionState.domain.repository; - -import com.moing.backend.domain.missionState.domain.entity.MissionState; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface MissionStateRepository extends JpaRepository,MissionStateCustomRepository { -} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java deleted file mode 100644 index b99aa8b0..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateDeleteService.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.moing.backend.domain.missionState.domain.service; - -import com.moing.backend.domain.missionState.domain.entity.MissionState; -import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; -import com.moing.backend.global.annotation.DomainService; -import lombok.RequiredArgsConstructor; - -import javax.transaction.Transactional; -import java.util.List; - -@DomainService -@Transactional -@RequiredArgsConstructor -public class MissionStateDeleteService { - - private final MissionStateRepository missionStateRepository; - - public void deleteMissionState(List missionStates) { - - missionStateRepository.deleteAll(missionStates); - } - public void deleteMissionState(MissionState missionStates) { - - missionStateRepository.delete(missionStates); - } - - public void deleteMissionStateByMission(Long missionId) { - - List missionStates = missionStateRepository.findByMissionId(missionId); - missionStateRepository.deleteAll(missionStates); - } -} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java deleted file mode 100644 index 1a1fc6e9..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.moing.backend.domain.missionState.domain.service; - -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.domain.missionState.domain.entity.MissionState; -import com.moing.backend.domain.missionState.domain.entity.Status; -import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; -import com.moing.backend.global.annotation.DomainService; -import lombok.RequiredArgsConstructor; - -import javax.transaction.Transactional; - -@DomainService -@Transactional -@RequiredArgsConstructor -public class MissionStateSaveService { - - private final MissionStateRepository missionStateRepository; - - public void saveMissionState(Member member, Mission mission, MissionArchiveStatus status) { - missionStateRepository.save(MissionState.builder() - .mission(mission) - .member(member) - .status(status) - .build()); - } - -} diff --git a/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java b/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java deleted file mode 100644 index 91a716c3..00000000 --- a/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.moing.backend.domain.missionState.domain.service; - -import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; -import com.moing.backend.domain.missionState.domain.repository.MissionStateCustomRepository; -import com.moing.backend.domain.missionState.domain.repository.MissionStateCustomRepositoryImpl; -import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; - -import javax.persistence.EntityManager; - -import static org.junit.jupiter.api.Assertions.*; - -@SpringBootTest -class MissionStateQueryServiceTest { - - - @MockBean - MissionStateQueryService missionStateQueryService ; - @MockBean - MissionStateCustomRepositoryImpl missionStateCustomRepository ; - - - @Test - public void missionDonePeople() { - System.out.println(missionStateQueryService.stateCountByMissionId(4L)); - } - - - - - -} \ No newline at end of file From e28224fd09b381eea2937a166551f11fa56f277d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Apr 2024 08:37:24 +0900 Subject: [PATCH 548/619] =?UTF-8?q?refactor=20:=20missionState=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveCreateUseCase.java | 12 +----- .../service/MissionArchiveDeleteUseCase.java | 20 ---------- .../service/MissionArchiveUpdateUseCase.java | 9 ----- .../service/MissionStateScheduleUseCase.java | 10 +---- .../service/MissionStateUseCase.java | 19 ++-------- .../MissionArchiveStateQueryService.java | 21 +++++++++++ .../service/MissionStateQueryService.java | 37 ------------------- 7 files changed, 28 insertions(+), 100 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 2cc3df06..983041c1 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -16,11 +16,9 @@ import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; import com.moing.backend.domain.missionArchive.exception.NotYetMissionArchiveException; import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; -import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; -import com.moing.backend.global.utils.BaseService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,17 +30,11 @@ public class MissionArchiveCreateUseCase { private final MissionArchiveSaveService missionArchiveSaveService; private final MissionArchiveQueryService missionArchiveQueryService; - private final MissionArchiveDeleteService missionArchiveDeleteService; - - private final MissionHeartQueryService missionHeartQueryService; - private final MissionQueryService missionQueryService; - private final MemberGetService memberGetService; - private final MissionStateSaveService missionStateSaveService; + private final MemberGetService memberGetService; private final MissionStateUseCase missionStateUseCase; - private final TeamScoreLogicUseCase teamScoreLogicUseCase; public MissionArchiveRes createArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { @@ -101,7 +93,7 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss } // 이 미션을 완료 했는지 - public Boolean isDoneMission(Long memberId,Mission mission) { + private Boolean isDoneMission(Long memberId,Mission mission) { return missionArchiveQueryService.findMyDoneArchives(memberId, mission.getId()) >= mission.getNumber(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java index a66bc217..6e8065ef 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java @@ -1,27 +1,15 @@ package com.moing.backend.domain.missionArchive.application.service; -import com.moing.backend.domain.infra.image.application.service.IssuePresignedUrlUseCase; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; -import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; -import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; import com.moing.backend.domain.missionArchive.exception.NoAccessMissionArchiveException; -import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; -import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; -import com.moing.backend.domain.missionState.domain.entity.MissionState; -import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; -import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; -import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.utils.UpdateUtils; import lombok.RequiredArgsConstructor; @@ -35,18 +23,12 @@ @RequiredArgsConstructor public class MissionArchiveDeleteUseCase { - private final MissionArchiveSaveService missionArchiveSaveService; private final MissionArchiveQueryService missionArchiveQueryService; private final MissionArchiveDeleteService missionArchiveDeleteService; - private final MissionHeartQueryService missionHeartQueryService; - private final MissionQueryService missionQueryService; private final MemberGetService memberGetService; - private final MissionStateDeleteService missionStateDeleteService; - private final MissionStateQueryService missionStateQueryService; - private final UpdateUtils updateUtils; @@ -59,7 +41,6 @@ public Long deleteArchive(String userSocialId, Long missionId,Long count) { Team team = mission.getTeam(); MissionArchive deleteArchive = missionArchiveQueryService.findOneMyArchive(memberId, missionId,count).get(0); - MissionState missionState = missionStateQueryService.findMissionState(member, mission); LocalDateTime createdDate = deleteArchive.getCreatedDate(); LocalDateTime today = LocalDateTime.now(); @@ -75,7 +56,6 @@ public Long deleteArchive(String userSocialId, Long missionId,Long count) { } missionArchiveDeleteService.deleteMissionArchive(deleteArchive); - missionStateDeleteService.deleteMissionState(missionState); return deleteArchive.getId(); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index b306f349..2b3f61df 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -1,6 +1,5 @@ package com.moing.backend.domain.missionArchive.application.service; -import com.moing.backend.domain.infra.image.application.service.IssuePresignedUrlUseCase; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; import com.moing.backend.domain.mission.domain.entity.Mission; @@ -12,12 +11,9 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; -import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; -import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.missionArchive.exception.NoAccessMissionArchiveException; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; @@ -33,16 +29,11 @@ public class MissionArchiveUpdateUseCase { private final MissionArchiveSaveService missionArchiveSaveService; private final MissionArchiveQueryService missionArchiveQueryService; - private final MissionArchiveDeleteService missionArchiveDeleteService; - private final MissionHeartQueryService missionHeartQueryService; private final MissionQueryService missionQueryService; private final MemberGetService memberGetService; - private final IssuePresignedUrlUseCase getPresignedUrlUseCase; - - private final MissionStateSaveService missionStateSaveService; private final MissionStateUseCase missionStateUseCase; diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java index b3f0acb2..5f97a90f 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java @@ -5,10 +5,6 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.mission.domain.service.MissionSaveService; -import com.moing.backend.domain.missionState.domain.entity.MissionState; -import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; -import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,7 +15,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDateTime; import java.util.List; @Slf4j @@ -34,9 +29,6 @@ public class MissionStateScheduleUseCase { private final MissionStateUseCase missionStateUseCase; private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; private final MissionQueryService missionQueryService; - private final MissionStateQueryService missionStateQueryService; - private final MissionStateDeleteService missionStateDeleteService; - private final TeamScoreLogicUseCase teamScoreLogicUseCase; private final SendMissionStartAlarmUseCase sendMissionStartAlarmUseCase; @@ -51,7 +43,7 @@ public void sundayRepeatMissionRoutine() { // 모든 진행중인 반복 미션 모아서 List ongoingRepeatMissions = missionQueryService.findOngoingRepeatMissions(); - // 팀 스코어 반영 ( 배치 처리 해야하는데 ) + // 팀 스코어 반영 for (Long id : ongoingRepeatMissions) { teamScoreLogicUseCase.updateTeamScore(id); } diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java index 0e70b913..05b467df 100644 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -4,21 +4,14 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionState.domain.entity.MissionState; -import com.moing.backend.domain.missionState.domain.service.MissionStateDeleteService; -import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; -import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; -import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.missionState.domain.service.MissionArchiveStateQueryService; import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; - @Slf4j @Service @Transactional @@ -28,11 +21,7 @@ public class MissionStateUseCase { // 미션 종료 직전인지 확인 // missionId, missionstate num mission.team.personum - private final MissionQueryService missionQueryService; - private final MissionStateQueryService missionStateQueryService; - private final MissionStateSaveService missionStateSaveService; - private final MissionStateDeleteService missionStateDeleteService; - + private final MissionArchiveStateQueryService missionArchiveStateQueryService; private final TeamScoreLogicUseCase teamScoreLogicUseCase; @@ -49,7 +38,7 @@ public boolean isAbleToEnd(Mission mission) { } public Long donePeople(Mission mission) { - return Long.valueOf(missionStateQueryService.stateCountByMissionId(mission.getId())); + return Long.valueOf(missionArchiveStateQueryService.stateCountByMissionId(mission.getId())); } public Long totalPeople(Mission mission) { @@ -61,7 +50,7 @@ public void updateMissionState(Member member, Mission mission, MissionArchive mi MissionType missionType = mission.getType(); Long missionId = mission.getId(); - missionStateSaveService.saveMissionState(member,mission, missionArchive.getStatus()); +// missionStateSaveService.saveMissionState(member,mission, missionArchive.getStatus()); if (missionType == MissionType.ONCE) { diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java new file mode 100644 index 00000000..3ff2eba4 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java @@ -0,0 +1,21 @@ +package com.moing.backend.domain.missionState.domain.service; + +import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionArchiveStateQueryService { + + private final MissionArchiveRepository missionArchiveRepository; + + public int stateCountByMissionId(Long missionId) { + return missionArchiveRepository.getCountsByMissionId(missionId); + } + + + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java deleted file mode 100644 index 507a9529..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.moing.backend.domain.missionState.domain.service; - -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.missionState.domain.entity.MissionState; -import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; -import com.moing.backend.global.annotation.DomainService; -import lombok.RequiredArgsConstructor; -import com.moing.backend.domain.missionState.exception.NotFoundMissionStateException; -import javax.transaction.Transactional; -import java.util.List; - -@DomainService -@Transactional -@RequiredArgsConstructor -public class MissionStateQueryService { - - private final MissionStateRepository missionStateRepository; - - public int stateCountByMissionId(Long missionId) { - return missionStateRepository.getCountsByMissionId(missionId); - } - - public List findByMissionId(List missionId) { - return missionStateRepository.findByMissionId(missionId); - } - - public List findFinishMission() { - return missionStateRepository.findFinishMission().orElseThrow(NotFoundMissionStateException::new); - } - - public MissionState findMissionState(Member member, Mission mission) { - return missionStateRepository.findMissionStateByMemberAndMission(member, mission).orElseThrow(NotFoundMissionStateException::new); - } - - -} From c42e32f275a673c69e8748c6f7dcc5cfe517d3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Apr 2024 08:38:13 +0900 Subject: [PATCH 549/619] =?UTF-8?q?refactor=20:=20missionState=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=A9=94=EC=86=8C=EB=93=9C=20missionArchive=20?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionArchiveRepository.java | 3 +- .../MissionArchiveStateCustomRepository.java | 18 +++++++ ...ssionArchiveStateCustomRepositoryImpl.java | 50 +++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepositoryImpl.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java index 7d9726a6..2c88d112 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.moing.backend.domain.missionState.domain.repository.MissionArchiveStateCustomRepository; import com.querydsl.core.Tuple; import feign.Param; import org.hibernate.annotations.NamedNativeQuery; @@ -21,7 +22,7 @@ import java.util.Optional; @Repository -public interface MissionArchiveRepository extends JpaRepository,MissionArchiveCustomRepository { +public interface MissionArchiveRepository extends JpaRepository,MissionArchiveCustomRepository , MissionArchiveStateCustomRepository { @Query("select m from MissionArchive as m where m.member =:memberId" ) Optional> findByMemberId(@Param("memberId") Long memberId); diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepository.java new file mode 100644 index 00000000..307bdb45 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepository.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.missionState.domain.repository; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionState.domain.entity.MissionState; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface MissionArchiveStateCustomRepository { + + int getCountsByMissionId(Long missionId) ; + + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepositoryImpl.java new file mode 100644 index 00000000..f3d0c497 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepositoryImpl.java @@ -0,0 +1,50 @@ +package com.moing.backend.domain.missionState.domain.repository; + +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.temporal.TemporalAdjusters; + +import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; + +public class MissionArchiveStateCustomRepositoryImpl implements MissionArchiveStateCustomRepository { + + private final JPAQueryFactory queryFactory; + + public MissionArchiveStateCustomRepositoryImpl(EntityManager entityManager) { + this.queryFactory = new JPAQueryFactory(entityManager); + } + + + @Override + public int getCountsByMissionId(Long missionId) { + + LocalDate now = LocalDate.now(); + DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; // 한 주의 시작일을 월요일로 설정 + LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); + LocalDate endOfWeek = startOfWeek.plusDays(6); // 한 주의 마지막일을 일요일로 설정 + + BooleanExpression repeatTypeCondition = (missionArchive.mission.type.eq(MissionType.REPEAT) + .and(missionArchive.createdDate.goe(startOfWeek.atStartOfDay())) + .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1)))).or(missionArchive.mission.type.eq(MissionType.ONCE)); + + // 기본 조건 + BooleanExpression baseCondition = missionArchive.mission.id.eq(missionId); + // 조건 적용 + BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); + + + return queryFactory + .select(missionArchive) + .from(missionArchive) + .where(finalCondition) + .fetch().size(); + } + + + +} From a383205e1ee6257d6e420d00c759c4ef1516aac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Apr 2024 08:38:48 +0900 Subject: [PATCH 550/619] =?UTF-8?q?refactor=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20@Transactional=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/TeamScoreLogicUseCase.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java index eb4b5a91..c81b2bcc 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -3,8 +3,7 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; -import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.missionState.domain.service.MissionArchiveStateQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.team.domain.service.TeamGetService; import com.moing.backend.domain.team.domain.service.TeamSaveService; @@ -18,16 +17,12 @@ import org.springframework.transaction.annotation.Transactional; @Slf4j @Service -@Transactional @RequiredArgsConstructor public class TeamScoreLogicUseCase { - private final TeamGetService teamGetService; private final MissionQueryService missionQueryService; private final TeamScoreQueryService teamScoreQueryService; - private final TeamScoreSaveService teamScoreSaveService; - private final MissionStateQueryService missionStateQueryService; - private final TeamSaveService teamSaveService; + private final MissionArchiveStateQueryService missionArchiveStateQueryService; public TeamScoreRes getTeamScoreInfo(Long teamId) { @@ -38,6 +33,7 @@ public TeamScoreRes getTeamScoreInfo(Long teamId) { ; } + @Transactional public Long updateTeamScore(Long missionId) { Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); @@ -46,9 +42,6 @@ public Long updateTeamScore(Long missionId) { teamScore.updateScore(getScoreByMission(mission)); teamScore.levelUp(); - teamScoreSaveService.save(teamScore); - teamSaveService.saveTeam(team); - return teamScore.getScore(); } @@ -73,7 +66,7 @@ public Long getScoreByMission(Mission mission) { } public float donePeople(Mission mission) { - return Float.valueOf(missionStateQueryService.stateCountByMissionId(mission.getId())); + return Float.valueOf(missionArchiveStateQueryService.stateCountByMissionId(mission.getId())); } public float totalPeople(Mission mission) { From 4a3f139a6833c06deea8de53aa16e4cd8134e5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 9 Apr 2024 08:39:23 +0900 Subject: [PATCH 551/619] =?UTF-8?q?feat=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98=20=ED=83=AD=EC=97=90=EC=84=9C=20=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=ED=98=84=ED=99=A9=20=EC=9D=B8?= =?UTF-8?q?=EC=9B=90=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/GatherSingleMissionRes.java | 14 ++++++++++- .../MissionCustomRepositoryImpl.java | 25 ++++++++++++------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java index 0b173365..718a4b87 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java @@ -3,9 +3,11 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.ToString; @Getter @Builder +@ToString @AllArgsConstructor public class GatherSingleMissionRes { private Long missionId; @@ -14,6 +16,16 @@ public class GatherSingleMissionRes { private String missionTitle; private String dueTo; private String status; + private Long done; + private Long total; - + public GatherSingleMissionRes(Long missionId, Long teamId, String teamName, String missionTitle, String dueTo, String status, Long total) { + this.missionId = missionId; + this.teamId = teamId; + this.teamName = teamName; + this.missionTitle = missionTitle; + this.dueTo = dueTo; + this.status = status; + this.total = total; + } } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index a585c651..312791d8 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -9,11 +9,14 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; import com.moing.backend.domain.missionState.domain.entity.QMissionState; +import com.querydsl.core.types.ExpressionUtils; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; +import com.querydsl.core.Tuple; + import javax.persistence.EntityManager; @@ -28,6 +31,7 @@ import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; +import static com.querydsl.jpa.JPAExpressions.select; public class MissionCustomRepositoryImpl implements MissionCustomRepository{ @@ -140,6 +144,8 @@ public Optional> findRepeatMissionByStatus(MissionStatus missionSt @Override public Optional> findSingleMissionByMemberId(Long memberId, List teams) { + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherSingleMissionRes.class, mission.id, @@ -147,18 +153,19 @@ public Optional> findSingleMissionByMemberId(Long m mission.team.name, mission.title, mission.dueTo.stringValue(), - mission.status.stringValue() + mission.status.stringValue(), + mission.team.numOfMember.longValue() )) .from(mission) - .leftJoin(missionState).on( - mission.eq(missionState.mission), - missionState.member.memberId.eq(memberId) - ) + .leftJoin(missionArchive) + .on( + mission.eq(missionArchive.mission), + missionArchive.member.memberId.eq(memberId) + ) .where( mission.team.teamId.in(teams), mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), - mission.type.eq(MissionType.ONCE), - missionState.id.isNull() + mission.type.eq(MissionType.ONCE) ) .orderBy(mission.dueTo.asc()) .fetch()); @@ -220,8 +227,8 @@ private BooleanExpression createRepeatTypeConditionByState() { // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 // BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); - BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) - .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) + .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 return dateInRange.and(dateInRange); From 4085656f6ea01807b8840a53febaa2f8df36c835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 15 Apr 2024 00:10:13 +0900 Subject: [PATCH 552/619] =?UTF-8?q?feat=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98-=ED=95=9C=EB=B2=88/=EB=B0=98=EB=B3=B5?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=EC=9D=B8=EC=9B=90=20?= =?UTF-8?q?=ED=98=84=ED=99=A9=20=EA=B5=AC=ED=98=84=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/GatherRepeatMissionRes.java | 2 + .../MissionCustomRepositoryImpl.java | 61 +++++++++++++------ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java index 993fd70e..a0d91b61 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java @@ -16,6 +16,8 @@ public class GatherRepeatMissionRes { private String totalNum; private String doneNum; private String status; + private String donePeople; + private String totalPeople; } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 312791d8..d8e5da8a 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -7,15 +7,10 @@ import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -import com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive; -import com.moing.backend.domain.missionState.domain.entity.QMissionState; -import com.querydsl.core.types.ExpressionUtils; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.JPAExpressions; -import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; -import com.querydsl.core.Tuple; import javax.persistence.EntityManager; @@ -29,9 +24,7 @@ import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; -import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; -import static com.querydsl.jpa.JPAExpressions.select; public class MissionCustomRepositoryImpl implements MissionCustomRepository{ @@ -56,7 +49,8 @@ public Long findMissionsCountByTeam(Long teamId) { public Optional> findRepeatMissionByMemberId(Long memberId,Listteams) { - BooleanExpression dateInRange = createRepeatTypeConditionByState(); + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + BooleanExpression hasAlreadyVerifiedToday = hasAlreadyVerifiedToday(); return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherRepeatMissionRes.class, @@ -65,14 +59,26 @@ public Optional> findRepeatMissionByMemberId(Long m mission.team.name, mission.title, mission.number.stringValue(), - missionState.count().stringValue(), - mission.status.stringValue() + missionArchive.count().stringValue(), //고쳐야함 -> 내가 지금까지 한 + missionArchive.status.coalesce(mission.status).stringValue(), + + JPAExpressions + .select(missionArchive.member.count().stringValue()) + .from(missionArchive) + .where( + missionArchive.mission.id.eq(mission.id), + missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange).and(hasAlreadyVerifiedToday) + .or(missionArchive.mission.type.eq(MissionType.ONCE)) + ), + + mission.team.numOfMember.stringValue() )) .from(mission) - .leftJoin(missionState) - .on(missionState.mission.eq(mission), - missionState.member.memberId.eq(memberId), + .leftJoin(missionArchive) + .on(missionArchive.mission.eq(mission), + missionArchive.member.memberId.eq(memberId), +// hasAlreadyVerifiedToday, dateInRange ) .where( @@ -81,10 +87,11 @@ public Optional> findRepeatMissionByMemberId(Long m mission.type.eq(MissionType.REPEAT) ) - .groupBy(mission.id,mission.number) - .having(missionState.count().lt(mission.number) - ) // HAVING 절을 사용하여 조건 적용 - .orderBy(missionState.count().desc()) + .groupBy(mission) +// .groupBy(mission.id,mission.number) +// .having(missionArchive.count().lt(mission.number) +// ) // HAVING 절을 사용하여 조건 적용 + .orderBy(mission.createdDate.desc()) .fetch()); } @@ -153,7 +160,17 @@ public Optional> findSingleMissionByMemberId(Long m mission.team.name, mission.title, mission.dueTo.stringValue(), - mission.status.stringValue(), + missionArchive.status.coalesce(mission.status).stringValue(), + + JPAExpressions + .select(missionArchive.member.count().longValue()) + .from(missionArchive) + .where( + missionArchive.mission.id.eq(mission.id), + missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) + .or(missionArchive.mission.type.eq(MissionType.ONCE)) + ), + mission.team.numOfMember.longValue() )) .from(mission) @@ -234,6 +251,14 @@ private BooleanExpression createRepeatTypeConditionByState() { return dateInRange.and(dateInRange); } + private BooleanExpression hasAlreadyVerifiedToday() { + LocalDateTime today = LocalDateTime.now(); + LocalDateTime startOfToday = today.withHour(0).withMinute(0).withSecond(0).withNano(0); + LocalDateTime endOfToday = today.withHour(23).withMinute(59).withSecond(59).withNano(999999999); + + return missionArchive.createdDate.between(startOfToday, endOfToday); + } + } From 940f4f940ff8b5b9e5da373cc78237ac5b831c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 15 Apr 2024 09:04:19 +0900 Subject: [PATCH 553/619] =?UTF-8?q?feat=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=20=EB=AF=B8=EC=85=98=20=ED=95=9C=EB=B2=88/=EB=B0=98=EB=B3=B5?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=EC=9D=B8=EC=9B=90=20?= =?UTF-8?q?=ED=98=84=ED=99=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionCustomRepositoryImpl.java | 26 ++----------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index d8e5da8a..eb547844 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -48,7 +48,6 @@ public Long findMissionsCountByTeam(Long teamId) { @Override public Optional> findRepeatMissionByMemberId(Long memberId,Listteams) { - BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); BooleanExpression hasAlreadyVerifiedToday = hasAlreadyVerifiedToday(); @@ -59,7 +58,7 @@ public Optional> findRepeatMissionByMemberId(Long m mission.team.name, mission.title, mission.number.stringValue(), - missionArchive.count().stringValue(), //고쳐야함 -> 내가 지금까지 한 + missionArchive.count.max().coalesce(0L).stringValue(), missionArchive.status.coalesce(mission.status).stringValue(), JPAExpressions @@ -88,9 +87,6 @@ public Optional> findRepeatMissionByMemberId(Long m ) .groupBy(mission) -// .groupBy(mission.id,mission.number) -// .having(missionArchive.count().lt(mission.number) -// ) // HAVING 절을 사용하여 조건 적용 .orderBy(mission.createdDate.desc()) .fetch()); } @@ -227,29 +223,11 @@ private BooleanExpression createRepeatTypeConditionByArchive() { LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); LocalDate endOfWeek = startOfWeek.plusDays(6); - // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 -// BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); - BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) + return missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); - // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 - return dateInRange.and(dateInRange); } - private BooleanExpression createRepeatTypeConditionByState() { - LocalDate now = LocalDate.now(); - DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; - LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); - LocalDate endOfWeek = startOfWeek.plusDays(6); - - // MissionType.REPEAT 인 경우의 추가적인 날짜 범위 조건 -// BooleanExpression isRepeatType = missionArchive.mission.type.eq(MissionType.REPEAT); - BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) - .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); - - // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 - return dateInRange.and(dateInRange); - } private BooleanExpression hasAlreadyVerifiedToday() { LocalDateTime today = LocalDateTime.now(); From 837acbcfb8a1c08c4b83558a0932dbd91145a628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 15 Apr 2024 09:12:26 +0900 Subject: [PATCH 554/619] =?UTF-8?q?feat=20:=20=EB=82=98=EC=9D=98=20?= =?UTF-8?q?=EC=84=B1=EA=B3=B5=20=ED=9A=9F=EC=88=98=20=EB=A6=AC=ED=84=B4=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/constant/MissionArchiveResponseMessage.java | 1 + .../representation/MissionArchiveControllerTest.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java index 4be74d90..88ab1b4d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/constant/MissionArchiveResponseMessage.java @@ -14,6 +14,7 @@ public enum MissionArchiveResponseMessage { READ_TEAM_ARCHIVE_SUCCESS("팀원 미션 인증 현황 조회를 완료 했습니다."), HEART_UPDATE_SUCCESS("미션 인증 좋아요를 성공적으로 눌렀습니다."), MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS("미션 인증 성공한 인원 상태 조회를 완료 했습니다."), + MISSION_ARCHIVE_MY_STATUS_SUCCESS("미션 인증 성공한 나의 현황 조회를 완료 했습니다."), ACTIVE_SINGLE_MISSION_SUCCESS("진행 중인 모든 한번 인증 미션 조회를 완료 했습니다."), ACTIVE_REPEAT_MISSION_SUCCESS("진행 중인 모든 반복 인증 미션 조회를 완료 했습니다."), ACTIVE_TEAM_SINGLE_MISSION_SUCCESS("진행 중인 팀별 한번 인증 미션 조회를 완료 했습니다."), diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 97ea9614..181c1247 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -433,7 +433,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { ), responseFields( fieldWithPath("isSuccess").description("true"), - fieldWithPath("message").description(MISSION_ARCHIVE_PEOPLE_STATUS_SUCCESS.getMessage()), + fieldWithPath("message").description(MISSION_ARCHIVE_MY_STATUS_SUCCESS.getMessage()), fieldWithPath("data.total").description("전체 미션 참여자"), fieldWithPath("data.done").description("미션 인증 완료한 미션 참여자 ") From 3a152767abe360ef3ebfc147ff80626604f74985 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 16 Apr 2024 00:24:17 +0900 Subject: [PATCH 555/619] =?UTF-8?q?MNG-22=20fix=20:=20=ED=95=9C=EB=B2=88?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EB=B3=80=EA=B2=BD=EC=82=AC=ED=95=AD=20API?= =?UTF-8?q?=20=EB=AC=B8=EC=84=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionGatherControllerTest.java | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index eb414ec2..ae0b21c2 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -5,7 +5,6 @@ import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.application.dto.res.MyTeamsRes; -import com.moing.backend.domain.missionArchive.application.service.MissionArchiveReadUseCase; import com.moing.backend.domain.missionArchive.presentation.MissionGatherController; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; @@ -25,8 +24,6 @@ import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.payload.PayloadDocumentation.*; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; @WebMvcTest(MissionGatherController.class) public class MissionGatherControllerTest extends CommonControllerTest { @@ -45,7 +42,9 @@ public class MissionGatherControllerTest extends CommonControllerTest { .dueTo("2023-09-03T21:32:33.888") .teamName("team name") .missionTitle("mission title") - .status("WAIT/ONGOING/END/FAIL/SUCCESS") + .status("WAIT/ONGOING/SKIP/COMPLETE") + .done(0L) + .total(5L) .build()); given(missionGatherBoardUseCase.getAllActiveSingleMissions(any())).willReturn(output); @@ -75,7 +74,9 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].dueTo").description("미션 마감 시각"), fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목"), - fieldWithPath("data[].status").description("미션 상태") + fieldWithPath("data[].status").description("WAIT/ONGOING=인증하지 않음 SKIP/COMPLETE=인증 완료"), + fieldWithPath("data[].done").description("미션 인증 한 인원수"), + fieldWithPath("data[].total").description("팀 전체 인원수") ) ) @@ -95,7 +96,9 @@ public class MissionGatherControllerTest extends CommonControllerTest { .missionTitle("mission title") .doneNum("0") .totalNum("0") - .status("WAIT/ONGOING/END/FAIL/SUCCESS") + .status("WAIT/ONGOING/SKIP/COMPLETE") + .donePeople("0") + .totalPeople("0") .build()); given(missionGatherBoardUseCase.getAllActiveRepeatMissions(any())).willReturn(output); @@ -124,9 +127,11 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].teamId").description("팀 아이디"), fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목"), - fieldWithPath("data[].doneNum").description("완료한 횟수"), + fieldWithPath("data[].doneNum").description("내가 완료한 횟수"), fieldWithPath("data[].totalNum").description("전체 횟수"), - fieldWithPath("data[].status").description("미션 상태") + fieldWithPath("data[].status").description("미션 상태"), + fieldWithPath("data[].donePeople").description("미션 완료한 인원수"), + fieldWithPath("data[].totalPeople").description("팀 전체 인원수") ) @@ -146,7 +151,9 @@ public class MissionGatherControllerTest extends CommonControllerTest { .dueTo("2023-09-03T21:32:33.888") .teamName("team name") .missionTitle("mission title") - .status("WAIT/ONGOING/END/FAIL/SUCCESS") + .status("WAIT/ONGOING/SKIP/COMPLETE") + .done(0L) + .total(5L) .build()); given(missionGatherBoardUseCase.getTeamActiveSingleMissions(any(),any())).willReturn(output); @@ -177,7 +184,9 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].dueTo").description("미션 마감 시각"), fieldWithPath("data[].teamName").description("팀 이름"), fieldWithPath("data[].missionTitle").description("미션 제목"), - fieldWithPath("data[].status").description("미션 상태") + fieldWithPath("data[].status").description("WAIT/ONGOING=인증하지 않음 SKIP/COMPLETE=인증 완료"), + fieldWithPath("data[].done").description("미션 인증 한 인원수"), + fieldWithPath("data[].total").description("팀 전체 인원수") ) ) @@ -197,7 +206,9 @@ public class MissionGatherControllerTest extends CommonControllerTest { .missionTitle("mission title") .doneNum("0") .totalNum("0") - .status("WAIT/ONGOING/END/FAIL/SUCCESS") + .status("WAIT/ONGOING/SKIP/COMPLETE") + .donePeople("0") + .totalPeople("0") .build()); given(missionGatherBoardUseCase.getTeamActiveRepeatMissions(any(),any())).willReturn(output); @@ -229,7 +240,9 @@ public class MissionGatherControllerTest extends CommonControllerTest { fieldWithPath("data[].missionTitle").description("미션 제목"), fieldWithPath("data[].doneNum").description("완료한 횟수"), fieldWithPath("data[].totalNum").description("전체 횟수"), - fieldWithPath("data[].status").description("미션 상태") + fieldWithPath("data[].status").description("미션 상태"), + fieldWithPath("data[].donePeople").description("미션 완료한 인원수"), + fieldWithPath("data[].totalPeople").description("팀 전체 인원수") ) From 1a87c66f804e94dd44678aa31d9e675be1fd2c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:17:48 +0900 Subject: [PATCH 556/619] =?UTF-8?q?fix=20:=20=EB=AA=A8=EB=93=A0=20score=20?= =?UTF-8?q?=EA=B0=92=20100=20=EB=84=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamScore/application/service/TeamScoreGetUseCase.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java index a51f4026..16206b9c 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java @@ -30,13 +30,9 @@ public TeamScoreRes getTeamScoreInfo(Long teamId) { Long level = teamScore.getLevel(); Long score = teamScore.getScore(); - // 70 레벨 이상은 경험치 120 되어야 레벨업 가능. level을 각 레벨 별 필요한 경험치 수에 따르 퍼센트로 계산 - if (level > 70) { - score = ( score / 120 ) * 100; - } return TeamScoreRes.builder() - .score(score) + .score(score%100) .level(level) .build(); From 66dc5b7cefd892d0ce4e754df314426e586b6e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:17:48 +0900 Subject: [PATCH 557/619] =?UTF-8?q?fix=20:=20=EB=AA=A8=EB=93=A0=20score=20?= =?UTF-8?q?=EA=B0=92=20100=20=EB=84=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamScore/application/service/TeamScoreGetUseCase.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java index a51f4026..16206b9c 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java @@ -30,13 +30,9 @@ public TeamScoreRes getTeamScoreInfo(Long teamId) { Long level = teamScore.getLevel(); Long score = teamScore.getScore(); - // 70 레벨 이상은 경험치 120 되어야 레벨업 가능. level을 각 레벨 별 필요한 경험치 수에 따르 퍼센트로 계산 - if (level > 70) { - score = ( score / 120 ) * 100; - } return TeamScoreRes.builder() - .score(score) + .score(score%100) .level(level) .build(); From 59d82a77c4daef29eb09909ab4aa28bf8890f927 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 21 Apr 2024 13:03:06 +0900 Subject: [PATCH 558/619] fix : main merge comflict complete --- .../service/MissionArchiveCreateUseCase.java | 9 +-- .../service/MissionArchiveUpdateUseCase.java | 3 - .../service/MissionStateUseCase.java | 67 ------------------- .../MissionArchiveStateQueryService.java | 2 +- .../service/TeamScoreGetUseCase.java | 7 -- .../service/TeamScoreUpdateUseCase.java | 1 - 6 files changed, 2 insertions(+), 87 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 7f526c2a..618a02c7 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -13,7 +13,6 @@ import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; -import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; import com.moing.backend.domain.teamScore.domain.entity.ScoreStatus; @@ -33,8 +32,6 @@ public class MissionArchiveCreateUseCase { private final MissionQueryService missionQueryService; private final MemberGetService memberGetService; - private final MissionStateUseCase missionStateUseCase; - private final TeamScoreUpdateUseCase teamScoreUpdateUseCase; public MissionArchiveRes createArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { @@ -61,8 +58,6 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss } newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId) + 1); - missionStateUseCase.updateMissionState(member, mission, newArchive); - missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); } @@ -76,8 +71,6 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss } newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); - missionStateUseCase.updateMissionState(member, mission, newArchive); - missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); // 인증 후 n/n명 인증 성공 리턴값 업데이트 @@ -134,4 +127,4 @@ private boolean isAbleToFinishOnceMission(Mission mission) { } -} +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index 564f0f2c..aa6f97ba 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -13,7 +13,6 @@ import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; -import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; import com.moing.backend.domain.missionArchive.exception.NoAccessMissionArchiveException; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; @@ -34,8 +33,6 @@ public class MissionArchiveUpdateUseCase { private final MemberGetService memberGetService; - private final MissionStateUseCase missionStateUseCase; - // 미션 재인증 (수정하기도 포함됨) -> 사용하지 않음 public MissionArchiveRes updateArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java deleted file mode 100644 index 05b467df..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.moing.backend.domain.missionState.application.service; - -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionState.domain.service.MissionArchiveStateQueryService; -import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Slf4j -@Service -@Transactional -@RequiredArgsConstructor -public class MissionStateUseCase { - - // 미션 종료 직전인지 확인 - // missionId, missionstate num mission.team.personum - - private final MissionArchiveStateQueryService missionArchiveStateQueryService; - private final TeamScoreLogicUseCase teamScoreLogicUseCase; - - - /* - 모든 모임원이 미션을 완료했는지 여부 확인 - */ - public boolean isAbleToEnd(Mission mission) { - - Long total = totalPeople(mission); - Long done = donePeople(mission); - - return done > total; - - } - - public Long donePeople(Mission mission) { - return Long.valueOf(missionArchiveStateQueryService.stateCountByMissionId(mission.getId())); - } - - public Long totalPeople(Mission mission) { - return Long.valueOf(mission.getTeam().getNumOfMember()); - } - - public void updateMissionState(Member member, Mission mission, MissionArchive missionArchive) { - - MissionType missionType = mission.getType(); - Long missionId = mission.getId(); - -// missionStateSaveService.saveMissionState(member,mission, missionArchive.getStatus()); - - if (missionType == MissionType.ONCE) { - - if (isAbleToEnd(mission)) { - mission.updateStatus(MissionStatus.SUCCESS); - teamScoreLogicUseCase.updateTeamScore(missionId); - } - - } - - } - - -} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java index 3ff2eba4..e9fed1fa 100644 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java @@ -13,7 +13,7 @@ public class MissionArchiveStateQueryService { private final MissionArchiveRepository missionArchiveRepository; public int stateCountByMissionId(Long missionId) { - return missionArchiveRepository.getCountsByMissionId(missionId); + return missionArchiveRepository.getCountsByMissionId(missionId).intValue(); } diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java index a51f4026..df25b80c 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreGetUseCase.java @@ -1,16 +1,9 @@ package com.moing.backend.domain.teamScore.application.service; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; -import com.moing.backend.domain.team.domain.entity.Team; -import com.moing.backend.domain.team.domain.service.TeamGetService; -import com.moing.backend.domain.team.domain.service.TeamSaveService; import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; import com.moing.backend.domain.teamScore.domain.entity.TeamScore; import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; -import com.moing.backend.domain.teamScore.domain.service.TeamScoreSaveService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java index 04c88904..9b1c548a 100644 --- a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreUpdateUseCase.java @@ -73,5 +73,4 @@ public void gainScoreOfBonus(Mission mission) { - } From 8168c14ed9d04e568a7695e20678f8c2db1c0771 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 21 Apr 2024 16:20:03 +0900 Subject: [PATCH 559/619] =?UTF-8?q?MNG-22=20fix=20:=20=EB=B0=98=EB=B3=B5?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=ED=98=84=ED=99=A9=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/res/GatherRepeatMissionRes.java | 4 +- .../MissionCustomRepositoryImpl.java | 61 ++++++++++++++++--- .../MissionGatherControllerTest.java | 4 +- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java index a0d91b61..356418d4 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java @@ -4,6 +4,8 @@ import lombok.Builder; import lombok.Getter; +import java.util.List; + @Getter @Builder @AllArgsConstructor @@ -16,7 +18,7 @@ public class GatherRepeatMissionRes { private String totalNum; private String doneNum; private String status; - private String donePeople; + private Long donePeople; private String totalPeople; diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 982c4f99..b3e8918b 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -10,7 +10,9 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.NumberPath; import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; import javax.persistence.EntityManager; @@ -20,13 +22,12 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.time.temporal.TemporalAdjusters; -import java.util.List; -import java.util.Optional; +import java.util.*; -import static com.moing.backend.domain.mission.domain.entity.QMission.*; import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; +import static com.querydsl.jpa.JPAExpressions.select; public class MissionCustomRepositoryImpl implements MissionCustomRepository{ @@ -51,7 +52,6 @@ public Long findMissionsCountByTeam(Long teamId) { public Optional> findRepeatMissionByMemberId(Long memberId,Listteams) { BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); - BooleanExpression hasAlreadyVerifiedToday = hasAlreadyVerifiedToday(); return Optional.ofNullable(queryFactory .select(Projections.constructor(GatherRepeatMissionRes.class, @@ -64,12 +64,13 @@ public Optional> findRepeatMissionByMemberId(Long m missionArchive.status.coalesce(mission.status).stringValue(), JPAExpressions - .select(missionArchive.member.count().stringValue()) - .from(missionArchive) + .select(teamMember.member.countDistinct()) + .from(teamMember) .where( - missionArchive.mission.id.eq(mission.id), - missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange).and(hasAlreadyVerifiedToday) - .or(missionArchive.mission.type.eq(MissionType.ONCE)) + teamMember.team.eq(mission.team), + teamMember.member.memberId.in(allMissionDone(mission.id)) + .or(teamMember.member.memberId.in(todayRepeatMissionDone(mission.id))), + teamMember.isDeleted.ne(Boolean.TRUE) ), mission.team.numOfMember.stringValue() @@ -79,7 +80,6 @@ public Optional> findRepeatMissionByMemberId(Long m .leftJoin(missionArchive) .on(missionArchive.mission.eq(mission), missionArchive.member.memberId.eq(memberId), -// hasAlreadyVerifiedToday, dateInRange ) .where( @@ -93,6 +93,47 @@ public Optional> findRepeatMissionByMemberId(Long m .fetch()); } + private JPQLQuery todayRepeatMissionDone(NumberPath missionId) { + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + BooleanExpression hasAlreadyVerifiedToday = hasAlreadyVerifiedToday(); + + return + select(missionArchive.member.memberId) + .from(missionArchive, mission) + .where(missionArchive.mission.id.eq(missionId), + mission.id.eq(missionId), + (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange).and(hasAlreadyVerifiedToday)).or(missionArchive.mission.type.eq(MissionType.ONCE)) + ) + .groupBy(missionArchive.member.memberId, + missionArchive.mission.id, + missionArchive.count, + mission.number, + missionArchive.mission.type); +// .having( +//// missionArchive.mission.id.eq(missionId) +// ); + } + + private JPQLQuery allMissionDone(NumberPath missionId) { + + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); + + return + select(missionArchive.member.memberId) + .from(missionArchive, mission) + .where(missionArchive.mission.id.eq(missionId), + mission.id.eq(missionId), + (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) + ) + .groupBy(missionArchive.member.memberId, + missionArchive.mission.id, + missionArchive.count, + mission.number) + .having( + missionArchive.count.max().goe(mission.number) + ); + } + @Override public Optional> findMissionByDueTo() { diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index ae0b21c2..45ea728c 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -97,7 +97,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .doneNum("0") .totalNum("0") .status("WAIT/ONGOING/SKIP/COMPLETE") - .donePeople("0") + .donePeople(0L) .totalPeople("0") .build()); @@ -207,7 +207,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .doneNum("0") .totalNum("0") .status("WAIT/ONGOING/SKIP/COMPLETE") - .donePeople("0") + .donePeople(0L) .totalPeople("0") .build()); From e9380df2efbf17b65ed30cc9dcddcfb5ca1087c9 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 21 Apr 2024 17:13:24 +0900 Subject: [PATCH 560/619] =?UTF-8?q?MNG-21=20feat=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EC=9D=B8=EC=A6=9D=20=EB=AC=B8=EA=B5=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/req/MissionArchiveReq.java | 7 ++++- .../dto/res/MissionArchiveRes.java | 1 + .../dto/res/PersonalArchiveRes.java | 5 ++++ .../mapper/MissionArchiveMapper.java | 4 ++- .../domain/entity/MissionArchive.java | 4 ++- .../MissionArchiveControllerTest.java | 29 ++++++++++++++----- 6 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java index a973aa29..bba83666 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java @@ -2,6 +2,7 @@ import lombok.*; +import javax.annotation.Nullable; import javax.validation.constraints.Size; @Builder @@ -10,12 +11,16 @@ public class MissionArchiveReq { private String status; + @Size(min = 1, max = 1000) private String archive; //사진일 경우 파일명, 이외에는 text,link + private String contents; + @Builder - public MissionArchiveReq(String status, String archive) { + public MissionArchiveReq(String status, String archive, String contents) { this.status = status; this.archive = archive; + this.contents = contents; } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index 10b73af9..a0d5e88f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -18,6 +18,7 @@ public class MissionArchiveRes { private Long count; private String heartStatus; private Long hearts; + private String contents; public void updateCount(Long count) { this.count = count; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java index 47df8949..2d50538d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java @@ -2,6 +2,8 @@ import lombok.*; +import javax.annotation.Nullable; + @AllArgsConstructor @Builder @NoArgsConstructor @@ -24,5 +26,8 @@ public class PersonalArchiveRes { private Long makerId; + @Nullable + private String contents; + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index deac83d6..b84fe771 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -2,7 +2,6 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; -import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; @@ -29,6 +28,7 @@ public static MissionArchive mapToMissionArchive(MissionArchiveReq missionArchiv .member(member) .mission(mission) .heartList(new ArrayList<>()) + .contents(missionArchiveReq.getContents()) .build(); } @@ -50,6 +50,7 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc .filter(heart -> heart.getHeartStatus() == ( MissionHeartStatus.True)) .filter(heart -> heart.getMissionArchive().equals( missionArchive))// heartStatus가 true인 요소만 필터링 .count()) + .contents(missionArchive.getContents()) .build(); } @@ -84,6 +85,7 @@ public static PersonalArchiveRes mapToPersonalArchive(MissionArchive missionArch .filter(heart -> heart.getMissionArchive().equals( missionArchive))// heartStatus가 true인 요소만 필터링 .count()) .makerId(missionArchive.getMember().getMemberId()) + .contents(missionArchive.getContents()) .build(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index 9cc2a7bf..90826b52 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -39,12 +39,14 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 @Enumerated(value = EnumType.STRING) private MissionArchiveStatus status; - @Column(nullable = false, columnDefinition="TEXT", length = 4000) private String archive; //링크, 글, 사진 뭐든 가능 private Long count; // 횟수 + @Column(nullable = true, columnDefinition="TEXT", length = 1000) + private String contents; + @OneToMany(mappedBy = "missionArchive", cascade = CascadeType.REMOVE) private List heartList = new ArrayList<>(); diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 97ea9614..8b8fa697 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -1,7 +1,6 @@ package com.moing.backend.domain.missionArchive.representation; import com.moing.backend.config.CommonControllerTest; -import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveHeartReq; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionArchive.application.dto.res.*; import com.moing.backend.domain.missionArchive.application.service.*; @@ -65,6 +64,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .count(1L) .heartStatus("[True/False]") .hearts(1L) + .contents("contents") .build(); given(missionArchiveCreateUseCase.createArchive(any(),any(),any())).willReturn(output); @@ -93,7 +93,10 @@ public class MissionArchiveControllerTest extends CommonControllerTest { ), requestFields( fieldWithPath("status").description("미션 인증 상태 [COMPLETE/SKIP]"), - fieldWithPath("archive").description("미션 인증물 [s3URL/text/링크] ") + fieldWithPath("archive").description("미션 인증물 [s3URL/text/링크] "), + fieldWithPath("contents").description("미션 인증 문구 [null 허용] ") + + ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -105,7 +108,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.status").description("미션 인증 상태"), fieldWithPath("data.count").description("미션 인증 횟수"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태") + fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태"), + fieldWithPath("data.contents").description("미션 인증 문구") ) ) ) @@ -132,6 +136,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .count(1L) .heartStatus("[True/False]") .hearts(1L) + .contents("contents") .build(); given(missionArchiveUpdateUseCase.updateArchive(any(),any(),any())).willReturn(output); @@ -160,7 +165,9 @@ public class MissionArchiveControllerTest extends CommonControllerTest { ), requestFields( fieldWithPath("status").description("미션 인증 상태 [COMPLETE/SKIP]"), - fieldWithPath("archive").description("미션 인증물 [s3URL/text/링크] ") + fieldWithPath("archive").description("미션 인증물 [s3URL/text/링크] "), + fieldWithPath("contents").description("미션 인증 문구 [null 허용] ") + ), responseFields( fieldWithPath("isSuccess").description("true"), @@ -173,7 +180,9 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.status").description("미션 인증 상태"), fieldWithPath("data.count").description("미션 인증 횟수"), fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태"), - fieldWithPath("data.hearts").description("미션 인증 좋아요 수") + fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), + fieldWithPath("data.contents").description("미션 인증 문구") + ) ) ) @@ -236,6 +245,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .count(1L) .heartStatus("[True/False]") .hearts(1L) + .contents("contents") .build()); MyMissionArchiveRes output = MyMissionArchiveRes.builder() @@ -278,7 +288,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.archives[].status").description("미션 인증 상태"), fieldWithPath("data.archives[].count").description("미션 인증 횟수"), fieldWithPath("data.archives[].heartStatus").description("미션 인증 좋아요 상태"), - fieldWithPath("data.archives[].hearts").description("미션 인증 좋아요 수") + fieldWithPath("data.archives[].hearts").description("미션 인증 좋아요 수"), + fieldWithPath("data.archives[].contents").description("미션 인증 문구") ) @@ -304,6 +315,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .heartStatus("[True/False]") .hearts(3) .makerId(1L) + .contents("contents") .build()); given(missionArchiveReadUseCase.getPersonalArchive(any(),any())).willReturn(output); @@ -343,10 +355,11 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data[].count").description("미션 인증 횟수"), fieldWithPath("data[].heartStatus").description("미션 인증 좋아요 상태 "), fieldWithPath("data[].hearts").description("미션 인증 좋아요 수 "), - fieldWithPath("data[].makerId").description("미션 인증한 사람 ") + fieldWithPath("data[].makerId").description("미션 인증한 사람 "), + fieldWithPath("data[].contents").description("미션 인증 문구") - ) + ) ) ) .andReturn(); From 74e669463d15a4dcd5df6adecd9b5dfdca7a4b47 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 21 Apr 2024 20:51:15 +0900 Subject: [PATCH 561/619] =?UTF-8?q?MNG-21=20feat=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EC=9D=B8=EC=A6=9D=20=EB=AC=B8=EA=B5=AC=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20API=20=EB=AC=B8=EC=84=9C=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../representation/MissionArchiveControllerTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 8b8fa697..14a05e86 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -51,6 +51,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { MissionArchiveReq input = MissionArchiveReq.builder() .status("COMPLETE/SKIP") .archive("content[s3 Link / text / link]") + .contents("contents") .build(); String body = objectMapper.writeValueAsString(input); @@ -123,6 +124,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { MissionArchiveReq input = MissionArchiveReq.builder() .status("COMPLETE/SKIP") .archive("content[s3 Link / text / link]") + .contents("contents") .build(); String body = objectMapper.writeValueAsString(input); From 95dbf8b892562dae0f1078016c4e1542448a0a3c Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Wed, 24 Apr 2024 21:52:14 +0900 Subject: [PATCH 562/619] =?UTF-8?q?MNG-22=20fix=20:=20Mission=20Entity=20?= =?UTF-8?q?=EC=97=90=EC=84=9C=20MissionState=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moing/backend/domain/mission/domain/entity/Mission.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index c609fdff..d5d6c80f 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -6,7 +6,6 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionRead.domain.entity.MissionRead; -import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; @@ -56,9 +55,6 @@ public class Mission extends BaseTimeEntity { @OneToMany(mappedBy = "mission") List missionArchiveList = new ArrayList<>(); - - @OneToMany(mappedBy = "mission") - List missionStateList = new ArrayList<>(); @OneToMany(mappedBy = "mission") List missionReads=new ArrayList<>(); From baccb8399b162be502544dd5a765cdd9201d7549 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Wed, 24 Apr 2024 21:52:36 +0900 Subject: [PATCH 563/619] =?UTF-8?q?MNG-22=20fix=20:=20MissionState=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionArchiveCustomRepositoryImpl.java | 30 +++++++++---------- .../service/ReportCreateUseCase.java | 1 - 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 9e016dfe..b222e0f2 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -37,7 +37,7 @@ import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; -import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; +//import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; @Slf4j @@ -68,13 +68,13 @@ public Optional> findSingleMissionInComplete(Long me .from(mission) .where(mission.notIn (JPAExpressions - .select(missionState.mission) - .from(missionState) - .where(missionState.member.memberId.eq(memberId), - missionState.mission.team.teamId.eq(teamId), - missionState.mission.type.eq(MissionType.ONCE), - missionState.mission.status.eq(MissionStatus.SUCCESS) - .or(missionState.mission.status.eq(MissionStatus.ONGOING)) + .select(missionArchive.mission) + .from(missionArchive) + .where(missionArchive.member.memberId.eq(memberId), + missionArchive.mission.team.teamId.eq(teamId), + missionArchive.mission.type.eq(MissionType.ONCE), + missionArchive.mission.status.eq(MissionStatus.SUCCESS) + .or(missionArchive.mission.status.eq(MissionStatus.ONGOING)) )), mission.type.eq(MissionType.ONCE), mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), @@ -269,16 +269,16 @@ public Optional> findRepeatMissionArchivesByMemberId mission.id, mission.title, // missionState.count().coalesce(0L).as("done"), - missionState.count(), + missionArchive.count(), mission.number, mission.way.stringValue(), mission.status.stringValue(), isReadExpression.as("isRead") )) .from(mission) - .leftJoin(missionState) - .on(missionState.mission.eq(mission), - missionState.member.memberId.eq(memberId), + .leftJoin(missionArchive) + .on(missionArchive.mission.eq(mission), + missionArchive.member.memberId.eq(memberId), dateInRange ) .where( @@ -288,7 +288,7 @@ public Optional> findRepeatMissionArchivesByMemberId ) .groupBy(mission.id,mission.number) // .having(missionState.count().lt(mission.number)) // HAVING 절을 사용하여 조건 적용 - .orderBy(missionState.count().desc()) + .orderBy(missionArchive.count().desc()) .fetch()); } @@ -401,8 +401,8 @@ private BooleanExpression createRepeatTypeConditionByState() { LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); LocalDate endOfWeek = startOfWeek.plusDays(6); - BooleanExpression dateInRange = missionState.createdDate.goe(startOfWeek.atStartOfDay()) - .and(missionState.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); + BooleanExpression dateInRange = missionArchive.createdDate.goe(startOfWeek.atStartOfDay()) + .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1))); // 조건이 MissionType.REPEAT 인 경우에만 날짜 범위 조건 적용 return dateInRange.and(dateInRange); diff --git a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java index 999140b9..704cc979 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java @@ -13,7 +13,6 @@ import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; -import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.report.application.mapper.ReportMapper; import com.moing.backend.domain.report.domain.entity.Report; import com.moing.backend.domain.report.domain.entity.constant.ReportType; From aef1816d5418157b5e27c3dfe95e9ff9621ea2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:12:34 +0900 Subject: [PATCH 564/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=83=9D=EC=84=B1=20=EA=B0=9C=EC=88=98=20?= =?UTF-8?q?=EC=A0=9C=ED=95=9C=20=EC=97=90=EB=9F=AC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionCreateUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java index 4f2d2a33..c4d223ec 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCreateUseCase.java @@ -49,7 +49,7 @@ public MissionCreateRes createMission(String socialId, Long teamId, MissionReq m throw new NoAccessCreateMission(); // 반복미션은 최대 2개 생성 가능 } else if (missionQueryService.isAbleCreateRepeatMission(team.getTeamId())) { - throw new NoAccessCreateMission(); + throw new NoMoreCreateMission(); } // 반복미션 유예 해제 mission.updateStatus(MissionStatus.ONGOING); From 642178a9374076a3a26e579bb3f8e0d51c943ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:13:09 +0900 Subject: [PATCH 565/619] =?UTF-8?q?fix=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=EB=AF=B8=EC=85=98-=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=ED=95=9C=EC=9D=B8=EC=9B=90+=EC=98=A4?= =?UTF-8?q?=EB=8A=98=20=EC=9D=B8=EC=A6=9D=ED=95=9C=20=EC=9D=B8=EC=9B=90=20?= =?UTF-8?q?count=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MissionCustomRepositoryImpl.java | 49 +++++++------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index b3e8918b..dbdeca8a 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -68,8 +68,8 @@ public Optional> findRepeatMissionByMemberId(Long m .from(teamMember) .where( teamMember.team.eq(mission.team), - teamMember.member.memberId.in(allMissionDone(mission.id)) - .or(teamMember.member.memberId.in(todayRepeatMissionDone(mission.id))), + teamMember.member.memberId.in(RepeatMissionDonePeopleByWeek(mission.id)) + .or(teamMember.member.memberId.in(RepeatMissionDonePeopleByDay(mission.id))), teamMember.isDeleted.ne(Boolean.TRUE) ), @@ -93,45 +93,34 @@ public Optional> findRepeatMissionByMemberId(Long m .fetch()); } - private JPQLQuery todayRepeatMissionDone(NumberPath missionId) { + private JPQLQuery RepeatMissionDonePeopleByDay(NumberPath missionId) { + BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); BooleanExpression hasAlreadyVerifiedToday = hasAlreadyVerifiedToday(); return select(missionArchive.member.memberId) .from(missionArchive, mission) - .where(missionArchive.mission.id.eq(missionId), - mission.id.eq(missionId), - (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange).and(hasAlreadyVerifiedToday)).or(missionArchive.mission.type.eq(MissionType.ONCE)) - ) - .groupBy(missionArchive.member.memberId, - missionArchive.mission.id, - missionArchive.count, - mission.number, - missionArchive.mission.type); -// .having( -//// missionArchive.mission.id.eq(missionId) -// ); + .where( + missionArchive.mission.id.eq(missionId), + (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange).and(hasAlreadyVerifiedToday)) + ).distinct(); } - private JPQLQuery allMissionDone(NumberPath missionId) { + private JPQLQuery RepeatMissionDonePeopleByWeek(NumberPath missionId) { BooleanExpression dateInRange = createRepeatTypeConditionByArchive(); - return - select(missionArchive.member.memberId) - .from(missionArchive, mission) - .where(missionArchive.mission.id.eq(missionId), - mission.id.eq(missionId), - (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)).or(missionArchive.mission.type.eq(MissionType.ONCE)) - ) - .groupBy(missionArchive.member.memberId, - missionArchive.mission.id, - missionArchive.count, - mission.number) - .having( - missionArchive.count.max().goe(mission.number) - ); + return select(missionArchive.member.memberId) + .from(missionArchive) + .where( + missionArchive.mission.id.eq(missionId), + (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)) + ) + .groupBy(missionArchive.mission.number, missionArchive.count) + .having(missionArchive.count.max().goe(missionArchive.mission.number)) + .distinct(); + } From 4f6eb73e506677d2b207cb10c131cdeb8148d4cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:26:35 +0900 Subject: [PATCH 566/619] =?UTF-8?q?fix=20:=20=EC=A7=84=ED=96=89=EC=A4=91?= =?UTF-8?q?=EB=AF=B8=EC=85=98-=EB=B0=98=EB=B3=B5=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=ED=95=9C=EC=9D=B8=EC=9B=90+=EC=98=A4?= =?UTF-8?q?=EB=8A=98=20=EC=9D=B8=EC=A6=9D=ED=95=9C=20=EC=9D=B8=EC=9B=90=20?= =?UTF-8?q?count=20=EB=A6=AC=ED=84=B4=20=EA=B0=92=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/dto/res/GatherRepeatMissionRes.java | 2 +- .../domain/repository/MissionCustomRepositoryImpl.java | 2 +- .../representation/MissionGatherControllerTest.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java index 356418d4..1859d7d1 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherRepeatMissionRes.java @@ -18,7 +18,7 @@ public class GatherRepeatMissionRes { private String totalNum; private String doneNum; private String status; - private Long donePeople; + private String donePeople; private String totalPeople; diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index dbdeca8a..c1011cda 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -64,7 +64,7 @@ public Optional> findRepeatMissionByMemberId(Long m missionArchive.status.coalesce(mission.status).stringValue(), JPAExpressions - .select(teamMember.member.countDistinct()) + .select(teamMember.member.countDistinct().stringValue()) .from(teamMember) .where( teamMember.team.eq(mission.team), diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index 45ea728c..ae0b21c2 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -97,7 +97,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .doneNum("0") .totalNum("0") .status("WAIT/ONGOING/SKIP/COMPLETE") - .donePeople(0L) + .donePeople("0") .totalPeople("0") .build()); @@ -207,7 +207,7 @@ public class MissionGatherControllerTest extends CommonControllerTest { .doneNum("0") .totalNum("0") .status("WAIT/ONGOING/SKIP/COMPLETE") - .donePeople(0L) + .donePeople("0") .totalPeople("0") .build()); From 4f26f849f95a8c28302408d89624f3169a231d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 29 Apr 2024 18:02:15 +0900 Subject: [PATCH 567/619] =?UTF-8?q?fix=20:=20MissionState=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MissionArchiveRepository.java | 3 +- .../NoAccessMissionArchiveException.java | 3 +- .../application/dto/MissionStatusRes.java | 8 --- .../service/MissionStateScheduleUseCase.java | 58 ------------------- .../domain/entity/MissionState.java | 34 ----------- .../missionState/domain/entity/Status.java | 5 -- .../MissionArchiveStateCustomRepository.java | 18 ------ ...ssionArchiveStateCustomRepositoryImpl.java | 50 ---------------- .../MissionArchiveStateQueryService.java | 21 ------- .../exception/MissionStateException.java | 11 ---- .../NotFoundMissionStateException.java | 11 ---- 11 files changed, 2 insertions(+), 220 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/missionState/application/dto/MissionStatusRes.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepository.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepositoryImpl.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/exception/MissionStateException.java delete mode 100644 src/main/java/com/moing/backend/domain/missionState/exception/NotFoundMissionStateException.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java index 2c88d112..7d9726a6 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveRepository.java @@ -5,7 +5,6 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.domain.missionState.domain.repository.MissionArchiveStateCustomRepository; import com.querydsl.core.Tuple; import feign.Param; import org.hibernate.annotations.NamedNativeQuery; @@ -22,7 +21,7 @@ import java.util.Optional; @Repository -public interface MissionArchiveRepository extends JpaRepository,MissionArchiveCustomRepository , MissionArchiveStateCustomRepository { +public interface MissionArchiveRepository extends JpaRepository,MissionArchiveCustomRepository { @Query("select m from MissionArchive as m where m.member =:memberId" ) Optional> findByMemberId(@Param("memberId") Long memberId); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/exception/NoAccessMissionArchiveException.java b/src/main/java/com/moing/backend/domain/missionArchive/exception/NoAccessMissionArchiveException.java index 6ce6ada1..8bb4402e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/exception/NoAccessMissionArchiveException.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/exception/NoAccessMissionArchiveException.java @@ -1,10 +1,9 @@ package com.moing.backend.domain.missionArchive.exception; -import com.moing.backend.domain.missionState.exception.MissionStateException; import com.moing.backend.global.response.ErrorCode; import org.springframework.http.HttpStatus; -public class NoAccessMissionArchiveException extends MissionStateException { +public class NoAccessMissionArchiveException extends MissionArchiveException { public NoAccessMissionArchiveException() { super(ErrorCode.NO_MORE_ARCHIVE_ERROR, HttpStatus.NOT_FOUND); diff --git a/src/main/java/com/moing/backend/domain/missionState/application/dto/MissionStatusRes.java b/src/main/java/com/moing/backend/domain/missionState/application/dto/MissionStatusRes.java deleted file mode 100644 index 0e12354f..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/application/dto/MissionStatusRes.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.moing.backend.domain.missionState.application.dto; - -public class MissionStatusRes { - - private Long done; - private Long total; - -} diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java deleted file mode 100644 index 2562c902..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateScheduleUseCase.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.moing.backend.domain.missionState.application.service; - -import com.moing.backend.domain.mission.application.service.MissionRemindAlarmUseCase; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Profile; -import org.springframework.scheduling.annotation.EnableAsync; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -@Slf4j -@Service -@Transactional -@EnableAsync -@EnableScheduling // 스케줄링 활성화 -@RequiredArgsConstructor -@Profile("prod") -public class MissionStateScheduleUseCase { - - private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; - private final MissionQueryService missionQueryService; - - /** - * 단일 미션 마감 - * 해당 시간 미션 마감 - * 한시간 마다 실행 - */ - @Scheduled(cron = "0 1 * * * *") - public void singleMissionEndRoutine() { - - List missionByDueTo = missionQueryService.findMissionByDueTo(); - - for (Mission mission : missionByDueTo) { - mission.updateStatus(MissionStatus.END); - } - - } - - - @Scheduled(cron = "0 0 20 * * *") - public void MissionRemindAlarm() { - missionRemindAlarmUseCase.sendRemindMissionAlarm(); - } - - -// @Scheduled(cron = "0 0 17 * * *") -// public void UpdatePushAlarm() { -// updateRemindAlarmUseCase.sendUpdateAppPushAlarm(); -// } - -} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java deleted file mode 100644 index 22a550b8..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.moing.backend.domain.missionState.domain.entity; - -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.global.entity.BaseTimeEntity; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.persistence.*; - -@Entity -@NoArgsConstructor -@AllArgsConstructor -@Getter -@Builder -public class MissionState extends BaseTimeEntity { - - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "missionState_id") - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private Mission mission; - @OneToOne - private Member member; - - @Enumerated(value = EnumType.STRING) - private MissionArchiveStatus status; - -} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java b/src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java deleted file mode 100644 index 56f082a8..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.moing.backend.domain.missionState.domain.entity; - -public enum Status { - SUCCESS,FAIL -} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepository.java deleted file mode 100644 index 1fabc051..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepository.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.moing.backend.domain.missionState.domain.repository; - -import com.moing.backend.domain.member.domain.entity.Member; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionState.domain.entity.MissionState; -import org.springframework.stereotype.Repository; - -import java.util.List; -import java.util.Optional; - -@Repository -public interface MissionArchiveStateCustomRepository { - - Long getCountsByMissionId(Long missionId) ; - - -} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepositoryImpl.java deleted file mode 100644 index a823a1ae..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionArchiveStateCustomRepositoryImpl.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.moing.backend.domain.missionState.domain.repository; - -import com.moing.backend.domain.mission.domain.entity.constant.MissionType; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.jpa.impl.JPAQueryFactory; - -import javax.persistence.EntityManager; -import java.time.DayOfWeek; -import java.time.LocalDate; -import java.time.temporal.TemporalAdjusters; - -import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.missionArchive; - -public class MissionArchiveStateCustomRepositoryImpl implements MissionArchiveStateCustomRepository { - - private final JPAQueryFactory queryFactory; - - public MissionArchiveStateCustomRepositoryImpl(EntityManager entityManager) { - this.queryFactory = new JPAQueryFactory(entityManager); - } - - - @Override - public Long getCountsByMissionId(Long missionId) { - - LocalDate now = LocalDate.now(); - DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY; // 한 주의 시작일을 월요일로 설정 - LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); - LocalDate endOfWeek = startOfWeek.plusDays(6); // 한 주의 마지막일을 일요일로 설정 - - BooleanExpression repeatTypeCondition = (missionArchive.mission.type.eq(MissionType.REPEAT) - .and(missionArchive.createdDate.goe(startOfWeek.atStartOfDay())) - .and(missionArchive.createdDate.loe(endOfWeek.atStartOfDay().plusDays(1).minusNanos(1)))).or(missionArchive.mission.type.eq(MissionType.ONCE)); - - // 기본 조건 - BooleanExpression baseCondition = missionArchive.mission.id.eq(missionId); - // 조건 적용 - BooleanExpression finalCondition = baseCondition.and(repeatTypeCondition); - - - return (long) queryFactory - .select(missionArchive) - .from(missionArchive) - .where(finalCondition) - .fetch().size(); - } - - - -} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java deleted file mode 100644 index e9fed1fa..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionArchiveStateQueryService.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.moing.backend.domain.missionState.domain.service; - -import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; -import com.moing.backend.global.annotation.DomainService; -import lombok.RequiredArgsConstructor; -import javax.transaction.Transactional; - -@DomainService -@Transactional -@RequiredArgsConstructor -public class MissionArchiveStateQueryService { - - private final MissionArchiveRepository missionArchiveRepository; - - public int stateCountByMissionId(Long missionId) { - return missionArchiveRepository.getCountsByMissionId(missionId).intValue(); - } - - - -} diff --git a/src/main/java/com/moing/backend/domain/missionState/exception/MissionStateException.java b/src/main/java/com/moing/backend/domain/missionState/exception/MissionStateException.java deleted file mode 100644 index 54c72e46..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/exception/MissionStateException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.moing.backend.domain.missionState.exception; - -import com.moing.backend.global.exception.ApplicationException; -import com.moing.backend.global.response.ErrorCode; -import org.springframework.http.HttpStatus; - -public abstract class MissionStateException extends ApplicationException { - protected MissionStateException(ErrorCode errorCode, HttpStatus httpStatus) { - super(errorCode, httpStatus); - } -} diff --git a/src/main/java/com/moing/backend/domain/missionState/exception/NotFoundMissionStateException.java b/src/main/java/com/moing/backend/domain/missionState/exception/NotFoundMissionStateException.java deleted file mode 100644 index 2baae393..00000000 --- a/src/main/java/com/moing/backend/domain/missionState/exception/NotFoundMissionStateException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.moing.backend.domain.missionState.exception; - -import com.moing.backend.global.response.ErrorCode; -import org.springframework.http.HttpStatus; - -public class NotFoundMissionStateException extends MissionStateException{ - public NotFoundMissionStateException() { - super(ErrorCode.NOT_FOUND_END_MISSION, HttpStatus.NOT_FOUND); - - } -} From 208f7394344640602ab1562fbc31096cbfce17fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 6 May 2024 21:23:51 +0900 Subject: [PATCH 568/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=9D=B8=EC=9B=90=EC=88=98=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionCustomRepositoryImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index c1011cda..606f5ed3 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -100,7 +100,7 @@ private JPQLQuery RepeatMissionDonePeopleByDay(NumberPath missionId) return select(missionArchive.member.memberId) - .from(missionArchive, mission) + .from(missionArchive) .where( missionArchive.mission.id.eq(missionId), (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange).and(hasAlreadyVerifiedToday)) @@ -118,7 +118,8 @@ private JPQLQuery RepeatMissionDonePeopleByWeek(NumberPath missionId (missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange)) ) .groupBy(missionArchive.mission.number, missionArchive.count) - .having(missionArchive.count.max().goe(missionArchive.mission.number)) + .having( + missionArchive.count.max().goe(missionArchive.mission.number)) .distinct(); } From 02c7527c4ad310cb84f1e4f1631f2deed6c97a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 6 May 2024 23:41:45 +0900 Subject: [PATCH 569/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=9D=B8=EC=9B=90=EC=88=98=20=EB=A6=AC=ED=84=B4=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/GatherSingleMissionRes.java | 6 +++--- .../domain/repository/MissionCustomRepositoryImpl.java | 2 +- .../representation/MissionGatherControllerTest.java | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java index 718a4b87..27b6a46e 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/GatherSingleMissionRes.java @@ -16,10 +16,10 @@ public class GatherSingleMissionRes { private String missionTitle; private String dueTo; private String status; - private Long done; - private Long total; + private String done; + private String total; - public GatherSingleMissionRes(Long missionId, Long teamId, String teamName, String missionTitle, String dueTo, String status, Long total) { + public GatherSingleMissionRes(Long missionId, Long teamId, String teamName, String missionTitle, String dueTo, String status, String total) { this.missionId = missionId; this.teamId = teamId; this.teamName = teamName; diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 606f5ed3..8dc96cd1 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -192,7 +192,7 @@ public Optional> findSingleMissionByMemberId(Long m missionArchive.status.coalesce(mission.status).stringValue(), JPAExpressions - .select(missionArchive.member.count().longValue()) + .select(missionArchive.member.count().stringValue()) .from(missionArchive) .where( missionArchive.mission.id.eq(mission.id), diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java index ae0b21c2..93ff8e5d 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionGatherControllerTest.java @@ -43,8 +43,8 @@ public class MissionGatherControllerTest extends CommonControllerTest { .teamName("team name") .missionTitle("mission title") .status("WAIT/ONGOING/SKIP/COMPLETE") - .done(0L) - .total(5L) + .done("0") + .total("5") .build()); given(missionGatherBoardUseCase.getAllActiveSingleMissions(any())).willReturn(output); @@ -152,8 +152,8 @@ public class MissionGatherControllerTest extends CommonControllerTest { .teamName("team name") .missionTitle("mission title") .status("WAIT/ONGOING/SKIP/COMPLETE") - .done(0L) - .total(5L) + .done("0") + .total("5") .build()); given(missionGatherBoardUseCase.getTeamActiveSingleMissions(any(),any())).willReturn(output); From fe4e18fac94b4fa02999103bb077504b3beb0384 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 7 May 2024 01:08:23 +0900 Subject: [PATCH 570/619] =?UTF-8?q?MNG-20=20feat:=20BoardComment,=20Missio?= =?UTF-8?q?nComment=20=EA=B3=B5=ED=86=B5=20=EB=B6=80=EB=B6=84=20=EB=B9=BC?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/CreateCommentRequest.java} | 4 ++-- .../dto/response/CommentBlocks.java | 8 +++---- .../dto/response/CreateCommentResponse.java} | 6 ++--- .../dto/response/GetCommentResponse.java} | 4 ++-- .../domain/comment/domain/entity/Comment.java | 24 +++++++++++++++++++ .../domain/service/CommentDeleteService.java | 5 ++++ .../domain/service/CommentGetService.java | 14 +++++++++++ .../domain/service/CommentSaveService.java | 5 ++++ 8 files changed, 59 insertions(+), 11 deletions(-) rename src/main/java/com/moing/backend/domain/{boardComment/application/dto/request/CreateBoardCommentRequest.java => comment/application/dto/request/CreateCommentRequest.java} (79%) rename src/main/java/com/moing/backend/domain/{boardComment => comment}/application/dto/response/CommentBlocks.java (78%) rename src/main/java/com/moing/backend/domain/{boardComment/application/dto/response/CreateBoardCommentResponse.java => comment/application/dto/response/CreateCommentResponse.java} (53%) rename src/main/java/com/moing/backend/domain/{boardComment/application/dto/response/GetBoardCommentResponse.java => comment/application/dto/response/GetCommentResponse.java} (68%) create mode 100644 src/main/java/com/moing/backend/domain/comment/domain/entity/Comment.java create mode 100644 src/main/java/com/moing/backend/domain/comment/domain/service/CommentDeleteService.java create mode 100644 src/main/java/com/moing/backend/domain/comment/domain/service/CommentGetService.java create mode 100644 src/main/java/com/moing/backend/domain/comment/domain/service/CommentSaveService.java diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java b/src/main/java/com/moing/backend/domain/comment/application/dto/request/CreateCommentRequest.java similarity index 79% rename from src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java rename to src/main/java/com/moing/backend/domain/comment/application/dto/request/CreateCommentRequest.java index 9cc0841d..84d79633 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/request/CreateBoardCommentRequest.java +++ b/src/main/java/com/moing/backend/domain/comment/application/dto/request/CreateCommentRequest.java @@ -1,4 +1,4 @@ -package com.moing.backend.domain.boardComment.application.dto.request; +package com.moing.backend.domain.comment.application.dto.request; import lombok.AllArgsConstructor; import lombok.Builder; @@ -12,7 +12,7 @@ @Builder @NoArgsConstructor @Getter -public class CreateBoardCommentRequest { +public class CreateCommentRequest { @NotBlank(message = "content 을 입력해 주세요.") @Size(min = 0, max = 300, message = "댓글 글자수를 초과했습니다.") diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java b/src/main/java/com/moing/backend/domain/comment/application/dto/response/CommentBlocks.java similarity index 78% rename from src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java rename to src/main/java/com/moing/backend/domain/comment/application/dto/response/CommentBlocks.java index af02defe..40164051 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CommentBlocks.java +++ b/src/main/java/com/moing/backend/domain/comment/application/dto/response/CommentBlocks.java @@ -1,4 +1,4 @@ -package com.moing.backend.domain.boardComment.application.dto.response; +package com.moing.backend.domain.comment.application.dto.response; import com.querydsl.core.annotations.QueryProjection; import lombok.AllArgsConstructor; @@ -13,7 +13,7 @@ @AllArgsConstructor public class CommentBlocks { - private Long boardCommentId; + private Long commentId; private String content; @@ -32,8 +32,8 @@ public class CommentBlocks { private Long makerId; @QueryProjection - public CommentBlocks(Long boardCommentId, String content, String writerNickName, Boolean writerIsLeader, String writerProfileImage, Boolean isWriter, Boolean writerIsDeleted, LocalDateTime createdDate, Long makerId) { - this.boardCommentId = boardCommentId; + public CommentBlocks(Long commentId, String content, String writerNickName, Boolean writerIsLeader, String writerProfileImage, Boolean isWriter, Boolean writerIsDeleted, LocalDateTime createdDate, Long makerId) { + this.commentId = commentId; this.writerNickName = writerNickName; this.writerIsLeader = writerIsLeader; this.writerProfileImage = writerProfileImage; diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CreateBoardCommentResponse.java b/src/main/java/com/moing/backend/domain/comment/application/dto/response/CreateCommentResponse.java similarity index 53% rename from src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CreateBoardCommentResponse.java rename to src/main/java/com/moing/backend/domain/comment/application/dto/response/CreateCommentResponse.java index 8967920c..b392489c 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/CreateBoardCommentResponse.java +++ b/src/main/java/com/moing/backend/domain/comment/application/dto/response/CreateCommentResponse.java @@ -1,4 +1,4 @@ -package com.moing.backend.domain.boardComment.application.dto.response; +package com.moing.backend.domain.comment.application.dto.response; import lombok.AllArgsConstructor; import lombok.Builder; @@ -9,6 +9,6 @@ @Builder @NoArgsConstructor @Getter -public class CreateBoardCommentResponse { - private Long boardCommentId; +public class CreateCommentResponse { + private Long commentId; } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/GetBoardCommentResponse.java b/src/main/java/com/moing/backend/domain/comment/application/dto/response/GetCommentResponse.java similarity index 68% rename from src/main/java/com/moing/backend/domain/boardComment/application/dto/response/GetBoardCommentResponse.java rename to src/main/java/com/moing/backend/domain/comment/application/dto/response/GetCommentResponse.java index 94bbbe1d..06df8937 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/dto/response/GetBoardCommentResponse.java +++ b/src/main/java/com/moing/backend/domain/comment/application/dto/response/GetCommentResponse.java @@ -1,4 +1,4 @@ -package com.moing.backend.domain.boardComment.application.dto.response; +package com.moing.backend.domain.comment.application.dto.response; import lombok.AllArgsConstructor; import lombok.Builder; @@ -11,6 +11,6 @@ @Builder @NoArgsConstructor @Getter -public class GetBoardCommentResponse { +public class GetCommentResponse { private List commentBlocks; } diff --git a/src/main/java/com/moing/backend/domain/comment/domain/entity/Comment.java b/src/main/java/com/moing/backend/domain/comment/domain/entity/Comment.java new file mode 100644 index 00000000..5410bf33 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/comment/domain/entity/Comment.java @@ -0,0 +1,24 @@ +package com.moing.backend.domain.comment.domain.entity; + +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.Getter; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; + +@Getter +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public class Comment extends BaseTimeEntity { + + @Column(nullable = false, length = 300) + protected String content; + + protected boolean isLeader; /*작성자 소모임장유무*/ + public void updateContent(String content) { + this.content = content; + } + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/comment/domain/service/CommentDeleteService.java b/src/main/java/com/moing/backend/domain/comment/domain/service/CommentDeleteService.java new file mode 100644 index 00000000..1bd99c90 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/comment/domain/service/CommentDeleteService.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.comment.domain.service; + +public interface CommentDeleteService { + void deleteComment(T comment); +} diff --git a/src/main/java/com/moing/backend/domain/comment/domain/service/CommentGetService.java b/src/main/java/com/moing/backend/domain/comment/domain/service/CommentGetService.java new file mode 100644 index 00000000..3f6cb854 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/comment/domain/service/CommentGetService.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.comment.domain.service; + +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; + +import java.util.List; +import java.util.Optional; + +public interface CommentGetService { + T getComment(Long commentId); + GetCommentResponse getCommentAll(Long boardId, TeamMember teamMember); + Optional> getNewUploadInfo(Long memberId, Long boardId); +} diff --git a/src/main/java/com/moing/backend/domain/comment/domain/service/CommentSaveService.java b/src/main/java/com/moing/backend/domain/comment/domain/service/CommentSaveService.java new file mode 100644 index 00000000..b0a73f8b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/comment/domain/service/CommentSaveService.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.comment.domain.service; + +public interface CommentSaveService { + T saveComment(T comment); +} From 6fc0d5507284f3dc83228b5d1788ba851656df91 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 7 May 2024 01:09:39 +0900 Subject: [PATCH 571/619] =?UTF-8?q?MNG-20=20refactor:=20BoardComment?= =?UTF-8?q?=EA=B0=80=20Comment=EC=9D=98=20=EA=B3=B5=ED=86=B5=20=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=EB=A5=BC=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/presentation/BoardController.java | 13 ++++++++ .../mapper/BoardCommentMapper.java | 10 +++--- .../service/CreateBoardCommentUseCase.java | 10 +++--- .../service/DeleteBoardCommentUseCase.java | 4 +-- .../service/GetBoardCommentUseCase.java | 6 ++-- .../domain/entity/BoardComment.java | 16 +++------- .../BoardCommentCustomRepository.java | 4 +-- .../BoardCommentCustomRepositoryImpl.java | 10 +++--- .../repository/BoardCommentRepository.java | 1 - .../service/BoardCommentDeleteService.java | 7 +++-- .../service/BoardCommentGetService.java | 14 ++++++--- .../service/BoardCommentSaveService.java | 8 +++-- .../presentattion/BoardCommentController.java | 31 +++++++++---------- .../dto/res/MissionArchiveRes.java | 9 +++--- 14 files changed, 78 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java index 739935e4..8ae0002f 100644 --- a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java +++ b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java @@ -91,4 +91,17 @@ public ResponseEntity> getBoardAll(@Authent @PathVariable Long teamId) { return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_ALL_SUCCESS.getMessage(), this.getBoardUseCase.getAllBoard(user.getSocialId(), teamId))); } + + @PostMapping("/test") + public void test() { + Thread thread1 = new Thread(() -> { + this.getBoardUseCase.getBoardDetail("KAKAO@tester01", 1L,1L); + }); + Thread thread2 = new Thread(() -> { + this.getBoardUseCase.getBoardDetail("KAKAO@tester01", 1L,1L); + }); + thread1.start(); + thread2.start(); + } + } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java b/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java index e2311e2a..00f9f751 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/mapper/BoardCommentMapper.java @@ -1,7 +1,7 @@ package com.moing.backend.domain.boardComment.application.mapper; import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; +import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import lombok.RequiredArgsConstructor; @@ -10,11 +10,9 @@ @Component @RequiredArgsConstructor public class BoardCommentMapper { - public static BoardComment toBoardComment(TeamMember teamMember, Board board, CreateBoardCommentRequest createBoardCommentRequest, boolean isLeader) { - BoardComment boardComment= BoardComment.builder() - .content(createBoardCommentRequest.getContent()) - .isLeader(isLeader) - .build(); + public static BoardComment toBoardComment(TeamMember teamMember, Board board, CreateCommentRequest createCommentRequest, boolean isLeader) { + BoardComment boardComment= new BoardComment(); + boardComment.init(createCommentRequest.getContent(),isLeader); boardComment.updateBoard(board); boardComment.updateTeamMember(teamMember); return boardComment; diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java index 3530d8a5..ffac8705 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java @@ -1,10 +1,10 @@ package com.moing.backend.domain.boardComment.application.service; -import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; -import com.moing.backend.domain.boardComment.application.dto.response.CreateBoardCommentResponse; import com.moing.backend.domain.boardComment.application.mapper.BoardCommentMapper; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.service.BoardCommentSaveService; +import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest; +import com.moing.backend.domain.comment.application.dto.response.CreateCommentResponse; import com.moing.backend.domain.team.application.service.CheckLeaderUseCase; import com.moing.backend.global.response.BaseBoardServiceResponse; import com.moing.backend.global.utils.BaseBoardService; @@ -25,15 +25,15 @@ public class CreateBoardCommentUseCase { /** * 게시글 댓글 생성 */ - public CreateBoardCommentResponse createBoardComment(String socialId, Long teamId, Long boardId, CreateBoardCommentRequest createBoardCommentRequest) { + public CreateCommentResponse createBoardComment(String socialId, Long teamId, Long boardId, CreateCommentRequest createCommentRequest) { // 1. 게시글 댓글 생성 BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); boolean isLeader = checkLeaderUseCase.isTeamLeader(data.getMember(), data.getTeam()); - BoardComment boardComment = boardCommentSaveService.saveBoardComment(BoardCommentMapper.toBoardComment(data.getTeamMember(), data.getBoard(), createBoardCommentRequest, isLeader)); + BoardComment boardComment = boardCommentSaveService.saveComment(BoardCommentMapper.toBoardComment(data.getTeamMember(), data.getBoard(), createCommentRequest, isLeader)); // 2. 게시글 댓글 개수 증가 data.getBoard().incrComNum(); // 3. 게시글 댓글 알림 sendCommentAlarmUseCase.sendNewUploadAlarm(data, boardComment); - return new CreateBoardCommentResponse(boardComment.getBoardCommentId()); + return new CreateCommentResponse(boardComment.getBoardCommentId()); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java index 0937123d..7c5a4611 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/DeleteBoardCommentUseCase.java @@ -27,11 +27,11 @@ public class DeleteBoardCommentUseCase { public void deleteBoardComment(String socialId, Long teamId, Long boardId, Long boardCommentId){ // 1. 게시글 댓글 조회 BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); - BoardComment boardComment=boardCommentGetService.getBoardComment(boardCommentId); + BoardComment boardComment=boardCommentGetService.getComment(boardCommentId); // 2. 게시글 댓글 작성자만 if (data.getTeamMember() == boardComment.getTeamMember()) { // 3. 삭제 - boardCommentDeleteService.deleteBoardComment(boardComment); + boardCommentDeleteService.deleteComment(boardComment); // 4. 댓글 개수 줄이기 data.getBoard().decrComNum(); } else throw new NotAuthByBoardCommentException(); diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java index a3163427..d34816cd 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/GetBoardCommentUseCase.java @@ -1,7 +1,7 @@ package com.moing.backend.domain.boardComment.application.service; -import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; import com.moing.backend.global.response.BaseBoardServiceResponse; import com.moing.backend.global.utils.BaseBoardService; import lombok.RequiredArgsConstructor; @@ -20,8 +20,8 @@ public class GetBoardCommentUseCase { /** * 게시글 댓글 전체 조회 */ - public GetBoardCommentResponse getBoardCommentAll(String socialId, Long teamId, Long boardId){ + public GetCommentResponse getBoardCommentAll(String socialId, Long teamId, Long boardId){ BaseBoardServiceResponse data = baseBoardService.getCommonData(socialId, teamId, boardId); - return boardCommentGetService.getBoardCommentAll(boardId, data.getTeamMember()); + return boardCommentGetService.getCommentAll(boardId, data.getTeamMember()); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java index 7edf67cb..6a4092d4 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java @@ -1,9 +1,8 @@ package com.moing.backend.domain.boardComment.domain.entity; import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; +import com.moing.backend.domain.comment.domain.entity.Comment; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; -import com.moing.backend.global.entity.BaseTimeEntity; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -16,16 +15,13 @@ @NoArgsConstructor @AllArgsConstructor @Getter -public class BoardComment extends BaseTimeEntity { +public class BoardComment extends Comment { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "board_comment_id") private Long boardCommentId; - @Column(nullable = false, length = 300) - private String content; - @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_member_id") private TeamMember teamMember; @@ -34,8 +30,6 @@ public class BoardComment extends BaseTimeEntity { @JoinColumn(name = "board_id") private Board board; - private boolean isLeader; /*작성자 소모임장유무*/ - /** * 연관관계 매핑 */ @@ -48,8 +42,8 @@ public void updateTeamMember(TeamMember teamMember) { this.teamMember = teamMember; } - public void updateBoardComment(CreateBoardCommentRequest createBoardCommentRequest) { - this.content = createBoardCommentRequest.getContent(); + public void init(String content, boolean isLeader){ + this.content=content; + this.isLeader=isLeader; } - } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java index 25a70306..8040bf28 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepository.java @@ -1,6 +1,6 @@ package com.moing.backend.domain.boardComment.domain.repository; -import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; @@ -8,7 +8,7 @@ import java.util.Optional; public interface BoardCommentCustomRepository { - GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember teamMember); + GetCommentResponse findBoardCommentAll(Long boardId, TeamMember teamMember); Optional> findNewUploadInfo(Long memberId, Long boardId); } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index 048fa21f..413f4203 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -1,9 +1,9 @@ package com.moing.backend.domain.boardComment.domain.repository; import com.moing.backend.domain.block.domain.repository.BlockRepositoryUtils; -import com.moing.backend.domain.boardComment.application.dto.response.CommentBlocks; -import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; -import com.moing.backend.domain.boardComment.application.dto.response.QCommentBlocks; +import com.moing.backend.domain.comment.application.dto.response.CommentBlocks; +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; +import com.moing.backend.domain.comment.application.dto.response.QCommentBlocks; import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; @@ -31,7 +31,7 @@ public BoardCommentCustomRepositoryImpl(EntityManager em) { @Override - public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember teamMember) { + public GetCommentResponse findBoardCommentAll(Long boardId, TeamMember teamMember) { BooleanExpression blockCondition = BlockRepositoryUtils.blockCondition(teamMember.getTeamMemberId(), boardComment.teamMember.member.memberId); @@ -59,7 +59,7 @@ public GetBoardCommentResponse findBoardCommentAll(Long boardId, TeamMember team .orderBy(boardComment.createdDate.asc()) .fetch(); - return new GetBoardCommentResponse(commentBlocks); + return new GetCommentResponse(commentBlocks); } @Override diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentRepository.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentRepository.java index 8ccec194..99a7b2a3 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentRepository.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentRepository.java @@ -1,6 +1,5 @@ package com.moing.backend.domain.boardComment.domain.repository; -import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentDeleteService.java b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentDeleteService.java index c3bd102f..63e55f09 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentDeleteService.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentDeleteService.java @@ -2,15 +2,18 @@ import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; +import com.moing.backend.domain.comment.domain.service.CommentDeleteService; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; @DomainService @RequiredArgsConstructor -public class BoardCommentDeleteService { +public class BoardCommentDeleteService implements CommentDeleteService { private final BoardCommentRepository boardCommentRepository; - public void deleteBoardComment(BoardComment boardComment){ + @Override + public void deleteComment(BoardComment boardComment){ this.boardCommentRepository.delete(boardComment); } + } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java index 28023ab0..1f2eaea0 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentGetService.java @@ -1,9 +1,10 @@ package com.moing.backend.domain.boardComment.domain.service; -import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; import com.moing.backend.domain.boardComment.exception.NotFoundByBoardCommentIdException; +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; +import com.moing.backend.domain.comment.domain.service.CommentGetService; import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.teamMember.domain.entity.TeamMember; import com.moing.backend.global.annotation.DomainService; @@ -16,18 +17,21 @@ @DomainService @Transactional @RequiredArgsConstructor -public class BoardCommentGetService { +public class BoardCommentGetService implements CommentGetService { private final BoardCommentRepository boardCommentRepository; - public BoardComment getBoardComment(Long boardCommentId){ - return boardCommentRepository.findBoardCommentByBoardCommentId(boardCommentId).orElseThrow(()->new NotFoundByBoardCommentIdException()); + @Override + public BoardComment getComment(Long boardCommentId){ + return boardCommentRepository.findBoardCommentByBoardCommentId(boardCommentId).orElseThrow(NotFoundByBoardCommentIdException::new); } - public GetBoardCommentResponse getBoardCommentAll(Long boardId, TeamMember teamMember){ + @Override + public GetCommentResponse getCommentAll(Long boardId, TeamMember teamMember){ return boardCommentRepository.findBoardCommentAll(boardId, teamMember); } + @Override public Optional> getNewUploadInfo(Long memberId, Long boardId) { return boardCommentRepository.findNewUploadInfo(memberId, boardId); } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentSaveService.java b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentSaveService.java index 48b634aa..f4ac6d04 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentSaveService.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/service/BoardCommentSaveService.java @@ -1,17 +1,19 @@ package com.moing.backend.domain.boardComment.domain.service; -import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.repository.BoardCommentRepository; +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.comment.domain.service.CommentSaveService; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; @DomainService @RequiredArgsConstructor -public class BoardCommentSaveService { +public class BoardCommentSaveService implements CommentSaveService { private final BoardCommentRepository boardCommentRepository; - public BoardComment saveBoardComment(BoardComment boardComment){ + @Override + public BoardComment saveComment(BoardComment boardComment){ return this.boardCommentRepository.save(boardComment); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java b/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java index 506d9250..501f0cfd 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java +++ b/src/main/java/com/moing/backend/domain/boardComment/presentattion/BoardCommentController.java @@ -1,11 +1,12 @@ package com.moing.backend.domain.boardComment.presentattion; -import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; -import com.moing.backend.domain.boardComment.application.dto.response.CreateBoardCommentResponse; -import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; import com.moing.backend.domain.boardComment.application.service.CreateBoardCommentUseCase; import com.moing.backend.domain.boardComment.application.service.DeleteBoardCommentUseCase; import com.moing.backend.domain.boardComment.application.service.GetBoardCommentUseCase; +import com.moing.backend.domain.boardComment.presentattion.constant.BoardCommentResponseMessage; +import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest; +import com.moing.backend.domain.comment.application.dto.response.CreateCommentResponse; +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; @@ -15,9 +16,7 @@ import javax.validation.Valid; -import static com.moing.backend.domain.board.presentation.constant.BoardResponseMessage.GET_BOARD_ALL_SUCCESS; -import static com.moing.backend.domain.boardComment.presentattion.constant.BoardCommentResponseMessage.CREATE_BOARD_COMMENT_SUCCESS; -import static com.moing.backend.domain.boardComment.presentattion.constant.BoardCommentResponseMessage.DELETE_BOARD_COMMENT_SUCCESS; +import static com.moing.backend.domain.boardComment.presentattion.constant.BoardCommentResponseMessage.GET_BOARD_COMMENT_ALL_SUCCESS; @RestController @AllArgsConstructor @@ -34,11 +33,11 @@ public class BoardCommentController { * 작성자 : 김민수 */ @PostMapping - public ResponseEntity> createBoardComment(@AuthenticationPrincipal User user, - @PathVariable Long teamId, - @PathVariable Long boardId, - @Valid @RequestBody CreateBoardCommentRequest createBoardCommentRequest) { - return ResponseEntity.ok(SuccessResponse.create(CREATE_BOARD_COMMENT_SUCCESS.getMessage(), this.createBoardCommentUseCase.createBoardComment(user.getSocialId(), teamId, boardId, createBoardCommentRequest))); + public ResponseEntity> createBoardComment(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long boardId, + @Valid @RequestBody CreateCommentRequest createCommentRequest) { + return ResponseEntity.ok(SuccessResponse.create(BoardCommentResponseMessage.CREATE_BOARD_COMMENT_SUCCESS.getMessage(), this.createBoardCommentUseCase.createBoardComment(user.getSocialId(), teamId, boardId, createCommentRequest))); } /** @@ -52,7 +51,7 @@ public ResponseEntity deleteBoardComment(@AuthenticationPrincip @PathVariable Long boardId, @PathVariable Long commentId) { this.deleteBoardCommentUseCase.deleteBoardComment(user.getSocialId(), teamId, boardId, commentId); - return ResponseEntity.ok(SuccessResponse.create(DELETE_BOARD_COMMENT_SUCCESS.getMessage())); + return ResponseEntity.ok(SuccessResponse.create(BoardCommentResponseMessage.DELETE_BOARD_COMMENT_SUCCESS.getMessage())); } @@ -62,9 +61,9 @@ public ResponseEntity deleteBoardComment(@AuthenticationPrincip * 작성자 : 김민수 */ @GetMapping - public ResponseEntity> getBoardCommentAll(@AuthenticationPrincipal User user, - @PathVariable Long teamId, - @PathVariable Long boardId) { - return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_ALL_SUCCESS.getMessage(), this.getBoardCommentUseCase.getBoardCommentAll(user.getSocialId(), teamId, boardId))); + public ResponseEntity> getBoardCommentAll(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long boardId) { + return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_COMMENT_ALL_SUCCESS.getMessage(), this.getBoardCommentUseCase.getBoardCommentAll(user.getSocialId(), teamId, boardId))); } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java index a0d5e88f..871786c3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/MissionArchiveRes.java @@ -1,9 +1,9 @@ package com.moing.backend.domain.missionArchive.application.dto.res; -import lombok.*; - -import javax.annotation.Nullable; -import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; @AllArgsConstructor @Builder @NoArgsConstructor @@ -19,6 +19,7 @@ public class MissionArchiveRes { private String heartStatus; private Long hearts; private String contents; + private Long comments; public void updateCount(Long count) { this.count = count; From d73cf59ff7682075fbd4af14e1ef433c291c52c2 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 7 May 2024 01:10:49 +0900 Subject: [PATCH 572/619] =?UTF-8?q?MNG-20=20feat:=20MissionComment=20CRUD?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/MissionArchiveMapper.java | 1 + .../domain/entity/MissionArchive.java | 10 ++- .../mapper/MissionCommentMapper.java | 20 +++++ .../service/CreateMissionCommentUseCase.java | 41 +++++++++ .../service/DeleteMissionCommentUseCase.java | 39 +++++++++ .../service/GetMissionCommentUseCase.java | 27 ++++++ .../service/SendMissionAlarmUseCase.java | 4 + .../domain/entity/MissionComment.java | 48 +++++++++++ .../MissionCommentCustomRepository.java | 14 +++ .../MissionCommentCustomRepositoryImpl.java | 86 +++++++++++++++++++ .../repository/MissionCommentRepository.java | 12 +++ .../service/MissionCommentDeleteService.java | 18 ++++ .../service/MissionCommentGetService.java | 34 ++++++++ .../service/MissionCommentSaveService.java | 19 ++++ .../exception/MissionCommentException.java | 11 +++ .../NotAuthByMissionCommentException.java | 11 +++ .../NotFoundByMissionCommentIdException.java | 11 +++ .../MissionCommentController.java | 69 +++++++++++++++ .../service/ReportCreateUseCase.java | 8 +- .../team/presentation/TeamController.java | 12 +++ .../response/BaseMissionServiceResponse.java | 19 ++++ .../backend/global/response/ErrorCode.java | 5 +- .../global/utils/BaseMissionService.java | 32 +++++++ 23 files changed, 543 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionComment/application/mapper/MissionCommentMapper.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/application/service/CreateMissionCommentUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/application/service/DeleteMissionCommentUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/application/service/GetMissionCommentUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionAlarmUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/domain/entity/MissionComment.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepositoryImpl.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentRepository.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentDeleteService.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentGetService.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentSaveService.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/exception/MissionCommentException.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/exception/NotAuthByMissionCommentException.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/exception/NotFoundByMissionCommentIdException.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/presentation/MissionCommentController.java create mode 100644 src/main/java/com/moing/backend/global/response/BaseMissionServiceResponse.java create mode 100644 src/main/java/com/moing/backend/global/utils/BaseMissionService.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index b84fe771..7dc09888 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -51,6 +51,7 @@ public static MissionArchiveRes mapToMissionArchiveRes(MissionArchive missionArc .filter(heart -> heart.getMissionArchive().equals( missionArchive))// heartStatus가 true인 요소만 필터링 .count()) .contents(missionArchive.getContents()) + .comments(missionArchive.getCommentNum()) .build(); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index 90826b52..2a60411f 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -3,7 +3,6 @@ import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; import com.moing.backend.global.entity.BaseTimeEntity; @@ -50,6 +49,8 @@ public class MissionArchive extends BaseTimeEntity { // 1회 미션을 저장 @OneToMany(mappedBy = "missionArchive", cascade = CascadeType.REMOVE) private List heartList = new ArrayList<>(); + //반정규화 + private Long commentNum; public void updateArchive(MissionArchiveReq missionArchiveReq) { this.archive = missionArchiveReq.getArchive(); @@ -60,6 +61,13 @@ public void updateCount(Long count) { this.count = count; } + public void incrComNum() { + this.commentNum++; + } + + public void decrComNum() { + this.commentNum--; + } } diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/mapper/MissionCommentMapper.java b/src/main/java/com/moing/backend/domain/missionComment/application/mapper/MissionCommentMapper.java new file mode 100644 index 00000000..a47b6e68 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/application/mapper/MissionCommentMapper.java @@ -0,0 +1,20 @@ +package com.moing.backend.domain.missionComment.application.mapper; + +import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionComment.domain.entity.MissionComment; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class MissionCommentMapper { + public static MissionComment toMissionComment(TeamMember teamMember, MissionArchive missionArchive, CreateCommentRequest createCommentRequest, boolean isLeader) { + MissionComment missionComment=new MissionComment(); + missionComment.init(createCommentRequest.getContent(),isLeader); + missionComment.updateMissionArchive(missionArchive); + missionComment.updateTeamMember(teamMember); + return missionComment; + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/CreateMissionCommentUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/CreateMissionCommentUseCase.java new file mode 100644 index 00000000..54a0ef10 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/application/service/CreateMissionCommentUseCase.java @@ -0,0 +1,41 @@ +package com.moing.backend.domain.missionComment.application.service; + +import com.moing.backend.domain.boardComment.application.service.SendCommentAlarmUseCase; +import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest; +import com.moing.backend.domain.comment.application.dto.response.CreateCommentResponse; +import com.moing.backend.domain.missionComment.application.mapper.MissionCommentMapper; +import com.moing.backend.domain.missionComment.domain.entity.MissionComment; +import com.moing.backend.domain.missionComment.domain.service.MissionCommentSaveService; +import com.moing.backend.domain.team.application.service.CheckLeaderUseCase; +import com.moing.backend.global.response.BaseMissionServiceResponse; +import com.moing.backend.global.utils.BaseMissionService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +public class CreateMissionCommentUseCase { + + private final MissionCommentSaveService missionCommentSaveService; + private final BaseMissionService baseMissionService; + private final CheckLeaderUseCase checkLeaderUseCase; + private final SendCommentAlarmUseCase sendCommentAlarmUseCase; + /** + * 게시글 댓글 생성 + */ + public CreateCommentResponse createBoardComment(String socialId, Long teamId, Long missionArchiveId, CreateCommentRequest createCommentRequest) { + // 1. 미션 게시글 댓글 생성 + BaseMissionServiceResponse data = baseMissionService.getCommonData(socialId, teamId, missionArchiveId); + boolean isLeader = checkLeaderUseCase.isTeamLeader(data.getMember(), data.getTeam()); + MissionComment missionComment = missionCommentSaveService.saveComment(MissionCommentMapper.toMissionComment(data.getTeamMember(), data.getMissionArchive(), createCommentRequest, isLeader)); + // 2. 미션 게시글 댓글 개수 증가 + data.getMissionArchive().incrComNum(); +// // 3. 미션 게시글 댓글 알림 +// sendCommentAlarmUseCase.sendNewUploadAlarm(data, missionComment); + return new CreateCommentResponse(missionComment.getMissionCommentId()); + } +} + diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/DeleteMissionCommentUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/DeleteMissionCommentUseCase.java new file mode 100644 index 00000000..0c87c5b4 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/application/service/DeleteMissionCommentUseCase.java @@ -0,0 +1,39 @@ +package com.moing.backend.domain.missionComment.application.service; + +import com.moing.backend.domain.boardComment.exception.NotAuthByBoardCommentException; +import com.moing.backend.domain.missionComment.domain.entity.MissionComment; +import com.moing.backend.domain.missionComment.domain.service.MissionCommentDeleteService; +import com.moing.backend.domain.missionComment.domain.service.MissionCommentGetService; +import com.moing.backend.global.response.BaseMissionServiceResponse; +import com.moing.backend.global.utils.BaseMissionService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class DeleteMissionCommentUseCase { + + private final MissionCommentGetService missionCommentGetService; + private final MissionCommentDeleteService missionCommentDeleteService; + private final BaseMissionService baseMissionService; + + /** + * 게시글 댓글 삭제 + */ + + public void deleteMissionComment(String socialId, Long teamId, Long missionArchiveId, Long boardCommentId){ + // 1. 게시글 댓글 조회 + BaseMissionServiceResponse data = baseMissionService.getCommonData(socialId, teamId, missionArchiveId); + MissionComment missionComment =missionCommentGetService.getComment(boardCommentId); + // 2. 게시글 댓글 작성자만 + if (data.getTeamMember() == missionComment.getTeamMember()) { + // 3. 삭제 + missionCommentDeleteService.deleteComment(missionComment); + // 4. 댓글 개수 줄이기 + data.getMissionArchive().decrComNum(); + } else throw new NotAuthByBoardCommentException(); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/GetMissionCommentUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/GetMissionCommentUseCase.java new file mode 100644 index 00000000..b3d5ca70 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/application/service/GetMissionCommentUseCase.java @@ -0,0 +1,27 @@ +package com.moing.backend.domain.missionComment.application.service; + +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; +import com.moing.backend.domain.missionComment.domain.service.MissionCommentGetService; +import com.moing.backend.global.response.BaseMissionServiceResponse; +import com.moing.backend.global.utils.BaseMissionService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class GetMissionCommentUseCase { + + private final MissionCommentGetService missionCommentGetService; + private final BaseMissionService baseMissionService; + + /** + * 게시글 댓글 전체 조회 + */ + public GetCommentResponse getBoardCommentAll(String socialId, Long teamId, Long missionArchiveId){ + BaseMissionServiceResponse data = baseMissionService.getCommonData(socialId, teamId, missionArchiveId); + return missionCommentGetService.getCommentAll(missionArchiveId, data.getTeamMember()); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionAlarmUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionAlarmUseCase.java new file mode 100644 index 00000000..ced7594c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionAlarmUseCase.java @@ -0,0 +1,4 @@ +package com.moing.backend.domain.missionComment.application.service; + +public class SendMissionAlarmUseCase { +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/entity/MissionComment.java b/src/main/java/com/moing/backend/domain/missionComment/domain/entity/MissionComment.java new file mode 100644 index 00000000..a3941527 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/entity/MissionComment.java @@ -0,0 +1,48 @@ +package com.moing.backend.domain.missionComment.domain.entity; + +import com.moing.backend.domain.comment.domain.entity.Comment; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class MissionComment extends Comment { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "mission_comment_id") + private Long missionCommentId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "team_member_id") + private TeamMember teamMember; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "mission_archive_id") + private MissionArchive missionArchive; + + /** + * 연관관계 매핑 + */ + public void updateMissionArchive(MissionArchive missionArchive) { + this.missionArchive=missionArchive; + } + + public void updateTeamMember(TeamMember teamMember) { + this.teamMember = teamMember; + } + + public void init(String content, boolean isLeader){ + this.content=content; + this.isLeader=isLeader; + } +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepository.java b/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepository.java new file mode 100644 index 00000000..253b0654 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepository.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.missionComment.domain.repository; + +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; + +import java.util.List; +import java.util.Optional; + +public interface MissionCommentCustomRepository { + GetCommentResponse findMissionCommentAll(Long missionArchiveId, TeamMember teamMember); + + Optional> findNewUploadInfo(Long memberId, Long missionArchiveId); +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepositoryImpl.java new file mode 100644 index 00000000..aecacdad --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepositoryImpl.java @@ -0,0 +1,86 @@ +package com.moing.backend.domain.missionComment.domain.repository; + +import com.moing.backend.domain.block.domain.repository.BlockRepositoryUtils; +import com.moing.backend.domain.comment.application.dto.response.CommentBlocks; +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; +import com.moing.backend.domain.comment.application.dto.response.QCommentBlocks; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.teamMember.domain.entity.QTeamMember; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.querydsl.core.types.ExpressionUtils; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; +import java.util.List; +import java.util.Optional; + +import static com.moing.backend.domain.member.domain.entity.QMember.member; +import static com.moing.backend.domain.missionComment.domain.entity.QMissionComment.missionComment; +import static com.moing.backend.domain.teamMember.domain.entity.QTeamMember.teamMember; + +public class MissionCommentCustomRepositoryImpl implements MissionCommentCustomRepository{ + + private final JPAQueryFactory queryFactory; + + public MissionCommentCustomRepositoryImpl(EntityManager em) { + this.queryFactory = new JPAQueryFactory(em); + } + + + @Override + public GetCommentResponse findMissionCommentAll(Long missionArchiveId, TeamMember teamMember) { + + BooleanExpression blockCondition = BlockRepositoryUtils.blockCondition(teamMember.getTeamMemberId(), missionComment.teamMember.member.memberId); + + List commentBlocks = queryFactory + .select(new QCommentBlocks( + missionComment.missionCommentId, + missionComment.content, + missionComment.teamMember.member.nickName, + missionComment.isLeader, + missionComment.teamMember.member.profileImage, + ExpressionUtils.as(JPAExpressions + .selectOne() + .from(QTeamMember.teamMember) + .where(QTeamMember.teamMember.eq(teamMember) + .and(QTeamMember.teamMember.eq(missionComment.teamMember))) + .exists(), "isWriter"), + missionComment.teamMember.isDeleted, + missionComment.createdDate, + missionComment.teamMember.member.memberId)) + .from(missionComment) + .leftJoin(missionComment.teamMember, QTeamMember.teamMember) + .leftJoin(missionComment.teamMember.member, member) + .where(missionComment.missionArchive.id.eq(missionArchiveId) + .and(blockCondition)) + .orderBy(missionComment.createdDate.asc()) + .fetch(); + + return new GetCommentResponse(commentBlocks); + } + + @Override + public Optional> findNewUploadInfo(Long memberId, Long missionArchiveId) { + BooleanExpression blockCondition= BlockRepositoryUtils.blockCondition(missionComment.teamMember.member.memberId, memberId); + + List result = queryFactory.select(Projections.constructor(NewUploadInfo.class, + missionComment.teamMember.member.fcmToken, + missionComment.teamMember.member.memberId, + missionComment.teamMember.member.isNewUploadPush, + missionComment.teamMember.member.isSignOut)) + .distinct() + .from(missionComment) + .leftJoin(missionComment.teamMember, teamMember) + .leftJoin(missionComment.teamMember.member, member) + .where(missionComment.missionArchive.id.eq(missionArchiveId) //게시글의 댓글인데 + .and(missionComment.teamMember.member.memberId.ne(memberId)) //나는 포함 안하고 + .and(missionComment.teamMember.isDeleted.eq(false)) //탈퇴한 사람도 포함 안함 + .and(blockCondition)) + .fetch(); + + return result.isEmpty() ? Optional.empty() : Optional.of(result); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentRepository.java b/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentRepository.java new file mode 100644 index 00000000..8c7d8e35 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentRepository.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.missionComment.domain.repository; + +import com.moing.backend.domain.missionComment.domain.entity.MissionComment; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface MissionCommentRepository extends JpaRepository, MissionCommentCustomRepository { + + Optional findMissionCommentByMissionCommentId(Long missionCommentId); + +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentDeleteService.java b/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentDeleteService.java new file mode 100644 index 00000000..b41f541a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentDeleteService.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.missionComment.domain.service; + +import com.moing.backend.domain.comment.domain.service.CommentDeleteService; +import com.moing.backend.domain.missionComment.domain.entity.MissionComment; +import com.moing.backend.domain.missionComment.domain.repository.MissionCommentRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class MissionCommentDeleteService implements CommentDeleteService { + + private final MissionCommentRepository missionCommentRepository; + @Override + public void deleteComment(MissionComment comment) { + missionCommentRepository.delete(comment); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentGetService.java b/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentGetService.java new file mode 100644 index 00000000..501dfe2b --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentGetService.java @@ -0,0 +1,34 @@ +package com.moing.backend.domain.missionComment.domain.service; + +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; +import com.moing.backend.domain.comment.domain.service.CommentGetService; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.missionComment.domain.entity.MissionComment; +import com.moing.backend.domain.missionComment.domain.repository.MissionCommentRepository; +import com.moing.backend.domain.missionComment.exception.NotFoundByMissionCommentIdException; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import java.util.List; +import java.util.Optional; +@DomainService +@RequiredArgsConstructor +public class MissionCommentGetService implements CommentGetService { + private final MissionCommentRepository missionCommentRepository; + + @Override + public MissionComment getComment(Long commentId) { + return missionCommentRepository.findMissionCommentByMissionCommentId(commentId).orElseThrow(NotFoundByMissionCommentIdException::new); + } + + @Override + public GetCommentResponse getCommentAll(Long missionArchiveId, TeamMember teamMember) { + return missionCommentRepository.findMissionCommentAll(missionArchiveId, teamMember); + } + + @Override + public Optional> getNewUploadInfo(Long memberId, Long missionArchiveId) { + return missionCommentRepository.findNewUploadInfo(memberId, missionArchiveId); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentSaveService.java b/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentSaveService.java new file mode 100644 index 00000000..a62e2e5a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentSaveService.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.missionComment.domain.service; + +import com.moing.backend.domain.comment.domain.service.CommentSaveService; +import com.moing.backend.domain.missionComment.domain.entity.MissionComment; +import com.moing.backend.domain.missionComment.domain.repository.MissionCommentRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +@DomainService +@RequiredArgsConstructor +public class MissionCommentSaveService implements CommentSaveService { + + private final MissionCommentRepository missionCommentRepository; + + @Override + public MissionComment saveComment(MissionComment comment) { + return missionCommentRepository.save(comment); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/exception/MissionCommentException.java b/src/main/java/com/moing/backend/domain/missionComment/exception/MissionCommentException.java new file mode 100644 index 00000000..3079b682 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/exception/MissionCommentException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.missionComment.exception; + +import com.moing.backend.global.exception.ApplicationException; +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public abstract class MissionCommentException extends ApplicationException { + protected MissionCommentException(ErrorCode errorCode, HttpStatus httpStatus) { + super(errorCode, httpStatus); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionComment/exception/NotAuthByMissionCommentException.java b/src/main/java/com/moing/backend/domain/missionComment/exception/NotAuthByMissionCommentException.java new file mode 100644 index 00000000..04e9b114 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/exception/NotAuthByMissionCommentException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.missionComment.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotAuthByMissionCommentException extends MissionCommentException { + public NotAuthByMissionCommentException() { + super(ErrorCode.NOT_AUTH_BY_MISSION_COMMENT_ID_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/exception/NotFoundByMissionCommentIdException.java b/src/main/java/com/moing/backend/domain/missionComment/exception/NotFoundByMissionCommentIdException.java new file mode 100644 index 00000000..94c9fcae --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/exception/NotFoundByMissionCommentIdException.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.missionComment.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundByMissionCommentIdException extends MissionCommentException { + public NotFoundByMissionCommentIdException() { + super(ErrorCode.NOT_FOUND_BY_MISSION_COMMENT_ID_ERROR, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionComment/presentation/MissionCommentController.java b/src/main/java/com/moing/backend/domain/missionComment/presentation/MissionCommentController.java new file mode 100644 index 00000000..21b3ac18 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/presentation/MissionCommentController.java @@ -0,0 +1,69 @@ +package com.moing.backend.domain.missionComment.presentation; + +import com.moing.backend.domain.boardComment.presentattion.constant.BoardCommentResponseMessage; +import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest; +import com.moing.backend.domain.comment.application.dto.response.CreateCommentResponse; +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; +import com.moing.backend.domain.missionComment.application.service.CreateMissionCommentUseCase; +import com.moing.backend.domain.missionComment.application.service.DeleteMissionCommentUseCase; +import com.moing.backend.domain.missionComment.application.service.GetMissionCommentUseCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +import static com.moing.backend.domain.boardComment.presentattion.constant.BoardCommentResponseMessage.GET_BOARD_COMMENT_ALL_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/{teamId}/{missionArchiveId}/mcomment") +public class MissionCommentController { + + private final CreateMissionCommentUseCase createMissionCommentUseCase; + private final DeleteMissionCommentUseCase deleteMissionCommentUseCase; + private final GetMissionCommentUseCase getMissionCommentUseCase; + + /** + * 댓글 생성 + * [POST] api/{teamId}/{missionArchiveId}/comment + * 작성자 : 김민수 + */ + @PostMapping + public ResponseEntity> createMissionComment(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long missionArchiveId, + @Valid @RequestBody CreateCommentRequest createCommentRequest) { + return ResponseEntity.ok(SuccessResponse.create(BoardCommentResponseMessage.CREATE_BOARD_COMMENT_SUCCESS.getMessage(), this.createMissionCommentUseCase.createBoardComment(user.getSocialId(), teamId, missionArchiveId, createCommentRequest))); + } + + /** + * 댓글 삭제 + * [DELETE] api/{teamId}/{missionArchiveId}/comment/{commentId} + * 작성자 : 김민수 + */ + @DeleteMapping("/{commentId}") + public ResponseEntity deleteMissionComment(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long missionArchiveId, + @PathVariable Long commentId) { + this.deleteMissionCommentUseCase.deleteMissionComment(user.getSocialId(), teamId, missionArchiveId, commentId); + return ResponseEntity.ok(SuccessResponse.create(BoardCommentResponseMessage.DELETE_BOARD_COMMENT_SUCCESS.getMessage())); + } + + + /** + * 댓글 전체 조회 + * [GET] api/{teamId}/{missionArchiveId}/mcomment + * 작성자 : 김민수 + */ + @GetMapping + public ResponseEntity> getMissionCommentAll(@AuthenticationPrincipal User user, + @PathVariable Long teamId, + @PathVariable Long missionArchiveId) { + return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_COMMENT_ALL_SUCCESS.getMessage(), this.getMissionCommentUseCase.getBoardCommentAll(user.getSocialId(), teamId, missionArchiveId))); + } +} diff --git a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java index 999140b9..d96b35ee 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java @@ -3,7 +3,6 @@ import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; import com.moing.backend.domain.board.domain.entity.Board; import com.moing.backend.domain.board.domain.service.BoardGetService; -import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; import com.moing.backend.domain.boardComment.domain.entity.BoardComment; import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; import com.moing.backend.domain.member.domain.service.MemberGetService; @@ -13,7 +12,6 @@ import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; -import com.moing.backend.domain.missionState.domain.entity.MissionState; import com.moing.backend.domain.report.application.mapper.ReportMapper; import com.moing.backend.domain.report.domain.entity.Report; import com.moing.backend.domain.report.domain.entity.constant.ReportType; @@ -56,12 +54,10 @@ public Long createReport(String socialId, Long targetId, String reportType) { .build()); } else if (reportType.equals(ReportType.COMMENT.name())) { - BoardComment boardComment = boardCommentGetService.getBoardComment(targetId); + BoardComment boardComment = boardCommentGetService.getComment(targetId); targetMemberNickName = boardComment.getTeamMember().getMember().getNickName(); + boardComment.updateContent(REPORT_BOARD_MESSAGE); - boardComment.updateBoardComment(CreateBoardCommentRequest.builder() - .content(REPORT_BOARD_MESSAGE) - .build()); } else { MissionArchive missionArchive = missionArchiveQueryService.findByMissionArchiveId(targetId); diff --git a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java index 8e24226f..12de51b9 100644 --- a/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java +++ b/src/main/java/com/moing/backend/domain/team/presentation/TeamController.java @@ -137,4 +137,16 @@ public ResponseEntity> getTeamCount(@Authe return ResponseEntity.ok(SuccessResponse.create(GET_TEAM_COUNT_SUCCESS.getMessage(), this.getTeamUseCase.getTeamCount(user.getSocialId(),teamId))); } + @PostMapping(value = "/test", name = "테스트") + public void test() { + Thread thread1 = new Thread(() -> { + this.signInTeamUseCase.signInTeam("KAKAO@tester01", 1L); + }); + Thread thread2 = new Thread(() -> { + this.signInTeamUseCase.signInTeam("KAKAO@tester01", 1L); + }); + thread1.start(); + thread2.start(); + } + } diff --git a/src/main/java/com/moing/backend/global/response/BaseMissionServiceResponse.java b/src/main/java/com/moing/backend/global/response/BaseMissionServiceResponse.java new file mode 100644 index 00000000..f0ee645d --- /dev/null +++ b/src/main/java/com/moing/backend/global/response/BaseMissionServiceResponse.java @@ -0,0 +1,19 @@ +package com.moing.backend.global.response; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class BaseMissionServiceResponse { + private Member member; + private Team team; + private MissionArchive missionArchive; + private TeamMember teamMember; +} diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index fc28ead7..72516a96 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -2,7 +2,6 @@ import lombok.AllArgsConstructor; import lombok.Getter; -import org.springframework.http.HttpStatus; @Getter @AllArgsConstructor @@ -63,6 +62,10 @@ public enum ErrorCode { NOT_FOUND_BY_BOARD_COMMENT_ID_ERROR("BC0001","해당 boardCommentId인 댓글이 존재하지 않습니다."), NOT_AUTH_BY_BOARD_COMMENT_ID_ERROR("BC0002","권한이 없습니다."), + //미션 댓글 관련 에러 코드 + NOT_FOUND_BY_MISSION_COMMENT_ID_ERROR("MC0001", "해당 missionCommentId인 댓글이 존재하지 않습니다."), + NOT_AUTH_BY_MISSION_COMMENT_ID_ERROR("MC0002", "권한이 없습니다."), + //알림 관련 에러 코드 NOT_FOUND_BY_ALARM_HISOTRY_ID_ERROR("AH0001","해당 alarmHistoryId인 알림이 존재하지 않습니다."), diff --git a/src/main/java/com/moing/backend/global/utils/BaseMissionService.java b/src/main/java/com/moing/backend/global/utils/BaseMissionService.java new file mode 100644 index 00000000..84311b40 --- /dev/null +++ b/src/main/java/com/moing/backend/global/utils/BaseMissionService.java @@ -0,0 +1,32 @@ +package com.moing.backend.global.utils; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamMember.domain.entity.TeamMember; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.response.BaseMissionServiceResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class BaseMissionService { + + private final MemberGetService memberGetService; + private final TeamGetService teamGetService; + private final MissionArchiveQueryService missionArchiveQueryService; + private final TeamMemberGetService teamMemberGetService; + + public BaseMissionServiceResponse getCommonData(String socialId, Long teamId, Long missionArchiveId){ + Member member = memberGetService.getMemberBySocialId(socialId); + Team team = teamGetService.getTeamByTeamId(teamId); + MissionArchive missionArchive=missionArchiveQueryService.findByMissionArchiveId(missionArchiveId); + TeamMember teamMember = teamMemberGetService.getTeamMember(member, team); + + return new BaseMissionServiceResponse(member, team, missionArchive, teamMember); + } +} From cd5ac80d4c1a95ab2f9bdcd5727d0c66a2805b64 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 7 May 2024 01:12:48 +0900 Subject: [PATCH 573/619] =?UTF-8?q?MNG-20=20docs:=20docs=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../asciidoc/MissionArchiveComment_API.adoc | 17 ++ src/docs/asciidoc/api.adoc | 2 + .../board/presentation/BoardController.java | 12 -- .../BoardCommentControllerTest.java | 22 +- .../MissionArchiveControllerTest.java | 17 +- .../domain/MissionRepositoryTest.java | 22 ++ .../MissionCommentControllerTest.java | 192 ++++++++++++++++++ 7 files changed, 256 insertions(+), 28 deletions(-) create mode 100644 src/docs/asciidoc/MissionArchiveComment_API.adoc create mode 100644 src/test/java/com/moing/backend/domain/missionComment/domain/MissionRepositoryTest.java create mode 100644 src/test/java/com/moing/backend/domain/missionComment/presentation/MissionCommentControllerTest.java diff --git a/src/docs/asciidoc/MissionArchiveComment_API.adoc b/src/docs/asciidoc/MissionArchiveComment_API.adoc new file mode 100644 index 00000000..9ec5e7fa --- /dev/null +++ b/src/docs/asciidoc/MissionArchiveComment_API.adoc @@ -0,0 +1,17 @@ +[[Mission-Comment-API]] += Mission Comment API + +[[Mission-Comment-댓글-생성]] +== Mission Comment 댓글 생성 +operation::mission-comment-controller-test/create_mission_comment[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] +--- + +[[Mission-Comment-댓글-삭제]] +== Mission Comment 댓글 삭제 +operation::mission-comment-controller-test/delete_mission_comment[snippets='http-request,path-parameters,response-fields'] +--- + +[[MissionArchive-Comment-댓글-전체-조회]] +== Mission Comment 댓글 전체 조회 +operation::mission-comment-controller-test/get_board_comment_all[snippets='http-request,path-parameters,http-response,response-fields'] +--- \ No newline at end of file diff --git a/src/docs/asciidoc/api.adoc b/src/docs/asciidoc/api.adoc index 41519d3c..0addb28b 100644 --- a/src/docs/asciidoc/api.adoc +++ b/src/docs/asciidoc/api.adoc @@ -22,6 +22,8 @@ include::Mission-API.adoc[] include::MissionArchive-API.adoc[] +include::MissionArchiveComment_API.adoc[] + include::MissionBoard-API.adoc[] include::MissionGatherBoard-API.adoc[] diff --git a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java index 8ae0002f..6e0c89c4 100644 --- a/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java +++ b/src/main/java/com/moing/backend/domain/board/presentation/BoardController.java @@ -92,16 +92,4 @@ public ResponseEntity> getBoardAll(@Authent return ResponseEntity.ok(SuccessResponse.create(GET_BOARD_ALL_SUCCESS.getMessage(), this.getBoardUseCase.getAllBoard(user.getSocialId(), teamId))); } - @PostMapping("/test") - public void test() { - Thread thread1 = new Thread(() -> { - this.getBoardUseCase.getBoardDetail("KAKAO@tester01", 1L,1L); - }); - Thread thread2 = new Thread(() -> { - this.getBoardUseCase.getBoardDetail("KAKAO@tester01", 1L,1L); - }); - thread1.start(); - thread2.start(); - } - } diff --git a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java index 0b8ea674..0d14b897 100644 --- a/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java +++ b/src/test/java/com/moing/backend/domain/boardComment/presentation/BoardCommentControllerTest.java @@ -1,14 +1,14 @@ package com.moing.backend.domain.boardComment.presentation; import com.moing.backend.config.CommonControllerTest; -import com.moing.backend.domain.boardComment.application.dto.request.CreateBoardCommentRequest; -import com.moing.backend.domain.boardComment.application.dto.response.CommentBlocks; -import com.moing.backend.domain.boardComment.application.dto.response.CreateBoardCommentResponse; -import com.moing.backend.domain.boardComment.application.dto.response.GetBoardCommentResponse; import com.moing.backend.domain.boardComment.application.service.CreateBoardCommentUseCase; import com.moing.backend.domain.boardComment.application.service.DeleteBoardCommentUseCase; import com.moing.backend.domain.boardComment.application.service.GetBoardCommentUseCase; import com.moing.backend.domain.boardComment.presentattion.BoardCommentController; +import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest; +import com.moing.backend.domain.comment.application.dto.response.CommentBlocks; +import com.moing.backend.domain.comment.application.dto.response.CreateCommentResponse; +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -44,14 +44,14 @@ public void create_board_comment() throws Exception { //given Long teamId = 1L; Long boardId = 1L; - CreateBoardCommentRequest input = CreateBoardCommentRequest.builder() + CreateCommentRequest input = CreateCommentRequest.builder() .content("게시글 내용") .build(); String body = objectMapper.writeValueAsString(input); - CreateBoardCommentResponse output = CreateBoardCommentResponse.builder() - .boardCommentId(1L) + CreateCommentResponse output = CreateCommentResponse.builder() + .commentId(1L) .build(); given(createBoardCommentUseCase.createBoardComment(any(), any(), any(), any())).willReturn(output); @@ -83,7 +83,7 @@ public void create_board_comment() throws Exception { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("댓글을 생성했습니다"), - fieldWithPath("data.boardCommentId").description("생성한 boardCommentId") + fieldWithPath("data.commentId").description("생성한 boardCommentId") ) ) ); @@ -135,7 +135,7 @@ public void get_board_comment_all() throws Exception { Long boardId = 1L; CommentBlocks commentBlock = CommentBlocks.builder() - .boardCommentId(1L) + .commentId(1L) .content("댓글 내용") .writerIsLeader(true) .writerNickName("작성자 닉네임") @@ -148,7 +148,7 @@ public void get_board_comment_all() throws Exception { commentBlocks.add(commentBlock); - GetBoardCommentResponse output = new GetBoardCommentResponse(commentBlocks); + GetCommentResponse output = new GetCommentResponse(commentBlocks); given(getBoardCommentUseCase.getBoardCommentAll(any(), any(), any())).willReturn(output); @@ -176,7 +176,7 @@ public void get_board_comment_all() throws Exception { responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description("댓글 목록을 모두 조회했습니다."), - fieldWithPath("data.commentBlocks[].boardCommentId").description("댓글 아이디"), + fieldWithPath("data.commentBlocks[].commentId").description("댓글 아이디"), fieldWithPath("data.commentBlocks[].content").description("댓글 내용"), fieldWithPath("data.commentBlocks[].writerIsLeader").description("작성자 소모임장 여부"), fieldWithPath("data.commentBlocks[].writerNickName").description("작성자 닉네임"), diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index 14a05e86..7ed677de 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -66,6 +66,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .heartStatus("[True/False]") .hearts(1L) .contents("contents") + .comments(1L) .build(); given(missionArchiveCreateUseCase.createArchive(any(),any(),any())).willReturn(output); @@ -110,8 +111,10 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.count").description("미션 인증 횟수"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태"), - fieldWithPath("data.contents").description("미션 인증 문구") - ) + fieldWithPath("data.contents").description("미션 인증 문구"), + fieldWithPath("data.comments").description("미션 댓글 개수") + + ) ) ) .andReturn(); @@ -139,6 +142,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .heartStatus("[True/False]") .hearts(1L) .contents("contents") + .comments(1L) .build(); given(missionArchiveUpdateUseCase.updateArchive(any(),any(),any())).willReturn(output); @@ -183,9 +187,10 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.count").description("미션 인증 횟수"), fieldWithPath("data.heartStatus").description("미션 인증 좋아요 상태"), fieldWithPath("data.hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data.contents").description("미션 인증 문구") + fieldWithPath("data.contents").description("미션 인증 문구"), + fieldWithPath("data.comments").description("미션 댓글 개수") - ) + ) ) ) .andReturn(); @@ -248,6 +253,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .heartStatus("[True/False]") .hearts(1L) .contents("contents") + .comments(1L) .build()); MyMissionArchiveRes output = MyMissionArchiveRes.builder() @@ -291,7 +297,8 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data.archives[].count").description("미션 인증 횟수"), fieldWithPath("data.archives[].heartStatus").description("미션 인증 좋아요 상태"), fieldWithPath("data.archives[].hearts").description("미션 인증 좋아요 수"), - fieldWithPath("data.archives[].contents").description("미션 인증 문구") + fieldWithPath("data.archives[].contents").description("미션 인증 문구"), + fieldWithPath("data.archives[].comments").description("미션 댓글 개수") ) diff --git a/src/test/java/com/moing/backend/domain/missionComment/domain/MissionRepositoryTest.java b/src/test/java/com/moing/backend/domain/missionComment/domain/MissionRepositoryTest.java new file mode 100644 index 00000000..ee4c9b6c --- /dev/null +++ b/src/test/java/com/moing/backend/domain/missionComment/domain/MissionRepositoryTest.java @@ -0,0 +1,22 @@ +package com.moing.backend.domain.missionComment.domain; + +import com.moing.backend.domain.missionComment.domain.repository.MissionCommentRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Transactional; + +@SpringBootTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ActiveProfiles("dev") +@Transactional +public class MissionRepositoryTest { + + @Autowired + MissionCommentRepository missionCommentRepository; + public void create_Mission_Comment(){ + + } + +} diff --git a/src/test/java/com/moing/backend/domain/missionComment/presentation/MissionCommentControllerTest.java b/src/test/java/com/moing/backend/domain/missionComment/presentation/MissionCommentControllerTest.java new file mode 100644 index 00000000..072bc3eb --- /dev/null +++ b/src/test/java/com/moing/backend/domain/missionComment/presentation/MissionCommentControllerTest.java @@ -0,0 +1,192 @@ +package com.moing.backend.domain.missionComment.presentation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest; +import com.moing.backend.domain.comment.application.dto.response.CommentBlocks; +import com.moing.backend.domain.comment.application.dto.response.CreateCommentResponse; +import com.moing.backend.domain.comment.application.dto.response.GetCommentResponse; +import com.moing.backend.domain.missionComment.application.service.CreateMissionCommentUseCase; +import com.moing.backend.domain.missionComment.application.service.DeleteMissionCommentUseCase; +import com.moing.backend.domain.missionComment.application.service.GetMissionCommentUseCase; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(MissionCommentController.class) +public class MissionCommentControllerTest extends CommonControllerTest { + + @MockBean + private CreateMissionCommentUseCase createMissionCommentUseCase; + @MockBean + private DeleteMissionCommentUseCase deleteMissionCommentUseCase; + @MockBean + private GetMissionCommentUseCase getMissionCommentUseCase; + + @Test + public void create_mission_comment() throws Exception { + + //given + Long teamId = 1L; + Long missionArchiveId = 1L; + CreateCommentRequest input = CreateCommentRequest.builder() + .content("게시글 내용") + .build(); + + String body = objectMapper.writeValueAsString(input); + + CreateCommentResponse output = CreateCommentResponse.builder() + .commentId(1L) + .build(); + + given(createMissionCommentUseCase.createBoardComment(any(), any(), any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + post("/api/{teamId}/{missionArchiveId}/mcomment", teamId, missionArchiveId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionArchiveId").description("미션 게시물 아이디") + ), + requestFields( + fieldWithPath("content").description("댓글 내용") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("댓글을 생성했습니다"), + fieldWithPath("data.commentId").description("생성한 boardCommentId") + ) + ) + ); + } + + @Test + public void delete_mission_comment() throws Exception { + + //given + Long teamId = 1L; + Long boardId = 1L; + Long missionArchiveId = 1L; + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + delete("/api/{teamId}/{missionArchiveId}/mcomment/{boardCommentId}", teamId, boardId, missionArchiveId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionArchiveId").description("미션 게시글 아이디"), + parameterWithName("boardCommentId").description("댓글 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("댓글을 삭제했습니다") + ) + ) + ); + } + + + @Test + public void get_board_comment_all() throws Exception { + //given + List commentBlocks = new ArrayList<>(); + Long teamId = 1L; + Long boardId = 1L; + + CommentBlocks commentBlock = CommentBlocks.builder() + .commentId(1L) + .content("댓글 내용") + .writerIsLeader(true) + .writerNickName("작성자 닉네임") + .writerProfileImage("작성자 프로필 이미지") + .writerIsDeleted(false) + .isWriter(true) + .createdDate("2023/12/05 23:29") + .makerId(1L) + .build(); + + commentBlocks.add(commentBlock); + + GetCommentResponse output = new GetCommentResponse(commentBlocks); + + given(getMissionCommentUseCase.getBoardCommentAll(any(), any(), any())).willReturn(output); + + + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/{teamId}/{missionArchiveId}/mcomment", teamId, boardId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + ); + + + //then + actions + .andExpect(status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + pathParameters( + parameterWithName("teamId").description("팀 아이디"), + parameterWithName("missionArchiveId").description("게시글 아이디") + ), + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description("댓글 목록을 모두 조회했습니다."), + fieldWithPath("data.commentBlocks[].commentId").description("댓글 아이디"), + fieldWithPath("data.commentBlocks[].content").description("댓글 내용"), + fieldWithPath("data.commentBlocks[].writerIsLeader").description("작성자 소모임장 여부"), + fieldWithPath("data.commentBlocks[].writerNickName").description("작성자 닉네임"), + fieldWithPath("data.commentBlocks[].writerProfileImage").description("작성자 프로필 이미지"), + fieldWithPath("data.commentBlocks[].writerIsDeleted").description("작성자 삭제 여부"), + fieldWithPath("data.commentBlocks[].isWriter").description("댓글 작성자 여부"), + fieldWithPath("data.commentBlocks[].createdDate").description("생성 시간"), + fieldWithPath("data.commentBlocks[].makerId").description("작성자 Id") + ) + + ) + ); + } +} From 6450a421d5b05b1d0a17274ab0e5337d4fa9ec40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 7 May 2024 01:13:21 +0900 Subject: [PATCH 574/619] =?UTF-8?q?fix=20:=20=EB=B0=98=EB=B3=B5=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EB=AA=A8=EC=95=84=EB=B3=B4=EA=B8=B0=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=9D=B8=EC=9B=90=EC=88=98=20=EB=A6=AC=ED=84=B4=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/domain/repository/MissionCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 8dc96cd1..ebf9471c 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -200,7 +200,7 @@ public Optional> findSingleMissionByMemberId(Long m .or(missionArchive.mission.type.eq(MissionType.ONCE)) ), - mission.team.numOfMember.longValue() + mission.team.numOfMember.stringValue() )) .from(mission) .leftJoin(missionArchive) From 67b954fb8cebf0aaadcf25ffe37188a54b83ad6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 7 May 2024 09:10:20 +0900 Subject: [PATCH 575/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=8B=9C=20commentNum=20=EB=94=94?= =?UTF-8?q?=ED=8F=B4=ED=8A=B8=EA=B0=92=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionArchive/application/mapper/MissionArchiveMapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 7dc09888..d9c4f86e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -29,6 +29,7 @@ public static MissionArchive mapToMissionArchive(MissionArchiveReq missionArchiv .mission(mission) .heartList(new ArrayList<>()) .contents(missionArchiveReq.getContents()) + .commentNum(0L) .build(); } From 8ed717dad7d0febffe5ee871f32616fdf12a9e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 7 May 2024 09:10:20 +0900 Subject: [PATCH 576/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=8B=9C=20commentNum=20=EB=94=94?= =?UTF-8?q?=ED=8F=B4=ED=8A=B8=EA=B0=92=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionArchive/application/mapper/MissionArchiveMapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index 7dc09888..d9c4f86e 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -29,6 +29,7 @@ public static MissionArchive mapToMissionArchive(MissionArchiveReq missionArchiv .mission(mission) .heartList(new ArrayList<>()) .contents(missionArchiveReq.getContents()) + .commentNum(0L) .build(); } From 58bcc3553430d251174ee920e39900c73b83e65d Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Thu, 9 May 2024 00:04:48 +0900 Subject: [PATCH 577/619] =?UTF-8?q?MNG-22=20fix=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20=EC=8A=A4=EC=BC=80=EC=A5=B4=EB=A7=81=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionScheduleUseCase.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java new file mode 100644 index 00000000..1223dba5 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java @@ -0,0 +1,44 @@ +package com.moing.backend.domain.mission.application.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +@Slf4j +@Service +@Transactional +@EnableAsync +@EnableScheduling +@RequiredArgsConstructor +@Profile("prod") +public class MissionScheduleUseCase { + + private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; + private final MissionUpdateUseCase missionUpdateUseCase; + + /** + * 단일 미션 마감 + * 해당 시간 미션 마감 + * 한시간 마다 실행 + */ + @Scheduled(cron = "0 1 * * * *") + public void singleMissionEndRoutine() { + missionUpdateUseCase.terminateMissionByAdmin(); + } + + /** + * 리마인드 알림 + * 인증하지 않은 미션이 있는 경우 알림 + * 매일 오후 8시 + */ + @Scheduled(cron = "0 0 20 * * *") + public void MissionRemindAlarm() { + missionRemindAlarmUseCase.sendRemindMissionAlarm(); + } +} \ No newline at end of file From 6cd134c72b85196157038b89bcad1c0481d9bb60 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Thu, 9 May 2024 00:05:28 +0900 Subject: [PATCH 578/619] =?UTF-8?q?MNG-22=20refactor=20:=20=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EA=B4=80=EB=A0=A8=20=EB=A9=94=EC=86=8C=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionRemindAlarmUseCase.java | 12 ++--- .../service/MissionTerminationUseCase.java | 48 ------------------- .../service/MissionUpdateUseCase.java | 18 +++---- .../MissionCustomRepositoryImpl.java | 4 +- .../presentation/MissionController.java | 17 ++----- .../representation/MissionControllerTest.java | 8 +--- 6 files changed, 18 insertions(+), 89 deletions(-) delete mode 100644 src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java index 5bcfa309..2a43ef79 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionRemindAlarmUseCase.java @@ -12,7 +12,6 @@ import com.moing.backend.global.config.fcm.dto.request.MultiRequest; import com.moing.backend.global.config.fcm.service.MultiMessageSender; import lombok.RequiredArgsConstructor; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.transaction.Transactional; @@ -31,7 +30,6 @@ public class MissionRemindAlarmUseCase { private final MissionArchiveScheduleQueryService missionArchiveScheduleQueryService; private final MissionQueryService missionQueryService; - private final ApplicationEventPublisher eventPublisher; private final MultiMessageSender multiMessageSender; private final SaveMultiAlarmHistoryUseCase saveMultiAlarmHistoryUseCase; @@ -39,7 +37,7 @@ public class MissionRemindAlarmUseCase { String REMIND_NAME = "미션 리마인드"; - public Boolean sendRemindMissionAlarm() { + public void sendRemindMissionAlarm() { Random random = new Random(System.currentTimeMillis()); String title = getTitle(random.nextInt(4)); @@ -50,16 +48,12 @@ public Boolean sendRemindMissionAlarm() { Optional> memberIdAndTokens = mapToMemberAndToken(remainMissionPeople); Optional> pushMemberIdAndToken = isPushMemberIdAndToken(remainMissionPeople); -// eventPublisher.publishEvent(new MultiFcmEvent(title, message, pushMemberIdAndToken, memberIdAndTokens, -// "",REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); - if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { multiMessageSender.send(new MultiRequest(pushMemberIdAndToken.get(), title, message, "", REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); } if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()),"",title,message,REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); } - return true; } @@ -137,7 +131,7 @@ public Boolean sendRepeatMissionRemindOnMonday() { } - public Optional> mapToMemberAndToken(List members) { + private Optional> mapToMemberAndToken(List members) { return Optional.of(members.stream() .map(member -> MemberIdAndToken.builder() .fcmToken(member.getFcmToken()) @@ -145,7 +139,7 @@ public Optional> mapToMemberAndToken(List members .build()) .collect(Collectors.toList())); } - public Optional> isPushMemberIdAndToken(List members) { + private Optional> isPushMemberIdAndToken(List members) { return Optional.of(members.stream() .map(member -> { if (member.isRemindPush() && !member.isSignOut()) { diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java deleted file mode 100644 index 243582d5..00000000 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.moing.backend.domain.mission.application.service; - -import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; -import com.moing.backend.domain.mission.domain.service.MissionQueryService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -@Service -@Transactional -@RequiredArgsConstructor -public class MissionTerminationUseCase { - - private final MemberGetService memberGetService; - private final MissionQueryService missionQueryService; - - // 스케쥴러에서 호출 - public void terminateMission() { - - List missionByDueTo = missionQueryService.findMissionByDueTo(); - - missionByDueTo.stream().forEach( - // 미션 종료 처리 - mission -> mission.updateStatus(MissionStatus.END) - - ); - } - - // 미션 점수 반영 -> MissionState - - - - // MissionState 조회 해서 미션 점수 현황조회 - - public void getMissionScoreStatus() { - - } - - // 팀별 점수 반영 - public void updateMissionScore() { - - } - -} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java index 37a42829..6e3f6bc6 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionUpdateUseCase.java @@ -10,8 +10,6 @@ import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.mission.domain.service.MissionSaveService; -import com.moing.backend.domain.mission.exception.NoAccessCreateMission; -import com.moing.backend.domain.mission.exception.NoAccessDeleteMission; import com.moing.backend.domain.mission.exception.NoAccessUpdateMission; import com.moing.backend.domain.team.domain.entity.Team; import lombok.RequiredArgsConstructor; @@ -19,6 +17,7 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.util.List; @Service @Transactional @@ -31,17 +30,12 @@ public class MissionUpdateUseCase { public MissionCreateRes updateMission(String userSocialId, Long missionId, MissionReq missionReq) { - Member member = memberGetService.getMemberBySocialId(userSocialId); Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); Long memberId = member.getMemberId(); - /** - * 미션 생성자 확인 - */ - if (!((memberId.equals(mission.getMakerId())) || memberId.equals(team.getLeaderId())) ) { throw new NoAccessUpdateMission(); } @@ -51,11 +45,11 @@ public MissionCreateRes updateMission(String userSocialId, Long missionId, Missi } - public MissionReadRes updateMissionStatus(String userSocialId, Long missionId) { - + public MissionReadRes terminateMissionByUser(String userSocialId, Long missionId) { Member member = memberGetService.getMemberBySocialId(userSocialId); Long memberId = member.getMemberId(); + Mission findMission = missionQueryService.findMissionById(missionId); Team team = findMission.getTeam(); @@ -69,4 +63,10 @@ public MissionReadRes updateMissionStatus(String userSocialId, Long missionId) { return MissionMapper.mapToMissionReadRes(findMission,member); } + + public void terminateMissionByAdmin() { + missionQueryService.findMissionByDueTo().stream().forEach( + mission -> mission.updateStatus(MissionStatus.END) + ); + } } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index ebf9471c..1baa1d3a 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -128,13 +128,11 @@ private JPQLQuery RepeatMissionDonePeopleByWeek(NumberPath missionId @Override public Optional> findMissionByDueTo() { - LocalDateTime now = LocalDateTime.now(); - return Optional.ofNullable(queryFactory .selectFrom(mission) .where( - mission.dueTo.before(now), mission.status.eq(MissionStatus.WAIT).or(mission.status.eq(MissionStatus.ONGOING)), + mission.dueTo.before(LocalDateTime.now()), mission.type.eq(MissionType.ONCE) ).fetch()); } diff --git a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java index f041b45b..56dccc52 100644 --- a/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java +++ b/src/main/java/com/moing/backend/domain/mission/presentation/MissionController.java @@ -20,14 +20,11 @@ @RequestMapping("/api/team/{teamId}/missions") public class MissionController { - private final MissionCreateUseCase missionCreateUseCase; private final MissionReadUseCase missionReadUseCase; private final MissionUpdateUseCase missionUpdateUseCase; private final MissionDeleteUseCase missionDeleteUseCase; -// private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; - /** * 미션 조회 * [GET] {teamId}/missions/{missionId} @@ -39,8 +36,6 @@ public ResponseEntity> getMission(@Authenticatio return ResponseEntity.ok(SuccessResponse.create(READ_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getMission(user.getSocialId(),missionId))); } - - /** * 미션 생성 * [POST] {teamId}/missions @@ -68,8 +63,8 @@ public ResponseEntity> updateMission(@Authenti * 작성자 : 정승연 */ @PutMapping("/{missionId}/end") - public ResponseEntity> endMission(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId,@PathVariable Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(END_MISSION_SUCCESS.getMessage(), this.missionUpdateUseCase.updateMissionStatus(user.getSocialId(),missionId))); + public ResponseEntity> terminateMission(@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, @PathVariable Long missionId) { + return ResponseEntity.ok(SuccessResponse.create(END_MISSION_SUCCESS.getMessage(), this.missionUpdateUseCase.terminateMissionByUser(user.getSocialId(),missionId))); } /** @@ -78,7 +73,7 @@ public ResponseEntity> endMission(@Authenticatio * 작성자 : 정승연 */ @DeleteMapping("/{missionId}") - public ResponseEntity> deleteMission(@AuthenticationPrincipal User user,@PathVariable Long missionId) { + public ResponseEntity> deleteMission(@AuthenticationPrincipal User user,@PathVariable("teamId") Long teamId,@PathVariable Long missionId) { return ResponseEntity.ok(SuccessResponse.create(DELETE_MISSION_SUCCESS.getMessage(), this.missionDeleteUseCase.deleteMission(user.getSocialId(),missionId))); } @@ -92,6 +87,7 @@ public ResponseEntity> deleteMission(@AuthenticationPrinci public ResponseEntity> recommendMission(@AuthenticationPrincipal User user,@PathVariable Long teamId) { return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionReadUseCase.getTeamCategory(teamId))); } + /** * 미션 추천 * [GET] {teamId}/missions/isLeader @@ -103,10 +99,6 @@ public ResponseEntity> isLeader(@AuthenticationPrincipa return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionCreateUseCase.getIsLeader(user.getSocialId(),teamId))); } -// @PostMapping("/remind") -// public ResponseEntity> remindAlarm(@AuthenticationPrincipal User user,@PathVariable Long teamId) { -// return ResponseEntity.ok(SuccessResponse.create(RECOMMEND_MISSION_SUCCESS.getMessage(), this.missionRemindAlarmUseCase.sendRepeatMissionRemind())); -// } /** * 미션 설명 확인 (미션 읽음 처리) @@ -124,5 +116,4 @@ public ResponseEntity> confirmMissionExplanat - } diff --git a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java index 83d8cc49..5ec529f4 100644 --- a/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mission/representation/MissionControllerTest.java @@ -9,19 +9,14 @@ import com.moing.backend.domain.mission.application.service.MissionDeleteUseCase; import com.moing.backend.domain.mission.application.service.MissionReadUseCase; import com.moing.backend.domain.mission.application.service.MissionUpdateUseCase; -import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.mission.domain.service.MissionQueryService; import com.moing.backend.domain.mission.presentation.MissionController; import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; -import org.springframework.restdocs.payload.JsonFieldType; import org.springframework.test.web.servlet.ResultActions; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import static com.moing.backend.domain.mission.presentation.constant.MissionResponseMessage.CONFIRM_MISSION_SUCCESS; @@ -35,7 +30,6 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @WebMvcTest(MissionController.class) public class MissionControllerTest extends CommonControllerTest { @@ -366,7 +360,7 @@ public class MissionControllerTest extends CommonControllerTest { .isLeader(Boolean.FALSE) .build(); - given(missionUpdateUseCase.updateMissionStatus(any(),any())).willReturn(output); + given(missionUpdateUseCase.terminateMissionByUser(any(),any())).willReturn(output); Long teamId = 2L; Long missionId = 1L; From aac3e5712bd3ae759c7c10ba4087fd0a46e62e3b Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 13 May 2024 23:20:54 +0900 Subject: [PATCH 579/619] =?UTF-8?q?MNG-20=20feat:=20=EB=AA=A8=EB=91=90?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B8=EC=A6=9D=20=ED=98=84=ED=99=A9=EC=97=90=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=9D=B8=EC=A6=9D=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/res/PersonalArchiveRes.java | 2 +- .../application/mapper/MissionArchiveMapper.java | 1 + .../representation/MissionArchiveControllerTest.java | 7 +++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java index 2d50538d..5ed6a0bb 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/res/PersonalArchiveRes.java @@ -28,6 +28,6 @@ public class PersonalArchiveRes { @Nullable private String contents; - + private Long comments; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java index d9c4f86e..6c4b40ae 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/mapper/MissionArchiveMapper.java @@ -88,6 +88,7 @@ public static PersonalArchiveRes mapToPersonalArchive(MissionArchive missionArch .count()) .makerId(missionArchive.getMember().getMemberId()) .contents(missionArchive.getContents()) + .comments(missionArchive.getCommentNum()) .build(); } diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java index ea12a408..d05c8dd6 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionArchiveControllerTest.java @@ -325,6 +325,7 @@ public class MissionArchiveControllerTest extends CommonControllerTest { .hearts(3) .makerId(1L) .contents("contents") + .comments(1L) .build()); given(missionArchiveReadUseCase.getPersonalArchive(any(),any())).willReturn(output); @@ -365,10 +366,12 @@ public class MissionArchiveControllerTest extends CommonControllerTest { fieldWithPath("data[].heartStatus").description("미션 인증 좋아요 상태 "), fieldWithPath("data[].hearts").description("미션 인증 좋아요 수 "), fieldWithPath("data[].makerId").description("미션 인증한 사람 "), - fieldWithPath("data[].contents").description("미션 인증 문구") + fieldWithPath("data[].contents").description("미션 인증 문구"), + fieldWithPath("data[].comments").description("미션 인증 댓글 수") - ) + + ) ) ) .andReturn(); From 2f41dc7a6e82380c906f963e3d45362b496ac9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 15 May 2024 17:36:48 +0900 Subject: [PATCH 580/619] =?UTF-8?q?fix=20:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EC=9E=AC=EC=9D=B8=EC=A6=9D(=EC=82=AD=EC=A0=9C)=20=EC=8B=9C=20?= =?UTF-8?q?=EC=97=B0=EA=B4=80=EA=B4=80=EA=B3=84=EC=97=90=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20missionComment=20=EC=82=AD=EC=A0=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionArchiveDeleteUseCase.java | 3 +++ .../domain/service/MissionArchiveDeleteService.java | 1 + .../domain/repository/MissionCommentRepository.java | 3 +++ .../domain/service/MissionCommentDeleteService.java | 4 ++++ 4 files changed, 11 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java index 362fec96..65e92852 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveDeleteUseCase.java @@ -12,6 +12,7 @@ import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; import com.moing.backend.domain.missionArchive.exception.NoAccessMissionArchiveException; +import com.moing.backend.domain.missionComment.domain.service.MissionCommentDeleteService; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; import com.moing.backend.domain.teamScore.application.service.TeamScoreUpdateUseCase; @@ -31,6 +32,7 @@ public class MissionArchiveDeleteUseCase { private final MissionArchiveQueryService missionArchiveQueryService; private final MissionArchiveDeleteService missionArchiveDeleteService; private final MissionQueryService missionQueryService; + private final MissionCommentDeleteService missionCommentDeleteService; private final MemberGetService memberGetService; private final TeamScoreUpdateUseCase teamScoreUpdateUseCase; @@ -61,6 +63,7 @@ public Long deleteArchive(String userSocialId, Long missionId,Long count) { updateUtils.deleteImgUrl(archive); } + missionCommentDeleteService.deleteAllCommentByMissionArchive(deleteArchive.getId()); missionArchiveDeleteService.deleteMissionArchive(deleteArchive); teamScoreUpdateUseCase.gainScoreOfArchive(mission, ScoreStatus.MINUS); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java index 3bb8f5c1..567f8ae9 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveDeleteService.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.repository.MissionArchiveRepository; +import com.moing.backend.domain.missionComment.domain.service.MissionCommentDeleteService; import com.moing.backend.global.annotation.DomainService; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentRepository.java b/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentRepository.java index 8c7d8e35..160b39a7 100644 --- a/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentRepository.java +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentRepository.java @@ -3,10 +3,13 @@ import com.moing.backend.domain.missionComment.domain.entity.MissionComment; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; import java.util.Optional; public interface MissionCommentRepository extends JpaRepository, MissionCommentCustomRepository { Optional findMissionCommentByMissionCommentId(Long missionCommentId); + void deleteAllMissionCommentsByMissionArchiveId(Long missionArchiveId); + } diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentDeleteService.java b/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentDeleteService.java index b41f541a..4a9ff9ec 100644 --- a/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentDeleteService.java +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/service/MissionCommentDeleteService.java @@ -15,4 +15,8 @@ public class MissionCommentDeleteService implements CommentDeleteService Date: Wed, 15 May 2024 19:36:50 +0900 Subject: [PATCH 581/619] =?UTF-8?q?MNG-24=20feat:=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=8D=BC=ED=8B=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/dto/response/UserProperty.java | 18 ++++++++++++++++++ .../dto/response/GetTeamResponse.java | 9 +++++++-- .../team/domain/service/TeamGetService.java | 2 +- .../team/presentation/TeamControllerTest.java | 9 ++++++++- 4 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/member/dto/response/UserProperty.java diff --git a/src/main/java/com/moing/backend/domain/member/dto/response/UserProperty.java b/src/main/java/com/moing/backend/domain/member/dto/response/UserProperty.java new file mode 100644 index 00000000..14eaa609 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/dto/response/UserProperty.java @@ -0,0 +1,18 @@ +package com.moing.backend.domain.member.dto.response; + +import com.moing.backend.domain.member.domain.constant.Gender; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class UserProperty { + private Gender gender; + private LocalDate birthDate; +} diff --git a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamResponse.java b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamResponse.java index bad378b3..3bacdbe8 100644 --- a/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamResponse.java +++ b/src/main/java/com/moing/backend/domain/team/application/dto/response/GetTeamResponse.java @@ -1,5 +1,7 @@ package com.moing.backend.domain.team.application.dto.response; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.member.dto.response.UserProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -16,13 +18,16 @@ public class GetTeamResponse { private String memberNickName; private Integer numOfTeam; private List teamBlocks = new ArrayList<>(); + private UserProperty userProperty; public GetTeamResponse(Integer numOfTeam, List teamBlocks) { this.numOfTeam=numOfTeam; this.teamBlocks = teamBlocks; } - public void updateMemberNickName(String memberNickName) { - this.memberNickName=memberNickName; + public void updateMemberInfo(Member member) { + this.memberNickName=member.getNickName(); + this.userProperty=new UserProperty(member.getGender(), member.getBirthDate()); + } } diff --git a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java index 360190f4..a89d672e 100644 --- a/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java +++ b/src/main/java/com/moing/backend/domain/team/domain/service/TeamGetService.java @@ -26,7 +26,7 @@ public class TeamGetService { public GetTeamResponse getTeamByMember(Member member) { GetTeamResponse getTeamResponse = teamRepository.findTeamByMemberId(member.getMemberId()); - getTeamResponse.updateMemberNickName(member.getNickName()); + getTeamResponse.updateMemberInfo(member); return getTeamResponse; } diff --git a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java index 7ccf996b..93a3fb28 100644 --- a/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java +++ b/src/test/java/com/moing/backend/domain/team/presentation/TeamControllerTest.java @@ -1,6 +1,8 @@ package com.moing.backend.domain.team.presentation; import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.member.domain.constant.Gender; +import com.moing.backend.domain.member.dto.response.UserProperty; import com.moing.backend.domain.team.application.dto.request.CreateTeamRequest; import com.moing.backend.domain.team.application.dto.request.UpdateTeamRequest; import com.moing.backend.domain.team.application.dto.response.*; @@ -12,6 +14,7 @@ import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; import org.springframework.test.web.servlet.ResultActions; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -129,10 +132,12 @@ public void get_team() throws Exception { teamBlocks.add(teamBlock1); teamBlocks.add(teamBlock2); + UserProperty userProperty=new UserProperty(Gender.WOMAN, LocalDate.of(2000, 3, 28)); GetTeamResponse output = GetTeamResponse.builder() .numOfTeam(1) .memberNickName("유저 닉네임") .teamBlocks(teamBlocks) + .userProperty(userProperty) .build(); given(getTeamUseCase.getTeam(any())).willReturn(output); @@ -167,7 +172,9 @@ public void get_team() throws Exception { fieldWithPath("data.teamBlocks[].category").description("소모임 카테고리"), fieldWithPath("data.teamBlocks[].startDate").description("소모임 시작일"), fieldWithPath("data.teamBlocks[].deletionTime").description("소모임 삭제 시간 (삭제 안했으면 null)"), - fieldWithPath("data.teamBlocks[].profileImgUrl").description("프로필 사진 url") + fieldWithPath("data.teamBlocks[].profileImgUrl").description("프로필 사진 url"), + fieldWithPath("data.userProperty.gender").description("유저 성별"), + fieldWithPath("data.userProperty.birthDate").description("유저 태어난 날") ) ) From 6395af7a36aeaa0319e31c7f766a578b5c4b0705 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Thu, 16 May 2024 23:16:23 +0900 Subject: [PATCH 582/619] =?UTF-8?q?MNG-20=20feat:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=8B=A0=EA=B3=A0=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/ReportCreateUseCase.java | 12 ++++++++++-- .../report/domain/entity/constant/ReportType.java | 2 +- .../report/presentation/ReportControllerTest.java | 7 +------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java index d96b35ee..5c6fa313 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java @@ -12,6 +12,8 @@ import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import com.moing.backend.domain.missionComment.domain.entity.MissionComment; +import com.moing.backend.domain.missionComment.domain.service.MissionCommentGetService; import com.moing.backend.domain.report.application.mapper.ReportMapper; import com.moing.backend.domain.report.domain.entity.Report; import com.moing.backend.domain.report.domain.entity.constant.ReportType; @@ -31,6 +33,7 @@ public class ReportCreateUseCase { private final BoardGetService boardGetService; private final MissionArchiveQueryService missionArchiveQueryService; private final BoardCommentGetService boardCommentGetService; + private final MissionCommentGetService missionCommentGetService; private final String REPORT_BOARD_TITLE ="신고 접수된 게시물입니다."; private final String REPORT_BOARD_MESSAGE ="신고 접수로 삭제된 게시물입니다."; @@ -53,12 +56,17 @@ public Long createReport(String socialId, Long targetId, String reportType) { .isNotice(board.isNotice()) .build()); } - else if (reportType.equals(ReportType.COMMENT.name())) { + else if (reportType.equals(ReportType.BCOMMENT.name())) { BoardComment boardComment = boardCommentGetService.getComment(targetId); targetMemberNickName = boardComment.getTeamMember().getMember().getNickName(); boardComment.updateContent(REPORT_BOARD_MESSAGE); - } else { + } else if(reportType.equals(ReportType.MCOMMENT.name())){ + MissionComment missionComment=missionCommentGetService.getComment(targetId); + targetMemberNickName=missionComment.getTeamMember().getMember().getNickName(); + missionComment.updateContent(REPORT_BOARD_MESSAGE); + } + else { MissionArchive missionArchive = missionArchiveQueryService.findByMissionArchiveId(targetId); Mission mission = missionArchive.getMission(); diff --git a/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java b/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java index 3d95530d..2dfe63d3 100644 --- a/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java +++ b/src/main/java/com/moing/backend/domain/report/domain/entity/constant/ReportType.java @@ -1,5 +1,5 @@ package com.moing.backend.domain.report.domain.entity.constant; public enum ReportType { - MISSION,BOARD,COMMENT + MISSION, BOARD, BCOMMENT, MCOMMENT } diff --git a/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java b/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java index 6d791bae..93e1953d 100644 --- a/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java +++ b/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java @@ -2,10 +2,7 @@ import com.moing.backend.config.CommonControllerTest; import com.moing.backend.domain.report.application.service.ReportCreateUseCase; -import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; -import com.moing.backend.domain.teamScore.presentation.TeamScoreController; import org.junit.jupiter.api.Test; -import org.mockito.Mock; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; @@ -14,8 +11,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.CREATE_REPORT_SUCCESS; -import static com.moing.backend.domain.teamScore.presentation.constant.TeamScoreResponseMessage.GET_TEAMSCORE_SUCCESS; -import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; @@ -59,7 +54,7 @@ public class ReportControllerTest extends CommonControllerTest { ), pathParameters( - parameterWithName("reportType").description("MISSION/BOARD/COMMENT"), + parameterWithName("reportType").description("MISSION/BOARD/BCOMMENT/MCOMMENT"), parameterWithName("targetId").description("신고할 board,missionArchive,comment 아이디") ), From ed3eee48fbce1ed7a0940d6f97363709b9a4b82d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Fri, 17 May 2024 09:06:04 +0900 Subject: [PATCH 583/619] =?UTF-8?q?hotfix=20fix=20:=20=EC=98=A4=EB=8A=98?= =?UTF-8?q?=20=EC=9D=B8=EC=A6=9D=20=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8?= =?UTF-8?q?=20=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index b222e0f2..5ef4b1f3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -371,7 +371,7 @@ public Boolean findMyArchivesToday(Long memberId, Long missionId) { .where( missionArchive.member.memberId.eq(memberId), missionArchive.mission.id.eq(missionId), - missionArchive.lastModifiedDate.between(startOfToday, endOfToday), // createdDate와 오늘의 시작과 끝을 비교, + missionArchive.createdDate.between(startOfToday, endOfToday), // createdDate와 오늘의 시작과 끝을 비교, missionArchive.mission.type.eq(MissionType.REPEAT).and(dateInRange) .or(missionArchive.mission.type.eq(MissionType.ONCE)) From d919cb25821405397fc2a25cdad842d79ea707ba Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Sun, 19 May 2024 17:47:43 +0900 Subject: [PATCH 584/619] =?UTF-8?q?MNG-22=20fix=20:=20=ED=95=9C=EB=B2=88?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=A0=95=EB=A0=AC=20=EA=B8=B0=EC=A4=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionCustomRepositoryImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 1baa1d3a..ac2a84d5 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -8,9 +8,12 @@ import com.moing.backend.domain.mission.domain.entity.QMission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.CaseBuilder; import com.querydsl.core.types.dsl.NumberPath; +import com.querydsl.core.types.dsl.SimpleExpression; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.JPQLQuery; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -211,10 +214,12 @@ public Optional> findSingleMissionByMemberId(Long m mission.status.eq(MissionStatus.ONGOING).or(mission.status.eq(MissionStatus.WAIT)), mission.type.eq(MissionType.ONCE) ) - .orderBy(mission.dueTo.asc()) + .orderBy(missionArchive.status.asc(),mission.dueTo.asc(),missionArchive.createdDate.desc()) .fetch()); } + + public boolean findRepeatMissionsByTeamId(Long teamId) { return queryFactory .select(mission) From 174b92a4e6e3a7990a8b0940b0dc676692e709f0 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 28 May 2024 00:08:50 +0900 Subject: [PATCH 585/619] =?UTF-8?q?refactor=20:=20=EC=8B=A0=EA=B3=A0?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20=EC=A0=84=EB=9E=B5?= =?UTF-8?q?=ED=8C=A8=ED=84=B4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/board/domain/entity/Board.java | 4 + .../domain/entity/BoardComment.java | 4 + .../domain/entity/MissionArchive.java | 3 + .../domain/entity/MissionComment.java | 4 + .../service/BoardCommentReportStrategy.java | 30 +++++++ .../service/BoardReportStrategy.java | 33 ++++++++ .../service/MissionArchiveReportStrategy.java | 50 ++++++++++++ .../service/MissionCommentReportStrategy.java | 31 ++++++++ .../service/ReportCreateUseCase.java | 79 ++----------------- .../application/service/ReportStrategy.java | 6 ++ .../report/presentation/ReportController.java | 13 ++- .../constant/ReportResponseMessage.java | 4 +- .../constant/StrategyCategory.java | 16 ++++ .../teamMember/domain/entity/TeamMember.java | 4 + .../presentation/ReportControllerTest.java | 1 - .../service/CreateTeamUseCaseTest.java | 12 +++ 16 files changed, 213 insertions(+), 81 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/report/application/service/BoardCommentReportStrategy.java create mode 100644 src/main/java/com/moing/backend/domain/report/application/service/BoardReportStrategy.java create mode 100644 src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java create mode 100644 src/main/java/com/moing/backend/domain/report/application/service/MissionCommentReportStrategy.java create mode 100644 src/main/java/com/moing/backend/domain/report/application/service/ReportStrategy.java create mode 100644 src/main/java/com/moing/backend/domain/report/presentation/constant/StrategyCategory.java create mode 100644 src/test/java/com/moing/backend/domain/team/application/service/CreateTeamUseCaseTest.java diff --git a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java index 7b6691ec..dc2b5899 100644 --- a/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java +++ b/src/main/java/com/moing/backend/domain/board/domain/entity/Board.java @@ -79,4 +79,8 @@ public void updateTeamMember(TeamMember teamMember) { public void updateTeam(Team team) { this.team = team; } + + public String getWriterNickName() { + return teamMember.getMemberNickName(); + } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java index 6a4092d4..6b39e57e 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/entity/BoardComment.java @@ -46,4 +46,8 @@ public void init(String content, boolean isLeader){ this.content=content; this.isLeader=isLeader; } + + public String getWriterNickName(){ + return teamMember.getMemberNickName(); + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index 2a60411f..71754b45 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -70,4 +70,7 @@ public void decrComNum() { } + public String getWriterNickName(){ + return member.getNickName(); + } } diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/entity/MissionComment.java b/src/main/java/com/moing/backend/domain/missionComment/domain/entity/MissionComment.java index a3941527..2cc87f50 100644 --- a/src/main/java/com/moing/backend/domain/missionComment/domain/entity/MissionComment.java +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/entity/MissionComment.java @@ -45,4 +45,8 @@ public void init(String content, boolean isLeader){ this.content=content; this.isLeader=isLeader; } + + public String getWriterNickName(){ + return teamMember.getMemberNickName(); + } } diff --git a/src/main/java/com/moing/backend/domain/report/application/service/BoardCommentReportStrategy.java b/src/main/java/com/moing/backend/domain/report/application/service/BoardCommentReportStrategy.java new file mode 100644 index 00000000..d3be8ffa --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/application/service/BoardCommentReportStrategy.java @@ -0,0 +1,30 @@ +package com.moing.backend.domain.report.application.service; + +import com.moing.backend.domain.boardComment.domain.entity.BoardComment; +import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.REPORT_MESSAGE; + +@Service +@Transactional +@RequiredArgsConstructor +public class BoardCommentReportStrategy implements ReportStrategy { + + + private final BoardCommentGetService boardCommentGetService; + + + @Override + public String processReport(Long targetId) { + BoardComment boardComment = boardCommentGetService.getComment(targetId); + boardComment.updateContent(REPORT_MESSAGE.getMessage()); + return getTargetMemberNickName(boardComment); + } + + private String getTargetMemberNickName(BoardComment boardComment){ + return boardComment.getWriterNickName(); + } +} diff --git a/src/main/java/com/moing/backend/domain/report/application/service/BoardReportStrategy.java b/src/main/java/com/moing/backend/domain/report/application/service/BoardReportStrategy.java new file mode 100644 index 00000000..a5cf41c1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/application/service/BoardReportStrategy.java @@ -0,0 +1,33 @@ +package com.moing.backend.domain.report.application.service; + +import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; +import com.moing.backend.domain.board.domain.entity.Board; +import com.moing.backend.domain.board.domain.service.BoardGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.REPORT_MESSAGE; + +@Service +@Transactional +@RequiredArgsConstructor +public class BoardReportStrategy implements ReportStrategy { + + private final BoardGetService boardGetService; + + @Override + public String processReport(Long targetId) { + Board board = boardGetService.getBoard(targetId); + board.updateBoard(UpdateBoardRequest.builder() + .title(REPORT_MESSAGE.getMessage()) + .content(REPORT_MESSAGE.getMessage()) + .isNotice(board.isNotice()) + .build()); + return getTargetMemberNickName(board); + } + + private String getTargetMemberNickName(Board board){ + return board.getWriterNickName(); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java b/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java new file mode 100644 index 00000000..6cce3fe7 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java @@ -0,0 +1,50 @@ +package com.moing.backend.domain.report.application.service; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.REPORT_MESSAGE; +import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.REPORT_PHOTO; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionArchiveReportStrategy implements ReportStrategy { + + + private final MissionArchiveQueryService missionArchiveQueryService; + + + @Override + public String processReport(Long targetId) { + MissionArchive missionArchive = missionArchiveQueryService.findByMissionArchiveId(targetId); + Mission mission = missionArchive.getMission(); + + if (mission.getWay().equals(MissionWay.PHOTO) && missionArchive.getStatus().equals(MissionArchiveStatus.COMPLETE)) { + missionArchive.updateArchive(MissionArchiveReq.builder() + .archive(REPORT_PHOTO.getMessage()) + .status(missionArchive.getStatus().name()) + .build()); + } else { + missionArchive.updateArchive(MissionArchiveReq.builder() + .archive(REPORT_MESSAGE.getMessage()) + .status(missionArchive.getStatus().name()) + .build()); + + } + + return getTargetMemberNickName(missionArchive); + } + + private String getTargetMemberNickName(MissionArchive missionArchive){ + return missionArchive.getWriterNickName(); + } + +} diff --git a/src/main/java/com/moing/backend/domain/report/application/service/MissionCommentReportStrategy.java b/src/main/java/com/moing/backend/domain/report/application/service/MissionCommentReportStrategy.java new file mode 100644 index 00000000..b9eab647 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/application/service/MissionCommentReportStrategy.java @@ -0,0 +1,31 @@ +package com.moing.backend.domain.report.application.service; + +import com.moing.backend.domain.missionComment.domain.entity.MissionComment; +import com.moing.backend.domain.missionComment.domain.service.MissionCommentGetService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.REPORT_MESSAGE; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionCommentReportStrategy implements ReportStrategy { + + + private final MissionCommentGetService missionCommentGetService; + + + @Override + public String processReport(Long targetId) { + MissionComment missionComment=missionCommentGetService.getComment(targetId); + missionComment.updateContent(REPORT_MESSAGE.getMessage()); + + return getTargetMemberNickName(missionComment); + } + + private String getTargetMemberNickName(MissionComment missionComment){ + return missionComment.getWriterNickName(); + } +} diff --git a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java index 5c6fa313..e3805608 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/ReportCreateUseCase.java @@ -1,95 +1,30 @@ package com.moing.backend.domain.report.application.service; -import com.moing.backend.domain.board.application.dto.request.UpdateBoardRequest; -import com.moing.backend.domain.board.domain.entity.Board; -import com.moing.backend.domain.board.domain.service.BoardGetService; -import com.moing.backend.domain.boardComment.domain.entity.BoardComment; -import com.moing.backend.domain.boardComment.domain.service.BoardCommentGetService; import com.moing.backend.domain.member.domain.service.MemberGetService; -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionWay; -import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; -import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; -import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; -import com.moing.backend.domain.missionComment.domain.entity.MissionComment; -import com.moing.backend.domain.missionComment.domain.service.MissionCommentGetService; import com.moing.backend.domain.report.application.mapper.ReportMapper; import com.moing.backend.domain.report.domain.entity.Report; -import com.moing.backend.domain.report.domain.entity.constant.ReportType; import com.moing.backend.domain.report.domain.service.ReportSaveService; +import com.moing.backend.domain.report.presentation.constant.StrategyCategory; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Map; + @Service @Transactional @RequiredArgsConstructor public class ReportCreateUseCase { private final ReportSaveService reportSaveService; + private final Map strategyMap; private final MemberGetService memberGetService; - private final BoardGetService boardGetService; - private final MissionArchiveQueryService missionArchiveQueryService; - private final BoardCommentGetService boardCommentGetService; - private final MissionCommentGetService missionCommentGetService; - - private final String REPORT_BOARD_TITLE ="신고 접수된 게시물입니다."; - private final String REPORT_BOARD_MESSAGE ="신고 접수로 삭제된 게시물입니다."; - private final String REPORT_MISSION_MESSAGE ="신고 접수로 삭제된 인증입니다."; - private final String REPORT_MISSION_PHOTO ="https://modagbul.s3.ap-northeast-2.amazonaws.com/reportImage.png"; - - public Long createReport(String socialId, Long targetId, String reportType) { + ReportStrategy strategy = strategyMap.get(StrategyCategory.valueOf(reportType).getStrategyName()); Long memberId = memberGetService.getMemberBySocialId(socialId).getMemberId(); - String targetMemberNickName = null ; - - if (reportType.equals(ReportType.BOARD.name())) { - Board board = boardGetService.getBoard(targetId); - - targetMemberNickName = board.getTeamMember().getMember().getNickName(); - - board.updateBoard(UpdateBoardRequest.builder() - .title(REPORT_BOARD_TITLE) - .content(REPORT_BOARD_MESSAGE) - .isNotice(board.isNotice()) - .build()); - } - else if (reportType.equals(ReportType.BCOMMENT.name())) { - BoardComment boardComment = boardCommentGetService.getComment(targetId); - targetMemberNickName = boardComment.getTeamMember().getMember().getNickName(); - boardComment.updateContent(REPORT_BOARD_MESSAGE); - - } else if(reportType.equals(ReportType.MCOMMENT.name())){ - MissionComment missionComment=missionCommentGetService.getComment(targetId); - targetMemberNickName=missionComment.getTeamMember().getMember().getNickName(); - missionComment.updateContent(REPORT_BOARD_MESSAGE); - } - else { - - MissionArchive missionArchive = missionArchiveQueryService.findByMissionArchiveId(targetId); - Mission mission = missionArchive.getMission(); - - targetMemberNickName = missionArchive.getMember().getNickName(); - - if (mission.getWay().equals(MissionWay.PHOTO) && missionArchive.getStatus().equals(MissionArchiveStatus.COMPLETE)) { - missionArchive.updateArchive(MissionArchiveReq.builder() - .archive(REPORT_MISSION_PHOTO) - .status(missionArchive.getStatus().name()) - .build()); - } else { - missionArchive.updateArchive(MissionArchiveReq.builder() - .archive(REPORT_MISSION_MESSAGE) - .status(missionArchive.getStatus().name()) - .build()); - - } - - } - - Report save = reportSaveService.save(ReportMapper.mapToReport(memberId, targetId, reportType,targetMemberNickName)); - + String targetMemberNickName= strategy.processReport(targetId); + Report save = reportSaveService.save(ReportMapper.mapToReport(memberId, targetId, reportType, targetMemberNickName)); return save.getTargetId(); } } diff --git a/src/main/java/com/moing/backend/domain/report/application/service/ReportStrategy.java b/src/main/java/com/moing/backend/domain/report/application/service/ReportStrategy.java new file mode 100644 index 00000000..45f1f2d3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/application/service/ReportStrategy.java @@ -0,0 +1,6 @@ +package com.moing.backend.domain.report.application.service; + +public interface ReportStrategy { + String processReport(Long targetId); + +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java b/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java index b0332b5e..957757d1 100644 --- a/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java +++ b/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java @@ -1,21 +1,20 @@ package com.moing.backend.domain.report.presentation; -import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.report.application.service.ReportCreateUseCase; -import com.moing.backend.domain.report.domain.entity.Report; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.CREATE_ARCHIVE_SUCCESS; import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.CREATE_REPORT_SUCCESS; @RestController -@AllArgsConstructor +@RequiredArgsConstructor @RequestMapping("/api/report") public class ReportController { diff --git a/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java b/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java index 60f5aa47..e5d9133a 100644 --- a/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java @@ -7,7 +7,9 @@ @RequiredArgsConstructor public enum ReportResponseMessage { - CREATE_REPORT_SUCCESS("게시글 신고를 완료 했습니다."); + CREATE_REPORT_SUCCESS("게시글 신고를 완료 했습니다."), + REPORT_MESSAGE("신고 접수로 삭제되었습니다."), + REPORT_PHOTO("https://modagbul.s3.ap-northeast-2.amazonaws.com/reportImage.png"); private final String message; diff --git a/src/main/java/com/moing/backend/domain/report/presentation/constant/StrategyCategory.java b/src/main/java/com/moing/backend/domain/report/presentation/constant/StrategyCategory.java new file mode 100644 index 00000000..b2acdf43 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/report/presentation/constant/StrategyCategory.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.report.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum StrategyCategory { + + BCOMMENT("boardCommentReportStrategy"), + BOARD("boardReportStrategy"), + MISSION("missionArchiveReportStrategy"), + MCOMMENT("missionCommentReportStrategy"); + + private final String strategyName; +} diff --git a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java index 9d7aa88e..d2ef4648 100644 --- a/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java +++ b/src/main/java/com/moing/backend/domain/teamMember/domain/entity/TeamMember.java @@ -48,4 +48,8 @@ public void deleteMember(Team team) { this.isDeleted = true; team.deleteTeamMember(); } + + public String getMemberNickName(){ + return member.getNickName(); + } } diff --git a/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java b/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java index 93e1953d..9437efa5 100644 --- a/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java +++ b/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java @@ -1,7 +1,6 @@ package com.moing.backend.domain.report.presentation; import com.moing.backend.config.CommonControllerTest; -import com.moing.backend.domain.report.application.service.ReportCreateUseCase; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; diff --git a/src/test/java/com/moing/backend/domain/team/application/service/CreateTeamUseCaseTest.java b/src/test/java/com/moing/backend/domain/team/application/service/CreateTeamUseCaseTest.java new file mode 100644 index 00000000..e38801c2 --- /dev/null +++ b/src/test/java/com/moing/backend/domain/team/application/service/CreateTeamUseCaseTest.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.team.application.service; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class CreateTeamUseCaseTest { + + @Test + void createTeam() { + } +} \ No newline at end of file From 4ffc33556e45b076af6444865a0dc59df3493739 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Tue, 28 May 2024 00:17:43 +0900 Subject: [PATCH 586/619] =?UTF-8?q?fix:=20import=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/report/presentation/ReportController.java | 4 ++-- .../domain/report/presentation/ReportControllerTest.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java b/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java index 957757d1..5489aedb 100644 --- a/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java +++ b/src/main/java/com/moing/backend/domain/report/presentation/ReportController.java @@ -3,7 +3,7 @@ import com.moing.backend.domain.report.application.service.ReportCreateUseCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; -import lombok.RequiredArgsConstructor; +import lombok.AllArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.PathVariable; @@ -14,7 +14,7 @@ import static com.moing.backend.domain.report.presentation.constant.ReportResponseMessage.CREATE_REPORT_SUCCESS; @RestController -@RequiredArgsConstructor +@AllArgsConstructor @RequestMapping("/api/report") public class ReportController { diff --git a/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java b/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java index 9437efa5..93e1953d 100644 --- a/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java +++ b/src/test/java/com/moing/backend/domain/report/presentation/ReportControllerTest.java @@ -1,6 +1,7 @@ package com.moing.backend.domain.report.presentation; import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.report.application.service.ReportCreateUseCase; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; From bae92a1b2ccd878ba805ff8c3b8a1e1236e49882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 28 May 2024 09:22:27 +0900 Subject: [PATCH 587/619] =?UTF-8?q?MNG-20=20fix=20:=20missionArchive=20rep?= =?UTF-8?q?ortStrategy=20=EA=B0=84=EC=86=8C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../missionArchive/domain/entity/MissionArchive.java | 4 ++++ .../service/MissionArchiveReportStrategy.java | 11 +++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java index 71754b45..558a6089 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/entity/MissionArchive.java @@ -57,6 +57,10 @@ public void updateArchive(MissionArchiveReq missionArchiveReq) { this.status = MissionArchiveStatus.valueOf(missionArchiveReq.getStatus()); } + public void updateArchive(String archive) { + this.archive = archive; + } + public void updateCount(Long count) { this.count = count; } diff --git a/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java b/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java index 6cce3fe7..2313f6ee 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java @@ -28,15 +28,10 @@ public String processReport(Long targetId) { Mission mission = missionArchive.getMission(); if (mission.getWay().equals(MissionWay.PHOTO) && missionArchive.getStatus().equals(MissionArchiveStatus.COMPLETE)) { - missionArchive.updateArchive(MissionArchiveReq.builder() - .archive(REPORT_PHOTO.getMessage()) - .status(missionArchive.getStatus().name()) - .build()); + missionArchive.updateArchive(REPORT_PHOTO.getMessage()); + } else { - missionArchive.updateArchive(MissionArchiveReq.builder() - .archive(REPORT_MESSAGE.getMessage()) - .status(missionArchive.getStatus().name()) - .build()); + missionArchive.updateArchive(REPORT_MESSAGE.getMessage()); } From 57893f5e2cee8866bc2683f5bf903e7b0b76ab76 Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 28 May 2024 23:01:07 +0900 Subject: [PATCH 588/619] =?UTF-8?q?MNG-20=20fix=20:=20=EA=B0=80=EB=8F=85?= =?UTF-8?q?=EC=84=B1=EA=B3=BC=20=EC=9C=A0=EC=A7=80=EB=B3=B4=EC=88=98?= =?UTF-8?q?=EC=84=B1=EC=9D=84=20=EC=9C=84=ED=95=9C=20if-else=20=EB=AC=B8?= =?UTF-8?q?=20=EC=A1=B0=EA=B1=B4=20=ED=95=A8=EC=88=98=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionArchiveReportStrategy.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java b/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java index 2313f6ee..7d50559c 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java @@ -25,14 +25,11 @@ public class MissionArchiveReportStrategy implements ReportStrategy { @Override public String processReport(Long targetId) { MissionArchive missionArchive = missionArchiveQueryService.findByMissionArchiveId(targetId); - Mission mission = missionArchive.getMission(); - if (mission.getWay().equals(MissionWay.PHOTO) && missionArchive.getStatus().equals(MissionArchiveStatus.COMPLETE)) { + if (isCompletePhotoMission(missionArchive)) { missionArchive.updateArchive(REPORT_PHOTO.getMessage()); - } else { missionArchive.updateArchive(REPORT_MESSAGE.getMessage()); - } return getTargetMemberNickName(missionArchive); @@ -42,4 +39,7 @@ private String getTargetMemberNickName(MissionArchive missionArchive){ return missionArchive.getWriterNickName(); } + private Boolean isCompletePhotoMission(MissionArchive archive) { + return archive.getMission().getWay().equals(MissionWay.PHOTO) && archive.getStatus().equals(MissionArchiveStatus.COMPLETE); + } } From 2a4e1c9e4acd07db01dde022764a70cd0d423b1a Mon Sep 17 00:00:00 2001 From: seungyeonnnnnni Date: Tue, 28 May 2024 23:07:25 +0900 Subject: [PATCH 589/619] =?UTF-8?q?MNG-20=20fix=20:=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/MissionArchiveReportStrategy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java b/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java index 7d50559c..c2485915 100644 --- a/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java +++ b/src/main/java/com/moing/backend/domain/report/application/service/MissionArchiveReportStrategy.java @@ -26,7 +26,7 @@ public class MissionArchiveReportStrategy implements ReportStrategy { public String processReport(Long targetId) { MissionArchive missionArchive = missionArchiveQueryService.findByMissionArchiveId(targetId); - if (isCompletePhotoMission(missionArchive)) { + if (isCompletedPhotoArchive(missionArchive)) { missionArchive.updateArchive(REPORT_PHOTO.getMessage()); } else { missionArchive.updateArchive(REPORT_MESSAGE.getMessage()); @@ -39,7 +39,7 @@ private String getTargetMemberNickName(MissionArchive missionArchive){ return missionArchive.getWriterNickName(); } - private Boolean isCompletePhotoMission(MissionArchive archive) { + private Boolean isCompletedPhotoArchive (MissionArchive archive) { return archive.getMission().getWay().equals(MissionWay.PHOTO) && archive.getStatus().equals(MissionArchiveStatus.COMPLETE); } } From a05c79f7b2ceecbd2ccaa8b43b700acc13083140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 5 Jun 2024 09:11:49 +0900 Subject: [PATCH 590/619] =?UTF-8?q?hotfix=20:=20v.1.0.7=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=ED=91=B8=EC=8B=9C=EC=95=8C?= =?UTF-8?q?=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/UpdateRemindAlarmUseCase.java | 2 +- .../application/service/MissionScheduleUseCase.java | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java index 0f535603..b039e9b8 100644 --- a/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java @@ -41,7 +41,7 @@ public class UpdateRemindAlarmUseCase { public Boolean sendUpdateAppPushAlarm() { String title = "MOING 업데이트 소식"; - String message = "이제 누구나 미션을 만들 수 있어요. 지금 업데이트하고 다른 소식도 확인해보세요!"; + String message = "이제 사진 인증에 설명을 추가할 수 있어요. 지금 업데이트하고 다른 소식도 확인해보세요!"; List allMemberOfPushAlarm = memberGetService.getAllMemberOfPushAlarm(); diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java index 1223dba5..f38058fe 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.mission.application.service; +import com.moing.backend.domain.member.application.service.UpdateRemindAlarmUseCase; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Profile; @@ -21,6 +22,7 @@ public class MissionScheduleUseCase { private final MissionRemindAlarmUseCase missionRemindAlarmUseCase; private final MissionUpdateUseCase missionUpdateUseCase; + private final UpdateRemindAlarmUseCase updateRemindAlarmUseCase; /** * 단일 미션 마감 @@ -41,4 +43,9 @@ public void singleMissionEndRoutine() { public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } + + @Scheduled(cron = "0 30 11 * * *") + public void UpdateRemindAlarm() { + updateRemindAlarmUseCase.sendUpdateAppPushAlarm(); + } } \ No newline at end of file From c8968133395117ade3eeb3d7fca924cf6cbf10c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonn-i@users.noreply.github.com> Date: Wed, 5 Jun 2024 09:22:25 +0900 Subject: [PATCH 591/619] =?UTF-8?q?hotfix=20:=20=ED=91=B8=EC=8B=9C?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=8B=9C=EA=B0=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionScheduleUseCase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java index f38058fe..5fa36e89 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java @@ -44,8 +44,8 @@ public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } - @Scheduled(cron = "0 30 11 * * *") + @Scheduled(cron = "0 00 11 * * *") public void UpdateRemindAlarm() { updateRemindAlarmUseCase.sendUpdateAppPushAlarm(); } -} \ No newline at end of file +} From 0a0a93ed7a5997bf3698595352053d0dc92a2839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonn-i@users.noreply.github.com> Date: Wed, 5 Jun 2024 09:25:15 +0900 Subject: [PATCH 592/619] =?UTF-8?q?hotfix=20:=20=ED=91=B8=EC=8B=9C?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=8B=9C=EA=B0=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionScheduleUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java index 5fa36e89..d2daa232 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java @@ -44,7 +44,7 @@ public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } - @Scheduled(cron = "0 00 11 * * *") + @Scheduled(cron = "0 0 11 * * *") public void UpdateRemindAlarm() { updateRemindAlarmUseCase.sendUpdateAppPushAlarm(); } From 7805b8d61f31250ad07a8dfc042d8a4ac5bec5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 5 Jun 2024 11:44:14 +0900 Subject: [PATCH 593/619] =?UTF-8?q?hotfix=20:=20FCM=20=EB=B0=9C=EC=86=A1?= =?UTF-8?q?=20=EC=A0=9C=ED=95=9C=EC=9C=BC=EB=A1=9C=20500=EB=AA=85=EC=94=A9?= =?UTF-8?q?=20=EB=82=98=EB=88=A0=EC=84=9C=20=EB=B3=B4=EB=82=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/UpdateRemindAlarmUseCase.java | 23 ++++++++++++++++--- .../service/MissionScheduleUseCase.java | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java index b039e9b8..df48d899 100644 --- a/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java @@ -45,8 +45,13 @@ public Boolean sendUpdateAppPushAlarm() { List allMemberOfPushAlarm = memberGetService.getAllMemberOfPushAlarm(); - Optional> memberIdAndTokens = mapToMemberAndToken(allMemberOfPushAlarm); - Optional> pushMemberIdAndToken = isPushMemberIdAndToken(allMemberOfPushAlarm); + // TODO : 500명 단위 배치처리 + + // FCM 제한으로 500명씩 나눠서 보내기 (0~498) + List firstMembers = allMemberOfPushAlarm.subList(0, 498); + + Optional> memberIdAndTokens = mapToMemberAndToken(firstMembers); + Optional> pushMemberIdAndToken = isPushMemberIdAndToken(firstMembers); if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { multiMessageSender.send(new MultiRequest(pushMemberIdAndToken.get(), title, message, "", REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); @@ -54,8 +59,20 @@ public Boolean sendUpdateAppPushAlarm() { if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); } - return true; + // FCM 제한으로 500명씩 나눠서 보내기 (498~) + List remainMembers = allMemberOfPushAlarm.subList(499, allMemberOfPushAlarm.size()); + + Optional> memberIdAndTokens2 = mapToMemberAndToken(remainMembers); + Optional> pushMemberIdAndToken2 = isPushMemberIdAndToken(remainMembers); + + if (pushMemberIdAndToken2.isPresent() && !pushMemberIdAndToken2.get().isEmpty()) { + multiMessageSender.send(new MultiRequest(pushMemberIdAndToken2.get(), title, message, "", REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + } + if (memberIdAndTokens2.isPresent() && !memberIdAndTokens2.get().isEmpty()) { + saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens2.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); + } + return true; } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java index f38058fe..f3fe7125 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java @@ -44,7 +44,7 @@ public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } - @Scheduled(cron = "0 30 11 * * *") + @Scheduled(cron = "0 0 14 * * *") public void UpdateRemindAlarm() { updateRemindAlarmUseCase.sendUpdateAppPushAlarm(); } From 25b203403576302b943d9fc8e56aba9993a815d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonn-i@users.noreply.github.com> Date: Thu, 6 Jun 2024 09:37:42 +0900 Subject: [PATCH 594/619] =?UTF-8?q?hotfix=20:=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=ED=91=B8=EC=8B=9C=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=8A=A4=EC=BC=80=EC=A5=B4=EB=A7=81=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mission/application/service/MissionScheduleUseCase.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java index f3fe7125..2de1f76d 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionScheduleUseCase.java @@ -44,8 +44,4 @@ public void MissionRemindAlarm() { missionRemindAlarmUseCase.sendRemindMissionAlarm(); } - @Scheduled(cron = "0 0 14 * * *") - public void UpdateRemindAlarm() { - updateRemindAlarmUseCase.sendUpdateAppPushAlarm(); - } } \ No newline at end of file From 99a592729bd4cdbfd58aa005346b67b9312c8db1 Mon Sep 17 00:00:00 2001 From: seungueonn Date: Sun, 23 Jun 2024 18:18:23 +0900 Subject: [PATCH 595/619] =?UTF-8?q?MNG-25=20feat=20:=20=EB=B6=88=EB=8D=98?= =?UTF-8?q?=EC=A7=80=EA=B8=B0=20=ED=91=B8=EC=8B=9C=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=B6=94=EA=B0=80=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20entity=20=EC=B9=BC=EB=9F=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/moing/backend/domain/fire/domain/entity/Fire.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java b/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java index 9b32a630..d4f2cbf9 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java @@ -25,4 +25,7 @@ public class Fire extends BaseTimeEntity { private Long receiveMemberId; + @Column(nullable = true, columnDefinition="TEXT", length = 100) + private String message; + } From 444580ac866f45d4893fb4c6eae51d7df04a4fed Mon Sep 17 00:00:00 2001 From: seungueonn Date: Sun, 23 Jun 2024 18:18:56 +0900 Subject: [PATCH 596/619] =?UTF-8?q?MNG-25=20feat=20:=20=EB=B6=88=EB=8D=98?= =?UTF-8?q?=EC=A7=80=EA=B8=B0=20=ED=91=B8=EC=8B=9C=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=B6=94=EA=B0=80=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/dto/req/FireThrowReq.java | 19 +++++++++++++++ .../service/FireThrowAlarmUseCase.java | 23 +++++++++++-------- .../application/service/FireThrowUseCase.java | 13 +++++++---- .../fire/presentation/FireController.java | 5 ++-- .../config/fcm/constant/FireThrowMessage.java | 16 ++++++++++--- .../representation/FireControllerTest.java | 11 ++++++++- 6 files changed, 67 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java diff --git a/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java b/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java new file mode 100644 index 00000000..b0845e15 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java @@ -0,0 +1,19 @@ +package com.moing.backend.domain.fire.application.dto.req; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.annotation.Nullable; + + +@AllArgsConstructor +@Builder +@NoArgsConstructor +@Getter +public class FireThrowReq { + + @Nullable + private String message; +} diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java index ca28e88a..4955176a 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -24,28 +24,31 @@ public class FireThrowAlarmUseCase { private final ApplicationEventPublisher eventPublisher; - public void sendFireThrowAlarm(Member throwMember, Member receiveMember, Team team, Mission mission) { + public void sendFireThrowAlarm(Member throwMember, Member receiveMember, Team team, Mission mission, String message) { - Random random = new Random(System.currentTimeMillis()); - int randomNum = random.nextInt(2); + int randomNum = new Random(System.currentTimeMillis()).nextInt(2); - String title = getTitle(throwMember.getNickName(), receiveMember.getNickName(), randomNum); - String message = getMessage(throwMember.getNickName(), receiveMember.getNickName(), randomNum); + String title = message != null ? NEW_FIRE_THROW_TITLE_WITH_COMMENT.to(throwMember.getNickName()) + : getRandomTitle(throwMember.getNickName(), receiveMember.getNickName(), randomNum); + message = message != null ? message + : getRandomMessage(throwMember.getNickName(), receiveMember.getNickName(), randomNum); String idInfo = createIdInfo(mission.getType() == MissionType.REPEAT, mission.getTeam().getTeamId(), mission.getId()); eventPublisher.publishEvent(new SingleFcmEvent(receiveMember, title, message, idInfo, team.getName(), AlarmType.FIRE, MISSION_PATH.getValue(), receiveMember.isFirePush())); } - public String getMessage(String pusher, String receiver, int num) { + public String getRandomMessage(String pusher, String receiver, int num) { switch (num) { - case 0: return pusher + "님이 " + receiver + NEW_FIRE_THROW_MESSAGE1.getMessage(); - case 1: return receiver + "님! " + pusher + NEW_FIRE_THROW_MESSAGE2.getMessage(); + case 0: + return NEW_FIRE_THROW_MESSAGE1.fromTo(pusher, receiver); + case 1: return NEW_FIRE_THROW_MESSAGE2.toFrom(receiver, pusher); + } - return pusher + "님이" + receiver + NEW_FIRE_THROW_MESSAGE1.getMessage(); + return NEW_FIRE_THROW_MESSAGE1.fromTo(pusher, receiver); } - public String getTitle(String pusher, String receiver, int num) { + public String getRandomTitle(String pusher, String receiver, int num) { switch (num) { case 0: diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java index 7fd5015b..fc1b0501 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.fire.application.service; +import com.moing.backend.domain.fire.application.dto.req.FireThrowReq; import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; import com.moing.backend.domain.fire.application.mapper.FireMapper; @@ -19,6 +20,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Optional; @Service @Transactional @@ -33,7 +35,7 @@ public class FireThrowUseCase { private final MissionQueryService missionQueryService; private final TeamGetService teamGetService; - public FireThrowRes createFireThrow(String userId, Long receiveMemberId, Long missionId, Long teamId) { + public FireThrowRes createFireThrow(String userId, Long receiveMemberId, Long missionId, Long teamId, FireThrowReq fireThrowReq) { Member throwMember = memberGetService.getMemberBySocialId(userId); Member receiveMember = memberGetService.getMemberByMemberId(receiveMemberId); @@ -50,12 +52,15 @@ public FireThrowRes createFireThrow(String userId, Long receiveMemberId, Long mi throw new NoAuthThrowFireException(); } - fireThrowAlarmUseCase.sendFireThrowAlarm(throwMember, receiveMember, team, mission); + fireThrowAlarmUseCase.sendFireThrowAlarm(throwMember, receiveMember, team, mission, fireThrowReq.getMessage()); - return FireMapper.mapToFireThrowRes(fireSaveService.save(Fire.builder() + Fire save = fireSaveService.save(Fire.builder() .throwMemberId(throwMember.getMemberId()) .receiveMemberId(receiveMemberId) - .build())); + .message(fireThrowReq.getMessage()) + .build()); + + return FireMapper.mapToFireThrowRes(fireSaveService.save(save)); } public List getFireReceiveList(String userId,Long teamId, Long missionId) { diff --git a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java index 5de8aa94..576a705f 100644 --- a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java +++ b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.fire.presentation; +import com.moing.backend.domain.fire.application.dto.req.FireThrowReq; import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; import com.moing.backend.domain.fire.application.service.FireThrowUseCase; @@ -30,8 +31,8 @@ public class FireController { @PostMapping("/{receiveMemberId}") public ResponseEntity> throwFire (@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, - @PathVariable("receiveMemberId") Long receiveMemberId, @PathVariable("missionId") Long missionId) { - return ResponseEntity.ok(SuccessResponse.create(THROW_FIRE_SUCCESS.getMessage(), this.fireThrowUseCase.createFireThrow(user.getSocialId(), receiveMemberId, missionId, teamId))); + @PathVariable("receiveMemberId") Long receiveMemberId, @PathVariable("missionId") Long missionId, @RequestBody FireThrowReq fireThrowReq) { + return ResponseEntity.ok(SuccessResponse.create(THROW_FIRE_SUCCESS.getMessage(), this.fireThrowUseCase.createFireThrow(user.getSocialId(), receiveMemberId, missionId, teamId, fireThrowReq))); } /** diff --git a/src/main/java/com/moing/backend/global/config/fcm/constant/FireThrowMessage.java b/src/main/java/com/moing/backend/global/config/fcm/constant/FireThrowMessage.java index dbfb2f79..ef720ec8 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/constant/FireThrowMessage.java +++ b/src/main/java/com/moing/backend/global/config/fcm/constant/FireThrowMessage.java @@ -10,14 +10,24 @@ public enum FireThrowMessage { NEW_FIRE_THROW_TITLE1("어라… 왜 이렇게 발등이 뜨겁지?\uD83E\uDD28"), NEW_FIRE_THROW_TITLE2("⚠\uFE0F불조심⚠\uFE0F "), + NEW_FIRE_THROW_TITLE_WITH_COMMENT("%s님이 불을 던졌어요!"), - NEW_FIRE_THROW_MESSAGE1("님에게 불을 던졌어요! 어서 미션을 인증해볼까요?"), - NEW_FIRE_THROW_MESSAGE2("님이 던진 불에 타버릴지도 몰라요! 어서 인증하러갈까요?"); - + NEW_FIRE_THROW_MESSAGE1("%s님이 %s님에게 불을 던졌어요! 어서 미션을 인증해볼까요?"), + NEW_FIRE_THROW_MESSAGE2("%s님! %s님이 던진 불에 타버릴지도 몰라요! 어서 인증하러갈까요?"); private final String message; + public String to(String pusher) { + return String.format(message, pusher); + } + public String fromTo(String pusher,String receiver) { + return String.format(message, pusher,receiver); + } + public String toFrom(String receiver,String pusher) { + return String.format(message, receiver,pusher); + } + } diff --git a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java index 0cdd119b..c7d78bb6 100644 --- a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java +++ b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java @@ -1,10 +1,12 @@ package com.moing.backend.domain.fire.representation; import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.fire.application.dto.req.FireThrowReq; import com.moing.backend.domain.fire.application.dto.res.FireReceiveRes; import com.moing.backend.domain.fire.application.dto.res.FireThrowRes; import com.moing.backend.domain.fire.application.service.FireThrowUseCase; import com.moing.backend.domain.fire.presentation.FireController; +import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -89,11 +91,17 @@ public class FireControllerTest extends CommonControllerTest { public void 불_던지기() throws Exception { //given + FireThrowReq input = FireThrowReq.builder() + .message("message") + .build(); + + String body = objectMapper.writeValueAsString(input); + FireThrowRes output = FireThrowRes.builder() .receiveMemberId(1L) .build(); - given(fireThrowUseCase.createFireThrow(any(), any(), any(), any())).willReturn(output); + given(fireThrowUseCase.createFireThrow(any(), any(), any(), any(),any())).willReturn(output); Long teamId = 2L; Long missionId = 2L; @@ -103,6 +111,7 @@ public class FireControllerTest extends CommonControllerTest { post("/api/team/{teamId}/missions/{missionId}/fire/{receiveMemberId}",teamId,missionId,receiveMemberId) .header("Authorization", "Bearer ACCESS_TOKEN") .contentType(MediaType.APPLICATION_JSON) + .content(body) ); //then From e43d564ff7e923df80c3a33913f547f86b6e22ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:15:15 +0900 Subject: [PATCH 597/619] =?UTF-8?q?feat=20:=20=EB=B6=88=20=EB=8D=98?= =?UTF-8?q?=EC=A7=80=EA=B8=B0=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EC=95=88=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fire/application/service/FireThrowAlarmUseCase.java | 7 ++++--- .../domain/fire/application/service/FireThrowUseCase.java | 3 +-- .../com/moing/backend/domain/fire/domain/entity/Fire.java | 4 ++-- .../backend/domain/fire/presentation/FireController.java | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java index 4955176a..ba2c35c4 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -1,5 +1,6 @@ package com.moing.backend.domain.fire.application.service; +import com.moing.backend.domain.fire.application.dto.req.FireThrowReq; import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; @@ -24,13 +25,13 @@ public class FireThrowAlarmUseCase { private final ApplicationEventPublisher eventPublisher; - public void sendFireThrowAlarm(Member throwMember, Member receiveMember, Team team, Mission mission, String message) { + public void sendFireThrowAlarm(Member throwMember, Member receiveMember, Team team, Mission mission, FireThrowReq fireThrowReq) { int randomNum = new Random(System.currentTimeMillis()).nextInt(2); - String title = message != null ? NEW_FIRE_THROW_TITLE_WITH_COMMENT.to(throwMember.getNickName()) + String title = fireThrowReq != null ? NEW_FIRE_THROW_TITLE_WITH_COMMENT.to(throwMember.getNickName()) : getRandomTitle(throwMember.getNickName(), receiveMember.getNickName(), randomNum); - message = message != null ? message + String message = fireThrowReq != null ? fireThrowReq.getMessage() : getRandomMessage(throwMember.getNickName(), receiveMember.getNickName(), randomNum); String idInfo = createIdInfo(mission.getType() == MissionType.REPEAT, mission.getTeam().getTeamId(), mission.getId()); diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java index fc1b0501..494a1c0d 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowUseCase.java @@ -52,12 +52,11 @@ public FireThrowRes createFireThrow(String userId, Long receiveMemberId, Long mi throw new NoAuthThrowFireException(); } - fireThrowAlarmUseCase.sendFireThrowAlarm(throwMember, receiveMember, team, mission, fireThrowReq.getMessage()); + fireThrowAlarmUseCase.sendFireThrowAlarm(throwMember, receiveMember, team, mission, fireThrowReq); Fire save = fireSaveService.save(Fire.builder() .throwMemberId(throwMember.getMemberId()) .receiveMemberId(receiveMemberId) - .message(fireThrowReq.getMessage()) .build()); return FireMapper.mapToFireThrowRes(fireSaveService.save(save)); diff --git a/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java b/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java index d4f2cbf9..11a7ec74 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java @@ -25,7 +25,7 @@ public class Fire extends BaseTimeEntity { private Long receiveMemberId; - @Column(nullable = true, columnDefinition="TEXT", length = 100) - private String message; +// @Column(nullable = true, columnDefinition="TEXT", length = 100) +// private String message; } diff --git a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java index 576a705f..76eb46a5 100644 --- a/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java +++ b/src/main/java/com/moing/backend/domain/fire/presentation/FireController.java @@ -31,7 +31,7 @@ public class FireController { @PostMapping("/{receiveMemberId}") public ResponseEntity> throwFire (@AuthenticationPrincipal User user, @PathVariable("teamId") Long teamId, - @PathVariable("receiveMemberId") Long receiveMemberId, @PathVariable("missionId") Long missionId, @RequestBody FireThrowReq fireThrowReq) { + @PathVariable("receiveMemberId") Long receiveMemberId, @PathVariable("missionId") Long missionId, @RequestBody(required = false) FireThrowReq fireThrowReq) { return ResponseEntity.ok(SuccessResponse.create(THROW_FIRE_SUCCESS.getMessage(), this.fireThrowUseCase.createFireThrow(user.getSocialId(), receiveMemberId, missionId, teamId, fireThrowReq))); } From c13f83c589d344c6e784216b78a20a9ceb490861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:06:03 +0900 Subject: [PATCH 598/619] =?UTF-8?q?MNG-25=20fix=20:=20=EB=B6=88=20?= =?UTF-8?q?=EB=8D=98=EC=A7=80=EA=B8=B0=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EC=95=88=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moing/backend/domain/fire/domain/entity/Fire.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java b/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java index 11a7ec74..8d6fe05c 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/entity/Fire.java @@ -15,7 +15,6 @@ @AllArgsConstructor public class Fire extends BaseTimeEntity { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "fire_id") @@ -25,7 +24,4 @@ public class Fire extends BaseTimeEntity { private Long receiveMemberId; -// @Column(nullable = true, columnDefinition="TEXT", length = 100) -// private String message; - } From b1f3679db8afcbc940ac483bbc6227fab47a0633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:56:24 +0900 Subject: [PATCH 599/619] =?UTF-8?q?MNG-26=20feat=20:=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EC=9D=B8=EC=A6=9D=20=EC=8B=9C=20=ED=91=B8=EC=8B=9C=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=A0=84=EC=86=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MissionArchiveCreateMessage.java | 22 +++++++ .../service/MissionArchiveCreateUseCase.java | 10 ++- .../SendMissionArchiveCreateAlarmUseCase.java | 62 +++++++++++++++++++ 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateMessage.java create mode 100644 src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateMessage.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateMessage.java new file mode 100644 index 00000000..bb3564b9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateMessage.java @@ -0,0 +1,22 @@ +package com.moing.backend.domain.missionArchive.application.service; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum MissionArchiveCreateMessage { + + CREATOR_CREATE_MISSION_ARCHIVE("%s님이 미션을 인증했어요!"), + TEAM_AND_TITLE("[%s] %s"); + + private final String message; + + public String to(String creator) { + return String.format(message, creator); + } + + public String teamAndTitle(String team, String title) { + return String.format(message, team, title); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index 618a02c7..2979b706 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -34,6 +34,8 @@ public class MissionArchiveCreateUseCase { private final TeamScoreUpdateUseCase teamScoreUpdateUseCase; + private final SendMissionArchiveCreateAlarmUseCase sendMissionArchiveCreateAlarmUseCase; + public MissionArchiveRes createArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); @@ -59,7 +61,6 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId) + 1); missionArchiveRes = MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive), memberId); - } // 한번 미션일 경우 @@ -78,13 +79,16 @@ public MissionArchiveRes createArchive(String userSocialId, Long missionId, Miss missionArchiveRes.updateCount(doneSingleArchives); } - // TODO : 소모임원 3명 이상일 경우 보너스 점수 + // 소모임원 3명 이상일 경우 보너스 점수 if (mission.getTeam().getNumOfMember() > 2) { gainBonusScore(mission, newArchive); } - // TODO : 미션 인증 1회당 점수 + // 미션 인증 1회당 점수 teamScoreUpdateUseCase.gainScoreOfArchive(mission, ScoreStatus.PLUS); + // 미션 인증 시 다른 팀원에게 알림 전송 + sendMissionArchiveCreateAlarmUseCase.sendNewMissionArchiveUploadAlarm(member,mission); + return missionArchiveRes; } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java new file mode 100644 index 00000000..dd553da3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java @@ -0,0 +1,62 @@ +package com.moing.backend.domain.missionArchive.application.service; + +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.entity.PagePath; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamMember.domain.service.TeamMemberGetService; +import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; +import lombok.RequiredArgsConstructor; +import net.minidev.json.JSONObject; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; + +import static com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateMessage.CREATOR_CREATE_MISSION_ARCHIVE; +import static com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateMessage.TEAM_AND_TITLE; +import static com.moing.backend.global.config.fcm.constant.NewMissionTitle.NEW_SINGLE_MISSION_COMING; + +@Service +@Transactional +@RequiredArgsConstructor +public class SendMissionArchiveCreateAlarmUseCase { + + private final TeamMemberGetService teamMemberGetService; + private final ApplicationEventPublisher eventPublisher; + + public void sendNewMissionArchiveUploadAlarm(Member member, Mission mission) { + Team team = mission.getTeam(); + + String title = CREATOR_CREATE_MISSION_ARCHIVE.to(member.getNickName()); + String message = TEAM_AND_TITLE.teamAndTitle(team.getName(),mission.getTitle()); + + String type = mission.getType().toString(); + String status = mission.getStatus().toString(); + + Optional> newUploadInfos=teamMemberGetService.getNewUploadInfo(team.getTeamId(), member.getMemberId()); + + Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); + Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); + // 알림 보내기 + eventPublisher.publishEvent(new MultiFcmEvent(title, message, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId(),mission.getType(),mission.getStatus()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.MISSION_PATH.getValue())); + } + + private String createIdInfo(Long teamId, Long missionId,MissionType type, MissionStatus status) { + JSONObject jo = new JSONObject(); + jo.put("isRepeated", type.equals(MissionType.REPEAT)); + jo.put("teamId", teamId); + jo.put("missionId", missionId); + jo.put("status", status.name()); + return jo.toJSONString(); + } +} + From 228836c79ce48183310dfd163d6a12cbb9fb323e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 2 Jul 2024 08:34:11 +0900 Subject: [PATCH 600/619] =?UTF-8?q?MNG-26=20fix=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=ED=95=84=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendMissionArchiveCreateAlarmUseCase.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java index dd553da3..303ccc6b 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java @@ -39,8 +39,6 @@ public void sendNewMissionArchiveUploadAlarm(Member member, Mission mission) { String title = CREATOR_CREATE_MISSION_ARCHIVE.to(member.getNickName()); String message = TEAM_AND_TITLE.teamAndTitle(team.getName(),mission.getTitle()); - String type = mission.getType().toString(); - String status = mission.getStatus().toString(); Optional> newUploadInfos=teamMemberGetService.getNewUploadInfo(team.getTeamId(), member.getMemberId()); From 77ead00985e8fc5d300e6d70c02b706a4460d8da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:23:22 +0900 Subject: [PATCH 601/619] =?UTF-8?q?MNG-25=20feat=20:=20=EB=B6=88=EB=8D=98?= =?UTF-8?q?=EC=A7=80=EA=B8=B0=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20API=20=EB=AC=B8=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/fire/application/dto/req/FireThrowReq.java | 9 +++++---- .../domain/fire/representation/FireControllerTest.java | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java b/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java index b0845e15..c668da02 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java +++ b/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java @@ -7,13 +7,14 @@ import javax.annotation.Nullable; - -@AllArgsConstructor -@Builder @NoArgsConstructor @Getter public class FireThrowReq { - @Nullable private String message; + + @Builder + public FireThrowReq(String message) { + this.message = message; + } } diff --git a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java index c7d78bb6..d87a66c4 100644 --- a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java +++ b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java @@ -24,8 +24,7 @@ import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; @@ -92,7 +91,7 @@ public class FireControllerTest extends CommonControllerTest { //given FireThrowReq input = FireThrowReq.builder() - .message("message") + .message("불던지기 메시지. 메시지가 없는경우 DTO 자체를 전송하지 않음") .build(); String body = objectMapper.writeValueAsString(input); @@ -122,12 +121,14 @@ public class FireControllerTest extends CommonControllerTest { requestHeaders( headerWithName("Authorization").description("접근 토큰") ), + requestFields( + fieldWithPath("message").description("불던지기 메시지. 메시지가 없는경우 DTO 자체를 전송하지 않음") + ), pathParameters( parameterWithName("teamId").description("팀 아이디"), parameterWithName("missionId").description("미션 아이디"), parameterWithName("receiveMemberId").description("불 받을 사람 아이디") ), - responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description(THROW_FIRE_SUCCESS.getMessage()), From 852b2a8c3cf38d4d3752c400078ef088c78b67e7 Mon Sep 17 00:00:00 2001 From: seungueonn Date: Sun, 7 Jul 2024 16:09:59 +0900 Subject: [PATCH 602/619] =?UTF-8?q?MNG-25=20chore=20:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC(logs/)=20gitignore=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 03d183bf..850b9ca6 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,4 @@ data.sql firebase-key.json apple-key.p8 +logs/ \ No newline at end of file From 5f62c3fb486d3c1f77c92f9aca0c40491e0cfcf9 Mon Sep 17 00:00:00 2001 From: seungueonn Date: Sun, 7 Jul 2024 16:24:42 +0900 Subject: [PATCH 603/619] =?UTF-8?q?MNG-25=20chore=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20import=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20?= =?UTF-8?q?field=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/fire/application/dto/req/FireThrowReq.java | 3 --- .../domain/fire/representation/FireControllerTest.java | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java b/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java index c668da02..34907e1b 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java +++ b/src/main/java/com/moing/backend/domain/fire/application/dto/req/FireThrowReq.java @@ -1,12 +1,9 @@ package com.moing.backend.domain.fire.application.dto.req; -import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.annotation.Nullable; - @NoArgsConstructor @Getter public class FireThrowReq { diff --git a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java index d87a66c4..1ee71150 100644 --- a/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java +++ b/src/test/java/com/moing/backend/domain/fire/representation/FireControllerTest.java @@ -121,14 +121,14 @@ public class FireControllerTest extends CommonControllerTest { requestHeaders( headerWithName("Authorization").description("접근 토큰") ), - requestFields( - fieldWithPath("message").description("불던지기 메시지. 메시지가 없는경우 DTO 자체를 전송하지 않음") - ), pathParameters( parameterWithName("teamId").description("팀 아이디"), parameterWithName("missionId").description("미션 아이디"), parameterWithName("receiveMemberId").description("불 받을 사람 아이디") ), + requestFields( + fieldWithPath("message").description("불던지기 메시지. 메시지가 없는경우 DTO 자체를 전송하지 않음") + ), responseFields( fieldWithPath("isSuccess").description("true"), fieldWithPath("message").description(THROW_FIRE_SUCCESS.getMessage()), From f1de5a67943a2b12b0d2fdfb28090819c144c8df Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 10 Jul 2024 22:40:59 +0900 Subject: [PATCH 604/619] =?UTF-8?q?MNG-28=20feat:=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=97=90=20isCommentPush=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/history/domain/entity/AlarmType.java | 3 ++- .../moing/backend/domain/member/domain/entity/Member.java | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmType.java b/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmType.java index fbf7fd58..e29851bf 100644 --- a/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmType.java +++ b/src/main/java/com/moing/backend/domain/history/domain/entity/AlarmType.java @@ -8,5 +8,6 @@ public enum AlarmType { FIRE, REMIND, APPROVE_TEAM, - REJECT_TEAM + REJECT_TEAM, + COMMENT } diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index d13b5886..c06c7af6 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -79,6 +79,10 @@ public class Member extends BaseTimeEntity { @Column(nullable = false) private boolean isFirePush; + @ColumnDefault("true") + @Column(nullable = false) + private boolean isCommentPush; + private boolean isDeleted; private LocalDateTime lastSignInTime; @@ -140,6 +144,10 @@ public void updateFirePush(boolean firePush) { this.isFirePush = firePush; } + public void updateCommentPush(boolean commentPush){ + this.isCommentPush=commentPush; + } + public void updateAllPush(boolean allPush) { this.isNewUploadPush = allPush; this.isRemindPush = allPush; From 563950691db475841c2cd7ee6e1b3a39f270633a Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 10 Jul 2024 22:44:12 +0900 Subject: [PATCH 605/619] =?UTF-8?q?MNG-28=20feat:=20=EB=AF=B8=EC=85=98=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=ED=91=B8?= =?UTF-8?q?=EC=8B=9C=20=EC=95=8C=EB=A6=BC=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CreateBoardCommentUseCase.java | 4 +- ...java => SendBoardCommentAlarmUseCase.java} | 8 +- .../BoardCommentCustomRepositoryImpl.java | 2 +- .../service/CreateMissionCommentUseCase.java | 7 +- .../service/SendMissionAlarmUseCase.java | 4 - .../SendMissionCommentAlarmUseCase.java | 92 +++++++++++++++++++ .../MissionCommentCustomRepositoryImpl.java | 2 +- .../dto/response/GetAlarmResponse.java | 2 +- .../application/service/AlarmUseCase.java | 6 +- .../mypage/presentation/MyPageController.java | 2 +- .../presentation/MypageControllerTest.java | 9 +- 11 files changed, 116 insertions(+), 22 deletions(-) rename src/main/java/com/moing/backend/domain/boardComment/application/service/{SendCommentAlarmUseCase.java => SendBoardCommentAlarmUseCase.java} (93%) delete mode 100644 src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionAlarmUseCase.java create mode 100644 src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java index ffac8705..47fb22f0 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/CreateBoardCommentUseCase.java @@ -21,7 +21,7 @@ public class CreateBoardCommentUseCase { private final BoardCommentSaveService boardCommentSaveService; private final BaseBoardService baseBoardService; private final CheckLeaderUseCase checkLeaderUseCase; - private final SendCommentAlarmUseCase sendCommentAlarmUseCase; + private final SendBoardCommentAlarmUseCase sendCommentAlarm; /** * 게시글 댓글 생성 */ @@ -33,7 +33,7 @@ public CreateCommentResponse createBoardComment(String socialId, Long teamId, Lo // 2. 게시글 댓글 개수 증가 data.getBoard().incrComNum(); // 3. 게시글 댓글 알림 - sendCommentAlarmUseCase.sendNewUploadAlarm(data, boardComment); + sendCommentAlarm.sendCommentAlarm(data, boardComment); return new CreateCommentResponse(boardComment.getBoardCommentId()); } } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java similarity index 93% rename from src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java rename to src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java index 84d1078a..42db80ac 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendCommentAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java @@ -28,12 +28,12 @@ @Service @RequiredArgsConstructor @Transactional -public class SendCommentAlarmUseCase { +public class SendBoardCommentAlarmUseCase { private final ApplicationEventPublisher eventPublisher; private final BoardCommentGetService boardCommentGetService; - public void sendNewUploadAlarm(BaseBoardServiceResponse response, BoardComment comment) { + public void sendCommentAlarm(BaseBoardServiceResponse response, BoardComment comment) { Member member = response.getMember(); Team team = response.getTeam(); Board board = response.getBoard(); @@ -50,7 +50,7 @@ private void sendBoardWriter(Board board, Member member, String title, String bo Member receiver = board.getTeamMember().getMember(); if (checkBoardWriter(receiver, member, newUploadInfos)) { - eventPublisher.publishEvent(new SingleFcmEvent(receiver, title, body, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue(), receiver.isNewUploadPush())); + eventPublisher.publishEvent(new SingleFcmEvent(receiver, title, body, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.COMMENT, PagePath.NOTICE_PATH.getValue(), receiver.isCommentPush())); } } @@ -58,7 +58,7 @@ private void sendBoardCommentWriter(Board board, Member member, String title, St Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); - eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); + eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.COMMENT, PagePath.NOTICE_PATH.getValue())); } private String createIdInfo(Long teamId, Long boardId) { diff --git a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java index 413f4203..9ac674c3 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/boardComment/domain/repository/BoardCommentCustomRepositoryImpl.java @@ -69,7 +69,7 @@ public Optional> findNewUploadInfo(Long memberId, Long board List result = queryFactory.select(Projections.constructor(NewUploadInfo.class, boardComment.teamMember.member.fcmToken, boardComment.teamMember.member.memberId, - boardComment.teamMember.member.isNewUploadPush, + boardComment.teamMember.member.isCommentPush, boardComment.teamMember.member.isSignOut)) .distinct() .from(boardComment) diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/CreateMissionCommentUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/CreateMissionCommentUseCase.java index 54a0ef10..7e2a2bbc 100644 --- a/src/main/java/com/moing/backend/domain/missionComment/application/service/CreateMissionCommentUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionComment/application/service/CreateMissionCommentUseCase.java @@ -1,6 +1,5 @@ package com.moing.backend.domain.missionComment.application.service; -import com.moing.backend.domain.boardComment.application.service.SendCommentAlarmUseCase; import com.moing.backend.domain.comment.application.dto.request.CreateCommentRequest; import com.moing.backend.domain.comment.application.dto.response.CreateCommentResponse; import com.moing.backend.domain.missionComment.application.mapper.MissionCommentMapper; @@ -22,7 +21,7 @@ public class CreateMissionCommentUseCase { private final MissionCommentSaveService missionCommentSaveService; private final BaseMissionService baseMissionService; private final CheckLeaderUseCase checkLeaderUseCase; - private final SendCommentAlarmUseCase sendCommentAlarmUseCase; + private final SendMissionCommentAlarmUseCase sendCommentAlarm; /** * 게시글 댓글 생성 */ @@ -33,8 +32,8 @@ public CreateCommentResponse createBoardComment(String socialId, Long teamId, Lo MissionComment missionComment = missionCommentSaveService.saveComment(MissionCommentMapper.toMissionComment(data.getTeamMember(), data.getMissionArchive(), createCommentRequest, isLeader)); // 2. 미션 게시글 댓글 개수 증가 data.getMissionArchive().incrComNum(); -// // 3. 미션 게시글 댓글 알림 -// sendCommentAlarmUseCase.sendNewUploadAlarm(data, missionComment); + // 3. 미션 게시글 댓글 알림 + sendCommentAlarm.sendCommentAlarm(data, missionComment); return new CreateCommentResponse(missionComment.getMissionCommentId()); } } diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionAlarmUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionAlarmUseCase.java deleted file mode 100644 index ced7594c..00000000 --- a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionAlarmUseCase.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.moing.backend.domain.missionComment.application.service; - -public class SendMissionAlarmUseCase { -} diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java new file mode 100644 index 00000000..5f5adadb --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java @@ -0,0 +1,92 @@ +package com.moing.backend.domain.missionComment.application.service; + +import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; +import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; +import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; +import com.moing.backend.domain.history.domain.entity.AlarmType; +import com.moing.backend.domain.history.domain.entity.PagePath; +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionComment.domain.entity.MissionComment; +import com.moing.backend.domain.missionComment.domain.service.MissionCommentGetService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.global.config.fcm.dto.event.MultiFcmEvent; +import com.moing.backend.global.config.fcm.dto.event.SingleFcmEvent; +import com.moing.backend.global.response.BaseMissionServiceResponse; +import lombok.RequiredArgsConstructor; +import net.minidev.json.JSONObject; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import static com.moing.backend.global.config.fcm.constant.NewCommentUploadMessage.NEW_COMMENT_UPLOAD_MESSAGE; + +@Service +@RequiredArgsConstructor +@Transactional +public class SendMissionCommentAlarmUseCase { + + private final ApplicationEventPublisher eventPublisher; + private final MissionCommentGetService missionCommentGetService; + + public void sendCommentAlarm(BaseMissionServiceResponse response, MissionComment comment) { + Member member = response.getMember(); + Team team = response.getTeam(); + MissionArchive missionArchive = response.getMissionArchive(); + Mission mission = missionArchive.getMission(); + + Optional> newUploadInfos = missionCommentGetService.getNewUploadInfo(member.getMemberId(), missionArchive.getId()); + String title = NEW_COMMENT_UPLOAD_MESSAGE.title(comment.getContent()); + String body = NEW_COMMENT_UPLOAD_MESSAGE.body(member.getNickName(), mission.getTitle()); + + sendMissionCommentWriter(mission, missionArchive, title, body, team, newUploadInfos); + sendMissionWriter(missionArchive, mission, member, title, body, team, newUploadInfos); + } + + + private void sendMissionWriter(MissionArchive missionArchive, Mission mission, + Member member, String title, String body, Team team, + Optional> newUploadInfos) { + Member receiver = missionArchive.getMember(); + if (checkMemberWriter(receiver, member, newUploadInfos)) { + eventPublisher.publishEvent(new SingleFcmEvent(receiver, title, body, createIdInfo(team.getTeamId(), mission.getId(), missionArchive.getId()), team.getName(), AlarmType.COMMENT, PagePath.NOTICE_PATH.getValue(), receiver.isCommentPush())); + } + } + + private void sendMissionCommentWriter(Mission mission, MissionArchive missionArchive, + String title, String body, Team team, + Optional> newUploadInfos) { + Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); + Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); + + eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId(), missionArchive.getId()), team.getName(), AlarmType.COMMENT, PagePath.MISSION_PATH.getValue())); + } + + + private boolean checkMemberWriter(Member missionWriter, Member commentWriter, Optional> newUploadInfos) { + // 댓글 작성자와 미션 게시글 작성자가 동일한 경우 알림을 보내지 않는다. + if (Objects.equals(missionWriter.getMemberId(), commentWriter.getMemberId())) { + return false; + } + + // newUploadInfos 리스트에 missionWriter memberId가 없는 경우만 알림을 보낸다. + // 리스트가 비어있거나, missionWriter의 memberId가 리스트에 없으면 true를 반환. + return newUploadInfos + .map(infos -> infos.stream().noneMatch(info -> info.getMemberId().equals(missionWriter.getMemberId()))) + .orElse(true); + } + + + private String createIdInfo(Long teamId, Long missionId, Long missionArchiveId) { + JSONObject jo = new JSONObject(); + jo.put("missionArchiveId", missionArchiveId); + jo.put("teamId", teamId); + jo.put("missionId", missionId); + return jo.toJSONString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepositoryImpl.java index aecacdad..9e295ee7 100644 --- a/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionComment/domain/repository/MissionCommentCustomRepositoryImpl.java @@ -69,7 +69,7 @@ public Optional> findNewUploadInfo(Long memberId, Long missi List result = queryFactory.select(Projections.constructor(NewUploadInfo.class, missionComment.teamMember.member.fcmToken, missionComment.teamMember.member.memberId, - missionComment.teamMember.member.isNewUploadPush, + missionComment.teamMember.member.isCommentPush, missionComment.teamMember.member.isSignOut)) .distinct() .from(missionComment) diff --git a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetAlarmResponse.java b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetAlarmResponse.java index 8d7e602c..9e858a34 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetAlarmResponse.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/dto/response/GetAlarmResponse.java @@ -4,7 +4,6 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.hibernate.annotations.ColumnDefault; @Builder @AllArgsConstructor @@ -15,4 +14,5 @@ public class GetAlarmResponse { private boolean isNewUploadPush; private boolean isRemindPush; private boolean isFirePush; + private boolean isCommentPush; } diff --git a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java index e632e679..5d7c7e78 100644 --- a/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mypage/application/service/AlarmUseCase.java @@ -17,7 +17,7 @@ public class AlarmUseCase { @Transactional(readOnly = true) public GetAlarmResponse getAlarm(String socialId){ Member member=memberGetService.getMemberBySocialId(socialId); - return new GetAlarmResponse(member.isNewUploadPush(),member.isRemindPush(), member.isFirePush()); + return new GetAlarmResponse(member.isNewUploadPush(),member.isRemindPush(), member.isFirePush(), member.isCommentPush()); } @Transactional @@ -38,9 +38,11 @@ public GetAlarmResponse updateAlarm(String socialId, String type, String status) case "isFirePush": member.updateFirePush(push); break; + case "isCommentPush": + member.updateCommentPush(push); default: throw new AlarmInvalidException(); } - return new GetAlarmResponse(member.isNewUploadPush(),member.isRemindPush(), member.isFirePush()); + return new GetAlarmResponse(member.isNewUploadPush(),member.isRemindPush(), member.isFirePush(), member.isCommentPush()); } } diff --git a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java index bea13408..f03563aa 100644 --- a/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java +++ b/src/main/java/com/moing/backend/domain/mypage/presentation/MyPageController.java @@ -107,7 +107,7 @@ public ResponseEntity> getAlarm(@Authenticatio /** * 알림정보 수정 - * [POST] api/mypage/alarm?type=all || isNewUploadPush || isRemindPush || isFirePush && status= on || off + * [POST] api/mypage/alarm?type=all || isNewUploadPush || isRemindPush || isFirePush || isCommentPush && status= on || off */ @PutMapping("/alarm") public ResponseEntity> updateAlarm(@AuthenticationPrincipal User user, diff --git a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java index f4d06b55..d2ea767c 100644 --- a/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java +++ b/src/test/java/com/moing/backend/domain/mypage/presentation/MypageControllerTest.java @@ -257,6 +257,7 @@ public void get_alarm() throws Exception { .isNewUploadPush(true) .isFirePush(true) .isRemindPush(true) + .isCommentPush(true) .build(); given(alarmUseCase.getAlarm(any())).willReturn(output); @@ -282,7 +283,8 @@ public void get_alarm() throws Exception { fieldWithPath("message").description("알람 정보를 조회했습니다"), fieldWithPath("data.newUploadPush").description("신규 공지 알림"), fieldWithPath("data.remindPush").description("미션 리마인드 알림"), - fieldWithPath("data.firePush").description("불 던지기 알림") + fieldWithPath("data.firePush").description("불 던지기 알림"), + fieldWithPath("data.commentPush").description("댓글 알림") ) ) ); @@ -295,6 +297,7 @@ public void update_alarm() throws Exception { .isNewUploadPush(true) .isFirePush(true) .isRemindPush(true) + .isCommentPush(true) .build(); given(alarmUseCase.updateAlarm(any(),any(),any())).willReturn(output); @@ -326,7 +329,9 @@ public void update_alarm() throws Exception { fieldWithPath("message").description("알람 정보를 수정했습니다"), fieldWithPath("data.newUploadPush").description("신규 공지 알림"), fieldWithPath("data.remindPush").description("미션 리마인드 알림"), - fieldWithPath("data.firePush").description("불 던지기 알림") + fieldWithPath("data.firePush").description("불 던지기 알림"), + fieldWithPath("data.commentPush").description("댓글 알림") + ) ) ); From 4a3950e0cf4efa81f4f76238f838ec9c37c7e699 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Wed, 10 Jul 2024 22:44:44 +0900 Subject: [PATCH 606/619] =?UTF-8?q?MNG-28=20docs:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=95=8C=EB=A6=BC=20Category=EC=97=90=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/AlarmHistory-API.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/docs/asciidoc/AlarmHistory-API.adoc b/src/docs/asciidoc/AlarmHistory-API.adoc index 5c31a28d..c3ee6871 100644 --- a/src/docs/asciidoc/AlarmHistory-API.adoc +++ b/src/docs/asciidoc/AlarmHistory-API.adoc @@ -24,6 +24,8 @@ operation::alarm-history-controller-test/get_all_alarm_history[snippets='http-re | `REJECT_TEAM` | 소모임 반려 +| `COMMENT` +| 댓글 생성 알림 |=== [[AlarmHistory-알림-단건-조회하기]] From ba7b49b8fd29f99e1c633dbdf5b00ca6e4ee0222 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 22 Jul 2024 21:42:46 +0900 Subject: [PATCH 607/619] =?UTF-8?q?MNG-28=20fix:=20missionComment=20path?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/SendMissionCommentAlarmUseCase.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java index 5f5adadb..d25facf4 100644 --- a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java @@ -47,18 +47,16 @@ public void sendCommentAlarm(BaseMissionServiceResponse response, MissionComment sendMissionCommentWriter(mission, missionArchive, title, body, team, newUploadInfos); sendMissionWriter(missionArchive, mission, member, title, body, team, newUploadInfos); } - - private void sendMissionWriter(MissionArchive missionArchive, Mission mission, Member member, String title, String body, Team team, Optional> newUploadInfos) { Member receiver = missionArchive.getMember(); if (checkMemberWriter(receiver, member, newUploadInfos)) { - eventPublisher.publishEvent(new SingleFcmEvent(receiver, title, body, createIdInfo(team.getTeamId(), mission.getId(), missionArchive.getId()), team.getName(), AlarmType.COMMENT, PagePath.NOTICE_PATH.getValue(), receiver.isCommentPush())); + eventPublisher.publishEvent(new SingleFcmEvent(receiver, title, body, createIdInfo(team.getTeamId(), mission.getId(), missionArchive.getId()), team.getName(), AlarmType.COMMENT, PagePath.MISSION_PATH.getValue(), receiver.isCommentPush())); } } - private void sendMissionCommentWriter(Mission mission, MissionArchive missionArchive, + private void sendMissionCommentWriter(Mission mission, MissionArchive missionArchive/ String title, String body, Team team, Optional> newUploadInfos) { Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); From e0dc9e0af6047b90021e0a61e1ca2c4450e848b9 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Mon, 22 Jul 2024 21:45:27 +0900 Subject: [PATCH 608/619] =?UTF-8?q?MNG-28=20fix:=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/SendMissionCommentAlarmUseCase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java index d25facf4..7a14209b 100644 --- a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java @@ -56,7 +56,7 @@ private void sendMissionWriter(MissionArchive missionArchive, Mission mission, } } - private void sendMissionCommentWriter(Mission mission, MissionArchive missionArchive/ + private void sendMissionCommentWriter(Mission mission, MissionArchive missionArchive, String title, String body, Team team, Optional> newUploadInfos) { Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); From 9b3a08125703628390b9d661511f834d82d30045 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 9 Aug 2024 13:38:18 +0900 Subject: [PATCH 609/619] =?UTF-8?q?MNG-28=20feat:=20=ED=91=B8=EC=8B=9C=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EB=B3=B4=EB=82=BC=20=EB=96=BC=20idInfo?= =?UTF-8?q?=EC=97=90=20type=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/application/service/SendBoardAlarmUseCase.java | 5 +++-- .../application/service/SendBoardCommentAlarmUseCase.java | 1 + .../fire/application/service/FireThrowAlarmUseCase.java | 5 +++-- .../application/service/SendMissionCreateAlarmUseCase.java | 5 +++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java index 3ed5f384..edb57a8c 100644 --- a/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/board/application/service/SendBoardAlarmUseCase.java @@ -4,7 +4,6 @@ import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; -import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.team.domain.entity.Team; @@ -20,6 +19,7 @@ import java.util.List; import java.util.Optional; +import static com.moing.backend.domain.history.domain.entity.AlarmType.NEW_UPLOAD; import static com.moing.backend.global.config.fcm.constant.NewNoticeUploadMessage.NEW_NOTICE_UPLOAD_MESSAGE; @Service @@ -41,7 +41,7 @@ public void sendNewUploadAlarm(BaseServiceResponse baseServiceResponse, Board bo Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); // 알림 보내기 - eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); + eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), board.getBoardId()), team.getName(), NEW_UPLOAD, PagePath.NOTICE_PATH.getValue())); } } @@ -49,6 +49,7 @@ private String createIdInfo(Long teamId, Long boardId) { JSONObject jo = new JSONObject(); jo.put("teamId", teamId); jo.put("boardId", boardId); + jo.put("type", "NEW_UPLOAD_BOARD"); return jo.toJSONString(); } diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java index 42db80ac..974060ed 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java @@ -65,6 +65,7 @@ private String createIdInfo(Long teamId, Long boardId) { JSONObject jo = new JSONObject(); jo.put("teamId", teamId); jo.put("boardId", boardId); + jo.put("type", "COMMENT"); return jo.toJSONString(); } diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java index ba2c35c4..b2451d61 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -1,7 +1,6 @@ package com.moing.backend.domain.fire.application.service; import com.moing.backend.domain.fire.application.dto.req.FireThrowReq; -import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; @@ -15,6 +14,7 @@ import javax.transaction.Transactional; import java.util.Random; +import static com.moing.backend.domain.history.domain.entity.AlarmType.FIRE; import static com.moing.backend.domain.history.domain.entity.PagePath.MISSION_PATH; import static com.moing.backend.global.config.fcm.constant.FireThrowMessage.*; @@ -35,7 +35,7 @@ public void sendFireThrowAlarm(Member throwMember, Member receiveMember, Team te : getRandomMessage(throwMember.getNickName(), receiveMember.getNickName(), randomNum); String idInfo = createIdInfo(mission.getType() == MissionType.REPEAT, mission.getTeam().getTeamId(), mission.getId()); - eventPublisher.publishEvent(new SingleFcmEvent(receiveMember, title, message, idInfo, team.getName(), AlarmType.FIRE, MISSION_PATH.getValue(), receiveMember.isFirePush())); + eventPublisher.publishEvent(new SingleFcmEvent(receiveMember, title, message, idInfo, team.getName(), FIRE, MISSION_PATH.getValue(), receiveMember.isFirePush())); } public String getRandomMessage(String pusher, String receiver, int num) { @@ -65,6 +65,7 @@ private String createIdInfo(boolean isRepeated, Long teamId, Long missionId) { jo.put("isRepeated", isRepeated); jo.put("teamId", teamId); jo.put("missionId", missionId); + jo.put("type", "FIRE"); return jo.toJSONString(); } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java index aabe793f..029f5420 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/mission/application/service/SendMissionCreateAlarmUseCase.java @@ -3,7 +3,6 @@ import com.moing.backend.domain.history.application.dto.response.MemberIdAndToken; import com.moing.backend.domain.history.application.dto.response.NewUploadInfo; import com.moing.backend.domain.history.application.mapper.AlarmHistoryMapper; -import com.moing.backend.domain.history.domain.entity.AlarmType; import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; @@ -21,6 +20,7 @@ import java.util.List; import java.util.Optional; +import static com.moing.backend.domain.history.domain.entity.AlarmType.NEW_UPLOAD; import static com.moing.backend.global.config.fcm.constant.NewMissionTitle.NEW_SINGLE_MISSION_COMING; @Service @@ -43,7 +43,7 @@ public void sendNewMissionUploadAlarm(Member member, Mission mission) { Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); // 알림 보내기 - eventPublisher.publishEvent(new MultiFcmEvent(title, message, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId(),mission.getType(),mission.getStatus()), team.getName(), AlarmType.NEW_UPLOAD, PagePath.MISSION_PATH.getValue())); + eventPublisher.publishEvent(new MultiFcmEvent(title, message, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId(),mission.getType(),mission.getStatus()), team.getName(), NEW_UPLOAD, PagePath.MISSION_PATH.getValue())); } private String createIdInfo(Long teamId, Long missionId,MissionType type, MissionStatus status) { @@ -52,6 +52,7 @@ private String createIdInfo(Long teamId, Long missionId,MissionType type, Missio jo.put("teamId", teamId); jo.put("missionId", missionId); jo.put("status", status.name()); + jo.put("type", "NEW_UPLOAD_MISSION"); return jo.toJSONString(); } } From df1681e22b0bbf3c7b7c4bdbf8bc59ae27b19714 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Fri, 9 Aug 2024 17:19:17 +0900 Subject: [PATCH 610/619] =?UTF-8?q?fix:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=EC=8B=9C=20=EB=AF=B8=EC=85=98=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=97=AC=EB=B6=80=20true=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moing/backend/domain/member/domain/entity/Member.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java index c06c7af6..206847e1 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java +++ b/src/main/java/com/moing/backend/domain/member/domain/entity/Member.java @@ -152,6 +152,7 @@ public void updateAllPush(boolean allPush) { this.isNewUploadPush = allPush; this.isRemindPush = allPush; this.isFirePush = allPush; + this.isCommentPush=allPush; } public void updateFcmToken(String fcmToken) { From 446e9aa69bc6442e1de6eb20a8124b689cdda062 Mon Sep 17 00:00:00 2001 From: minsu20 Date: Sun, 11 Aug 2024 21:58:16 +0900 Subject: [PATCH 611/619] =?UTF-8?q?MNG-28=20feat:=20=ED=91=B8=EC=8B=9C?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EB=B3=B4=EB=82=BC=20=EB=95=8C=20idInfo?= =?UTF-8?q?=EC=97=90=20tyep=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendBoardCommentAlarmUseCase.java | 2 +- .../application/service/FireThrowAlarmUseCase.java | 12 +++++++++--- .../SendMissionArchiveCreateAlarmUseCase.java | 2 +- .../service/SendMissionCommentAlarmUseCase.java | 1 + 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java index 974060ed..7b6ae5e3 100644 --- a/src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/boardComment/application/service/SendBoardCommentAlarmUseCase.java @@ -65,7 +65,7 @@ private String createIdInfo(Long teamId, Long boardId) { JSONObject jo = new JSONObject(); jo.put("teamId", teamId); jo.put("boardId", boardId); - jo.put("type", "COMMENT"); + jo.put("type", "COMMENT_BOARD"); return jo.toJSONString(); } diff --git a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java index b2451d61..0566dea0 100644 --- a/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/fire/application/service/FireThrowAlarmUseCase.java @@ -33,7 +33,7 @@ public void sendFireThrowAlarm(Member throwMember, Member receiveMember, Team te : getRandomTitle(throwMember.getNickName(), receiveMember.getNickName(), randomNum); String message = fireThrowReq != null ? fireThrowReq.getMessage() : getRandomMessage(throwMember.getNickName(), receiveMember.getNickName(), randomNum); - String idInfo = createIdInfo(mission.getType() == MissionType.REPEAT, mission.getTeam().getTeamId(), mission.getId()); + String idInfo = createIdInfo(mission.getType() == MissionType.REPEAT, mission.getTeam().getTeamId(), mission.getId(), fireThrowReq == null); eventPublisher.publishEvent(new SingleFcmEvent(receiveMember, title, message, idInfo, team.getName(), FIRE, MISSION_PATH.getValue(), receiveMember.isFirePush())); } @@ -60,14 +60,20 @@ public String getRandomTitle(String pusher, String receiver, int num) { return NEW_FIRE_THROW_TITLE1.getMessage(); } - private String createIdInfo(boolean isRepeated, Long teamId, Long missionId) { + private String createIdInfo(boolean isRepeated, Long teamId, Long missionId, boolean isMessageNull) { JSONObject jo = new JSONObject(); jo.put("isRepeated", isRepeated); jo.put("teamId", teamId); jo.put("missionId", missionId); - jo.put("type", "FIRE"); + jo.put("type", getType(isMessageNull)); return jo.toJSONString(); } + private String getType(boolean isMessageNull){ + if(isMessageNull) + return "FIRE_MESSAGE_NULL"; + return "FIRE_MESSAGE_EXIST"; + } + } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java index 303ccc6b..fdba87a2 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/SendMissionArchiveCreateAlarmUseCase.java @@ -23,7 +23,6 @@ import static com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateMessage.CREATOR_CREATE_MISSION_ARCHIVE; import static com.moing.backend.domain.missionArchive.application.service.MissionArchiveCreateMessage.TEAM_AND_TITLE; -import static com.moing.backend.global.config.fcm.constant.NewMissionTitle.NEW_SINGLE_MISSION_COMING; @Service @Transactional @@ -54,6 +53,7 @@ private String createIdInfo(Long teamId, Long missionId,MissionType type, Missio jo.put("teamId", teamId); jo.put("missionId", missionId); jo.put("status", status.name()); + jo.put("type", "COMPLETE_MISSION"); return jo.toJSONString(); } } diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java index 7a14209b..2237fa11 100644 --- a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java @@ -85,6 +85,7 @@ private String createIdInfo(Long teamId, Long missionId, Long missionArchiveId) jo.put("missionArchiveId", missionArchiveId); jo.put("teamId", teamId); jo.put("missionId", missionId); + jo.put("type", "COMMENT_MISSION"); return jo.toJSONString(); } } \ No newline at end of file From 8e7d9e23e07b2bfd1cfe5d3f439dee12b1e4c7ad Mon Sep 17 00:00:00 2001 From: seungueonn Date: Mon, 2 Sep 2024 22:55:21 +0900 Subject: [PATCH 612/619] =?UTF-8?q?fix/#307:=20=EC=8B=A0=EA=B3=A0=EB=90=9C?= =?UTF-8?q?=20=EC=9D=B8=EC=A6=9D=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20url=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/repository/MissionArchiveCustomRepositoryImpl.java | 3 ++- .../report/presentation/constant/ReportResponseMessage.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index 5ef4b1f3..8d751358 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -329,7 +329,8 @@ public Optional> findTop5ArchivesByTeam(List .where(missionArchive.mission.team.teamId.in(teamIds), missionArchive.mission.way.eq(MissionWay.PHOTO), missionArchive.status.eq(MissionArchiveStatus.COMPLETE), - missionArchive.archive.ne("https://modagbul.s3.ap-northeast-2.amazonaws.com/reportImage.png")) + missionArchive.archive.ne("https://modagbul.s3.ap-northeast-2.amazonaws.com/reportImage.png"), + missionArchive.archive.ne("https://mo-ing.s3.ap-northeast-2.amazonaws.com/reportImage.png")) .orderBy(missionArchive.createdDate.desc()) .limit(14) .fetch(); diff --git a/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java b/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java index e5d9133a..a7332498 100644 --- a/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java +++ b/src/main/java/com/moing/backend/domain/report/presentation/constant/ReportResponseMessage.java @@ -9,7 +9,7 @@ public enum ReportResponseMessage { CREATE_REPORT_SUCCESS("게시글 신고를 완료 했습니다."), REPORT_MESSAGE("신고 접수로 삭제되었습니다."), - REPORT_PHOTO("https://modagbul.s3.ap-northeast-2.amazonaws.com/reportImage.png"); + REPORT_PHOTO("https://mo-ing.s3.ap-northeast-2.amazonaws.com/reportImage.png"); private final String message; From ae59e523717d3bfc8064a286369988af17eea648 Mon Sep 17 00:00:00 2001 From: seungueonn Date: Mon, 2 Sep 2024 22:56:48 +0900 Subject: [PATCH 613/619] =?UTF-8?q?fix/#307:=20/mission/prove=20=EC=97=90?= =?UTF-8?q?=20=ED=95=B4=EB=8B=B9=ED=95=98=EB=8A=94=20idinfo=EC=97=90=20isR?= =?UTF-8?q?epeat=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/SendMissionCommentAlarmUseCase.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java index 2237fa11..ec809470 100644 --- a/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionComment/application/service/SendMissionCommentAlarmUseCase.java @@ -7,6 +7,7 @@ import com.moing.backend.domain.history.domain.entity.PagePath; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.moing.backend.domain.missionComment.domain.entity.MissionComment; import com.moing.backend.domain.missionComment.domain.service.MissionCommentGetService; @@ -52,7 +53,7 @@ private void sendMissionWriter(MissionArchive missionArchive, Mission mission, Optional> newUploadInfos) { Member receiver = missionArchive.getMember(); if (checkMemberWriter(receiver, member, newUploadInfos)) { - eventPublisher.publishEvent(new SingleFcmEvent(receiver, title, body, createIdInfo(team.getTeamId(), mission.getId(), missionArchive.getId()), team.getName(), AlarmType.COMMENT, PagePath.MISSION_PATH.getValue(), receiver.isCommentPush())); + eventPublisher.publishEvent(new SingleFcmEvent(receiver, title, body, createIdInfo(team.getTeamId(), mission.getId(), missionArchive.getId(),mission.getType()), team.getName(), AlarmType.COMMENT, PagePath.MISSION_PATH.getValue(), receiver.isCommentPush())); } } @@ -62,7 +63,7 @@ private void sendMissionCommentWriter(Mission mission, MissionArchive missionArc Optional> memberIdAndTokensByPush = AlarmHistoryMapper.getNewUploadPushInfo(newUploadInfos); Optional> memberIdAndTokensBySave = AlarmHistoryMapper.getNewUploadSaveInfo(newUploadInfos); - eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId(), missionArchive.getId()), team.getName(), AlarmType.COMMENT, PagePath.MISSION_PATH.getValue())); + eventPublisher.publishEvent(new MultiFcmEvent(title, body, memberIdAndTokensByPush, memberIdAndTokensBySave, createIdInfo(team.getTeamId(), mission.getId(), missionArchive.getId(),mission.getType()), team.getName(), AlarmType.COMMENT, PagePath.MISSION_PATH.getValue())); } @@ -80,12 +81,13 @@ private boolean checkMemberWriter(Member missionWriter, Member commentWriter, Op } - private String createIdInfo(Long teamId, Long missionId, Long missionArchiveId) { + private String createIdInfo(Long teamId, Long missionId, Long missionArchiveId, MissionType missionType) { JSONObject jo = new JSONObject(); jo.put("missionArchiveId", missionArchiveId); jo.put("teamId", teamId); jo.put("missionId", missionId); jo.put("type", "COMMENT_MISSION"); + jo.put("isRepeated", missionType.equals(MissionType.REPEAT)); return jo.toJSONString(); } } \ No newline at end of file From 54d2909e537350791a41062815ef512cc37e5f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:44:09 +0900 Subject: [PATCH 614/619] =?UTF-8?q?hotfix=20:=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EB=A6=AC=EB=A7=88=EC=9D=B8=EB=93=9C=20?= =?UTF-8?q?=ED=91=B8=EC=8B=9C=EC=95=8C=EB=A6=BC=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=EB=A1=9C=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/AlarmHistoryController.java | 3 ++ .../service/UpdateRemindAlarmUseCase.java | 30 +++++++++++-------- .../repository/MemberCustomRepository.java | 3 +- .../MemberCustomRepositoryImpl.java | 4 ++- .../domain/repository/MemberRepository.java | 2 ++ .../domain/service/MemberGetService.java | 4 +-- .../dto/request/PostUpdatePushAlarm.java | 14 +++++++++ .../presentation/RemindAlarmController.java | 29 ++++++++++++++++++ 8 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/moing/backend/domain/member/dto/request/PostUpdatePushAlarm.java create mode 100644 src/main/java/com/moing/backend/domain/member/presentation/RemindAlarmController.java diff --git a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java index ba847a61..e5d183f3 100644 --- a/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java +++ b/src/main/java/com/moing/backend/domain/history/presentation/AlarmHistoryController.java @@ -23,6 +23,7 @@ public class AlarmHistoryController { private final GetAlarmHistoryUseCase getAlarmHistoryUseCase; private final ReadAlarmHistoryUseCase readAlarmHistoryUseCase; + /** * 알림 전체 조회 * [GET] api/history/alarm @@ -52,4 +53,6 @@ public ResponseEntity readAlarmHistory(@AuthenticationPrincipal public ResponseEntity> getUnreadAlarmCount(@AuthenticationPrincipal User user) { return ResponseEntity.ok(SuccessResponse.create(GET_UNREAD_ALARM_HISTORY.getMessage(), getAlarmHistoryUseCase.getUnreadAlarmCount(user.getSocialId()))); } + + } diff --git a/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java index 0f535603..d4203f0d 100644 --- a/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java +++ b/src/main/java/com/moing/backend/domain/member/application/service/UpdateRemindAlarmUseCase.java @@ -38,23 +38,29 @@ public class UpdateRemindAlarmUseCase { String REMIND_NAME = "미션 리마인드"; - public Boolean sendUpdateAppPushAlarm() { + public void sendUpdateAppPushAlarm(String title, String message) { - String title = "MOING 업데이트 소식"; - String message = "이제 누구나 미션을 만들 수 있어요. 지금 업데이트하고 다른 소식도 확인해보세요!"; +// String title = "MOING 업데이트 소식"; +// String message = "이제 누구나 미션을 만들 수 있어요. 지금 업데이트하고 다른 소식도 확인해보세요!"; - List allMemberOfPushAlarm = memberGetService.getAllMemberOfPushAlarm(); + long count = memberGetService.getAllMemberOfPushAlarm(0L, Long.MAX_VALUE).size(); - Optional> memberIdAndTokens = mapToMemberAndToken(allMemberOfPushAlarm); - Optional> pushMemberIdAndToken = isPushMemberIdAndToken(allMemberOfPushAlarm); + for (Long offset = 0L; offset < count; offset += 499) { - if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { - multiMessageSender.send(new MultiRequest(pushMemberIdAndToken.get(), title, message, "", REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); - } - if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { - saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); + Long limit = offset+499; + + List allMemberOfPushAlarm = memberGetService.getAllMemberOfPushAlarm(offset, limit); + + Optional> memberIdAndTokens = mapToMemberAndToken(allMemberOfPushAlarm); + Optional> pushMemberIdAndToken = isPushMemberIdAndToken(allMemberOfPushAlarm); + + if (pushMemberIdAndToken.isPresent() && !pushMemberIdAndToken.get().isEmpty()) { + multiMessageSender.send(new MultiRequest(pushMemberIdAndToken.get(), title, message, "", REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue())); + } + if (memberIdAndTokens.isPresent() && !memberIdAndTokens.get().isEmpty()) { + saveMultiAlarmHistoryUseCase.saveAlarmHistories(AlarmHistoryMapper.getMemberIds(memberIdAndTokens.get()), "", title, message, REMIND_NAME, AlarmType.REMIND, PagePath.MISSION_ALL_PTAH.getValue()); + } } - return true; } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java index 4133dba8..b6b2f76e 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepository.java @@ -13,5 +13,6 @@ public interface MemberCustomRepository { Optional findNotDeletedByMemberId(Long id); Long getTodayNewMembers(); Long getYesterdayNewMembers(); - Optional> findAllMemberOnPushAlarm(); + + Optional> findAllMemberOnPushAlarm(Long offset, Long limit); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java index f5a2a5bd..1fa3873a 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberCustomRepositoryImpl.java @@ -88,7 +88,7 @@ public Long getYesterdayNewMembers() { } @Override - public Optional> findAllMemberOnPushAlarm() { + public Optional> findAllMemberOnPushAlarm(Long offset, Long limit) { return Optional.ofNullable( queryFactory.selectFrom(member) .where( @@ -96,6 +96,8 @@ public Optional> findAllMemberOnPushAlarm() { member.isRemindPush.eq(true), member.isSignOut.eq(false) ) + .offset(offset) + .limit(limit) .fetch() ); } diff --git a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java index 8bc9886c..c797cf41 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java +++ b/src/main/java/com/moing/backend/domain/member/domain/repository/MemberRepository.java @@ -2,5 +2,7 @@ import com.moing.backend.domain.member.domain.entity.Member; import org.springframework.data.jpa.repository.JpaRepository; + public interface MemberRepository extends JpaRepository, MemberCustomRepository { + } diff --git a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java index 85153003..36013dce 100644 --- a/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java +++ b/src/main/java/com/moing/backend/domain/member/domain/service/MemberGetService.java @@ -33,7 +33,7 @@ public Long getYesterdayNewMembers(){ } - public List getAllMemberOfPushAlarm() { - return memberRepository.findAllMemberOnPushAlarm().orElseThrow(NotFoundRemindAlarmException::new); + public List getAllMemberOfPushAlarm(Long offset, Long limit) { + return memberRepository.findAllMemberOnPushAlarm(offset,limit).orElseThrow(NotFoundRemindAlarmException::new); } } diff --git a/src/main/java/com/moing/backend/domain/member/dto/request/PostUpdatePushAlarm.java b/src/main/java/com/moing/backend/domain/member/dto/request/PostUpdatePushAlarm.java new file mode 100644 index 00000000..bc5d0fe6 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/dto/request/PostUpdatePushAlarm.java @@ -0,0 +1,14 @@ +package com.moing.backend.domain.member.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class PostUpdatePushAlarm { + + private String title; + private String message; +} diff --git a/src/main/java/com/moing/backend/domain/member/presentation/RemindAlarmController.java b/src/main/java/com/moing/backend/domain/member/presentation/RemindAlarmController.java new file mode 100644 index 00000000..799d7437 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/member/presentation/RemindAlarmController.java @@ -0,0 +1,29 @@ +package com.moing.backend.domain.member.presentation; + +import com.moing.backend.domain.member.application.service.UpdateRemindAlarmUseCase; +import com.moing.backend.domain.member.dto.request.PostUpdatePushAlarm; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/remind/alarm") +public class RemindAlarmController { + + private final UpdateRemindAlarmUseCase updateRemindAlarmUseCase; + + + @PostMapping("/update") + public ResponseEntity> postUpdateRemindAlarm(@AuthenticationPrincipal User user , @RequestBody PostUpdatePushAlarm postUpdatePushAlarm) { + updateRemindAlarmUseCase.sendUpdateAppPushAlarm(postUpdatePushAlarm.getTitle(), postUpdatePushAlarm.getMessage()); + return ResponseEntity.ok(SuccessResponse.create("remindAlarm Done")); + } + +} From c39f82e092b8769d09cee77f5225c44212337fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:12:02 +0900 Subject: [PATCH 615/619] =?UTF-8?q?fix:=20FCM=20SDK=20=EC=97=85=EA=B7=B8?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4ca667bb..a3f3499a 100644 --- a/build.gradle +++ b/build.gradle @@ -54,7 +54,7 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.7' // Push Alarm - implementation 'com.google.firebase:firebase-admin:8.2.0' + implementation 'com.google.firebase:firebase-admin:9.2.0' implementation 'com.google.firebase:firebase-messaging:23.0.0' // RestDocs From 18f5f150d3dc16b9da39d43ac2619adbc66012e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:34:19 +0900 Subject: [PATCH 616/619] =?UTF-8?q?hotfix=20:=20deprecated=20=EB=90=9C=20s?= =?UTF-8?q?endMulticast=20=EB=8C=80=EC=8B=A0=20sendEachForMulticast=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/global/config/fcm/service/MultiMessageSender.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/moing/backend/global/config/fcm/service/MultiMessageSender.java b/src/main/java/com/moing/backend/global/config/fcm/service/MultiMessageSender.java index ec54e038..f5bdcfba 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/service/MultiMessageSender.java +++ b/src/main/java/com/moing/backend/global/config/fcm/service/MultiMessageSender.java @@ -70,7 +70,8 @@ public void send(MultiRequest request) { .build(); try { - BatchResponse response = firebaseMessaging.sendMulticast(message); +// BatchResponse response = firebaseMessaging.sendMulticast(message); + BatchResponse response = firebaseMessaging.sendEachForMulticast(message); List failedTokens = new ArrayList<>(); From 46943aafd84f3fa1c8015643b39494e1e95cb8b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:34:41 +0900 Subject: [PATCH 617/619] =?UTF-8?q?hotfix=20:=20gitaction=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EB=B2=84=EC=A0=84=20?= =?UTF-8?q?=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/CD-prod.yml | 10 +++++----- .github/workflows/CI-dev.yml | 12 ++++++------ .github/workflows/CI-prod.yml | 12 ++++++------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/CD-prod.yml b/.github/workflows/CD-prod.yml index 4a541082..c14325ab 100644 --- a/.github/workflows/CD-prod.yml +++ b/.github/workflows/CD-prod.yml @@ -18,7 +18,7 @@ jobs: steps: # 소스 코드 체크아웃 - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # JDK 11 설정 - name: Set up JDK 11 @@ -29,7 +29,7 @@ jobs: # Gradle 패키지 캐시 - name: Cache Gradle packages - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: | ~/.gradle/caches @@ -49,17 +49,17 @@ jobs: echo "${{env.APPLE_KEY}}" > ./apple-key.p8 # 설정 파일을 작업공간에 저장 - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: application.yml path: ./src/main/resources/application.yml - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: firebase-key.json path: ./src/main/resources/firebase-key.json - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: apple-key.p8 path: ./src/main/resources/apple-key.p8 diff --git a/.github/workflows/CI-dev.yml b/.github/workflows/CI-dev.yml index caeb3688..608249cb 100644 --- a/.github/workflows/CI-dev.yml +++ b/.github/workflows/CI-dev.yml @@ -19,18 +19,18 @@ jobs: steps: # 소스 코드 체크아웃 - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # JDK 11 설정 - name: Set up JDK 11 - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'adopt' # Gradle 패키지 캐시 - name: Cache Gradle packages - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: | ~/.gradle/caches @@ -50,17 +50,17 @@ jobs: echo "${{env.APPLE_KEY}}" > ./apple-key.p8 # 설정 파일을 작업공간에 저장 - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: application.yml path: ./src/main/resources/application.yml - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: firebase-key.json path: ./src/main/resources/firebase-key.json - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: apple-key.p8 path: ./src/main/resources/apple-key.p8 diff --git a/.github/workflows/CI-prod.yml b/.github/workflows/CI-prod.yml index ee7e333c..57bd93bd 100644 --- a/.github/workflows/CI-prod.yml +++ b/.github/workflows/CI-prod.yml @@ -19,18 +19,18 @@ jobs: steps: # 소스 코드 체크아웃 - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # JDK 11 설정 - name: Set up JDK 11 - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'adopt' # Gradle 패키지 캐시 - name: Cache Gradle packages - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: | ~/.gradle/caches @@ -50,17 +50,17 @@ jobs: echo "${{env.APPLE_KEY}}" > ./apple-key.p8 # 설정 파일을 작업공간에 저장 - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: application.yml path: ./src/main/resources/application.yml - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: firebase-key.json path: ./src/main/resources/firebase-key.json - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: apple-key.p8 path: ./src/main/resources/apple-key.p8 From 244d626d03377a7c8e4b7384d8ed4a3edf3fd1fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:01:48 +0900 Subject: [PATCH 618/619] fix: github actions version up --- .github/workflows/CD-dev.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CD-dev.yml b/.github/workflows/CD-dev.yml index 581fe8c0..e2e47780 100644 --- a/.github/workflows/CD-dev.yml +++ b/.github/workflows/CD-dev.yml @@ -18,18 +18,18 @@ jobs: steps: # 소스 코드 체크아웃 - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # JDK 11 설정 - name: Set up JDK 11 - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'adopt' # Gradle 패키지 캐시 - name: Cache Gradle packages - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: | ~/.gradle/caches @@ -49,17 +49,17 @@ jobs: echo "${{env.APPLE_KEY}}" > ./apple-key.p8 # 설정 파일을 작업공간에 저장 - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: application.yml path: ./src/main/resources/application.yml - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: firebase-key.json path: ./src/main/resources/firebase-key.json - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: apple-key.p8 path: ./src/main/resources/apple-key.p8 From 7d08e95b265bc5cc95f0d20394aa1062916cdfbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=20=EC=8A=B9=20=EC=97=B0?= <53565255+seungyeonnnnnni@users.noreply.github.com> Date: Wed, 11 Sep 2024 14:27:36 +0900 Subject: [PATCH 619/619] =?UTF-8?q?fix:=20fcm=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EC=A0=84=EC=86=A1=20=EC=8B=A4=ED=8C=A8=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/global/config/fcm/exception/ExceptionHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/moing/backend/global/config/fcm/exception/ExceptionHandler.java b/src/main/java/com/moing/backend/global/config/fcm/exception/ExceptionHandler.java index b495c41a..daca80d0 100644 --- a/src/main/java/com/moing/backend/global/config/fcm/exception/ExceptionHandler.java +++ b/src/main/java/com/moing/backend/global/config/fcm/exception/ExceptionHandler.java @@ -18,6 +18,7 @@ public static NotificationException handleFirebaseMessagingException(FirebaseMes case "UNAVAILABLE": return new NotificationException("서비스를 사용할 수 없습니다: " + errorMessage); default: + e.printStackTrace(); return new NotificationException("메시지 전송에 실패했습니다: " + errorMessage); } }