From 5580db445a9521cb55d5844a86e76e705c822bb2 Mon Sep 17 00:00:00 2001 From: NadezhdaTA Date: Fri, 27 Jun 2025 11:43:57 +0400 Subject: [PATCH 1/9] =?UTF-8?q?=D0=A4=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2015?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8=D0=BD=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/shareit.mv.db | Bin 0 -> 40960 bytes db/shareit.trace.db | 162 ++++++++++++++++++ pom.xml | 26 ++- .../practicum/shareit/PersistenceConfig.java | 66 +++++++ .../ru/practicum/shareit/booking/Booking.java | 16 -- .../shareit/booking/BookingController.java | 39 ++++- .../shareit/booking/BookingServiceImpl.java | 120 +++++++++++++ .../shareit/booking/dto/BookingDto.java | 7 - .../booking/dto/BookingRequestDto.java | 35 ++++ .../booking/dto/BookingResponseDto.java | 31 ++++ .../booking/intrfaces/BookingRepository.java | 18 ++ .../intrfaces/BookingServiceInterface.java | 16 ++ .../shareit/booking/mapper/BookingMapper.java | 15 ++ .../shareit/booking/model/Booking.java | 42 +++++ .../booking/{ => model}/BookingStatus.java | 2 +- .../shareit/item/ItemController.java | 14 +- .../practicum/shareit/item/ItemService.java | 77 --------- .../shareit/item/ItemServiceImpl.java | 161 +++++++++++++++++ .../practicum/shareit/item/ItemStorage.java | 2 +- .../shareit/item/dto/CommentRequestDto.java | 19 ++ .../item/dto/CommentResponseCreatedDto.java | 17 ++ .../shareit/item/dto/CommentResponseDto.java | 17 ++ .../shareit/item/dto/ItemBookerDto.java | 18 ++ .../item/dto/ItemResponseDtoWithComments.java | 40 +++++ .../item/interfaces/CommentRepository.java | 13 ++ .../item/interfaces/ItemRepository.java | 20 +++ .../item/interfaces/ItemServiceInterface.java | 3 +- .../shareit/item/mapper/CommentMapper.java | 30 ++++ .../shareit/item/mapper/ItemMapper.java | 46 ++++- .../practicum/shareit/item/model/Comment.java | 34 ++++ .../ru/practicum/shareit/item/model/Item.java | 28 ++- .../shareit/request/ItemRequest.java | 22 +++ .../request/interfaces/RequestRepository.java | 8 + .../shareit/user/UserController.java | 2 +- ...{UserService.java => UserServiceImpl.java} | 33 ++-- .../shareit/user/dto/UserAuthorDto.java | 19 ++ .../shareit/user/dto/UserBookingDto.java | 20 +++ .../user/interfaces/UserRepository.java | 19 ++ .../shareit/user/mapper/UserMapper.java | 11 +- .../ru/practicum/shareit/user/model/User.java | 13 ++ src/main/resources/application.properties | 13 +- src/main/resources/schema.sql | 42 +++++ .../shareit/mapperTest/BookingMapperTest.java | 80 +++++++++ .../shareit/mapperTest/CommentMapperTest.java | 73 ++++++++ .../{ => mapperTest}/ItemMapperTest.java | 59 ++++++- .../{ => mapperTest}/UserMapperTest.java | 28 ++- src/test/resources/application.properties | 10 ++ 47 files changed, 1434 insertions(+), 152 deletions(-) create mode 100644 db/shareit.mv.db create mode 100644 db/shareit.trace.db create mode 100644 src/main/java/ru/practicum/shareit/PersistenceConfig.java delete mode 100644 src/main/java/ru/practicum/shareit/booking/Booking.java create mode 100644 src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java delete mode 100644 src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java create mode 100644 src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java create mode 100644 src/main/java/ru/practicum/shareit/booking/dto/BookingResponseDto.java create mode 100644 src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java create mode 100644 src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java create mode 100644 src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java create mode 100644 src/main/java/ru/practicum/shareit/booking/model/Booking.java rename src/main/java/ru/practicum/shareit/booking/{ => model}/BookingStatus.java (65%) delete mode 100644 src/main/java/ru/practicum/shareit/item/ItemService.java create mode 100644 src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/CommentRequestDto.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/CommentResponseCreatedDto.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/CommentResponseDto.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/ItemBookerDto.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java create mode 100644 src/main/java/ru/practicum/shareit/item/interfaces/CommentRepository.java create mode 100644 src/main/java/ru/practicum/shareit/item/interfaces/ItemRepository.java create mode 100644 src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java create mode 100644 src/main/java/ru/practicum/shareit/item/model/Comment.java create mode 100644 src/main/java/ru/practicum/shareit/request/interfaces/RequestRepository.java rename src/main/java/ru/practicum/shareit/user/{UserService.java => UserServiceImpl.java} (65%) create mode 100644 src/main/java/ru/practicum/shareit/user/dto/UserAuthorDto.java create mode 100644 src/main/java/ru/practicum/shareit/user/dto/UserBookingDto.java create mode 100644 src/main/java/ru/practicum/shareit/user/interfaces/UserRepository.java create mode 100644 src/main/resources/schema.sql create mode 100644 src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java create mode 100644 src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java rename src/test/java/ru/practicum/shareit/{ => mapperTest}/ItemMapperTest.java (57%) rename src/test/java/ru/practicum/shareit/{ => mapperTest}/UserMapperTest.java (72%) create mode 100644 src/test/resources/application.properties diff --git a/db/shareit.mv.db b/db/shareit.mv.db new file mode 100644 index 0000000000000000000000000000000000000000..c8db7fd9467ab22f599c466f85b22ea51cf95d9c GIT binary patch literal 40960 zcmeHQ&5zs06{lpaS6yfABu<=9C$wzGURO~${H9K!B(7KWuGW#Xj*Ye;D01X1vMU*D z*|l2)O%R|!Z$(iQJ+uhgpg@{GpvR(z9(w2@hob1Uz4ln3K+#JdXZR(G(rRNlAL#4? zA}P&q-u!0X<9qYo8*Ws^a&K?wzEjocv9tRv2art04992CX!U6EEE-lbx%;$q9RI)EDB;#(FLg|^-)nV9MustIKhtV zAj2uDf`>f`qoUSRk&OC6QI|bQ@dUl7YXWxrs$0~1x}hsF{N$e)a6|v3@2SW?aRh|= zAgiVjvB*EMj_lNASvaA)lFupnx3u`fga zWJ53ZdtSfq2~x4|_Hhr1==|{DcI9ocvVZ^XXn24tUa!)+x3_o0*}I1u&dBLLyn`22 zrkrYP^q_KsMtxw9H0U>WVcl_ol7|;lg@Lg4@Vg;NVX5QG;WS?qk&C*|W9V#QiFP&( z%?Mzt)EfMeKp^2HxxP2>hMU9N6*PV+YW}a) z5Sk#$GkCCrD)iH6U6qq%^x;pzV-)p}sZNo{?QIP@po}qjZX4 zH0lJML<7sHN9h!$?Dmp$hDv0TPEpIQ=i>tUT}FEWozwd_6HjSM|B`fu+G>(cNts3` z(N)LjB%D#TUnRpIO^$SZW&C$>;&(EqtLZuY8o4V4U7&MljP^kHzDSBuMwu)Xs=aIU zX3>0}EE%fs(fxqgNU2bTCOr?;dP-cttJ80$Ci*bPya~sHR-@xTb=nY%VQe^(txcIV zNd&`LniKO#$Rqfa@<_=eHIMWh&KWs1r{|;`e1q~x&UtyH<@z}-FM4?qb6oDDC)_-D zoGTIoumUDiaH1^l!}F%H>mB!Pz6zoTksg$v=K_OK3ZllT;V1=$BV6s?$JY}^q-cl& z`Etv*D0R31$zBy*YEinbZ&B(VQbcM|%6-S{rzw-mZk3-6ofHH@ev?!nqB`EW0cuslnN+^PEbo)M3SKf=YBK#35o~mBNu_D{vO9&xe3QNxcup# z5zYPByFVsJ_Q4Qf2rvW~0t^9$07HNwzz|>vFa#I^3;~9~R|$cX|NVZLMX$zL^sIzXq!)5z!j;|Epx#0~UM4xS>Zq z^S2N<%YDEt<#HUi`Uj3fKPSh$@a>alPC;SlezYVcjNwrTOD>pQj0X1!D) zH+O()v%@zVR;%0W-r_sfn>$vk zp1fh_R;O!i+2JoXL>Z_xNzv^F5^J_>A=8E>O3{{TmQa(e23nW(5<#f7v$2j zXK71o^U%8ny!7uwc&P~!KjJ0-V$r-*GbLGTn5M02HPx0?OR!B1X$YAc2 zI7_juxzpX)&gAQrwZfA}mN5X7aLGDx8L{dDD40BqYtwGy0eqyd+B(o`LTEbqY_1&6KA17kD!)6%mu- z?6~Dj)}E*ya5wbjQMtSDEWp^C4@N2;sZ^W+VLox z2vhyYgpf9HIev6a7m$VLKmh*z5CI5kz%@|XBLNs(FIoULYFfQ+nSyPBab(Ndx?$H$ zMYS7^bw$=yp;lACG)oCBB0}s27&s-q+uQ=R!`!-_E@ZVDhZPA2AT*m&&G=oOsq;X) z-JMRBCdilo%^%7LRF~LMfW4K z_*nqzTXO?-$TSF;VC)(53Sjl8MPXG-f#r`BZFC;Efci|lCd}^{BJouai60yy5(5(_ z5{Z*0&th~!RcJ_(q1&cl7`AMxqFqBE9K~9_R)^pzT`&Q!l&lJ9$yVh8JMR$F5Y$Is zXz@oATJ^c8oh`J^!DO9Z=|d@*6%R`(F(PY)63oykN?%lEE|CQdj!CR!D>Ee)DizK{ z*QOb86O4a&&w}wCso6Rz}V7k$}4STy8CX46OB_|X4P zwWl~)!cUNpV*P_C9yrQ}2$D5?#R#_hk7zcip3)=kf5};(_n+s%|DXR)ewX8llPN1| zn7g8dC;HKJ$LUEdOm~#Bb;l1w)i!u-1Z?_{+(81aQi(vwk0uFK+c*&@&~4Qq;qtf z2^#g7MxD?o_SGbbvl4;E^lx9BTxru-1m^#by@V4MwOnHU|FIYx=KrTrJTzX1`Ty6L z|35RlF7#lA5q81#qTOHfxy(~*z0Cg)VR(drXE=2e1IGOSi9niYVozWCX8wPOTx9-# z=KqhpkW&H#9*h4!u>V8jBw0C4C6fJ3bvRm6*H%F56PQJ(GU;G=#!LjhdFM=e!Q=jBnk{(OaJ0#6; zX8agS(hJfB;~bjlX^1RIFU+7#r;E;)ewJE`BVoNPNiUtsIFnyllHSdUMA|TY19J0O8Gb$XlfQSOVSH>CzzeU9H$DUWn)nPu`JRbmasTe|0%E}J=ohMP6-|}R#=iA z-QOqiJPWcJS&|-0(!0!(^rmcz#FF&LE*_s(lHStCFa55--sJq-gj=a8t zz13wnnD;F??5!^T`-9k9UBXR1Ctp4Dh;Mbt_s;!viCd0RWF|9XjG37+zYUWn4o_I7 zNfQWCBPO#Zg13Oqk*-XVCm@7qB6-4ylP5A0P_$1%QV&l+2}n&QphO8Cgw(mRPv#*t zI~S!N<)Rp4Z_SC*t&Wh3G9?Ksk&AK&oJN?QmCi-MB)m)04Wyo+=k%pC^c-GRqbFWU zvFa#I^3;~8f0)Zg@ bKa9VR;{Tm^|9?$(4al^Y7Z*$)-)ZH4hydT9 literal 0 HcmV?d00001 diff --git a/db/shareit.trace.db b/db/shareit.trace.db new file mode 100644 index 0000000..62ff604 --- /dev/null +++ b/db/shareit.trace.db @@ -0,0 +1,162 @@ +2025-06-26 07:25:54 jdbc[3]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 07:25:55 jdbc[3]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:26:44 jdbc[3]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:31:14 jdbc[3]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:31:16 jdbc[4]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:31:50 jdbc[5]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:31:50 jdbc[5]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Схема "INFORMATION_SCHEMA" не может быть удалена +Schema "INFORMATION_SCHEMA" cannot be dropped; SQL statement: +drop schema INFORMATION_SCHEMA [90090-220] + at org.h2.message.DbException.getJdbcSQLException(DbException.java:644) + at org.h2.message.DbException.getJdbcSQLException(DbException.java:489) + at org.h2.message.DbException.get(DbException.java:223) + at org.h2.message.DbException.get(DbException.java:199) + at org.h2.command.ddl.DropSchema.update(DropSchema.java:49) + at org.h2.command.CommandContainer.update(CommandContainer.java:169) + at org.h2.command.Command.executeUpdate(Command.java:252) + at org.h2.jdbc.JdbcStatement.executeUpdateInternal(JdbcStatement.java:190) + at org.h2.jdbc.JdbcStatement.executeUpdate(JdbcStatement.java:143) + at com.intellij.database.remote.jdbc.impl.RemoteStatementImpl.executeUpdate(RemoteStatementImpl.java:189) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:31:50 jdbc[6]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) diff --git a/pom.xml b/pom.xml index a3b4a77..091dc51 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,10 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-data-jpa + org.springframework.boot spring-boot-starter-actuator @@ -63,11 +67,11 @@ spring-boot-starter-validation - - org.mapstruct - mapstruct - ${org.mapstruct.version} - + + org.mapstruct + mapstruct + ${org.mapstruct.version} + org.projectlombok @@ -159,6 +163,18 @@ ${lombok-mapstruct-binding.version} + true + + + -Amapstruct.suppressGeneratorTimestamp=true + + + -Amapstruct.suppressGeneratorVersionInfoComment=true + + + -Amapstruct.verbose=true + + diff --git a/src/main/java/ru/practicum/shareit/PersistenceConfig.java b/src/main/java/ru/practicum/shareit/PersistenceConfig.java new file mode 100644 index 0000000..04d14b2 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/PersistenceConfig.java @@ -0,0 +1,66 @@ +package ru.practicum.shareit; + +import jakarta.persistence.EntityManagerFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@RequiredArgsConstructor +@EnableTransactionManagement +@EnableJpaRepositories(basePackages = "ru.practicum") +public class PersistenceConfig { + private final Environment environment; + + @Bean + public DataSource dataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(environment.getRequiredProperty("spring.datasource.driverClassName")); + dataSource.setUrl(environment.getRequiredProperty("spring.datasource.url")); + dataSource.setUsername(environment.getRequiredProperty("spring.datasource.username")); + dataSource.setPassword(environment.getRequiredProperty("spring.datasource.password")); + return dataSource; + } + + private Properties hibernateProperties() { + Properties properties = new Properties(); + properties.put("spring.jpa.properties.hibernate.jdbc.time_zone", + environment.getRequiredProperty("spring.jpa.properties.hibernate.jdbc.time_zone")); + properties.put("spring.jpa.properties.hibernate.format_sql", + environment.getProperty("spring.jpa.properties.hibernate.format_sql", "false")); + return properties; + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { + final HibernateJpaVendorAdapter vendorAdapter = + new HibernateJpaVendorAdapter(); + + final LocalContainerEntityManagerFactoryBean emf = + new LocalContainerEntityManagerFactoryBean(); + + emf.setDataSource(dataSource); + emf.setJpaVendorAdapter(vendorAdapter); + emf.setPackagesToScan("ru.practicum"); + emf.setJpaProperties(hibernateProperties()); + + return emf; + } + + @Bean + public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { + JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory); + return transactionManager; + } +} diff --git a/src/main/java/ru/practicum/shareit/booking/Booking.java b/src/main/java/ru/practicum/shareit/booking/Booking.java deleted file mode 100644 index 8facd50..0000000 --- a/src/main/java/ru/practicum/shareit/booking/Booking.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.practicum.shareit.booking; - -import java.time.LocalDate; - -/** - * TODO Sprint add-bookings. - */ -public class Booking { - - private Long bookingId; - private LocalDate start; - private LocalDate end; - private Long itemId; - private Long bookerId; - BookingStatus status; -} diff --git a/src/main/java/ru/practicum/shareit/booking/BookingController.java b/src/main/java/ru/practicum/shareit/booking/BookingController.java index b94493d..6d9e0d0 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingController.java +++ b/src/main/java/ru/practicum/shareit/booking/BookingController.java @@ -1,12 +1,41 @@ package ru.practicum.shareit.booking; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.booking.dto.BookingRequestDto; +import ru.practicum.shareit.booking.dto.BookingResponseDto; +import ru.practicum.shareit.booking.intrfaces.BookingServiceInterface; + +import java.util.Collection; -/** - * TODO Sprint add-bookings. - */ @RestController @RequestMapping(path = "/bookings") +@RequiredArgsConstructor public class BookingController { + private final BookingServiceInterface bookingService; + public static final String USER_ID = "X-Sharer-User-Id"; + + @PostMapping + public BookingResponseDto postBooking(@RequestBody BookingRequestDto booking, + @RequestHeader(USER_ID) Long bookerId) { + return bookingService.postBooking(booking, bookerId); + } + + @PatchMapping("/{bookingId}") + public BookingResponseDto bookingApprove(@PathVariable Long bookingId, + @RequestHeader (USER_ID) Long ownerId, + @RequestParam Boolean approved) { + return bookingService.bookingApprove(bookingId, ownerId, approved); + } + + @GetMapping("/{bookingId}") + public BookingResponseDto getBooking(@PathVariable Long bookingId) { + return bookingService.getBookingByBookingId(bookingId); + } + + @GetMapping + public Collection getBookingsForUser( + @RequestHeader (USER_ID) Long userId) { + return bookingService.getBookingsForUser(userId); + } } diff --git a/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java new file mode 100644 index 0000000..6967cb1 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java @@ -0,0 +1,120 @@ +package ru.practicum.shareit.booking; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.practicum.shareit.booking.dto.BookingRequestDto; +import ru.practicum.shareit.booking.dto.BookingResponseDto; +import ru.practicum.shareit.booking.intrfaces.BookingRepository; +import ru.practicum.shareit.booking.intrfaces.BookingServiceInterface; +import ru.practicum.shareit.booking.mapper.BookingMapper; +import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.exception.AnotherUserException; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.item.interfaces.ItemRepository; +import ru.practicum.shareit.item.mapper.ItemMapper; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.interfaces.UserRepository; +import ru.practicum.shareit.user.mapper.UserMapper; +import ru.practicum.shareit.user.model.User; + +import java.util.ArrayList; +import java.util.Collection; + +@Service +@RequiredArgsConstructor +public class BookingServiceImpl implements BookingServiceInterface { + private final BookingRepository storage; + private final UserRepository userStorage; + private final ItemRepository itemStorage; + + private final ItemMapper itemMapper; + private final UserMapper userMapper; + private final BookingRepository bookingRepository; + private final BookingMapper bookingMapper; + + + @Override + public BookingResponseDto postBooking(BookingRequestDto booking, Long bookerId) { + Item item = itemStorage.findById(booking.getItemId()) + .orElseThrow(() -> new NotFoundException("Item not found")); + + if (item.getIsAvailable().equals(false)) { + throw new RuntimeException("Booking item is not available"); + } + + Booking saved = bookingMapper.bookingRequestDtoToBooking(booking); + saved.setBooker(userStorage.getUserByUserId(bookerId).get()); + saved.setItem(item); + + if (item.getIsAvailable()) { + saved.setStatus(BookingStatus.WAITING); + } else { + saved.setStatus(BookingStatus.REJECTED); + throw new AnotherUserException("Booking item is rejected, item is not available"); + } + + storage.save(saved); + + BookingResponseDto responseDto = bookingMapper.bookingToBookingResponseDto(saved); + mapBookerAndItemToBooking(responseDto, saved); + return responseDto; + } + + @Override + public BookingResponseDto bookingApprove(Long bookingId, Long ownerId, Boolean isAvailable) { + Booking booking = bookingRepository.getBookingByBookingId(bookingId) + .orElseThrow(() -> new NotFoundException("Booking not found")); + + Item item = booking.getItem(); + if (!item.getOwner().getUserId().equals(ownerId)) { + throw new AnotherUserException("You are not allowed to approve this booking"); + } + + if (item.getIsAvailable().equals(false)) { + booking.setStatus(BookingStatus.REJECTED); + throw new RuntimeException("Booking item is rejected"); + } else { + booking.setStatus(BookingStatus.APPROVED); + } + + BookingResponseDto responseDto = bookingMapper.bookingToBookingResponseDto(booking); + mapBookerAndItemToBooking(responseDto, booking); + + return responseDto; + } + + @Override + public BookingResponseDto getBookingByBookingId(Long bookingId) { + Booking booking = bookingRepository.getBookingByBookingId(bookingId) + .orElseThrow(() -> new NotFoundException("Booking not found")); + + BookingResponseDto bookingDto = bookingMapper.bookingToBookingResponseDto(booking); + + mapBookerAndItemToBooking(bookingDto, booking); + + return bookingDto; + } + + @Override + public Collection getBookingsForUser(Long userId) { + User user = userStorage.getUserByUserId(userId) + .orElseThrow(() -> new NotFoundException("User not found")); + + Collection bookings = bookingRepository.getBookingsByBooker_UserId(user.getUserId()); + Collection bookingDtos = new ArrayList<>(); + + for (Booking booking : bookings) { + BookingResponseDto bookingDto = bookingMapper.bookingToBookingResponseDto(booking); + mapBookerAndItemToBooking(bookingDto, booking); + bookingDtos.add(bookingDto); + } + + return bookingDtos; + } + + private void mapBookerAndItemToBooking(BookingResponseDto bookingDto, Booking booking) { + bookingDto.setBooker(userMapper.toUserBookingDto(booking.getBooker())); + bookingDto.setItem(itemMapper.toItemBookerDto(booking.getItem())); + } +} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java deleted file mode 100644 index 861de9e..0000000 --- a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.practicum.shareit.booking.dto; - -/** - * TODO Sprint add-bookings. - */ -public class BookingDto { -} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java new file mode 100644 index 0000000..8c4033a --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java @@ -0,0 +1,35 @@ +package ru.practicum.shareit.booking.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.Future; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.practicum.shareit.booking.model.BookingStatus; + +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class BookingRequestDto { + @JsonProperty("id") + private Long bookingId; + + @NotNull + @Future + private LocalDateTime start; + + @NotNull + @Future + private LocalDateTime end; + + @NotNull + private Long itemId; + + @NotNull + private Long bookerId; + + private BookingStatus status; +} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingResponseDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingResponseDto.java new file mode 100644 index 0000000..c59d3a4 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingResponseDto.java @@ -0,0 +1,31 @@ +package ru.practicum.shareit.booking.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.item.dto.ItemBookerDto; +import ru.practicum.shareit.user.dto.UserBookingDto; + +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class BookingResponseDto { + + @JsonProperty("id") + private Long bookingId; + + private LocalDateTime start; + + private LocalDateTime end; + + private ItemBookerDto item; + + private UserBookingDto booker; + + private BookingStatus status; + +} diff --git a/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java new file mode 100644 index 0000000..a1948c5 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java @@ -0,0 +1,18 @@ +package ru.practicum.shareit.booking.intrfaces; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.practicum.shareit.booking.model.Booking; + +import java.util.Collection; +import java.util.Optional; + +public interface BookingRepository extends JpaRepository { + + Booking save(Booking booking); + + Optional getBookingByBookingId(Long bookingId); + + Collection getBookingsByBooker_UserId(Long bookerId); + + Collection getBookingsByItem_ItemId(Long itemId); +} diff --git a/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java new file mode 100644 index 0000000..55c627e --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java @@ -0,0 +1,16 @@ +package ru.practicum.shareit.booking.intrfaces; + +import ru.practicum.shareit.booking.dto.BookingRequestDto; +import ru.practicum.shareit.booking.dto.BookingResponseDto; + +import java.util.Collection; + +public interface BookingServiceInterface { + BookingResponseDto postBooking(BookingRequestDto booking, Long bookerId); + + BookingResponseDto bookingApprove(Long bookingId, Long ownerId, Boolean isAvailable); + + BookingResponseDto getBookingByBookingId(Long bookingId); + + Collection getBookingsForUser(Long userId); +} diff --git a/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java b/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java new file mode 100644 index 0000000..9d51d2c --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java @@ -0,0 +1,15 @@ +package ru.practicum.shareit.booking.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import ru.practicum.shareit.booking.dto.BookingRequestDto; +import ru.practicum.shareit.booking.dto.BookingResponseDto; +import ru.practicum.shareit.booking.model.Booking; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface BookingMapper { + Booking bookingRequestDtoToBooking(BookingRequestDto bookingRequestDto); + + BookingResponseDto bookingToBookingResponseDto(Booking booking); +} + diff --git a/src/main/java/ru/practicum/shareit/booking/model/Booking.java b/src/main/java/ru/practicum/shareit/booking/model/Booking.java new file mode 100644 index 0000000..c4b2ff2 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/model/Booking.java @@ -0,0 +1,42 @@ +package ru.practicum.shareit.booking.model; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.model.User; + +import java.time.LocalDateTime; + +@Data +@Entity +@Table(name = "bookings") +@AllArgsConstructor +@NoArgsConstructor +@ToString +public class Booking { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "booking_id") + private Long bookingId; + + @Column(name = "start_date") + private LocalDateTime start; + + @Column(name = "end_date") + private LocalDateTime end; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "item_id") + private Item item; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "booker_id") + private User booker; + + @Enumerated(EnumType.STRING) + private BookingStatus status; +} diff --git a/src/main/java/ru/practicum/shareit/booking/BookingStatus.java b/src/main/java/ru/practicum/shareit/booking/model/BookingStatus.java similarity index 65% rename from src/main/java/ru/practicum/shareit/booking/BookingStatus.java rename to src/main/java/ru/practicum/shareit/booking/model/BookingStatus.java index 51269e0..4eb25ea 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingStatus.java +++ b/src/main/java/ru/practicum/shareit/booking/model/BookingStatus.java @@ -1,4 +1,4 @@ -package ru.practicum.shareit.booking; +package ru.practicum.shareit.booking.model; public enum BookingStatus { WAITING, diff --git a/src/main/java/ru/practicum/shareit/item/ItemController.java b/src/main/java/ru/practicum/shareit/item/ItemController.java index d033939..9404d6f 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemController.java +++ b/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -6,8 +6,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import ru.practicum.shareit.item.dto.ItemRequestDto; -import ru.practicum.shareit.item.dto.ItemResponseDto; +import ru.practicum.shareit.item.dto.*; import java.util.Collection; @@ -19,7 +18,7 @@ public class ItemController { public static final String OWNER_ID = "X-Sharer-User-Id"; - private final ItemService itemService; + private final ItemServiceImpl itemService; @PostMapping public ItemResponseDto create(@RequestHeader(OWNER_ID) Long ownerId, @@ -35,7 +34,7 @@ public ItemResponseDto update(@RequestBody ItemRequestDto item, } @GetMapping("/{itemId}") - public ItemResponseDto getItemById(@PathVariable Long itemId) { + public ItemResponseDtoWithComments getItemById(@PathVariable Long itemId) { return itemService.getItemById(itemId); } @@ -50,4 +49,11 @@ public Collection searchItems(@RequestParam String text) { return itemService.searchByText(text); } + @PostMapping("/{itemId}/comment") + public CommentResponseCreatedDto addComment(@RequestBody CommentRequestDto comment, + @PathVariable Long itemId, + @RequestHeader(OWNER_ID) Long commentatorId) { + return itemService.addComment(commentatorId, comment, itemId); + } + } diff --git a/src/main/java/ru/practicum/shareit/item/ItemService.java b/src/main/java/ru/practicum/shareit/item/ItemService.java deleted file mode 100644 index 9dd0d0c..0000000 --- a/src/main/java/ru/practicum/shareit/item/ItemService.java +++ /dev/null @@ -1,77 +0,0 @@ -package ru.practicum.shareit.item; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import ru.practicum.shareit.exception.AnotherUserException; -import ru.practicum.shareit.exception.NotFoundException; -import ru.practicum.shareit.exception.ValidationException; -import ru.practicum.shareit.item.dto.ItemRequestDto; -import ru.practicum.shareit.item.dto.ItemResponseDto; -import ru.practicum.shareit.item.interfaces.ItemServiceInterface; -import ru.practicum.shareit.item.mapper.ItemMapper; -import ru.practicum.shareit.item.model.Item; -import ru.practicum.shareit.user.UserStorage; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class ItemService implements ItemServiceInterface { - - private final ItemStorage itemStorage; - private final UserStorage userStorage; - private final ItemMapper itemMapper; - - public ItemResponseDto createItem(ItemRequestDto item, Long ownerId) { - if (ownerId == null) { - throw new ValidationException("Owner id cannot be null"); - } - userStorage.getUserById(ownerId) - .orElseThrow(() -> new NotFoundException("User with id " + ownerId + " not found")); - Item itemSaved = itemMapper.toItem(item); - itemSaved.setOwnerId(ownerId); - return itemMapper.toItemResponseDto(itemStorage.createItem(itemSaved)); - } - - public ItemResponseDto getItemById(Long id) { - return itemMapper.toItemResponseDto(itemStorage.getItemById(id) - .orElseThrow(() -> new NotFoundException("Item with id " + id + " not found"))); - } - - public ItemResponseDto updateItem(Long itemId, - ItemRequestDto item, Long ownerId) { - findUserById(ownerId); - Item foundItem = itemStorage.getItemById(itemId) - .orElseThrow(() -> new NotFoundException("Item with id " + itemId + " not found")); - if (foundItem.getOwnerId().equals(ownerId)) { - item.setItemId(itemId); - foundItem = itemMapper.toItem(item); - } else { - throw new AnotherUserException("User with id " + ownerId + " is not owner of this Item"); - } - return itemMapper.toItemResponseDto(itemStorage.updateItem(foundItem)); - } - - public Collection getAllItemsForOwner(Long ownerId) { - return itemStorage.getAllItemsForOwner(ownerId).stream() - .map(itemMapper::toItemResponseDto) - .collect(Collectors.toList()); - } - - public Collection searchByText(String text) { - if (text == null || text.isEmpty()) { - return new ArrayList<>(); - } - return itemStorage.searchByText(text).stream() - .filter(Item::getIsAvailable) - .map(itemMapper::toItemResponseDto) - .collect(Collectors.toList()); - } - - private void findUserById(Long userId) { - userStorage.getUserById(userId) - .orElseThrow(() -> new NotFoundException("User with id = " + userId + " not found")); - } -} diff --git a/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java new file mode 100644 index 0000000..29d56ac --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java @@ -0,0 +1,161 @@ +package ru.practicum.shareit.item; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.practicum.shareit.booking.intrfaces.BookingRepository; +import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.exception.AnotherUserException; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.exception.ValidationException; +import ru.practicum.shareit.item.dto.*; +import ru.practicum.shareit.item.interfaces.CommentRepository; +import ru.practicum.shareit.item.interfaces.ItemRepository; +import ru.practicum.shareit.item.interfaces.ItemServiceInterface; +import ru.practicum.shareit.item.mapper.CommentMapper; +import ru.practicum.shareit.item.mapper.ItemMapper; +import ru.practicum.shareit.item.model.Comment; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.interfaces.UserRepository; +import ru.practicum.shareit.user.mapper.UserMapper; +import ru.practicum.shareit.user.model.User; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + + +@Service +@RequiredArgsConstructor +public class ItemServiceImpl implements ItemServiceInterface { + + private final ItemRepository itemRepository; + private final UserRepository userRepository; + private final CommentRepository commentRepository; + private final BookingRepository bookingRepository; + private final ItemMapper itemMapper; + private final UserMapper userMapper; + private final CommentMapper commentMapper; + + public ItemResponseDto createItem(ItemRequestDto item, Long ownerId) { + if (ownerId == null) { + throw new ValidationException("Owner id cannot be null"); + } + + User owner = userRepository.getUserByUserId(ownerId) + .orElseThrow(() -> new NotFoundException("User with id " + ownerId + " not found")); + + Item itemSaved = itemMapper.toItem(item); + itemSaved.setOwner(owner); + + itemRepository.save(itemSaved); + ItemResponseDto responseDto = itemMapper.toItemResponseDto(itemSaved); + mapResponseDto(itemSaved, responseDto); + + return responseDto; + } + + public ItemResponseDtoWithComments getItemById(Long id) { + ItemResponseDto item = itemMapper.toItemResponseDto(itemRepository.getItemByItemId(id) + .orElseThrow(() -> new NotFoundException("Item with id " + id + " not found"))); + + List comments = commentRepository.getCommentsByItem_ItemId(id).stream() + .map(commentMapper::toCommentResponseDto) + .collect(Collectors.toList()); + + ItemResponseDtoWithComments itemDto = itemMapper.toItemResponseDtoWithComments( + itemRepository.getItemByItemId(id).get()); + itemDto.setComments(comments); + + return itemDto; + } + + public ItemResponseDto updateItem(Long itemId, + ItemRequestDto item, Long ownerId) { + + User owner = userRepository.getUserByUserId(ownerId) + .orElseThrow(() -> new NotFoundException("User with id " + ownerId + " not found")); + + Item foundItem = itemRepository.getItemByItemId(itemId) + .orElseThrow(() -> new NotFoundException("Item with id " + itemId + " not found")); + + if (foundItem.getOwner().getUserId().equals(ownerId)) { + + if (item.getIsAvailable() != null) { + foundItem.setIsAvailable(item.getIsAvailable()); + } + + if (item.getItemName() != null) { + foundItem.setItemName(item.getItemName()); + } + + if (item.getItemDescription() != null) { + foundItem.setItemDescription(item.getItemDescription()); + } + + } else { + throw new AnotherUserException("User with id " + ownerId + " is not owner of this Item"); + } + + ItemResponseDto responseDto = itemMapper.toItemResponseDto(foundItem); + mapResponseDto(foundItem, responseDto); + + return responseDto; + } + + public Collection getAllItemsForOwner(Long ownerId) { + User owner = userRepository.getUserByUserId(ownerId) + .orElseThrow(() -> new NotFoundException("User with id " + ownerId + " not found")); + + return itemRepository.getItemsByOwner_UserId(ownerId).stream() + .map(itemMapper::toItemResponseDto) + .peek(item -> item.setOwnerId(ownerId)) + .collect(Collectors.toList()); + } + + public Collection searchByText(String text) { + if (text == null || text.isEmpty()) { + return new ArrayList<>(); + } + return itemRepository.searchByTextContainingIgnoreCase(text).stream() + .filter(Item::getIsAvailable) + .map(itemMapper::toItemResponseDto) + .collect(Collectors.toList()); + } + + public CommentResponseCreatedDto addComment(Long commentatorId, + CommentRequestDto commentDto, Long itemId) { + Collection bookings = bookingRepository.getBookingsByItem_ItemId(itemId); + + Booking booking = bookings.stream() + .filter(booking1 -> booking1.getBooker().getUserId().equals(commentatorId)) + .findFirst() + .orElseThrow(() -> new NotFoundException("Booking with bookerId " + commentatorId + " not found")); + + if (!booking.getEnd().isBefore(commentDto.getDate())) { + throw new ValidationException("Booking end date cannot be before comment date"); + } + + if (booking.getStatus().equals(BookingStatus.APPROVED)) { + throw new ValidationException("Booking status cannot be APPROVED"); + } + + Comment comment = commentMapper.toComment(commentDto); + comment.setItem(itemRepository.getItemByItemId(itemId).get()); + comment.setAuthor(userRepository.getUserByUserId(commentatorId).get()); + + return commentMapper.toCommentResponseCreatedDto( + commentRepository.save(comment)); + } + + private void mapResponseDto(Item item, ItemResponseDto itemResponseDto) { + itemResponseDto.setOwnerId(item.getOwner().getUserId()); + + if (item.getItemRequest() != null) { + itemResponseDto.setRequestId(item.getItemRequest().getItemRequestId()); + } + } + +} + diff --git a/src/main/java/ru/practicum/shareit/item/ItemStorage.java b/src/main/java/ru/practicum/shareit/item/ItemStorage.java index 6b234d5..e9ba003 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemStorage.java +++ b/src/main/java/ru/practicum/shareit/item/ItemStorage.java @@ -49,7 +49,7 @@ public Item updateItem(Item item) { public Collection getAllItemsForOwner(Long ownerId) { return items.values() .stream() - .filter(item -> Objects.equals(item.getOwnerId(), ownerId)) + .filter(item -> Objects.equals(item.getOwner().getUserId(), ownerId)) .collect(Collectors.toList()); } diff --git a/src/main/java/ru/practicum/shareit/item/dto/CommentRequestDto.java b/src/main/java/ru/practicum/shareit/item/dto/CommentRequestDto.java new file mode 100644 index 0000000..3462221 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/CommentRequestDto.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.item.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class CommentRequestDto { + + @JsonProperty("id") + private Long authorId; + + @JsonProperty("text") + private String text; + + private LocalDateTime date = LocalDateTime.now(); + +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/CommentResponseCreatedDto.java b/src/main/java/ru/practicum/shareit/item/dto/CommentResponseCreatedDto.java new file mode 100644 index 0000000..f47203c --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/CommentResponseCreatedDto.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.item.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class CommentResponseCreatedDto { + @JsonProperty("id") + private Long commentId; + + @JsonProperty("text") + private String text; + + private String authorName; + + private Boolean created = true; +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/CommentResponseDto.java b/src/main/java/ru/practicum/shareit/item/dto/CommentResponseDto.java new file mode 100644 index 0000000..9dc1ff9 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/CommentResponseDto.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.item.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import ru.practicum.shareit.user.dto.UserAuthorDto; + +@Data +public class CommentResponseDto { + + @JsonProperty("id") + private Long commentId; + + @JsonProperty("text") + private String text; + + private UserAuthorDto author; +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemBookerDto.java b/src/main/java/ru/practicum/shareit/item/dto/ItemBookerDto.java new file mode 100644 index 0000000..28d23ca --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/ItemBookerDto.java @@ -0,0 +1,18 @@ +package ru.practicum.shareit.item.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ItemBookerDto { + + @JsonProperty("id") + private Long itemId; + + @JsonProperty("name") + private String itemName; +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java b/src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java new file mode 100644 index 0000000..53e00e3 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java @@ -0,0 +1,40 @@ +package ru.practicum.shareit.item.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ItemResponseDtoWithComments { + + @NotNull + @JsonProperty("id") + private Long itemId; + + @JsonProperty("name") + private String itemName; + + @JsonProperty("description") + private String itemDescription; + + @JsonProperty("available") + private Boolean isAvailable; + + @JsonProperty("userId") + private Long ownerId; + + private Long requestId; + + private LocalDateTime lastBooking; + + private LocalDateTime nextBooking; + + private List comments; +} diff --git a/src/main/java/ru/practicum/shareit/item/interfaces/CommentRepository.java b/src/main/java/ru/practicum/shareit/item/interfaces/CommentRepository.java new file mode 100644 index 0000000..01f501c --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/interfaces/CommentRepository.java @@ -0,0 +1,13 @@ +package ru.practicum.shareit.item.interfaces; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.practicum.shareit.item.model.Comment; + +import java.util.Collection; + +public interface CommentRepository extends JpaRepository { + + Comment save(Comment comment); + + Collection getCommentsByItem_ItemId(Long itemId); +} diff --git a/src/main/java/ru/practicum/shareit/item/interfaces/ItemRepository.java b/src/main/java/ru/practicum/shareit/item/interfaces/ItemRepository.java new file mode 100644 index 0000000..d27984b --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/interfaces/ItemRepository.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.item.interfaces; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import ru.practicum.shareit.item.model.Item; + +import java.util.Collection; +import java.util.Optional; + +public interface ItemRepository extends JpaRepository { + Item save(Item item); + + Optional getItemByItemId(Long itemId); + + Collection getItemsByOwner_UserId(Long ownerUserId); + + @Query(value = "SELECT i FROM Item i WHERE upper(i.itemName) like upper(concat('%', ?1, '%')) " + + " OR upper(i.itemDescription) LIKE upper(concat('%', ?1, '%'))") + Collection searchByTextContainingIgnoreCase(String text); +} diff --git a/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java b/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java index 053d40c..f09f8d5 100644 --- a/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java +++ b/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java @@ -2,13 +2,14 @@ import ru.practicum.shareit.item.dto.ItemRequestDto; import ru.practicum.shareit.item.dto.ItemResponseDto; +import ru.practicum.shareit.item.dto.ItemResponseDtoWithComments; import java.util.Collection; public interface ItemServiceInterface { ItemResponseDto createItem(ItemRequestDto item, Long ownerId); - ItemResponseDto getItemById(Long id); + ItemResponseDtoWithComments getItemById(Long id); ItemResponseDto updateItem(Long itemId, ItemRequestDto item, Long ownerId); diff --git a/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java b/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java new file mode 100644 index 0000000..ff396e8 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java @@ -0,0 +1,30 @@ +package ru.practicum.shareit.item.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import ru.practicum.shareit.item.dto.CommentRequestDto; +import ru.practicum.shareit.item.dto.CommentResponseCreatedDto; +import ru.practicum.shareit.item.dto.CommentResponseDto; +import ru.practicum.shareit.item.model.Comment; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface CommentMapper { + Comment toComment(CommentRequestDto comment); + + CommentResponseDto toCommentResponseDto(Comment comment); + + + default CommentResponseCreatedDto toCommentResponseCreatedDto(Comment comment) { + if (comment == null) { + return null; + } + + CommentResponseCreatedDto commentResponseCreatedDto = new CommentResponseCreatedDto(); + commentResponseCreatedDto.setCommentId(comment.getCommentId()); + commentResponseCreatedDto.setText(comment.getText()); + commentResponseCreatedDto.setAuthorName(comment.getAuthor().getUserName()); + + return commentResponseCreatedDto; + } + +} diff --git a/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java b/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java index 6835d2c..f60e856 100644 --- a/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java +++ b/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java @@ -2,8 +2,10 @@ import org.mapstruct.Mapper; import org.mapstruct.MappingConstants; +import ru.practicum.shareit.item.dto.ItemBookerDto; import ru.practicum.shareit.item.dto.ItemRequestDto; import ru.practicum.shareit.item.dto.ItemResponseDto; +import ru.practicum.shareit.item.dto.ItemResponseDtoWithComments; import ru.practicum.shareit.item.model.Item; @Mapper(componentModel = MappingConstants.ComponentModel.SPRING) @@ -14,6 +16,48 @@ public interface ItemMapper { Item toItem(ItemRequestDto itemRequestDto); - ItemResponseDto toItemResponseDto(Item item); + default ItemResponseDto toItemResponseDto(Item item) { + if (item == null) { + return null; + } + + ItemResponseDto itemResponseDto = new ItemResponseDto(); + itemResponseDto.setItemId(item.getItemId()); + itemResponseDto.setItemName(item.getItemName()); + itemResponseDto.setItemDescription(item.getItemDescription()); + itemResponseDto.setIsAvailable(item.getIsAvailable()); + itemResponseDto.setOwnerId(item.getOwner().getUserId()); + + if(item.getItemRequest() != null) { + itemResponseDto.setRequestId(item.getItemRequest().getRequesterId()); + } + + return itemResponseDto; + + } + + ItemBookerDto toItemBookerDto(Item item); + + default ItemResponseDtoWithComments toItemResponseDtoWithComments(Item item) { + if (item == null) { + return null; + } + + ItemResponseDtoWithComments itemResponseDtoWithComments = new ItemResponseDtoWithComments(); + + itemResponseDtoWithComments.setItemId(item.getItemId()); + itemResponseDtoWithComments.setItemName(item.getItemName()); + itemResponseDtoWithComments.setItemDescription(item.getItemDescription()); + itemResponseDtoWithComments.setIsAvailable(item.getIsAvailable()); + itemResponseDtoWithComments.setItemId(item.getItemId()); + itemResponseDtoWithComments.setOwnerId(item.getOwner().getUserId()); + + if(item.getItemRequest() != null) { + itemResponseDtoWithComments.setRequestId(item.getItemRequest().getItemRequestId()); + } + + return itemResponseDtoWithComments; + + } } diff --git a/src/main/java/ru/practicum/shareit/item/model/Comment.java b/src/main/java/ru/practicum/shareit/item/model/Comment.java new file mode 100644 index 0000000..f979f3e --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/model/Comment.java @@ -0,0 +1,34 @@ +package ru.practicum.shareit.item.model; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import ru.practicum.shareit.user.model.User; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@Entity +@ToString +@Table(name = "comments") +public class Comment { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "comment_id") + private Long commentId; + + @Column(name = "text") + private String text; + + @ManyToOne(targetEntity = User.class, cascade = CascadeType.ALL) + @JoinColumn(name = "author_id") + private User author; + + @ManyToOne(targetEntity = Item.class,cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @JoinColumn(name = "item_id") + private Item item; + +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/item/model/Item.java b/src/main/java/ru/practicum/shareit/item/model/Item.java index 6fcf2d1..c1d6d11 100644 --- a/src/main/java/ru/practicum/shareit/item/model/Item.java +++ b/src/main/java/ru/practicum/shareit/item/model/Item.java @@ -1,20 +1,42 @@ package ru.practicum.shareit.item.model; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; - +import lombok.ToString; +import ru.practicum.shareit.request.ItemRequest; +import ru.practicum.shareit.user.model.User; @Data @NoArgsConstructor @AllArgsConstructor +@Entity +@ToString +@Table(name = "items") public class Item { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "item_id") private Long itemId; + + @Column(name = "item_name") private String itemName; + + @Column(name = "item_description") private String itemDescription; + + @Column(name = "is_available") private Boolean isAvailable; - private Long ownerId; - private Long requestId; + + @ManyToOne + @JoinColumn(name = "owner_id") + private User owner; + + @ManyToOne + @JoinColumn(name = "request_id") + private ItemRequest itemRequest; + } diff --git a/src/main/java/ru/practicum/shareit/request/ItemRequest.java b/src/main/java/ru/practicum/shareit/request/ItemRequest.java index c12fab1..0da7fda 100644 --- a/src/main/java/ru/practicum/shareit/request/ItemRequest.java +++ b/src/main/java/ru/practicum/shareit/request/ItemRequest.java @@ -1,13 +1,35 @@ package ru.practicum.shareit.request; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + import java.time.LocalDate; /** * TODO Sprint add-item-requests. */ +@Data +@Entity +@Table(name = "requests") +@AllArgsConstructor +@NoArgsConstructor +@ToString public class ItemRequest { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "request_id") private Long itemRequestId; + + @Column(name = "description") private String requestDescription; + + @Column(name = "requestor_id") private Long requesterId; + + @Transient private LocalDate requestDate; } diff --git a/src/main/java/ru/practicum/shareit/request/interfaces/RequestRepository.java b/src/main/java/ru/practicum/shareit/request/interfaces/RequestRepository.java new file mode 100644 index 0000000..cea05b1 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/interfaces/RequestRepository.java @@ -0,0 +1,8 @@ +package ru.practicum.shareit.request.interfaces; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.practicum.shareit.request.ItemRequest; + +public interface RequestRepository extends JpaRepository { + ItemRequest save(ItemRequest item); +} diff --git a/src/main/java/ru/practicum/shareit/user/UserController.java b/src/main/java/ru/practicum/shareit/user/UserController.java index 4c334a4..0289b90 100644 --- a/src/main/java/ru/practicum/shareit/user/UserController.java +++ b/src/main/java/ru/practicum/shareit/user/UserController.java @@ -12,7 +12,7 @@ @RequestMapping(path = "/users") @RequiredArgsConstructor public class UserController { - private final UserService userService; + private final UserServiceImpl userService; @PostMapping public UserResponseDto createUser(@Valid @RequestBody UserRequestDto user) { diff --git a/src/main/java/ru/practicum/shareit/user/UserService.java b/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java similarity index 65% rename from src/main/java/ru/practicum/shareit/user/UserService.java rename to src/main/java/ru/practicum/shareit/user/UserServiceImpl.java index e4c8802..c988d8a 100644 --- a/src/main/java/ru/practicum/shareit/user/UserService.java +++ b/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java @@ -6,6 +6,7 @@ import ru.practicum.shareit.exception.NotFoundException; import ru.practicum.shareit.user.dto.UserRequestDto; import ru.practicum.shareit.user.dto.UserResponseDto; +import ru.practicum.shareit.user.interfaces.UserRepository; import ru.practicum.shareit.user.interfaces.UserServiceInterface; import ru.practicum.shareit.user.mapper.UserMapper; import ru.practicum.shareit.user.model.User; @@ -15,42 +16,54 @@ @Service @AllArgsConstructor -public class UserService implements UserServiceInterface { +public class UserServiceImpl implements UserServiceInterface { - private final UserStorage userStorage; + private final UserRepository userStorage; private final UserMapper userMapper; public UserResponseDto createUser(UserRequestDto user) { validateEmail(user.getUserEmail()); User newUser = userMapper.toUser(user); - return userMapper.toUserResponseDto(userStorage.createUser(newUser)); + return userMapper.toUserResponseDto(userStorage.save(newUser)); } public UserResponseDto getUserById(Long userId) throws NotFoundException { - return userMapper.toUserResponseDto(userStorage.getUserById(userId) + return userMapper.toUserResponseDto(userStorage.getUserByUserId(userId) .orElseThrow(() -> new NotFoundException("User not found, id = " + userId))); } public UserResponseDto updateUser(Long userId, UserRequestDto user) throws NotFoundException { + User updated = userStorage.getUserByUserId(userId) + .orElseThrow(() -> new NotFoundException("User not found, id = " + userId)); + validateEmail(user.getUserEmail()); - return userMapper.toUserResponseDto(userStorage.updateUser(userId, userMapper.toUser(user))); + + if (user.getUserEmail() != null) { + updated.setUserEmail(user.getUserEmail()); + } + + if (user.getUserName() != null) { + updated.setUserName(user.getUserName()); + } + + return userMapper.toUserResponseDto(userStorage.save(updated)); } public void deleteUser(Long userId) throws NotFoundException { - getUserById(userId); - userStorage.deleteUser(userId); + User user = userMapper.toUser(getUserById(userId)); + userStorage.delete(user); } public void deleteAllUsers() { - userStorage.deleteAllUsers(); + userStorage.deleteAll(); } private void validateEmail(String email) { - Collection users = userStorage.getAllUsers(); + Collection users = userStorage.findAll(); if (!users.isEmpty()) { Optional first = - userStorage.getAllUsers().stream() + userStorage.findAll().stream() .map(User::getUserEmail) .filter(userEmail -> userEmail.equals(email)) .findFirst(); diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserAuthorDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserAuthorDto.java new file mode 100644 index 0000000..dbc923a --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/dto/UserAuthorDto.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.user.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UserAuthorDto { + @NotNull + @JsonProperty("id") + private Long userId; + + @JsonProperty("authorName") + private String userName; +} diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserBookingDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserBookingDto.java new file mode 100644 index 0000000..ef634fa --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/dto/UserBookingDto.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.user.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UserBookingDto { + @NotNull + @JsonProperty("id") + private Long userId; + + @JsonProperty("name") + private String userName; + +} diff --git a/src/main/java/ru/practicum/shareit/user/interfaces/UserRepository.java b/src/main/java/ru/practicum/shareit/user/interfaces/UserRepository.java new file mode 100644 index 0000000..2024294 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/interfaces/UserRepository.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.user.interfaces; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.practicum.shareit.user.model.User; + +import java.util.List; +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + User save(User user); + + Optional getUserByUserId(Long userId); + + List findAll(); + + void deleteUserByUserId(Long id); + + void deleteAll(); +} diff --git a/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java b/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java index 086a773..feeeb99 100644 --- a/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java +++ b/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java @@ -1,13 +1,13 @@ package ru.practicum.shareit.user.mapper; -import org.mapstruct.InjectionStrategy; import org.mapstruct.Mapper; +import ru.practicum.shareit.user.dto.UserAuthorDto; +import ru.practicum.shareit.user.dto.UserBookingDto; import ru.practicum.shareit.user.dto.UserRequestDto; import ru.practicum.shareit.user.dto.UserResponseDto; import ru.practicum.shareit.user.model.User; -@Mapper(componentModel = "spring", uses = UserMapper - .class, injectionStrategy = InjectionStrategy.CONSTRUCTOR) +@Mapper(componentModel = "spring") public interface UserMapper { UserRequestDto toUserRequestDto(User user); @@ -17,4 +17,9 @@ public interface UserMapper { UserResponseDto toUserResponseDto(User user); User toUser(UserResponseDto userDto); + + UserAuthorDto toUserAuthorDto(User user); + + UserBookingDto toUserBookingDto(User booker); + } diff --git a/src/main/java/ru/practicum/shareit/user/model/User.java b/src/main/java/ru/practicum/shareit/user/model/User.java index c7c00cc..5d289c4 100644 --- a/src/main/java/ru/practicum/shareit/user/model/User.java +++ b/src/main/java/ru/practicum/shareit/user/model/User.java @@ -1,14 +1,27 @@ package ru.practicum.shareit.user.model; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.ToString; @Data @NoArgsConstructor @AllArgsConstructor +@Entity +@ToString +@Table(name = "users") public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_id") private Long userId; + + @Column(name = "user_name") private String userName; + + @Column(name = "user_email") private String userEmail; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b9e5d4b..e1fc5d9 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,14 +1,13 @@ spring.jpa.hibernate.ddl-auto=none spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.jdbc.time_zone=UTC spring.sql.init.mode=always +spring.datasource.url=jdbc:postgresql://localhost:5432/postgres +spring.datasource.driverClassName=org.postgresql.Driver +spring.datasource.username=user +spring.datasource.password=12345 logging.level.org.springframework.orm.jpa=INFO logging.level.org.springframework.transaction=INFO logging.level.org.springframework.transaction.interceptor=TRACE -logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG - -# TODO Append connection to DB -#spring.datasource.driverClassName -#spring.datasource.url -#spring.datasource.username -#spring.datasource.password +logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG \ No newline at end of file diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000..c07802f --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,42 @@ +CREATE TABLE IF NOT EXISTS users ( + user_id BIGSERIAL PRIMARY KEY, + user_name CHARACTER VARYING(255) NOT NULL, + user_email CHARACTER VARYING(500) NOT NULL UNIQUE +); + +CREATE TABLE IF NOT EXISTS items ( + item_id BIGSERIAL PRIMARY KEY, + item_name CHARACTER VARYING(255) NOT NULL, + item_description CHARACTER VARYING(150) NOT NULL, + is_available BOOLEAN NOT NULL, + owner_id BIGINT NOT NULL, + request_id BIGINT, + CONSTRAINT fk_items_to_users FOREIGN KEY(owner_id) REFERENCES users(user_id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS comments ( + comment_id BIGSERIAL PRIMARY KEY, + text CHARACTER VARYING(2000) NOT NULL, + item_id BIGINT NOT NULL, + author_id BIGINT NOT NULL, + CONSTRAINT fk_comments_to_users FOREIGN KEY (author_id) REFERENCES users (user_id) ON DELETE CASCADE, + CONSTRAINT fk_comments_to_items FOREIGN KEY (item_id) REFERENCES items(item_id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS bookings ( + booking_id BIGSERIAL PRIMARY KEY, + start_date TIMESTAMP WITHOUT TIME ZONE NOT NULL, + end_date TIMESTAMP WITHOUT TIME ZONE NOT NULL, + item_id BIGINT NOT NULL, + booker_id BIGINT NOT NULL, + status CHARACTER VARYING (50), + FOREIGN KEY (item_id) REFERENCES items (item_id) ON DELETE CASCADE, + FOREIGN KEY (booker_id) REFERENCES users (user_id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS requests ( + request_id BIGSERIAL PRIMARY KEY, + requestor_id BIGINT NOT NULL, + description CHARACTER VARYING (200), + FOREIGN KEY (requestor_id) REFERENCES users (user_id) ON DELETE CASCADE +); \ No newline at end of file diff --git a/src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java new file mode 100644 index 0000000..631da06 --- /dev/null +++ b/src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java @@ -0,0 +1,80 @@ +package ru.practicum.shareit.mapperTest; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.booking.dto.BookingRequestDto; +import ru.practicum.shareit.booking.dto.BookingResponseDto; +import ru.practicum.shareit.booking.mapper.BookingMapper; +import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.item.dto.ItemBookerDto; +import ru.practicum.shareit.item.mapper.ItemMapper; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.request.ItemRequest; +import ru.practicum.shareit.user.dto.UserBookingDto; +import ru.practicum.shareit.user.mapper.UserMapper; +import ru.practicum.shareit.user.model.User; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +public class BookingMapperTest { + @Autowired + private BookingMapper bookingMapper; + + @Autowired + private UserMapper userMapper; + + @Autowired + private ItemMapper itemMapper; + + User user =new User(1L, "testName1", "test1@test.com"); + + ItemRequest itemRequest = new ItemRequest(1L, "testDescription1", + 1L, LocalDate.of(2025, 6, 25)); + + Item item = new Item(1L, "TestName1", "Test description1", true, user, itemRequest); + LocalDateTime startTime = LocalDateTime.of(2025, 6, 25, 12, 30); + LocalDateTime endTime = LocalDateTime.of(2025, 6, 27, 13, 30); + + @Test + public void bookingRequestDtoToBookingTest() { + BookingRequestDto bookingRequestDto = new BookingRequestDto(); + + bookingRequestDto.setBookingId(1L); + bookingRequestDto.setStart(startTime); + bookingRequestDto.setEnd(endTime); + bookingRequestDto.setStatus(BookingStatus.WAITING); + + Booking booking = bookingMapper.bookingRequestDtoToBooking(bookingRequestDto); + assertAll(() -> { + assertEquals(booking.getBookingId(), bookingRequestDto.getBookingId()); + assertEquals(booking.getStart(), bookingRequestDto.getStart()); + assertEquals(booking.getEnd(), bookingRequestDto.getEnd()); + assertEquals(booking.getStatus(), bookingRequestDto.getStatus()); + }); + } + + @Test + public void bookingToBookingResponseDtoTest() { + Booking booking = new Booking(3L, startTime, endTime, item, user, BookingStatus.APPROVED); + + BookingResponseDto bookingResponseDto = bookingMapper.bookingToBookingResponseDto(booking); + + ItemBookerDto itemBookerDto = itemMapper.toItemBookerDto(item); + UserBookingDto userBookingDto = userMapper.toUserBookingDto(user); + assertAll(() -> { + assertEquals(booking.getBookingId(), bookingResponseDto.getBookingId()); + assertEquals(booking.getStart(), bookingResponseDto.getStart()); + assertEquals(booking.getEnd(), bookingResponseDto.getEnd()); + assertEquals(booking.getStatus(), bookingResponseDto.getStatus()); + assertEquals(userBookingDto, bookingResponseDto.getBooker()); + assertEquals(itemBookerDto, bookingResponseDto.getItem()); + }); + } +} diff --git a/src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java new file mode 100644 index 0000000..63fc5d8 --- /dev/null +++ b/src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java @@ -0,0 +1,73 @@ +package ru.practicum.shareit.mapperTest; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.item.dto.CommentRequestDto; +import ru.practicum.shareit.item.dto.CommentResponseCreatedDto; +import ru.practicum.shareit.item.dto.CommentResponseDto; +import ru.practicum.shareit.item.mapper.CommentMapper; +import ru.practicum.shareit.item.model.Comment; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.request.ItemRequest; +import ru.practicum.shareit.user.dto.UserAuthorDto; +import ru.practicum.shareit.user.mapper.UserMapper; +import ru.practicum.shareit.user.model.User; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +public class CommentMapperTest { + @Autowired + private CommentMapper commentMapper; + + @Autowired + private UserMapper userMapper; + + User user =new User(1L, "testName1", "test1@test.com"); + + ItemRequest itemRequest = new ItemRequest(1L, "testDescription1", + 1L, LocalDate.of(2025, 6, 25)); + + Item item = new Item(1L, "TestName1", "Test description1", true, user, itemRequest); + + @Test + public void commentToCommentDtoTest() { + Comment comment = new Comment(1L, "testComment1", user, item); + UserAuthorDto authorDto = userMapper.toUserAuthorDto(user); + CommentResponseDto commentResponseDto = commentMapper.toCommentResponseDto(comment); + + assertAll(() -> { + assertEquals("testComment1", commentResponseDto.getText()); + assertEquals(1L, commentResponseDto.getCommentId()); + assertEquals(authorDto, commentResponseDto.getAuthor()); + }); + } + + @Test + public void commentToCommentResponseCreatedDtoTest() { + Comment comment = new Comment(1L, "testComment1", user, item); + + CommentResponseCreatedDto createdDto = commentMapper.toCommentResponseCreatedDto(comment); + assertAll(() -> { + assertEquals("testComment1", createdDto.getText()); + assertEquals(1L, createdDto.getCommentId()); + assertEquals(user.getUserName(), createdDto.getAuthorName()); + assertEquals(true, createdDto.getCreated()); + }); + } + + @Test + public void commentRequestDtoToCommentTest() { + CommentRequestDto commentRequestDto = new CommentRequestDto(); + commentRequestDto.setAuthorId(user.getUserId()); + commentRequestDto.setText("testComment1"); + + Comment comment = commentMapper.toComment(commentRequestDto); + + assertAll(() -> assertEquals("testComment1", comment.getText())); + } +} diff --git a/src/test/java/ru/practicum/shareit/ItemMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/ItemMapperTest.java similarity index 57% rename from src/test/java/ru/practicum/shareit/ItemMapperTest.java rename to src/test/java/ru/practicum/shareit/mapperTest/ItemMapperTest.java index 05ba9ca..4047ff9 100644 --- a/src/test/java/ru/practicum/shareit/ItemMapperTest.java +++ b/src/test/java/ru/practicum/shareit/mapperTest/ItemMapperTest.java @@ -1,12 +1,15 @@ -package ru.practicum.shareit; +package ru.practicum.shareit.mapperTest; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import ru.practicum.shareit.item.dto.ItemRequestDto; -import ru.practicum.shareit.item.dto.ItemResponseDto; +import ru.practicum.shareit.item.dto.*; import ru.practicum.shareit.item.mapper.ItemMapper; import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.request.ItemRequest; +import ru.practicum.shareit.user.model.User; + +import java.time.LocalDate; import static org.junit.jupiter.api.Assertions.*; @@ -16,6 +19,11 @@ public class ItemMapperTest { @Autowired private ItemMapper itemMapper; + User user =new User(1L, "testName1", "test1@test.com"); + + ItemRequest itemRequest = new ItemRequest(1L, "testDescription1", + 1L, LocalDate.of(2025, 6, 25)); + @Test public void itemRequestDtoToItemTest() { ItemRequestDto itemRequestDto = new ItemRequestDto( @@ -28,14 +36,13 @@ public void itemRequestDtoToItemTest() { assertEquals("TestName", item.getItemName()); assertEquals("Test description", item.getItemDescription()); assertEquals(true, item.getIsAvailable()); - assertNull(item.getOwnerId()); - assertEquals(1L, item.getRequestId()); + assertNull(item.getOwner()); }); } @Test public void itemToItemResponseDtoTest() { - Item item = new Item(2L, "TestName2", "Test description2", true, 2L, 2L); + Item item = new Item(2L, "TestName2", "Test description2", true, user, itemRequest); ItemResponseDto itemResponseDto = itemMapper.toItemResponseDto(item); assertAll(() -> { @@ -43,8 +50,8 @@ public void itemToItemResponseDtoTest() { assertEquals("TestName2", itemResponseDto.getItemName()); assertEquals("Test description2", itemResponseDto.getItemDescription()); assertEquals(true, itemResponseDto.getIsAvailable()); - assertEquals(2L, itemResponseDto.getOwnerId()); - assertEquals(2L, itemResponseDto.getRequestId()); + assertEquals(user.getUserId(), itemResponseDto.getOwnerId()); + assertEquals(itemRequest.getItemRequestId(), itemResponseDto.getRequestId()); }); } @@ -67,7 +74,8 @@ public void itemRequestDtoToItemResponseDtoTest() { @Test public void itemResponseDtoToItemRequestDtoTest() { ItemResponseDto itemResponseDto = new ItemResponseDto( - 4L, "TestName4", "Test description4", false, 4L, 4L); + 4L, "TestName4", "Test description4", + false, 4L, 4L); ItemRequestDto itemRequestDto = itemMapper.toItemRequestDto(itemResponseDto); assertAll(() -> { assertEquals(4L, itemRequestDto.getItemId()); @@ -78,4 +86,37 @@ public void itemResponseDtoToItemRequestDtoTest() { }); } + @Test + public void itemToItemResponseDtoWithCommentsTest() { + + Item item = new Item(2L, "testName2", "testDescription2", + true, user, itemRequest); + + ItemResponseDtoWithComments itemResponse = itemMapper.toItemResponseDtoWithComments(item); + + assertAll(() -> { + assertEquals(2L, itemResponse.getItemId()); + assertEquals("testName2", itemResponse.getItemName()); + assertEquals("testDescription2", itemResponse.getItemDescription()); + assertEquals(true, itemResponse.getIsAvailable()); + assertEquals(user.getUserId(), itemResponse.getOwnerId()); + assertEquals(itemRequest.getItemRequestId(), itemResponse.getRequestId()); + assertNull(itemResponse.getComments()); + assertNull(itemResponse.getLastBooking()); + assertNull(itemResponse.getNextBooking()); + }); + } + + @Test + public void itemToItemBookerDto() { + Item item = new Item(2L, "testName2", "testDescription2", + true, user, itemRequest); + + ItemBookerDto itemBookerDto = itemMapper.toItemBookerDto(item); + + assertAll(() -> { + assertEquals(2L, itemBookerDto.getItemId()); + assertEquals("testName2", itemBookerDto.getItemName()); + }); + } } diff --git a/src/test/java/ru/practicum/shareit/UserMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/UserMapperTest.java similarity index 72% rename from src/test/java/ru/practicum/shareit/UserMapperTest.java rename to src/test/java/ru/practicum/shareit/mapperTest/UserMapperTest.java index 0bd6da2..b79e842 100644 --- a/src/test/java/ru/practicum/shareit/UserMapperTest.java +++ b/src/test/java/ru/practicum/shareit/mapperTest/UserMapperTest.java @@ -1,8 +1,10 @@ -package ru.practicum.shareit; +package ru.practicum.shareit.mapperTest; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.user.dto.UserAuthorDto; +import ru.practicum.shareit.user.dto.UserBookingDto; import ru.practicum.shareit.user.dto.UserRequestDto; import ru.practicum.shareit.user.dto.UserResponseDto; import ru.practicum.shareit.user.mapper.UserMapper; @@ -62,4 +64,28 @@ public void userToUserResponseDtoTest() { assertEquals("test4@test.com", userResponseDto.getUserEmail()); }); } + + @Test + public void userToUserAuthorDtoTest() { + User user = new User(5L, "TestName5", "test5@test.com"); + + UserAuthorDto userAuthorDto = userMapper.toUserAuthorDto(user); + + assertAll(() -> { + assertEquals(5L, userAuthorDto.getUserId()); + assertEquals("TestName5", userAuthorDto.getUserName()); + }); + } + + @Test + public void userToUserBookingDtoTest() { + User user = new User(6L, "TestName6", "test6@test.com"); + + UserBookingDto userBookingDto = userMapper.toUserBookingDto(user); + + assertAll(() -> { + assertEquals(6L, userBookingDto.getUserId()); + assertEquals("TestName6", userBookingDto.getUserName()); + }); + } } diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..0024b61 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,10 @@ +spring.sql.init.mode=always +spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=user +spring.datasource.password=12345 + +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.jdbc.time_zone=UTC +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect \ No newline at end of file From f10a614d5c7109649e5f6a3494bf550140f8e512 Mon Sep 17 00:00:00 2001 From: NadezhdaTA Date: Fri, 27 Jun 2025 11:43:57 +0400 Subject: [PATCH 2/9] =?UTF-8?q?=D0=A4=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2015?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8=D0=BD=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/shareit.mv.db | Bin 0 -> 40960 bytes db/shareit.trace.db | 162 ++++++++++++++++++ pom.xml | 26 ++- .../practicum/shareit/PersistenceConfig.java | 66 +++++++ .../ru/practicum/shareit/booking/Booking.java | 16 -- .../shareit/booking/BookingController.java | 39 ++++- .../shareit/booking/BookingServiceImpl.java | 120 +++++++++++++ .../shareit/booking/dto/BookingDto.java | 7 - .../booking/dto/BookingRequestDto.java | 35 ++++ .../booking/dto/BookingResponseDto.java | 31 ++++ .../booking/intrfaces/BookingRepository.java | 18 ++ .../intrfaces/BookingServiceInterface.java | 16 ++ .../shareit/booking/mapper/BookingMapper.java | 15 ++ .../shareit/booking/model/Booking.java | 42 +++++ .../booking/{ => model}/BookingStatus.java | 2 +- .../shareit/item/ItemController.java | 14 +- .../practicum/shareit/item/ItemService.java | 77 --------- .../shareit/item/ItemServiceImpl.java | 161 +++++++++++++++++ .../practicum/shareit/item/ItemStorage.java | 2 +- .../shareit/item/dto/CommentRequestDto.java | 19 ++ .../item/dto/CommentResponseCreatedDto.java | 17 ++ .../shareit/item/dto/CommentResponseDto.java | 17 ++ .../shareit/item/dto/ItemBookerDto.java | 18 ++ .../item/dto/ItemResponseDtoWithComments.java | 40 +++++ .../item/interfaces/CommentRepository.java | 13 ++ .../item/interfaces/ItemRepository.java | 20 +++ .../item/interfaces/ItemServiceInterface.java | 3 +- .../shareit/item/mapper/CommentMapper.java | 30 ++++ .../shareit/item/mapper/ItemMapper.java | 46 ++++- .../practicum/shareit/item/model/Comment.java | 34 ++++ .../ru/practicum/shareit/item/model/Item.java | 28 ++- .../shareit/request/ItemRequest.java | 22 +++ .../request/interfaces/RequestRepository.java | 8 + .../shareit/user/UserController.java | 2 +- ...{UserService.java => UserServiceImpl.java} | 33 ++-- .../shareit/user/dto/UserAuthorDto.java | 19 ++ .../shareit/user/dto/UserBookingDto.java | 20 +++ .../user/interfaces/UserRepository.java | 19 ++ .../shareit/user/mapper/UserMapper.java | 11 +- .../ru/practicum/shareit/user/model/User.java | 13 ++ src/main/resources/application.properties | 13 +- src/main/resources/schema.sql | 42 +++++ .../shareit/mapperTest/BookingMapperTest.java | 80 +++++++++ .../shareit/mapperTest/CommentMapperTest.java | 73 ++++++++ .../{ => mapperTest}/ItemMapperTest.java | 59 ++++++- .../{ => mapperTest}/UserMapperTest.java | 28 ++- src/test/resources/application.properties | 10 ++ 47 files changed, 1434 insertions(+), 152 deletions(-) create mode 100644 db/shareit.mv.db create mode 100644 db/shareit.trace.db create mode 100644 src/main/java/ru/practicum/shareit/PersistenceConfig.java delete mode 100644 src/main/java/ru/practicum/shareit/booking/Booking.java create mode 100644 src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java delete mode 100644 src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java create mode 100644 src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java create mode 100644 src/main/java/ru/practicum/shareit/booking/dto/BookingResponseDto.java create mode 100644 src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java create mode 100644 src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java create mode 100644 src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java create mode 100644 src/main/java/ru/practicum/shareit/booking/model/Booking.java rename src/main/java/ru/practicum/shareit/booking/{ => model}/BookingStatus.java (65%) delete mode 100644 src/main/java/ru/practicum/shareit/item/ItemService.java create mode 100644 src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/CommentRequestDto.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/CommentResponseCreatedDto.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/CommentResponseDto.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/ItemBookerDto.java create mode 100644 src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java create mode 100644 src/main/java/ru/practicum/shareit/item/interfaces/CommentRepository.java create mode 100644 src/main/java/ru/practicum/shareit/item/interfaces/ItemRepository.java create mode 100644 src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java create mode 100644 src/main/java/ru/practicum/shareit/item/model/Comment.java create mode 100644 src/main/java/ru/practicum/shareit/request/interfaces/RequestRepository.java rename src/main/java/ru/practicum/shareit/user/{UserService.java => UserServiceImpl.java} (65%) create mode 100644 src/main/java/ru/practicum/shareit/user/dto/UserAuthorDto.java create mode 100644 src/main/java/ru/practicum/shareit/user/dto/UserBookingDto.java create mode 100644 src/main/java/ru/practicum/shareit/user/interfaces/UserRepository.java create mode 100644 src/main/resources/schema.sql create mode 100644 src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java create mode 100644 src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java rename src/test/java/ru/practicum/shareit/{ => mapperTest}/ItemMapperTest.java (57%) rename src/test/java/ru/practicum/shareit/{ => mapperTest}/UserMapperTest.java (72%) create mode 100644 src/test/resources/application.properties diff --git a/db/shareit.mv.db b/db/shareit.mv.db new file mode 100644 index 0000000000000000000000000000000000000000..c8db7fd9467ab22f599c466f85b22ea51cf95d9c GIT binary patch literal 40960 zcmeHQ&5zs06{lpaS6yfABu<=9C$wzGURO~${H9K!B(7KWuGW#Xj*Ye;D01X1vMU*D z*|l2)O%R|!Z$(iQJ+uhgpg@{GpvR(z9(w2@hob1Uz4ln3K+#JdXZR(G(rRNlAL#4? zA}P&q-u!0X<9qYo8*Ws^a&K?wzEjocv9tRv2art04992CX!U6EEE-lbx%;$q9RI)EDB;#(FLg|^-)nV9MustIKhtV zAj2uDf`>f`qoUSRk&OC6QI|bQ@dUl7YXWxrs$0~1x}hsF{N$e)a6|v3@2SW?aRh|= zAgiVjvB*EMj_lNASvaA)lFupnx3u`fga zWJ53ZdtSfq2~x4|_Hhr1==|{DcI9ocvVZ^XXn24tUa!)+x3_o0*}I1u&dBLLyn`22 zrkrYP^q_KsMtxw9H0U>WVcl_ol7|;lg@Lg4@Vg;NVX5QG;WS?qk&C*|W9V#QiFP&( z%?Mzt)EfMeKp^2HxxP2>hMU9N6*PV+YW}a) z5Sk#$GkCCrD)iH6U6qq%^x;pzV-)p}sZNo{?QIP@po}qjZX4 zH0lJML<7sHN9h!$?Dmp$hDv0TPEpIQ=i>tUT}FEWozwd_6HjSM|B`fu+G>(cNts3` z(N)LjB%D#TUnRpIO^$SZW&C$>;&(EqtLZuY8o4V4U7&MljP^kHzDSBuMwu)Xs=aIU zX3>0}EE%fs(fxqgNU2bTCOr?;dP-cttJ80$Ci*bPya~sHR-@xTb=nY%VQe^(txcIV zNd&`LniKO#$Rqfa@<_=eHIMWh&KWs1r{|;`e1q~x&UtyH<@z}-FM4?qb6oDDC)_-D zoGTIoumUDiaH1^l!}F%H>mB!Pz6zoTksg$v=K_OK3ZllT;V1=$BV6s?$JY}^q-cl& z`Etv*D0R31$zBy*YEinbZ&B(VQbcM|%6-S{rzw-mZk3-6ofHH@ev?!nqB`EW0cuslnN+^PEbo)M3SKf=YBK#35o~mBNu_D{vO9&xe3QNxcup# z5zYPByFVsJ_Q4Qf2rvW~0t^9$07HNwzz|>vFa#I^3;~9~R|$cX|NVZLMX$zL^sIzXq!)5z!j;|Epx#0~UM4xS>Zq z^S2N<%YDEt<#HUi`Uj3fKPSh$@a>alPC;SlezYVcjNwrTOD>pQj0X1!D) zH+O()v%@zVR;%0W-r_sfn>$vk zp1fh_R;O!i+2JoXL>Z_xNzv^F5^J_>A=8E>O3{{TmQa(e23nW(5<#f7v$2j zXK71o^U%8ny!7uwc&P~!KjJ0-V$r-*GbLGTn5M02HPx0?OR!B1X$YAc2 zI7_juxzpX)&gAQrwZfA}mN5X7aLGDx8L{dDD40BqYtwGy0eqyd+B(o`LTEbqY_1&6KA17kD!)6%mu- z?6~Dj)}E*ya5wbjQMtSDEWp^C4@N2;sZ^W+VLox z2vhyYgpf9HIev6a7m$VLKmh*z5CI5kz%@|XBLNs(FIoULYFfQ+nSyPBab(Ndx?$H$ zMYS7^bw$=yp;lACG)oCBB0}s27&s-q+uQ=R!`!-_E@ZVDhZPA2AT*m&&G=oOsq;X) z-JMRBCdilo%^%7LRF~LMfW4K z_*nqzTXO?-$TSF;VC)(53Sjl8MPXG-f#r`BZFC;Efci|lCd}^{BJouai60yy5(5(_ z5{Z*0&th~!RcJ_(q1&cl7`AMxqFqBE9K~9_R)^pzT`&Q!l&lJ9$yVh8JMR$F5Y$Is zXz@oATJ^c8oh`J^!DO9Z=|d@*6%R`(F(PY)63oykN?%lEE|CQdj!CR!D>Ee)DizK{ z*QOb86O4a&&w}wCso6Rz}V7k$}4STy8CX46OB_|X4P zwWl~)!cUNpV*P_C9yrQ}2$D5?#R#_hk7zcip3)=kf5};(_n+s%|DXR)ewX8llPN1| zn7g8dC;HKJ$LUEdOm~#Bb;l1w)i!u-1Z?_{+(81aQi(vwk0uFK+c*&@&~4Qq;qtf z2^#g7MxD?o_SGbbvl4;E^lx9BTxru-1m^#by@V4MwOnHU|FIYx=KrTrJTzX1`Ty6L z|35RlF7#lA5q81#qTOHfxy(~*z0Cg)VR(drXE=2e1IGOSi9niYVozWCX8wPOTx9-# z=KqhpkW&H#9*h4!u>V8jBw0C4C6fJ3bvRm6*H%F56PQJ(GU;G=#!LjhdFM=e!Q=jBnk{(OaJ0#6; zX8agS(hJfB;~bjlX^1RIFU+7#r;E;)ewJE`BVoNPNiUtsIFnyllHSdUMA|TY19J0O8Gb$XlfQSOVSH>CzzeU9H$DUWn)nPu`JRbmasTe|0%E}J=ohMP6-|}R#=iA z-QOqiJPWcJS&|-0(!0!(^rmcz#FF&LE*_s(lHStCFa55--sJq-gj=a8t zz13wnnD;F??5!^T`-9k9UBXR1Ctp4Dh;Mbt_s;!viCd0RWF|9XjG37+zYUWn4o_I7 zNfQWCBPO#Zg13Oqk*-XVCm@7qB6-4ylP5A0P_$1%QV&l+2}n&QphO8Cgw(mRPv#*t zI~S!N<)Rp4Z_SC*t&Wh3G9?Ksk&AK&oJN?QmCi-MB)m)04Wyo+=k%pC^c-GRqbFWU zvFa#I^3;~8f0)Zg@ bKa9VR;{Tm^|9?$(4al^Y7Z*$)-)ZH4hydT9 literal 0 HcmV?d00001 diff --git a/db/shareit.trace.db b/db/shareit.trace.db new file mode 100644 index 0000000..62ff604 --- /dev/null +++ b/db/shareit.trace.db @@ -0,0 +1,162 @@ +2025-06-26 07:25:54 jdbc[3]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 07:25:55 jdbc[3]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:26:44 jdbc[3]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:31:14 jdbc[3]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:31:16 jdbc[4]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:31:50 jdbc[5]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:31:50 jdbc[5]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Схема "INFORMATION_SCHEMA" не может быть удалена +Schema "INFORMATION_SCHEMA" cannot be dropped; SQL statement: +drop schema INFORMATION_SCHEMA [90090-220] + at org.h2.message.DbException.getJdbcSQLException(DbException.java:644) + at org.h2.message.DbException.getJdbcSQLException(DbException.java:489) + at org.h2.message.DbException.get(DbException.java:223) + at org.h2.message.DbException.get(DbException.java:199) + at org.h2.command.ddl.DropSchema.update(DropSchema.java:49) + at org.h2.command.CommandContainer.update(CommandContainer.java:169) + at org.h2.command.Command.executeUpdate(Command.java:252) + at org.h2.jdbc.JdbcStatement.executeUpdateInternal(JdbcStatement.java:190) + at org.h2.jdbc.JdbcStatement.executeUpdate(JdbcStatement.java:143) + at com.intellij.database.remote.jdbc.impl.RemoteStatementImpl.executeUpdate(RemoteStatementImpl.java:189) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) +2025-06-26 08:31:50 jdbc[6]: exception +java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. + at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) + at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) + at java.base/java.lang.reflect.Method.invoke(Method.java:580) + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) + at java.base/java.lang.Thread.run(Thread.java:1583) diff --git a/pom.xml b/pom.xml index a3b4a77..091dc51 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,10 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-data-jpa + org.springframework.boot spring-boot-starter-actuator @@ -63,11 +67,11 @@ spring-boot-starter-validation - - org.mapstruct - mapstruct - ${org.mapstruct.version} - + + org.mapstruct + mapstruct + ${org.mapstruct.version} + org.projectlombok @@ -159,6 +163,18 @@ ${lombok-mapstruct-binding.version} + true + + + -Amapstruct.suppressGeneratorTimestamp=true + + + -Amapstruct.suppressGeneratorVersionInfoComment=true + + + -Amapstruct.verbose=true + + diff --git a/src/main/java/ru/practicum/shareit/PersistenceConfig.java b/src/main/java/ru/practicum/shareit/PersistenceConfig.java new file mode 100644 index 0000000..04d14b2 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/PersistenceConfig.java @@ -0,0 +1,66 @@ +package ru.practicum.shareit; + +import jakarta.persistence.EntityManagerFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@RequiredArgsConstructor +@EnableTransactionManagement +@EnableJpaRepositories(basePackages = "ru.practicum") +public class PersistenceConfig { + private final Environment environment; + + @Bean + public DataSource dataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(environment.getRequiredProperty("spring.datasource.driverClassName")); + dataSource.setUrl(environment.getRequiredProperty("spring.datasource.url")); + dataSource.setUsername(environment.getRequiredProperty("spring.datasource.username")); + dataSource.setPassword(environment.getRequiredProperty("spring.datasource.password")); + return dataSource; + } + + private Properties hibernateProperties() { + Properties properties = new Properties(); + properties.put("spring.jpa.properties.hibernate.jdbc.time_zone", + environment.getRequiredProperty("spring.jpa.properties.hibernate.jdbc.time_zone")); + properties.put("spring.jpa.properties.hibernate.format_sql", + environment.getProperty("spring.jpa.properties.hibernate.format_sql", "false")); + return properties; + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { + final HibernateJpaVendorAdapter vendorAdapter = + new HibernateJpaVendorAdapter(); + + final LocalContainerEntityManagerFactoryBean emf = + new LocalContainerEntityManagerFactoryBean(); + + emf.setDataSource(dataSource); + emf.setJpaVendorAdapter(vendorAdapter); + emf.setPackagesToScan("ru.practicum"); + emf.setJpaProperties(hibernateProperties()); + + return emf; + } + + @Bean + public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { + JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory); + return transactionManager; + } +} diff --git a/src/main/java/ru/practicum/shareit/booking/Booking.java b/src/main/java/ru/practicum/shareit/booking/Booking.java deleted file mode 100644 index 8facd50..0000000 --- a/src/main/java/ru/practicum/shareit/booking/Booking.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.practicum.shareit.booking; - -import java.time.LocalDate; - -/** - * TODO Sprint add-bookings. - */ -public class Booking { - - private Long bookingId; - private LocalDate start; - private LocalDate end; - private Long itemId; - private Long bookerId; - BookingStatus status; -} diff --git a/src/main/java/ru/practicum/shareit/booking/BookingController.java b/src/main/java/ru/practicum/shareit/booking/BookingController.java index b94493d..6d9e0d0 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingController.java +++ b/src/main/java/ru/practicum/shareit/booking/BookingController.java @@ -1,12 +1,41 @@ package ru.practicum.shareit.booking; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; +import ru.practicum.shareit.booking.dto.BookingRequestDto; +import ru.practicum.shareit.booking.dto.BookingResponseDto; +import ru.practicum.shareit.booking.intrfaces.BookingServiceInterface; + +import java.util.Collection; -/** - * TODO Sprint add-bookings. - */ @RestController @RequestMapping(path = "/bookings") +@RequiredArgsConstructor public class BookingController { + private final BookingServiceInterface bookingService; + public static final String USER_ID = "X-Sharer-User-Id"; + + @PostMapping + public BookingResponseDto postBooking(@RequestBody BookingRequestDto booking, + @RequestHeader(USER_ID) Long bookerId) { + return bookingService.postBooking(booking, bookerId); + } + + @PatchMapping("/{bookingId}") + public BookingResponseDto bookingApprove(@PathVariable Long bookingId, + @RequestHeader (USER_ID) Long ownerId, + @RequestParam Boolean approved) { + return bookingService.bookingApprove(bookingId, ownerId, approved); + } + + @GetMapping("/{bookingId}") + public BookingResponseDto getBooking(@PathVariable Long bookingId) { + return bookingService.getBookingByBookingId(bookingId); + } + + @GetMapping + public Collection getBookingsForUser( + @RequestHeader (USER_ID) Long userId) { + return bookingService.getBookingsForUser(userId); + } } diff --git a/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java new file mode 100644 index 0000000..6967cb1 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java @@ -0,0 +1,120 @@ +package ru.practicum.shareit.booking; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.practicum.shareit.booking.dto.BookingRequestDto; +import ru.practicum.shareit.booking.dto.BookingResponseDto; +import ru.practicum.shareit.booking.intrfaces.BookingRepository; +import ru.practicum.shareit.booking.intrfaces.BookingServiceInterface; +import ru.practicum.shareit.booking.mapper.BookingMapper; +import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.exception.AnotherUserException; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.item.interfaces.ItemRepository; +import ru.practicum.shareit.item.mapper.ItemMapper; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.interfaces.UserRepository; +import ru.practicum.shareit.user.mapper.UserMapper; +import ru.practicum.shareit.user.model.User; + +import java.util.ArrayList; +import java.util.Collection; + +@Service +@RequiredArgsConstructor +public class BookingServiceImpl implements BookingServiceInterface { + private final BookingRepository storage; + private final UserRepository userStorage; + private final ItemRepository itemStorage; + + private final ItemMapper itemMapper; + private final UserMapper userMapper; + private final BookingRepository bookingRepository; + private final BookingMapper bookingMapper; + + + @Override + public BookingResponseDto postBooking(BookingRequestDto booking, Long bookerId) { + Item item = itemStorage.findById(booking.getItemId()) + .orElseThrow(() -> new NotFoundException("Item not found")); + + if (item.getIsAvailable().equals(false)) { + throw new RuntimeException("Booking item is not available"); + } + + Booking saved = bookingMapper.bookingRequestDtoToBooking(booking); + saved.setBooker(userStorage.getUserByUserId(bookerId).get()); + saved.setItem(item); + + if (item.getIsAvailable()) { + saved.setStatus(BookingStatus.WAITING); + } else { + saved.setStatus(BookingStatus.REJECTED); + throw new AnotherUserException("Booking item is rejected, item is not available"); + } + + storage.save(saved); + + BookingResponseDto responseDto = bookingMapper.bookingToBookingResponseDto(saved); + mapBookerAndItemToBooking(responseDto, saved); + return responseDto; + } + + @Override + public BookingResponseDto bookingApprove(Long bookingId, Long ownerId, Boolean isAvailable) { + Booking booking = bookingRepository.getBookingByBookingId(bookingId) + .orElseThrow(() -> new NotFoundException("Booking not found")); + + Item item = booking.getItem(); + if (!item.getOwner().getUserId().equals(ownerId)) { + throw new AnotherUserException("You are not allowed to approve this booking"); + } + + if (item.getIsAvailable().equals(false)) { + booking.setStatus(BookingStatus.REJECTED); + throw new RuntimeException("Booking item is rejected"); + } else { + booking.setStatus(BookingStatus.APPROVED); + } + + BookingResponseDto responseDto = bookingMapper.bookingToBookingResponseDto(booking); + mapBookerAndItemToBooking(responseDto, booking); + + return responseDto; + } + + @Override + public BookingResponseDto getBookingByBookingId(Long bookingId) { + Booking booking = bookingRepository.getBookingByBookingId(bookingId) + .orElseThrow(() -> new NotFoundException("Booking not found")); + + BookingResponseDto bookingDto = bookingMapper.bookingToBookingResponseDto(booking); + + mapBookerAndItemToBooking(bookingDto, booking); + + return bookingDto; + } + + @Override + public Collection getBookingsForUser(Long userId) { + User user = userStorage.getUserByUserId(userId) + .orElseThrow(() -> new NotFoundException("User not found")); + + Collection bookings = bookingRepository.getBookingsByBooker_UserId(user.getUserId()); + Collection bookingDtos = new ArrayList<>(); + + for (Booking booking : bookings) { + BookingResponseDto bookingDto = bookingMapper.bookingToBookingResponseDto(booking); + mapBookerAndItemToBooking(bookingDto, booking); + bookingDtos.add(bookingDto); + } + + return bookingDtos; + } + + private void mapBookerAndItemToBooking(BookingResponseDto bookingDto, Booking booking) { + bookingDto.setBooker(userMapper.toUserBookingDto(booking.getBooker())); + bookingDto.setItem(itemMapper.toItemBookerDto(booking.getItem())); + } +} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java deleted file mode 100644 index 861de9e..0000000 --- a/src/main/java/ru/practicum/shareit/booking/dto/BookingDto.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.practicum.shareit.booking.dto; - -/** - * TODO Sprint add-bookings. - */ -public class BookingDto { -} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java new file mode 100644 index 0000000..8c4033a --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java @@ -0,0 +1,35 @@ +package ru.practicum.shareit.booking.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.Future; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.practicum.shareit.booking.model.BookingStatus; + +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class BookingRequestDto { + @JsonProperty("id") + private Long bookingId; + + @NotNull + @Future + private LocalDateTime start; + + @NotNull + @Future + private LocalDateTime end; + + @NotNull + private Long itemId; + + @NotNull + private Long bookerId; + + private BookingStatus status; +} diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingResponseDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingResponseDto.java new file mode 100644 index 0000000..c59d3a4 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingResponseDto.java @@ -0,0 +1,31 @@ +package ru.practicum.shareit.booking.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.item.dto.ItemBookerDto; +import ru.practicum.shareit.user.dto.UserBookingDto; + +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class BookingResponseDto { + + @JsonProperty("id") + private Long bookingId; + + private LocalDateTime start; + + private LocalDateTime end; + + private ItemBookerDto item; + + private UserBookingDto booker; + + private BookingStatus status; + +} diff --git a/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java new file mode 100644 index 0000000..a1948c5 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java @@ -0,0 +1,18 @@ +package ru.practicum.shareit.booking.intrfaces; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.practicum.shareit.booking.model.Booking; + +import java.util.Collection; +import java.util.Optional; + +public interface BookingRepository extends JpaRepository { + + Booking save(Booking booking); + + Optional getBookingByBookingId(Long bookingId); + + Collection getBookingsByBooker_UserId(Long bookerId); + + Collection getBookingsByItem_ItemId(Long itemId); +} diff --git a/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java new file mode 100644 index 0000000..55c627e --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java @@ -0,0 +1,16 @@ +package ru.practicum.shareit.booking.intrfaces; + +import ru.practicum.shareit.booking.dto.BookingRequestDto; +import ru.practicum.shareit.booking.dto.BookingResponseDto; + +import java.util.Collection; + +public interface BookingServiceInterface { + BookingResponseDto postBooking(BookingRequestDto booking, Long bookerId); + + BookingResponseDto bookingApprove(Long bookingId, Long ownerId, Boolean isAvailable); + + BookingResponseDto getBookingByBookingId(Long bookingId); + + Collection getBookingsForUser(Long userId); +} diff --git a/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java b/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java new file mode 100644 index 0000000..9d51d2c --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java @@ -0,0 +1,15 @@ +package ru.practicum.shareit.booking.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import ru.practicum.shareit.booking.dto.BookingRequestDto; +import ru.practicum.shareit.booking.dto.BookingResponseDto; +import ru.practicum.shareit.booking.model.Booking; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface BookingMapper { + Booking bookingRequestDtoToBooking(BookingRequestDto bookingRequestDto); + + BookingResponseDto bookingToBookingResponseDto(Booking booking); +} + diff --git a/src/main/java/ru/practicum/shareit/booking/model/Booking.java b/src/main/java/ru/practicum/shareit/booking/model/Booking.java new file mode 100644 index 0000000..c4b2ff2 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/booking/model/Booking.java @@ -0,0 +1,42 @@ +package ru.practicum.shareit.booking.model; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.model.User; + +import java.time.LocalDateTime; + +@Data +@Entity +@Table(name = "bookings") +@AllArgsConstructor +@NoArgsConstructor +@ToString +public class Booking { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "booking_id") + private Long bookingId; + + @Column(name = "start_date") + private LocalDateTime start; + + @Column(name = "end_date") + private LocalDateTime end; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "item_id") + private Item item; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "booker_id") + private User booker; + + @Enumerated(EnumType.STRING) + private BookingStatus status; +} diff --git a/src/main/java/ru/practicum/shareit/booking/BookingStatus.java b/src/main/java/ru/practicum/shareit/booking/model/BookingStatus.java similarity index 65% rename from src/main/java/ru/practicum/shareit/booking/BookingStatus.java rename to src/main/java/ru/practicum/shareit/booking/model/BookingStatus.java index 51269e0..4eb25ea 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingStatus.java +++ b/src/main/java/ru/practicum/shareit/booking/model/BookingStatus.java @@ -1,4 +1,4 @@ -package ru.practicum.shareit.booking; +package ru.practicum.shareit.booking.model; public enum BookingStatus { WAITING, diff --git a/src/main/java/ru/practicum/shareit/item/ItemController.java b/src/main/java/ru/practicum/shareit/item/ItemController.java index d033939..9404d6f 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemController.java +++ b/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -6,8 +6,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import ru.practicum.shareit.item.dto.ItemRequestDto; -import ru.practicum.shareit.item.dto.ItemResponseDto; +import ru.practicum.shareit.item.dto.*; import java.util.Collection; @@ -19,7 +18,7 @@ public class ItemController { public static final String OWNER_ID = "X-Sharer-User-Id"; - private final ItemService itemService; + private final ItemServiceImpl itemService; @PostMapping public ItemResponseDto create(@RequestHeader(OWNER_ID) Long ownerId, @@ -35,7 +34,7 @@ public ItemResponseDto update(@RequestBody ItemRequestDto item, } @GetMapping("/{itemId}") - public ItemResponseDto getItemById(@PathVariable Long itemId) { + public ItemResponseDtoWithComments getItemById(@PathVariable Long itemId) { return itemService.getItemById(itemId); } @@ -50,4 +49,11 @@ public Collection searchItems(@RequestParam String text) { return itemService.searchByText(text); } + @PostMapping("/{itemId}/comment") + public CommentResponseCreatedDto addComment(@RequestBody CommentRequestDto comment, + @PathVariable Long itemId, + @RequestHeader(OWNER_ID) Long commentatorId) { + return itemService.addComment(commentatorId, comment, itemId); + } + } diff --git a/src/main/java/ru/practicum/shareit/item/ItemService.java b/src/main/java/ru/practicum/shareit/item/ItemService.java deleted file mode 100644 index 9dd0d0c..0000000 --- a/src/main/java/ru/practicum/shareit/item/ItemService.java +++ /dev/null @@ -1,77 +0,0 @@ -package ru.practicum.shareit.item; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import ru.practicum.shareit.exception.AnotherUserException; -import ru.practicum.shareit.exception.NotFoundException; -import ru.practicum.shareit.exception.ValidationException; -import ru.practicum.shareit.item.dto.ItemRequestDto; -import ru.practicum.shareit.item.dto.ItemResponseDto; -import ru.practicum.shareit.item.interfaces.ItemServiceInterface; -import ru.practicum.shareit.item.mapper.ItemMapper; -import ru.practicum.shareit.item.model.Item; -import ru.practicum.shareit.user.UserStorage; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class ItemService implements ItemServiceInterface { - - private final ItemStorage itemStorage; - private final UserStorage userStorage; - private final ItemMapper itemMapper; - - public ItemResponseDto createItem(ItemRequestDto item, Long ownerId) { - if (ownerId == null) { - throw new ValidationException("Owner id cannot be null"); - } - userStorage.getUserById(ownerId) - .orElseThrow(() -> new NotFoundException("User with id " + ownerId + " not found")); - Item itemSaved = itemMapper.toItem(item); - itemSaved.setOwnerId(ownerId); - return itemMapper.toItemResponseDto(itemStorage.createItem(itemSaved)); - } - - public ItemResponseDto getItemById(Long id) { - return itemMapper.toItemResponseDto(itemStorage.getItemById(id) - .orElseThrow(() -> new NotFoundException("Item with id " + id + " not found"))); - } - - public ItemResponseDto updateItem(Long itemId, - ItemRequestDto item, Long ownerId) { - findUserById(ownerId); - Item foundItem = itemStorage.getItemById(itemId) - .orElseThrow(() -> new NotFoundException("Item with id " + itemId + " not found")); - if (foundItem.getOwnerId().equals(ownerId)) { - item.setItemId(itemId); - foundItem = itemMapper.toItem(item); - } else { - throw new AnotherUserException("User with id " + ownerId + " is not owner of this Item"); - } - return itemMapper.toItemResponseDto(itemStorage.updateItem(foundItem)); - } - - public Collection getAllItemsForOwner(Long ownerId) { - return itemStorage.getAllItemsForOwner(ownerId).stream() - .map(itemMapper::toItemResponseDto) - .collect(Collectors.toList()); - } - - public Collection searchByText(String text) { - if (text == null || text.isEmpty()) { - return new ArrayList<>(); - } - return itemStorage.searchByText(text).stream() - .filter(Item::getIsAvailable) - .map(itemMapper::toItemResponseDto) - .collect(Collectors.toList()); - } - - private void findUserById(Long userId) { - userStorage.getUserById(userId) - .orElseThrow(() -> new NotFoundException("User with id = " + userId + " not found")); - } -} diff --git a/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java new file mode 100644 index 0000000..29d56ac --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java @@ -0,0 +1,161 @@ +package ru.practicum.shareit.item; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.practicum.shareit.booking.intrfaces.BookingRepository; +import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.exception.AnotherUserException; +import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.exception.ValidationException; +import ru.practicum.shareit.item.dto.*; +import ru.practicum.shareit.item.interfaces.CommentRepository; +import ru.practicum.shareit.item.interfaces.ItemRepository; +import ru.practicum.shareit.item.interfaces.ItemServiceInterface; +import ru.practicum.shareit.item.mapper.CommentMapper; +import ru.practicum.shareit.item.mapper.ItemMapper; +import ru.practicum.shareit.item.model.Comment; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.user.interfaces.UserRepository; +import ru.practicum.shareit.user.mapper.UserMapper; +import ru.practicum.shareit.user.model.User; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + + +@Service +@RequiredArgsConstructor +public class ItemServiceImpl implements ItemServiceInterface { + + private final ItemRepository itemRepository; + private final UserRepository userRepository; + private final CommentRepository commentRepository; + private final BookingRepository bookingRepository; + private final ItemMapper itemMapper; + private final UserMapper userMapper; + private final CommentMapper commentMapper; + + public ItemResponseDto createItem(ItemRequestDto item, Long ownerId) { + if (ownerId == null) { + throw new ValidationException("Owner id cannot be null"); + } + + User owner = userRepository.getUserByUserId(ownerId) + .orElseThrow(() -> new NotFoundException("User with id " + ownerId + " not found")); + + Item itemSaved = itemMapper.toItem(item); + itemSaved.setOwner(owner); + + itemRepository.save(itemSaved); + ItemResponseDto responseDto = itemMapper.toItemResponseDto(itemSaved); + mapResponseDto(itemSaved, responseDto); + + return responseDto; + } + + public ItemResponseDtoWithComments getItemById(Long id) { + ItemResponseDto item = itemMapper.toItemResponseDto(itemRepository.getItemByItemId(id) + .orElseThrow(() -> new NotFoundException("Item with id " + id + " not found"))); + + List comments = commentRepository.getCommentsByItem_ItemId(id).stream() + .map(commentMapper::toCommentResponseDto) + .collect(Collectors.toList()); + + ItemResponseDtoWithComments itemDto = itemMapper.toItemResponseDtoWithComments( + itemRepository.getItemByItemId(id).get()); + itemDto.setComments(comments); + + return itemDto; + } + + public ItemResponseDto updateItem(Long itemId, + ItemRequestDto item, Long ownerId) { + + User owner = userRepository.getUserByUserId(ownerId) + .orElseThrow(() -> new NotFoundException("User with id " + ownerId + " not found")); + + Item foundItem = itemRepository.getItemByItemId(itemId) + .orElseThrow(() -> new NotFoundException("Item with id " + itemId + " not found")); + + if (foundItem.getOwner().getUserId().equals(ownerId)) { + + if (item.getIsAvailable() != null) { + foundItem.setIsAvailable(item.getIsAvailable()); + } + + if (item.getItemName() != null) { + foundItem.setItemName(item.getItemName()); + } + + if (item.getItemDescription() != null) { + foundItem.setItemDescription(item.getItemDescription()); + } + + } else { + throw new AnotherUserException("User with id " + ownerId + " is not owner of this Item"); + } + + ItemResponseDto responseDto = itemMapper.toItemResponseDto(foundItem); + mapResponseDto(foundItem, responseDto); + + return responseDto; + } + + public Collection getAllItemsForOwner(Long ownerId) { + User owner = userRepository.getUserByUserId(ownerId) + .orElseThrow(() -> new NotFoundException("User with id " + ownerId + " not found")); + + return itemRepository.getItemsByOwner_UserId(ownerId).stream() + .map(itemMapper::toItemResponseDto) + .peek(item -> item.setOwnerId(ownerId)) + .collect(Collectors.toList()); + } + + public Collection searchByText(String text) { + if (text == null || text.isEmpty()) { + return new ArrayList<>(); + } + return itemRepository.searchByTextContainingIgnoreCase(text).stream() + .filter(Item::getIsAvailable) + .map(itemMapper::toItemResponseDto) + .collect(Collectors.toList()); + } + + public CommentResponseCreatedDto addComment(Long commentatorId, + CommentRequestDto commentDto, Long itemId) { + Collection bookings = bookingRepository.getBookingsByItem_ItemId(itemId); + + Booking booking = bookings.stream() + .filter(booking1 -> booking1.getBooker().getUserId().equals(commentatorId)) + .findFirst() + .orElseThrow(() -> new NotFoundException("Booking with bookerId " + commentatorId + " not found")); + + if (!booking.getEnd().isBefore(commentDto.getDate())) { + throw new ValidationException("Booking end date cannot be before comment date"); + } + + if (booking.getStatus().equals(BookingStatus.APPROVED)) { + throw new ValidationException("Booking status cannot be APPROVED"); + } + + Comment comment = commentMapper.toComment(commentDto); + comment.setItem(itemRepository.getItemByItemId(itemId).get()); + comment.setAuthor(userRepository.getUserByUserId(commentatorId).get()); + + return commentMapper.toCommentResponseCreatedDto( + commentRepository.save(comment)); + } + + private void mapResponseDto(Item item, ItemResponseDto itemResponseDto) { + itemResponseDto.setOwnerId(item.getOwner().getUserId()); + + if (item.getItemRequest() != null) { + itemResponseDto.setRequestId(item.getItemRequest().getItemRequestId()); + } + } + +} + diff --git a/src/main/java/ru/practicum/shareit/item/ItemStorage.java b/src/main/java/ru/practicum/shareit/item/ItemStorage.java index 6b234d5..e9ba003 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemStorage.java +++ b/src/main/java/ru/practicum/shareit/item/ItemStorage.java @@ -49,7 +49,7 @@ public Item updateItem(Item item) { public Collection getAllItemsForOwner(Long ownerId) { return items.values() .stream() - .filter(item -> Objects.equals(item.getOwnerId(), ownerId)) + .filter(item -> Objects.equals(item.getOwner().getUserId(), ownerId)) .collect(Collectors.toList()); } diff --git a/src/main/java/ru/practicum/shareit/item/dto/CommentRequestDto.java b/src/main/java/ru/practicum/shareit/item/dto/CommentRequestDto.java new file mode 100644 index 0000000..3462221 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/CommentRequestDto.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.item.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class CommentRequestDto { + + @JsonProperty("id") + private Long authorId; + + @JsonProperty("text") + private String text; + + private LocalDateTime date = LocalDateTime.now(); + +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/CommentResponseCreatedDto.java b/src/main/java/ru/practicum/shareit/item/dto/CommentResponseCreatedDto.java new file mode 100644 index 0000000..f47203c --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/CommentResponseCreatedDto.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.item.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class CommentResponseCreatedDto { + @JsonProperty("id") + private Long commentId; + + @JsonProperty("text") + private String text; + + private String authorName; + + private Boolean created = true; +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/CommentResponseDto.java b/src/main/java/ru/practicum/shareit/item/dto/CommentResponseDto.java new file mode 100644 index 0000000..9dc1ff9 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/CommentResponseDto.java @@ -0,0 +1,17 @@ +package ru.practicum.shareit.item.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import ru.practicum.shareit.user.dto.UserAuthorDto; + +@Data +public class CommentResponseDto { + + @JsonProperty("id") + private Long commentId; + + @JsonProperty("text") + private String text; + + private UserAuthorDto author; +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemBookerDto.java b/src/main/java/ru/practicum/shareit/item/dto/ItemBookerDto.java new file mode 100644 index 0000000..28d23ca --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/ItemBookerDto.java @@ -0,0 +1,18 @@ +package ru.practicum.shareit.item.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ItemBookerDto { + + @JsonProperty("id") + private Long itemId; + + @JsonProperty("name") + private String itemName; +} diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java b/src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java new file mode 100644 index 0000000..53e00e3 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java @@ -0,0 +1,40 @@ +package ru.practicum.shareit.item.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ItemResponseDtoWithComments { + + @NotNull + @JsonProperty("id") + private Long itemId; + + @JsonProperty("name") + private String itemName; + + @JsonProperty("description") + private String itemDescription; + + @JsonProperty("available") + private Boolean isAvailable; + + @JsonProperty("userId") + private Long ownerId; + + private Long requestId; + + private LocalDateTime lastBooking; + + private LocalDateTime nextBooking; + + private List comments; +} diff --git a/src/main/java/ru/practicum/shareit/item/interfaces/CommentRepository.java b/src/main/java/ru/practicum/shareit/item/interfaces/CommentRepository.java new file mode 100644 index 0000000..01f501c --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/interfaces/CommentRepository.java @@ -0,0 +1,13 @@ +package ru.practicum.shareit.item.interfaces; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.practicum.shareit.item.model.Comment; + +import java.util.Collection; + +public interface CommentRepository extends JpaRepository { + + Comment save(Comment comment); + + Collection getCommentsByItem_ItemId(Long itemId); +} diff --git a/src/main/java/ru/practicum/shareit/item/interfaces/ItemRepository.java b/src/main/java/ru/practicum/shareit/item/interfaces/ItemRepository.java new file mode 100644 index 0000000..d27984b --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/interfaces/ItemRepository.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.item.interfaces; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import ru.practicum.shareit.item.model.Item; + +import java.util.Collection; +import java.util.Optional; + +public interface ItemRepository extends JpaRepository { + Item save(Item item); + + Optional getItemByItemId(Long itemId); + + Collection getItemsByOwner_UserId(Long ownerUserId); + + @Query(value = "SELECT i FROM Item i WHERE upper(i.itemName) like upper(concat('%', ?1, '%')) " + + " OR upper(i.itemDescription) LIKE upper(concat('%', ?1, '%'))") + Collection searchByTextContainingIgnoreCase(String text); +} diff --git a/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java b/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java index 053d40c..f09f8d5 100644 --- a/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java +++ b/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java @@ -2,13 +2,14 @@ import ru.practicum.shareit.item.dto.ItemRequestDto; import ru.practicum.shareit.item.dto.ItemResponseDto; +import ru.practicum.shareit.item.dto.ItemResponseDtoWithComments; import java.util.Collection; public interface ItemServiceInterface { ItemResponseDto createItem(ItemRequestDto item, Long ownerId); - ItemResponseDto getItemById(Long id); + ItemResponseDtoWithComments getItemById(Long id); ItemResponseDto updateItem(Long itemId, ItemRequestDto item, Long ownerId); diff --git a/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java b/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java new file mode 100644 index 0000000..ff396e8 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java @@ -0,0 +1,30 @@ +package ru.practicum.shareit.item.mapper; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; +import ru.practicum.shareit.item.dto.CommentRequestDto; +import ru.practicum.shareit.item.dto.CommentResponseCreatedDto; +import ru.practicum.shareit.item.dto.CommentResponseDto; +import ru.practicum.shareit.item.model.Comment; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface CommentMapper { + Comment toComment(CommentRequestDto comment); + + CommentResponseDto toCommentResponseDto(Comment comment); + + + default CommentResponseCreatedDto toCommentResponseCreatedDto(Comment comment) { + if (comment == null) { + return null; + } + + CommentResponseCreatedDto commentResponseCreatedDto = new CommentResponseCreatedDto(); + commentResponseCreatedDto.setCommentId(comment.getCommentId()); + commentResponseCreatedDto.setText(comment.getText()); + commentResponseCreatedDto.setAuthorName(comment.getAuthor().getUserName()); + + return commentResponseCreatedDto; + } + +} diff --git a/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java b/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java index 6835d2c..f60e856 100644 --- a/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java +++ b/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java @@ -2,8 +2,10 @@ import org.mapstruct.Mapper; import org.mapstruct.MappingConstants; +import ru.practicum.shareit.item.dto.ItemBookerDto; import ru.practicum.shareit.item.dto.ItemRequestDto; import ru.practicum.shareit.item.dto.ItemResponseDto; +import ru.practicum.shareit.item.dto.ItemResponseDtoWithComments; import ru.practicum.shareit.item.model.Item; @Mapper(componentModel = MappingConstants.ComponentModel.SPRING) @@ -14,6 +16,48 @@ public interface ItemMapper { Item toItem(ItemRequestDto itemRequestDto); - ItemResponseDto toItemResponseDto(Item item); + default ItemResponseDto toItemResponseDto(Item item) { + if (item == null) { + return null; + } + + ItemResponseDto itemResponseDto = new ItemResponseDto(); + itemResponseDto.setItemId(item.getItemId()); + itemResponseDto.setItemName(item.getItemName()); + itemResponseDto.setItemDescription(item.getItemDescription()); + itemResponseDto.setIsAvailable(item.getIsAvailable()); + itemResponseDto.setOwnerId(item.getOwner().getUserId()); + + if(item.getItemRequest() != null) { + itemResponseDto.setRequestId(item.getItemRequest().getRequesterId()); + } + + return itemResponseDto; + + } + + ItemBookerDto toItemBookerDto(Item item); + + default ItemResponseDtoWithComments toItemResponseDtoWithComments(Item item) { + if (item == null) { + return null; + } + + ItemResponseDtoWithComments itemResponseDtoWithComments = new ItemResponseDtoWithComments(); + + itemResponseDtoWithComments.setItemId(item.getItemId()); + itemResponseDtoWithComments.setItemName(item.getItemName()); + itemResponseDtoWithComments.setItemDescription(item.getItemDescription()); + itemResponseDtoWithComments.setIsAvailable(item.getIsAvailable()); + itemResponseDtoWithComments.setItemId(item.getItemId()); + itemResponseDtoWithComments.setOwnerId(item.getOwner().getUserId()); + + if(item.getItemRequest() != null) { + itemResponseDtoWithComments.setRequestId(item.getItemRequest().getItemRequestId()); + } + + return itemResponseDtoWithComments; + + } } diff --git a/src/main/java/ru/practicum/shareit/item/model/Comment.java b/src/main/java/ru/practicum/shareit/item/model/Comment.java new file mode 100644 index 0000000..f979f3e --- /dev/null +++ b/src/main/java/ru/practicum/shareit/item/model/Comment.java @@ -0,0 +1,34 @@ +package ru.practicum.shareit.item.model; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import ru.practicum.shareit.user.model.User; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@Entity +@ToString +@Table(name = "comments") +public class Comment { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "comment_id") + private Long commentId; + + @Column(name = "text") + private String text; + + @ManyToOne(targetEntity = User.class, cascade = CascadeType.ALL) + @JoinColumn(name = "author_id") + private User author; + + @ManyToOne(targetEntity = Item.class,cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @JoinColumn(name = "item_id") + private Item item; + +} \ No newline at end of file diff --git a/src/main/java/ru/practicum/shareit/item/model/Item.java b/src/main/java/ru/practicum/shareit/item/model/Item.java index 6fcf2d1..c1d6d11 100644 --- a/src/main/java/ru/practicum/shareit/item/model/Item.java +++ b/src/main/java/ru/practicum/shareit/item/model/Item.java @@ -1,20 +1,42 @@ package ru.practicum.shareit.item.model; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; - +import lombok.ToString; +import ru.practicum.shareit.request.ItemRequest; +import ru.practicum.shareit.user.model.User; @Data @NoArgsConstructor @AllArgsConstructor +@Entity +@ToString +@Table(name = "items") public class Item { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "item_id") private Long itemId; + + @Column(name = "item_name") private String itemName; + + @Column(name = "item_description") private String itemDescription; + + @Column(name = "is_available") private Boolean isAvailable; - private Long ownerId; - private Long requestId; + + @ManyToOne + @JoinColumn(name = "owner_id") + private User owner; + + @ManyToOne + @JoinColumn(name = "request_id") + private ItemRequest itemRequest; + } diff --git a/src/main/java/ru/practicum/shareit/request/ItemRequest.java b/src/main/java/ru/practicum/shareit/request/ItemRequest.java index c12fab1..0da7fda 100644 --- a/src/main/java/ru/practicum/shareit/request/ItemRequest.java +++ b/src/main/java/ru/practicum/shareit/request/ItemRequest.java @@ -1,13 +1,35 @@ package ru.practicum.shareit.request; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + import java.time.LocalDate; /** * TODO Sprint add-item-requests. */ +@Data +@Entity +@Table(name = "requests") +@AllArgsConstructor +@NoArgsConstructor +@ToString public class ItemRequest { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "request_id") private Long itemRequestId; + + @Column(name = "description") private String requestDescription; + + @Column(name = "requestor_id") private Long requesterId; + + @Transient private LocalDate requestDate; } diff --git a/src/main/java/ru/practicum/shareit/request/interfaces/RequestRepository.java b/src/main/java/ru/practicum/shareit/request/interfaces/RequestRepository.java new file mode 100644 index 0000000..cea05b1 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/request/interfaces/RequestRepository.java @@ -0,0 +1,8 @@ +package ru.practicum.shareit.request.interfaces; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.practicum.shareit.request.ItemRequest; + +public interface RequestRepository extends JpaRepository { + ItemRequest save(ItemRequest item); +} diff --git a/src/main/java/ru/practicum/shareit/user/UserController.java b/src/main/java/ru/practicum/shareit/user/UserController.java index 4c334a4..0289b90 100644 --- a/src/main/java/ru/practicum/shareit/user/UserController.java +++ b/src/main/java/ru/practicum/shareit/user/UserController.java @@ -12,7 +12,7 @@ @RequestMapping(path = "/users") @RequiredArgsConstructor public class UserController { - private final UserService userService; + private final UserServiceImpl userService; @PostMapping public UserResponseDto createUser(@Valid @RequestBody UserRequestDto user) { diff --git a/src/main/java/ru/practicum/shareit/user/UserService.java b/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java similarity index 65% rename from src/main/java/ru/practicum/shareit/user/UserService.java rename to src/main/java/ru/practicum/shareit/user/UserServiceImpl.java index e4c8802..c988d8a 100644 --- a/src/main/java/ru/practicum/shareit/user/UserService.java +++ b/src/main/java/ru/practicum/shareit/user/UserServiceImpl.java @@ -6,6 +6,7 @@ import ru.practicum.shareit.exception.NotFoundException; import ru.practicum.shareit.user.dto.UserRequestDto; import ru.practicum.shareit.user.dto.UserResponseDto; +import ru.practicum.shareit.user.interfaces.UserRepository; import ru.practicum.shareit.user.interfaces.UserServiceInterface; import ru.practicum.shareit.user.mapper.UserMapper; import ru.practicum.shareit.user.model.User; @@ -15,42 +16,54 @@ @Service @AllArgsConstructor -public class UserService implements UserServiceInterface { +public class UserServiceImpl implements UserServiceInterface { - private final UserStorage userStorage; + private final UserRepository userStorage; private final UserMapper userMapper; public UserResponseDto createUser(UserRequestDto user) { validateEmail(user.getUserEmail()); User newUser = userMapper.toUser(user); - return userMapper.toUserResponseDto(userStorage.createUser(newUser)); + return userMapper.toUserResponseDto(userStorage.save(newUser)); } public UserResponseDto getUserById(Long userId) throws NotFoundException { - return userMapper.toUserResponseDto(userStorage.getUserById(userId) + return userMapper.toUserResponseDto(userStorage.getUserByUserId(userId) .orElseThrow(() -> new NotFoundException("User not found, id = " + userId))); } public UserResponseDto updateUser(Long userId, UserRequestDto user) throws NotFoundException { + User updated = userStorage.getUserByUserId(userId) + .orElseThrow(() -> new NotFoundException("User not found, id = " + userId)); + validateEmail(user.getUserEmail()); - return userMapper.toUserResponseDto(userStorage.updateUser(userId, userMapper.toUser(user))); + + if (user.getUserEmail() != null) { + updated.setUserEmail(user.getUserEmail()); + } + + if (user.getUserName() != null) { + updated.setUserName(user.getUserName()); + } + + return userMapper.toUserResponseDto(userStorage.save(updated)); } public void deleteUser(Long userId) throws NotFoundException { - getUserById(userId); - userStorage.deleteUser(userId); + User user = userMapper.toUser(getUserById(userId)); + userStorage.delete(user); } public void deleteAllUsers() { - userStorage.deleteAllUsers(); + userStorage.deleteAll(); } private void validateEmail(String email) { - Collection users = userStorage.getAllUsers(); + Collection users = userStorage.findAll(); if (!users.isEmpty()) { Optional first = - userStorage.getAllUsers().stream() + userStorage.findAll().stream() .map(User::getUserEmail) .filter(userEmail -> userEmail.equals(email)) .findFirst(); diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserAuthorDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserAuthorDto.java new file mode 100644 index 0000000..dbc923a --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/dto/UserAuthorDto.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.user.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UserAuthorDto { + @NotNull + @JsonProperty("id") + private Long userId; + + @JsonProperty("authorName") + private String userName; +} diff --git a/src/main/java/ru/practicum/shareit/user/dto/UserBookingDto.java b/src/main/java/ru/practicum/shareit/user/dto/UserBookingDto.java new file mode 100644 index 0000000..ef634fa --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/dto/UserBookingDto.java @@ -0,0 +1,20 @@ +package ru.practicum.shareit.user.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UserBookingDto { + @NotNull + @JsonProperty("id") + private Long userId; + + @JsonProperty("name") + private String userName; + +} diff --git a/src/main/java/ru/practicum/shareit/user/interfaces/UserRepository.java b/src/main/java/ru/practicum/shareit/user/interfaces/UserRepository.java new file mode 100644 index 0000000..2024294 --- /dev/null +++ b/src/main/java/ru/practicum/shareit/user/interfaces/UserRepository.java @@ -0,0 +1,19 @@ +package ru.practicum.shareit.user.interfaces; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.practicum.shareit.user.model.User; + +import java.util.List; +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + User save(User user); + + Optional getUserByUserId(Long userId); + + List findAll(); + + void deleteUserByUserId(Long id); + + void deleteAll(); +} diff --git a/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java b/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java index 086a773..feeeb99 100644 --- a/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java +++ b/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java @@ -1,13 +1,13 @@ package ru.practicum.shareit.user.mapper; -import org.mapstruct.InjectionStrategy; import org.mapstruct.Mapper; +import ru.practicum.shareit.user.dto.UserAuthorDto; +import ru.practicum.shareit.user.dto.UserBookingDto; import ru.practicum.shareit.user.dto.UserRequestDto; import ru.practicum.shareit.user.dto.UserResponseDto; import ru.practicum.shareit.user.model.User; -@Mapper(componentModel = "spring", uses = UserMapper - .class, injectionStrategy = InjectionStrategy.CONSTRUCTOR) +@Mapper(componentModel = "spring") public interface UserMapper { UserRequestDto toUserRequestDto(User user); @@ -17,4 +17,9 @@ public interface UserMapper { UserResponseDto toUserResponseDto(User user); User toUser(UserResponseDto userDto); + + UserAuthorDto toUserAuthorDto(User user); + + UserBookingDto toUserBookingDto(User booker); + } diff --git a/src/main/java/ru/practicum/shareit/user/model/User.java b/src/main/java/ru/practicum/shareit/user/model/User.java index c7c00cc..5d289c4 100644 --- a/src/main/java/ru/practicum/shareit/user/model/User.java +++ b/src/main/java/ru/practicum/shareit/user/model/User.java @@ -1,14 +1,27 @@ package ru.practicum.shareit.user.model; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.ToString; @Data @NoArgsConstructor @AllArgsConstructor +@Entity +@ToString +@Table(name = "users") public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_id") private Long userId; + + @Column(name = "user_name") private String userName; + + @Column(name = "user_email") private String userEmail; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b9e5d4b..e1fc5d9 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,14 +1,13 @@ spring.jpa.hibernate.ddl-auto=none spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.jdbc.time_zone=UTC spring.sql.init.mode=always +spring.datasource.url=jdbc:postgresql://localhost:5432/postgres +spring.datasource.driverClassName=org.postgresql.Driver +spring.datasource.username=user +spring.datasource.password=12345 logging.level.org.springframework.orm.jpa=INFO logging.level.org.springframework.transaction=INFO logging.level.org.springframework.transaction.interceptor=TRACE -logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG - -# TODO Append connection to DB -#spring.datasource.driverClassName -#spring.datasource.url -#spring.datasource.username -#spring.datasource.password +logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG \ No newline at end of file diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000..c07802f --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,42 @@ +CREATE TABLE IF NOT EXISTS users ( + user_id BIGSERIAL PRIMARY KEY, + user_name CHARACTER VARYING(255) NOT NULL, + user_email CHARACTER VARYING(500) NOT NULL UNIQUE +); + +CREATE TABLE IF NOT EXISTS items ( + item_id BIGSERIAL PRIMARY KEY, + item_name CHARACTER VARYING(255) NOT NULL, + item_description CHARACTER VARYING(150) NOT NULL, + is_available BOOLEAN NOT NULL, + owner_id BIGINT NOT NULL, + request_id BIGINT, + CONSTRAINT fk_items_to_users FOREIGN KEY(owner_id) REFERENCES users(user_id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS comments ( + comment_id BIGSERIAL PRIMARY KEY, + text CHARACTER VARYING(2000) NOT NULL, + item_id BIGINT NOT NULL, + author_id BIGINT NOT NULL, + CONSTRAINT fk_comments_to_users FOREIGN KEY (author_id) REFERENCES users (user_id) ON DELETE CASCADE, + CONSTRAINT fk_comments_to_items FOREIGN KEY (item_id) REFERENCES items(item_id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS bookings ( + booking_id BIGSERIAL PRIMARY KEY, + start_date TIMESTAMP WITHOUT TIME ZONE NOT NULL, + end_date TIMESTAMP WITHOUT TIME ZONE NOT NULL, + item_id BIGINT NOT NULL, + booker_id BIGINT NOT NULL, + status CHARACTER VARYING (50), + FOREIGN KEY (item_id) REFERENCES items (item_id) ON DELETE CASCADE, + FOREIGN KEY (booker_id) REFERENCES users (user_id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS requests ( + request_id BIGSERIAL PRIMARY KEY, + requestor_id BIGINT NOT NULL, + description CHARACTER VARYING (200), + FOREIGN KEY (requestor_id) REFERENCES users (user_id) ON DELETE CASCADE +); \ No newline at end of file diff --git a/src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java new file mode 100644 index 0000000..631da06 --- /dev/null +++ b/src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java @@ -0,0 +1,80 @@ +package ru.practicum.shareit.mapperTest; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.booking.dto.BookingRequestDto; +import ru.practicum.shareit.booking.dto.BookingResponseDto; +import ru.practicum.shareit.booking.mapper.BookingMapper; +import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; +import ru.practicum.shareit.item.dto.ItemBookerDto; +import ru.practicum.shareit.item.mapper.ItemMapper; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.request.ItemRequest; +import ru.practicum.shareit.user.dto.UserBookingDto; +import ru.practicum.shareit.user.mapper.UserMapper; +import ru.practicum.shareit.user.model.User; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +public class BookingMapperTest { + @Autowired + private BookingMapper bookingMapper; + + @Autowired + private UserMapper userMapper; + + @Autowired + private ItemMapper itemMapper; + + User user =new User(1L, "testName1", "test1@test.com"); + + ItemRequest itemRequest = new ItemRequest(1L, "testDescription1", + 1L, LocalDate.of(2025, 6, 25)); + + Item item = new Item(1L, "TestName1", "Test description1", true, user, itemRequest); + LocalDateTime startTime = LocalDateTime.of(2025, 6, 25, 12, 30); + LocalDateTime endTime = LocalDateTime.of(2025, 6, 27, 13, 30); + + @Test + public void bookingRequestDtoToBookingTest() { + BookingRequestDto bookingRequestDto = new BookingRequestDto(); + + bookingRequestDto.setBookingId(1L); + bookingRequestDto.setStart(startTime); + bookingRequestDto.setEnd(endTime); + bookingRequestDto.setStatus(BookingStatus.WAITING); + + Booking booking = bookingMapper.bookingRequestDtoToBooking(bookingRequestDto); + assertAll(() -> { + assertEquals(booking.getBookingId(), bookingRequestDto.getBookingId()); + assertEquals(booking.getStart(), bookingRequestDto.getStart()); + assertEquals(booking.getEnd(), bookingRequestDto.getEnd()); + assertEquals(booking.getStatus(), bookingRequestDto.getStatus()); + }); + } + + @Test + public void bookingToBookingResponseDtoTest() { + Booking booking = new Booking(3L, startTime, endTime, item, user, BookingStatus.APPROVED); + + BookingResponseDto bookingResponseDto = bookingMapper.bookingToBookingResponseDto(booking); + + ItemBookerDto itemBookerDto = itemMapper.toItemBookerDto(item); + UserBookingDto userBookingDto = userMapper.toUserBookingDto(user); + assertAll(() -> { + assertEquals(booking.getBookingId(), bookingResponseDto.getBookingId()); + assertEquals(booking.getStart(), bookingResponseDto.getStart()); + assertEquals(booking.getEnd(), bookingResponseDto.getEnd()); + assertEquals(booking.getStatus(), bookingResponseDto.getStatus()); + assertEquals(userBookingDto, bookingResponseDto.getBooker()); + assertEquals(itemBookerDto, bookingResponseDto.getItem()); + }); + } +} diff --git a/src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java new file mode 100644 index 0000000..63fc5d8 --- /dev/null +++ b/src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java @@ -0,0 +1,73 @@ +package ru.practicum.shareit.mapperTest; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.item.dto.CommentRequestDto; +import ru.practicum.shareit.item.dto.CommentResponseCreatedDto; +import ru.practicum.shareit.item.dto.CommentResponseDto; +import ru.practicum.shareit.item.mapper.CommentMapper; +import ru.practicum.shareit.item.model.Comment; +import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.request.ItemRequest; +import ru.practicum.shareit.user.dto.UserAuthorDto; +import ru.practicum.shareit.user.mapper.UserMapper; +import ru.practicum.shareit.user.model.User; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +public class CommentMapperTest { + @Autowired + private CommentMapper commentMapper; + + @Autowired + private UserMapper userMapper; + + User user =new User(1L, "testName1", "test1@test.com"); + + ItemRequest itemRequest = new ItemRequest(1L, "testDescription1", + 1L, LocalDate.of(2025, 6, 25)); + + Item item = new Item(1L, "TestName1", "Test description1", true, user, itemRequest); + + @Test + public void commentToCommentDtoTest() { + Comment comment = new Comment(1L, "testComment1", user, item); + UserAuthorDto authorDto = userMapper.toUserAuthorDto(user); + CommentResponseDto commentResponseDto = commentMapper.toCommentResponseDto(comment); + + assertAll(() -> { + assertEquals("testComment1", commentResponseDto.getText()); + assertEquals(1L, commentResponseDto.getCommentId()); + assertEquals(authorDto, commentResponseDto.getAuthor()); + }); + } + + @Test + public void commentToCommentResponseCreatedDtoTest() { + Comment comment = new Comment(1L, "testComment1", user, item); + + CommentResponseCreatedDto createdDto = commentMapper.toCommentResponseCreatedDto(comment); + assertAll(() -> { + assertEquals("testComment1", createdDto.getText()); + assertEquals(1L, createdDto.getCommentId()); + assertEquals(user.getUserName(), createdDto.getAuthorName()); + assertEquals(true, createdDto.getCreated()); + }); + } + + @Test + public void commentRequestDtoToCommentTest() { + CommentRequestDto commentRequestDto = new CommentRequestDto(); + commentRequestDto.setAuthorId(user.getUserId()); + commentRequestDto.setText("testComment1"); + + Comment comment = commentMapper.toComment(commentRequestDto); + + assertAll(() -> assertEquals("testComment1", comment.getText())); + } +} diff --git a/src/test/java/ru/practicum/shareit/ItemMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/ItemMapperTest.java similarity index 57% rename from src/test/java/ru/practicum/shareit/ItemMapperTest.java rename to src/test/java/ru/practicum/shareit/mapperTest/ItemMapperTest.java index 05ba9ca..4047ff9 100644 --- a/src/test/java/ru/practicum/shareit/ItemMapperTest.java +++ b/src/test/java/ru/practicum/shareit/mapperTest/ItemMapperTest.java @@ -1,12 +1,15 @@ -package ru.practicum.shareit; +package ru.practicum.shareit.mapperTest; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import ru.practicum.shareit.item.dto.ItemRequestDto; -import ru.practicum.shareit.item.dto.ItemResponseDto; +import ru.practicum.shareit.item.dto.*; import ru.practicum.shareit.item.mapper.ItemMapper; import ru.practicum.shareit.item.model.Item; +import ru.practicum.shareit.request.ItemRequest; +import ru.practicum.shareit.user.model.User; + +import java.time.LocalDate; import static org.junit.jupiter.api.Assertions.*; @@ -16,6 +19,11 @@ public class ItemMapperTest { @Autowired private ItemMapper itemMapper; + User user =new User(1L, "testName1", "test1@test.com"); + + ItemRequest itemRequest = new ItemRequest(1L, "testDescription1", + 1L, LocalDate.of(2025, 6, 25)); + @Test public void itemRequestDtoToItemTest() { ItemRequestDto itemRequestDto = new ItemRequestDto( @@ -28,14 +36,13 @@ public void itemRequestDtoToItemTest() { assertEquals("TestName", item.getItemName()); assertEquals("Test description", item.getItemDescription()); assertEquals(true, item.getIsAvailable()); - assertNull(item.getOwnerId()); - assertEquals(1L, item.getRequestId()); + assertNull(item.getOwner()); }); } @Test public void itemToItemResponseDtoTest() { - Item item = new Item(2L, "TestName2", "Test description2", true, 2L, 2L); + Item item = new Item(2L, "TestName2", "Test description2", true, user, itemRequest); ItemResponseDto itemResponseDto = itemMapper.toItemResponseDto(item); assertAll(() -> { @@ -43,8 +50,8 @@ public void itemToItemResponseDtoTest() { assertEquals("TestName2", itemResponseDto.getItemName()); assertEquals("Test description2", itemResponseDto.getItemDescription()); assertEquals(true, itemResponseDto.getIsAvailable()); - assertEquals(2L, itemResponseDto.getOwnerId()); - assertEquals(2L, itemResponseDto.getRequestId()); + assertEquals(user.getUserId(), itemResponseDto.getOwnerId()); + assertEquals(itemRequest.getItemRequestId(), itemResponseDto.getRequestId()); }); } @@ -67,7 +74,8 @@ public void itemRequestDtoToItemResponseDtoTest() { @Test public void itemResponseDtoToItemRequestDtoTest() { ItemResponseDto itemResponseDto = new ItemResponseDto( - 4L, "TestName4", "Test description4", false, 4L, 4L); + 4L, "TestName4", "Test description4", + false, 4L, 4L); ItemRequestDto itemRequestDto = itemMapper.toItemRequestDto(itemResponseDto); assertAll(() -> { assertEquals(4L, itemRequestDto.getItemId()); @@ -78,4 +86,37 @@ public void itemResponseDtoToItemRequestDtoTest() { }); } + @Test + public void itemToItemResponseDtoWithCommentsTest() { + + Item item = new Item(2L, "testName2", "testDescription2", + true, user, itemRequest); + + ItemResponseDtoWithComments itemResponse = itemMapper.toItemResponseDtoWithComments(item); + + assertAll(() -> { + assertEquals(2L, itemResponse.getItemId()); + assertEquals("testName2", itemResponse.getItemName()); + assertEquals("testDescription2", itemResponse.getItemDescription()); + assertEquals(true, itemResponse.getIsAvailable()); + assertEquals(user.getUserId(), itemResponse.getOwnerId()); + assertEquals(itemRequest.getItemRequestId(), itemResponse.getRequestId()); + assertNull(itemResponse.getComments()); + assertNull(itemResponse.getLastBooking()); + assertNull(itemResponse.getNextBooking()); + }); + } + + @Test + public void itemToItemBookerDto() { + Item item = new Item(2L, "testName2", "testDescription2", + true, user, itemRequest); + + ItemBookerDto itemBookerDto = itemMapper.toItemBookerDto(item); + + assertAll(() -> { + assertEquals(2L, itemBookerDto.getItemId()); + assertEquals("testName2", itemBookerDto.getItemName()); + }); + } } diff --git a/src/test/java/ru/practicum/shareit/UserMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/UserMapperTest.java similarity index 72% rename from src/test/java/ru/practicum/shareit/UserMapperTest.java rename to src/test/java/ru/practicum/shareit/mapperTest/UserMapperTest.java index 0bd6da2..b79e842 100644 --- a/src/test/java/ru/practicum/shareit/UserMapperTest.java +++ b/src/test/java/ru/practicum/shareit/mapperTest/UserMapperTest.java @@ -1,8 +1,10 @@ -package ru.practicum.shareit; +package ru.practicum.shareit.mapperTest; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import ru.practicum.shareit.user.dto.UserAuthorDto; +import ru.practicum.shareit.user.dto.UserBookingDto; import ru.practicum.shareit.user.dto.UserRequestDto; import ru.practicum.shareit.user.dto.UserResponseDto; import ru.practicum.shareit.user.mapper.UserMapper; @@ -62,4 +64,28 @@ public void userToUserResponseDtoTest() { assertEquals("test4@test.com", userResponseDto.getUserEmail()); }); } + + @Test + public void userToUserAuthorDtoTest() { + User user = new User(5L, "TestName5", "test5@test.com"); + + UserAuthorDto userAuthorDto = userMapper.toUserAuthorDto(user); + + assertAll(() -> { + assertEquals(5L, userAuthorDto.getUserId()); + assertEquals("TestName5", userAuthorDto.getUserName()); + }); + } + + @Test + public void userToUserBookingDtoTest() { + User user = new User(6L, "TestName6", "test6@test.com"); + + UserBookingDto userBookingDto = userMapper.toUserBookingDto(user); + + assertAll(() -> { + assertEquals(6L, userBookingDto.getUserId()); + assertEquals("TestName6", userBookingDto.getUserName()); + }); + } } diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..0024b61 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,10 @@ +spring.sql.init.mode=always +spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=user +spring.datasource.password=12345 + +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.jdbc.time_zone=UTC +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect \ No newline at end of file From 547ca0b92047a1e72a4c8eb616621721b65c2f19 Mon Sep 17 00:00:00 2001 From: NadezhdaTA Date: Fri, 27 Jun 2025 11:58:13 +0400 Subject: [PATCH 3/9] Delete db/shareit.trace.db --- db/shareit.trace.db | 162 -------------------------------------------- 1 file changed, 162 deletions(-) delete mode 100644 db/shareit.trace.db diff --git a/db/shareit.trace.db b/db/shareit.trace.db deleted file mode 100644 index 62ff604..0000000 --- a/db/shareit.trace.db +++ /dev/null @@ -1,162 +0,0 @@ -2025-06-26 07:25:54 jdbc[3]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 07:25:55 jdbc[3]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:26:44 jdbc[3]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:31:14 jdbc[3]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:31:16 jdbc[4]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:31:50 jdbc[5]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:31:50 jdbc[5]: exception -org.h2.jdbc.JdbcSQLSyntaxErrorException: Схема "INFORMATION_SCHEMA" не может быть удалена -Schema "INFORMATION_SCHEMA" cannot be dropped; SQL statement: -drop schema INFORMATION_SCHEMA [90090-220] - at org.h2.message.DbException.getJdbcSQLException(DbException.java:644) - at org.h2.message.DbException.getJdbcSQLException(DbException.java:489) - at org.h2.message.DbException.get(DbException.java:223) - at org.h2.message.DbException.get(DbException.java:199) - at org.h2.command.ddl.DropSchema.update(DropSchema.java:49) - at org.h2.command.CommandContainer.update(CommandContainer.java:169) - at org.h2.command.Command.executeUpdate(Command.java:252) - at org.h2.jdbc.JdbcStatement.executeUpdateInternal(JdbcStatement.java:190) - at org.h2.jdbc.JdbcStatement.executeUpdate(JdbcStatement.java:143) - at com.intellij.database.remote.jdbc.impl.RemoteStatementImpl.executeUpdate(RemoteStatementImpl.java:189) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:31:50 jdbc[6]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) From a41ce91a7ef7cf64277b5632d95a319ab94dfb42 Mon Sep 17 00:00:00 2001 From: NadezhdaTA Date: Fri, 27 Jun 2025 12:00:41 +0400 Subject: [PATCH 4/9] =?UTF-8?q?=D0=A4=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2015?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8=D0=BD=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/shareit.mv.db | Bin 40960 -> 0 bytes db/shareit.trace.db | 162 -------------------------------------------- 2 files changed, 162 deletions(-) delete mode 100644 db/shareit.mv.db delete mode 100644 db/shareit.trace.db diff --git a/db/shareit.mv.db b/db/shareit.mv.db deleted file mode 100644 index c8db7fd9467ab22f599c466f85b22ea51cf95d9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40960 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 bKa9VR;{Tm^|9?$(4al^Y7Z*$)-)ZH4hydT9 diff --git a/db/shareit.trace.db b/db/shareit.trace.db deleted file mode 100644 index 62ff604..0000000 --- a/db/shareit.trace.db +++ /dev/null @@ -1,162 +0,0 @@ -2025-06-26 07:25:54 jdbc[3]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 07:25:55 jdbc[3]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:26:44 jdbc[3]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:31:14 jdbc[3]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:31:16 jdbc[4]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:31:50 jdbc[5]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:31:50 jdbc[5]: exception -org.h2.jdbc.JdbcSQLSyntaxErrorException: Схема "INFORMATION_SCHEMA" не может быть удалена -Schema "INFORMATION_SCHEMA" cannot be dropped; SQL statement: -drop schema INFORMATION_SCHEMA [90090-220] - at org.h2.message.DbException.getJdbcSQLException(DbException.java:644) - at org.h2.message.DbException.getJdbcSQLException(DbException.java:489) - at org.h2.message.DbException.get(DbException.java:223) - at org.h2.message.DbException.get(DbException.java:199) - at org.h2.command.ddl.DropSchema.update(DropSchema.java:49) - at org.h2.command.CommandContainer.update(CommandContainer.java:169) - at org.h2.command.Command.executeUpdate(Command.java:252) - at org.h2.jdbc.JdbcStatement.executeUpdateInternal(JdbcStatement.java:190) - at org.h2.jdbc.JdbcStatement.executeUpdate(JdbcStatement.java:143) - at com.intellij.database.remote.jdbc.impl.RemoteStatementImpl.executeUpdate(RemoteStatementImpl.java:189) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) -2025-06-26 08:31:50 jdbc[6]: exception -java.sql.SQLClientInfoException: Client info name 'ApplicationName' not supported. - at org.h2.jdbc.JdbcConnection.setClientInfo(JdbcConnection.java:1573) - at com.intellij.database.remote.jdbc.impl.RemoteConnectionImpl.setClientInfo(RemoteConnectionImpl.java:469) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) - at java.base/java.lang.reflect.Method.invoke(Method.java:580) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) - at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) - at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) - at java.base/java.lang.Thread.run(Thread.java:1583) From a5e44652551b9ccb943654eb353ce4c6e8106f9f Mon Sep 17 00:00:00 2001 From: NadezhdaTA Date: Fri, 27 Jun 2025 12:04:50 +0400 Subject: [PATCH 5/9] =?UTF-8?q?=D0=A4=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2015?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8=D0=BD=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/shareit.mv.db | Bin 40960 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 db/shareit.mv.db diff --git a/db/shareit.mv.db b/db/shareit.mv.db deleted file mode 100644 index c8db7fd9467ab22f599c466f85b22ea51cf95d9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40960 zcmeHQ&5zs06{lpaS6yfABu<=9C$wzGURO~${H9K!B(7KWuGW#Xj*Ye;D01X1vMU*D z*|l2)O%R|!Z$(iQJ+uhgpg@{GpvR(z9(w2@hob1Uz4ln3K+#JdXZR(G(rRNlAL#4? zA}P&q-u!0X<9qYo8*Ws^a&K?wzEjocv9tRv2art04992CX!U6EEE-lbx%;$q9RI)EDB;#(FLg|^-)nV9MustIKhtV zAj2uDf`>f`qoUSRk&OC6QI|bQ@dUl7YXWxrs$0~1x}hsF{N$e)a6|v3@2SW?aRh|= zAgiVjvB*EMj_lNASvaA)lFupnx3u`fga zWJ53ZdtSfq2~x4|_Hhr1==|{DcI9ocvVZ^XXn24tUa!)+x3_o0*}I1u&dBLLyn`22 zrkrYP^q_KsMtxw9H0U>WVcl_ol7|;lg@Lg4@Vg;NVX5QG;WS?qk&C*|W9V#QiFP&( z%?Mzt)EfMeKp^2HxxP2>hMU9N6*PV+YW}a) z5Sk#$GkCCrD)iH6U6qq%^x;pzV-)p}sZNo{?QIP@po}qjZX4 zH0lJML<7sHN9h!$?Dmp$hDv0TPEpIQ=i>tUT}FEWozwd_6HjSM|B`fu+G>(cNts3` z(N)LjB%D#TUnRpIO^$SZW&C$>;&(EqtLZuY8o4V4U7&MljP^kHzDSBuMwu)Xs=aIU zX3>0}EE%fs(fxqgNU2bTCOr?;dP-cttJ80$Ci*bPya~sHR-@xTb=nY%VQe^(txcIV zNd&`LniKO#$Rqfa@<_=eHIMWh&KWs1r{|;`e1q~x&UtyH<@z}-FM4?qb6oDDC)_-D zoGTIoumUDiaH1^l!}F%H>mB!Pz6zoTksg$v=K_OK3ZllT;V1=$BV6s?$JY}^q-cl& z`Etv*D0R31$zBy*YEinbZ&B(VQbcM|%6-S{rzw-mZk3-6ofHH@ev?!nqB`EW0cuslnN+^PEbo)M3SKf=YBK#35o~mBNu_D{vO9&xe3QNxcup# z5zYPByFVsJ_Q4Qf2rvW~0t^9$07HNwzz|>vFa#I^3;~9~R|$cX|NVZLMX$zL^sIzXq!)5z!j;|Epx#0~UM4xS>Zq z^S2N<%YDEt<#HUi`Uj3fKPSh$@a>alPC;SlezYVcjNwrTOD>pQj0X1!D) zH+O()v%@zVR;%0W-r_sfn>$vk zp1fh_R;O!i+2JoXL>Z_xNzv^F5^J_>A=8E>O3{{TmQa(e23nW(5<#f7v$2j zXK71o^U%8ny!7uwc&P~!KjJ0-V$r-*GbLGTn5M02HPx0?OR!B1X$YAc2 zI7_juxzpX)&gAQrwZfA}mN5X7aLGDx8L{dDD40BqYtwGy0eqyd+B(o`LTEbqY_1&6KA17kD!)6%mu- z?6~Dj)}E*ya5wbjQMtSDEWp^C4@N2;sZ^W+VLox z2vhyYgpf9HIev6a7m$VLKmh*z5CI5kz%@|XBLNs(FIoULYFfQ+nSyPBab(Ndx?$H$ zMYS7^bw$=yp;lACG)oCBB0}s27&s-q+uQ=R!`!-_E@ZVDhZPA2AT*m&&G=oOsq;X) z-JMRBCdilo%^%7LRF~LMfW4K z_*nqzTXO?-$TSF;VC)(53Sjl8MPXG-f#r`BZFC;Efci|lCd}^{BJouai60yy5(5(_ z5{Z*0&th~!RcJ_(q1&cl7`AMxqFqBE9K~9_R)^pzT`&Q!l&lJ9$yVh8JMR$F5Y$Is zXz@oATJ^c8oh`J^!DO9Z=|d@*6%R`(F(PY)63oykN?%lEE|CQdj!CR!D>Ee)DizK{ z*QOb86O4a&&w}wCso6Rz}V7k$}4STy8CX46OB_|X4P zwWl~)!cUNpV*P_C9yrQ}2$D5?#R#_hk7zcip3)=kf5};(_n+s%|DXR)ewX8llPN1| zn7g8dC;HKJ$LUEdOm~#Bb;l1w)i!u-1Z?_{+(81aQi(vwk0uFK+c*&@&~4Qq;qtf z2^#g7MxD?o_SGbbvl4;E^lx9BTxru-1m^#by@V4MwOnHU|FIYx=KrTrJTzX1`Ty6L z|35RlF7#lA5q81#qTOHfxy(~*z0Cg)VR(drXE=2e1IGOSi9niYVozWCX8wPOTx9-# z=KqhpkW&H#9*h4!u>V8jBw0C4C6fJ3bvRm6*H%F56PQJ(GU;G=#!LjhdFM=e!Q=jBnk{(OaJ0#6; zX8agS(hJfB;~bjlX^1RIFU+7#r;E;)ewJE`BVoNPNiUtsIFnyllHSdUMA|TY19J0O8Gb$XlfQSOVSH>CzzeU9H$DUWn)nPu`JRbmasTe|0%E}J=ohMP6-|}R#=iA z-QOqiJPWcJS&|-0(!0!(^rmcz#FF&LE*_s(lHStCFa55--sJq-gj=a8t zz13wnnD;F??5!^T`-9k9UBXR1Ctp4Dh;Mbt_s;!viCd0RWF|9XjG37+zYUWn4o_I7 zNfQWCBPO#Zg13Oqk*-XVCm@7qB6-4ylP5A0P_$1%QV&l+2}n&QphO8Cgw(mRPv#*t zI~S!N<)Rp4Z_SC*t&Wh3G9?Ksk&AK&oJN?QmCi-MB)m)04Wyo+=k%pC^c-GRqbFWU zvFa#I^3;~8f0)Zg@ bKa9VR;{Tm^|9?$(4al^Y7Z*$)-)ZH4hydT9 From 4c6df918cc630f22481fa0d15bc30c9e6dcdd1b1 Mon Sep 17 00:00:00 2001 From: NadezhdaTA Date: Fri, 27 Jun 2025 12:10:29 +0400 Subject: [PATCH 6/9] =?UTF-8?q?=D0=A4=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2015?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8=D0=BD=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/practicum/shareit/booking/mapper/BookingMapper.java | 2 +- .../ru/practicum/shareit/item/mapper/CommentMapper.java | 4 ++-- .../java/ru/practicum/shareit/item/mapper/ItemMapper.java | 6 +++--- .../java/ru/practicum/shareit/user/mapper/UserMapper.java | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java b/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java index 9d51d2c..7144648 100644 --- a/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java +++ b/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java @@ -6,7 +6,7 @@ import ru.practicum.shareit.booking.dto.BookingResponseDto; import ru.practicum.shareit.booking.model.Booking; -@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +@Mapper(componentModel=MappingConstants.ComponentModel.SPRING) public interface BookingMapper { Booking bookingRequestDtoToBooking(BookingRequestDto bookingRequestDto); diff --git a/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java b/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java index ff396e8..5b47ad3 100644 --- a/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java +++ b/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java @@ -7,7 +7,7 @@ import ru.practicum.shareit.item.dto.CommentResponseDto; import ru.practicum.shareit.item.model.Comment; -@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +@Mapper(componentModel=MappingConstants.ComponentModel.SPRING) public interface CommentMapper { Comment toComment(CommentRequestDto comment); @@ -15,7 +15,7 @@ public interface CommentMapper { default CommentResponseCreatedDto toCommentResponseCreatedDto(Comment comment) { - if (comment == null) { + if(comment == null) { return null; } diff --git a/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java b/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java index f60e856..dce21e9 100644 --- a/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java +++ b/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java @@ -8,7 +8,7 @@ import ru.practicum.shareit.item.dto.ItemResponseDtoWithComments; import ru.practicum.shareit.item.model.Item; -@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +@Mapper(componentModel=MappingConstants.ComponentModel.SPRING) public interface ItemMapper { ItemResponseDto toItemResponseDto(ItemRequestDto itemRequestDto); @@ -17,7 +17,7 @@ public interface ItemMapper { Item toItem(ItemRequestDto itemRequestDto); default ItemResponseDto toItemResponseDto(Item item) { - if (item == null) { + if(item == null) { return null; } @@ -39,7 +39,7 @@ default ItemResponseDto toItemResponseDto(Item item) { ItemBookerDto toItemBookerDto(Item item); default ItemResponseDtoWithComments toItemResponseDtoWithComments(Item item) { - if (item == null) { + if(item == null) { return null; } diff --git a/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java b/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java index feeeb99..10f8aee 100644 --- a/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java +++ b/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java @@ -7,7 +7,7 @@ import ru.practicum.shareit.user.dto.UserResponseDto; import ru.practicum.shareit.user.model.User; -@Mapper(componentModel = "spring") +@Mapper(componentModel="spring") public interface UserMapper { UserRequestDto toUserRequestDto(User user); From dd49cd954b95a6ff86208b9c033b61413e814398 Mon Sep 17 00:00:00 2001 From: NadezhdaTA Date: Fri, 27 Jun 2025 12:20:22 +0400 Subject: [PATCH 7/9] =?UTF-8?q?=D0=A4=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2015?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=81=D0=BF=D1=80=D0=B8=D0=BD=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shareit/booking/mapper/BookingMapper.java | 2 +- .../practicum/shareit/item/mapper/CommentMapper.java | 4 ++-- .../ru/practicum/shareit/item/mapper/ItemMapper.java | 10 +++++----- .../ru/practicum/shareit/user/mapper/UserMapper.java | 2 +- .../shareit/mapperTest/BookingMapperTest.java | 2 +- .../shareit/mapperTest/CommentMapperTest.java | 2 +- .../practicum/shareit/mapperTest/ItemMapperTest.java | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java b/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java index 7144648..9d51d2c 100644 --- a/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java +++ b/src/main/java/ru/practicum/shareit/booking/mapper/BookingMapper.java @@ -6,7 +6,7 @@ import ru.practicum.shareit.booking.dto.BookingResponseDto; import ru.practicum.shareit.booking.model.Booking; -@Mapper(componentModel=MappingConstants.ComponentModel.SPRING) +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) public interface BookingMapper { Booking bookingRequestDtoToBooking(BookingRequestDto bookingRequestDto); diff --git a/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java b/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java index 5b47ad3..ff396e8 100644 --- a/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java +++ b/src/main/java/ru/practicum/shareit/item/mapper/CommentMapper.java @@ -7,7 +7,7 @@ import ru.practicum.shareit.item.dto.CommentResponseDto; import ru.practicum.shareit.item.model.Comment; -@Mapper(componentModel=MappingConstants.ComponentModel.SPRING) +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) public interface CommentMapper { Comment toComment(CommentRequestDto comment); @@ -15,7 +15,7 @@ public interface CommentMapper { default CommentResponseCreatedDto toCommentResponseCreatedDto(Comment comment) { - if(comment == null) { + if (comment == null) { return null; } diff --git a/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java b/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java index dce21e9..38eb932 100644 --- a/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java +++ b/src/main/java/ru/practicum/shareit/item/mapper/ItemMapper.java @@ -8,7 +8,7 @@ import ru.practicum.shareit.item.dto.ItemResponseDtoWithComments; import ru.practicum.shareit.item.model.Item; -@Mapper(componentModel=MappingConstants.ComponentModel.SPRING) +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) public interface ItemMapper { ItemResponseDto toItemResponseDto(ItemRequestDto itemRequestDto); @@ -17,7 +17,7 @@ public interface ItemMapper { Item toItem(ItemRequestDto itemRequestDto); default ItemResponseDto toItemResponseDto(Item item) { - if(item == null) { + if (item == null) { return null; } @@ -28,7 +28,7 @@ default ItemResponseDto toItemResponseDto(Item item) { itemResponseDto.setIsAvailable(item.getIsAvailable()); itemResponseDto.setOwnerId(item.getOwner().getUserId()); - if(item.getItemRequest() != null) { + if (item.getItemRequest() != null) { itemResponseDto.setRequestId(item.getItemRequest().getRequesterId()); } @@ -39,7 +39,7 @@ default ItemResponseDto toItemResponseDto(Item item) { ItemBookerDto toItemBookerDto(Item item); default ItemResponseDtoWithComments toItemResponseDtoWithComments(Item item) { - if(item == null) { + if (item == null) { return null; } @@ -52,7 +52,7 @@ default ItemResponseDtoWithComments toItemResponseDtoWithComments(Item item) { itemResponseDtoWithComments.setItemId(item.getItemId()); itemResponseDtoWithComments.setOwnerId(item.getOwner().getUserId()); - if(item.getItemRequest() != null) { + if (item.getItemRequest() != null) { itemResponseDtoWithComments.setRequestId(item.getItemRequest().getItemRequestId()); } diff --git a/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java b/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java index 10f8aee..feeeb99 100644 --- a/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java +++ b/src/main/java/ru/practicum/shareit/user/mapper/UserMapper.java @@ -7,7 +7,7 @@ import ru.practicum.shareit.user.dto.UserResponseDto; import ru.practicum.shareit.user.model.User; -@Mapper(componentModel="spring") +@Mapper(componentModel = "spring") public interface UserMapper { UserRequestDto toUserRequestDto(User user); diff --git a/src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java index 631da06..5744f96 100644 --- a/src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java +++ b/src/test/java/ru/practicum/shareit/mapperTest/BookingMapperTest.java @@ -33,7 +33,7 @@ public class BookingMapperTest { @Autowired private ItemMapper itemMapper; - User user =new User(1L, "testName1", "test1@test.com"); + User user = new User(1L, "testName1", "test1@test.com"); ItemRequest itemRequest = new ItemRequest(1L, "testDescription1", 1L, LocalDate.of(2025, 6, 25)); diff --git a/src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java index 63fc5d8..6b7179f 100644 --- a/src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java +++ b/src/test/java/ru/practicum/shareit/mapperTest/CommentMapperTest.java @@ -27,7 +27,7 @@ public class CommentMapperTest { @Autowired private UserMapper userMapper; - User user =new User(1L, "testName1", "test1@test.com"); + User user = new User(1L, "testName1", "test1@test.com"); ItemRequest itemRequest = new ItemRequest(1L, "testDescription1", 1L, LocalDate.of(2025, 6, 25)); diff --git a/src/test/java/ru/practicum/shareit/mapperTest/ItemMapperTest.java b/src/test/java/ru/practicum/shareit/mapperTest/ItemMapperTest.java index 4047ff9..5143e32 100644 --- a/src/test/java/ru/practicum/shareit/mapperTest/ItemMapperTest.java +++ b/src/test/java/ru/practicum/shareit/mapperTest/ItemMapperTest.java @@ -19,7 +19,7 @@ public class ItemMapperTest { @Autowired private ItemMapper itemMapper; - User user =new User(1L, "testName1", "test1@test.com"); + User user = new User(1L, "testName1", "test1@test.com"); ItemRequest itemRequest = new ItemRequest(1L, "testDescription1", 1L, LocalDate.of(2025, 6, 25)); From e9fb54146529f69d37283a20327826b321cac7eb Mon Sep 17 00:00:00 2001 From: NadezhdaTA Date: Sun, 29 Jun 2025 15:28:28 +0400 Subject: [PATCH 8/9] =?UTF-8?q?=D0=A4=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2015?= =?UTF-8?q?=D0=B3=D0=BE=20(=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=20=D1=81=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=BD?= =?UTF-8?q?=D0=BE=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=D0=BC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shareit/booking/BookingController.java | 24 ++- .../shareit/booking/BookingServiceImpl.java | 146 ++++++++++++++---- .../booking/dto/BookingRequestDto.java | 1 - .../booking/intrfaces/BookingRepository.java | 19 +++ .../intrfaces/BookingServiceInterface.java | 8 +- .../shareit/item/ItemController.java | 5 +- .../shareit/item/ItemServiceImpl.java | 75 +++++---- .../item/dto/ItemResponseDtoWithComments.java | 6 +- .../item/interfaces/ItemServiceInterface.java | 2 +- 9 files changed, 203 insertions(+), 83 deletions(-) diff --git a/src/main/java/ru/practicum/shareit/booking/BookingController.java b/src/main/java/ru/practicum/shareit/booking/BookingController.java index 6d9e0d0..5d1a56c 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingController.java +++ b/src/main/java/ru/practicum/shareit/booking/BookingController.java @@ -1,5 +1,6 @@ package ru.practicum.shareit.booking; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import ru.practicum.shareit.booking.dto.BookingRequestDto; @@ -16,9 +17,9 @@ public class BookingController { public static final String USER_ID = "X-Sharer-User-Id"; @PostMapping - public BookingResponseDto postBooking(@RequestBody BookingRequestDto booking, - @RequestHeader(USER_ID) Long bookerId) { - return bookingService.postBooking(booking, bookerId); + public BookingResponseDto addBooking(@RequestBody @Valid BookingRequestDto booking, + @RequestHeader(USER_ID) Long bookerId) { + return bookingService.addBooking(booking, bookerId); } @PatchMapping("/{bookingId}") @@ -29,13 +30,20 @@ public BookingResponseDto bookingApprove(@PathVariable Long bookingId, } @GetMapping("/{bookingId}") - public BookingResponseDto getBooking(@PathVariable Long bookingId) { - return bookingService.getBookingByBookingId(bookingId); + public BookingResponseDto getBooking(@PathVariable Long bookingId, + @RequestHeader(USER_ID) Long userId) { + return bookingService.getBookingByBookingId(bookingId, userId); } @GetMapping - public Collection getBookingsForUser( - @RequestHeader (USER_ID) Long userId) { - return bookingService.getBookingsForUser(userId); + public Collection getBookingsByUser(@RequestHeader (USER_ID) Long userId, + @RequestParam(name = "state", defaultValue = "all") String state) { + return bookingService.getBookingsByUser(userId, state); + } + + @GetMapping("/owner") + public Collection getBookingsByOwner(@RequestHeader (USER_ID) Long userId, + @RequestParam(name = "state", defaultValue = "all") String state) { + return bookingService.getBookingsByOwner(userId, state); } } diff --git a/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java index 6967cb1..829b7dd 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java @@ -11,6 +11,7 @@ import ru.practicum.shareit.booking.model.BookingStatus; import ru.practicum.shareit.exception.AnotherUserException; import ru.practicum.shareit.exception.NotFoundException; +import ru.practicum.shareit.exception.ValidationException; import ru.practicum.shareit.item.interfaces.ItemRepository; import ru.practicum.shareit.item.mapper.ItemMapper; import ru.practicum.shareit.item.model.Item; @@ -18,8 +19,10 @@ import ru.practicum.shareit.user.mapper.UserMapper; import ru.practicum.shareit.user.model.User; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; @Service @RequiredArgsConstructor @@ -35,30 +38,27 @@ public class BookingServiceImpl implements BookingServiceInterface { @Override - public BookingResponseDto postBooking(BookingRequestDto booking, Long bookerId) { + public BookingResponseDto addBooking(BookingRequestDto booking, Long bookerId) { Item item = itemStorage.findById(booking.getItemId()) .orElseThrow(() -> new NotFoundException("Item not found")); - if (item.getIsAvailable().equals(false)) { - throw new RuntimeException("Booking item is not available"); - } + User booker = userStorage.getUserByUserId(bookerId) + .orElseThrow(() -> new NotFoundException("User not found")); Booking saved = bookingMapper.bookingRequestDtoToBooking(booking); - saved.setBooker(userStorage.getUserByUserId(bookerId).get()); + saved.setBooker(booker); saved.setItem(item); - if (item.getIsAvailable()) { - saved.setStatus(BookingStatus.WAITING); - } else { + if (item.getIsAvailable().equals(false)) { saved.setStatus(BookingStatus.REJECTED); - throw new AnotherUserException("Booking item is rejected, item is not available"); + storage.save(saved); + throw new RuntimeException("Booking is rejected, item is not available"); + } else { + saved.setStatus(BookingStatus.WAITING); + storage.save(saved); } - storage.save(saved); - - BookingResponseDto responseDto = bookingMapper.bookingToBookingResponseDto(saved); - mapBookerAndItemToBooking(responseDto, saved); - return responseDto; + return mapBookerAndItemToBooking(saved); } @Override @@ -66,55 +66,133 @@ public BookingResponseDto bookingApprove(Long bookingId, Long ownerId, Boolean i Booking booking = bookingRepository.getBookingByBookingId(bookingId) .orElseThrow(() -> new NotFoundException("Booking not found")); - Item item = booking.getItem(); + Item item = itemStorage.getItemByItemId(booking.getItem().getItemId()) + .orElseThrow(() -> new NotFoundException("Item not found")); + if (!item.getOwner().getUserId().equals(ownerId)) { throw new AnotherUserException("You are not allowed to approve this booking"); } if (item.getIsAvailable().equals(false)) { booking.setStatus(BookingStatus.REJECTED); - throw new RuntimeException("Booking item is rejected"); + throw new ValidationException("Booking item is rejected"); } else { booking.setStatus(BookingStatus.APPROVED); + bookingRepository.save(booking); } - BookingResponseDto responseDto = bookingMapper.bookingToBookingResponseDto(booking); - mapBookerAndItemToBooking(responseDto, booking); - - return responseDto; + return mapBookerAndItemToBooking(booking); } @Override - public BookingResponseDto getBookingByBookingId(Long bookingId) { + public BookingResponseDto getBookingByBookingId(Long bookingId, Long userId) { Booking booking = bookingRepository.getBookingByBookingId(bookingId) .orElseThrow(() -> new NotFoundException("Booking not found")); - BookingResponseDto bookingDto = bookingMapper.bookingToBookingResponseDto(booking); + if(booking.getBooker().getUserId().equals(userId) || + booking.getItem().getOwner().getUserId().equals(userId)) { + return mapBookerAndItemToBooking(booking); + } else { + throw new AnotherUserException("You are not allowed to view this booking"); + } + } - mapBookerAndItemToBooking(bookingDto, booking); + @Override + public Collection getBookingsByUser(Long userId, String state) { + User user = userStorage.getUserByUserId(userId) + .orElseThrow(() -> new NotFoundException("User not found")); - return bookingDto; + LocalDateTime date = LocalDateTime.now(); + + Collection bookings = new ArrayList<>(); + + if (state.equalsIgnoreCase("ALL")) { + bookings = bookingRepository.getBookingsByBooker_UserId(userId); + + } else if (state.equalsIgnoreCase("CURRENT") || + state.equalsIgnoreCase("PAST") || + state.equalsIgnoreCase("FUTURE")) { + + bookings = getBookingsByTimeState(date, state).stream() + .filter(booking -> booking.getBooker().getUserId().equals(userId)) + .toList(); + + } else if (state.equalsIgnoreCase("WAITING") || + state.equalsIgnoreCase("REJECTED")) { + + if (state.equalsIgnoreCase("WAITING")) { + bookings = bookingRepository.getBookingsByBooker_UserIdAndStatus(userId, BookingStatus.WAITING); + } else { + bookings = bookingRepository.getBookingsByBooker_UserIdAndStatus(userId, BookingStatus.REJECTED); + } + } + + return bookings.stream() + .map(this::mapBookerAndItemToBooking) + .sorted(Comparator.comparing(BookingResponseDto::getStart)) + .toList() + .reversed(); } @Override - public Collection getBookingsForUser(Long userId) { + public Collection getBookingsByOwner(Long userId, String state) { User user = userStorage.getUserByUserId(userId) .orElseThrow(() -> new NotFoundException("User not found")); - Collection bookings = bookingRepository.getBookingsByBooker_UserId(user.getUserId()); - Collection bookingDtos = new ArrayList<>(); + Item item = itemStorage.getItemsByOwner_UserId(userId).stream() + .findFirst() + .orElseThrow(() -> new NotFoundException("User with userId = " + userId + " has no Item")); - for (Booking booking : bookings) { - BookingResponseDto bookingDto = bookingMapper.bookingToBookingResponseDto(booking); - mapBookerAndItemToBooking(bookingDto, booking); - bookingDtos.add(bookingDto); - } + LocalDateTime date = LocalDateTime.now(); + + Collection bookings = new ArrayList<>(); + + if (state.equalsIgnoreCase("ALL")) { + bookings = bookingRepository.getBookingsByOwnerId(userId); + } else if (state.equalsIgnoreCase("CURRENT") || + state.equalsIgnoreCase("PAST") || + state.equalsIgnoreCase("FUTURE")) { - return bookingDtos; + bookings = getBookingsByTimeState(date, state).stream() + .filter(booking -> booking.getItem().getOwner().getUserId().equals(userId)) + .toList(); + + } else if (state.equalsIgnoreCase("WAITING") || + state.equalsIgnoreCase("REJECTED")) { + + if (state.equalsIgnoreCase("WAITING")) { + bookings = bookingRepository.getBookingsByStatus(BookingStatus.WAITING).stream() + .filter(booking -> booking.getItem().getOwner().getUserId().equals(userId)) + .toList(); + } else { + bookings = bookingRepository.getBookingsByStatus(BookingStatus.REJECTED).stream() + .filter(booking -> booking.getItem().getOwner().getUserId().equals(userId)) + .toList(); + } + } + return bookings.stream() + .map(this::mapBookerAndItemToBooking) + .sorted(Comparator.comparing(BookingResponseDto::getStart)) + .toList() + .reversed(); } - private void mapBookerAndItemToBooking(BookingResponseDto bookingDto, Booking booking) { + + private BookingResponseDto mapBookerAndItemToBooking(Booking booking) { + BookingResponseDto bookingDto = bookingMapper.bookingToBookingResponseDto(booking); bookingDto.setBooker(userMapper.toUserBookingDto(booking.getBooker())); bookingDto.setItem(itemMapper.toItemBookerDto(booking.getItem())); + return bookingDto; + } + + private Collection getBookingsByTimeState(LocalDateTime date, String state) { + Collection bookings = new ArrayList<>(); + switch (state.toUpperCase()) { + case "CURRENT" -> bookings = bookingRepository.getBookingsByBooker_UserIdCurrent(date); + case "PAST" -> bookings = bookingRepository.getBookingsByBooker_UserIdPast(date); + case "FUTURE" -> bookings = bookingRepository.getBookingsByBooker_UserIdFuture(date); + } + return bookings; } } + diff --git a/src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java b/src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java index 8c4033a..0e94f98 100644 --- a/src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java +++ b/src/main/java/ru/practicum/shareit/booking/dto/BookingRequestDto.java @@ -28,7 +28,6 @@ public class BookingRequestDto { @NotNull private Long itemId; - @NotNull private Long bookerId; private BookingStatus status; diff --git a/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java index a1948c5..f5c6a0d 100644 --- a/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java +++ b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingRepository.java @@ -1,8 +1,11 @@ package ru.practicum.shareit.booking.intrfaces; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import ru.practicum.shareit.booking.model.Booking; +import ru.practicum.shareit.booking.model.BookingStatus; +import java.time.LocalDateTime; import java.util.Collection; import java.util.Optional; @@ -15,4 +18,20 @@ public interface BookingRepository extends JpaRepository { Collection getBookingsByBooker_UserId(Long bookerId); Collection getBookingsByItem_ItemId(Long itemId); + + @Query(value = "SELECT b FROM Booking b WHERE ?1 between b.start and b.end") + Collection getBookingsByBooker_UserIdCurrent(LocalDateTime date); + + @Query(value = "SELECT b FROM Booking b WHERE b.end < ?1") + Collection getBookingsByBooker_UserIdPast(LocalDateTime date); + + @Query(value = "SELECT b FROM Booking b WHERE b.start > ?1") + Collection getBookingsByBooker_UserIdFuture(LocalDateTime date); + + Collection getBookingsByBooker_UserIdAndStatus(Long bookerId, BookingStatus status); + + @Query(value = "SELECT b FROM Booking b JOIN Item i on b.item.itemId = i.itemId WHERE i.owner.userId = ?1") + Collection getBookingsByOwnerId(Long ownerId); + + Collection getBookingsByStatus(BookingStatus status); } diff --git a/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java index 55c627e..539d1cf 100644 --- a/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java +++ b/src/main/java/ru/practicum/shareit/booking/intrfaces/BookingServiceInterface.java @@ -6,11 +6,13 @@ import java.util.Collection; public interface BookingServiceInterface { - BookingResponseDto postBooking(BookingRequestDto booking, Long bookerId); + BookingResponseDto addBooking(BookingRequestDto booking, Long bookerId); BookingResponseDto bookingApprove(Long bookingId, Long ownerId, Boolean isAvailable); - BookingResponseDto getBookingByBookingId(Long bookingId); + BookingResponseDto getBookingByBookingId(Long bookingId, Long userId); - Collection getBookingsForUser(Long userId); + Collection getBookingsByUser(Long userId, String state); + + Collection getBookingsByOwner(Long userId, String state); } diff --git a/src/main/java/ru/practicum/shareit/item/ItemController.java b/src/main/java/ru/practicum/shareit/item/ItemController.java index 9404d6f..418f8b6 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemController.java +++ b/src/main/java/ru/practicum/shareit/item/ItemController.java @@ -34,8 +34,9 @@ public ItemResponseDto update(@RequestBody ItemRequestDto item, } @GetMapping("/{itemId}") - public ItemResponseDtoWithComments getItemById(@PathVariable Long itemId) { - return itemService.getItemById(itemId); + public ItemResponseDtoWithComments getItemById(@PathVariable Long itemId, + @RequestHeader(OWNER_ID) Long ownerId) { + return itemService.getItemById(itemId, ownerId); } @GetMapping diff --git a/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java index 29d56ac..9f6d1d7 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java @@ -2,7 +2,9 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import ru.practicum.shareit.booking.dto.BookingResponseDto; import ru.practicum.shareit.booking.intrfaces.BookingRepository; +import ru.practicum.shareit.booking.mapper.BookingMapper; import ru.practicum.shareit.booking.model.Booking; import ru.practicum.shareit.booking.model.BookingStatus; import ru.practicum.shareit.exception.AnotherUserException; @@ -20,8 +22,10 @@ import ru.practicum.shareit.user.mapper.UserMapper; import ru.practicum.shareit.user.model.User; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -37,6 +41,7 @@ public class ItemServiceImpl implements ItemServiceInterface { private final ItemMapper itemMapper; private final UserMapper userMapper; private final CommentMapper commentMapper; + private final BookingMapper bookingMapper; public ItemResponseDto createItem(ItemRequestDto item, Long ownerId) { if (ownerId == null) { @@ -50,25 +55,48 @@ public ItemResponseDto createItem(ItemRequestDto item, Long ownerId) { itemSaved.setOwner(owner); itemRepository.save(itemSaved); - ItemResponseDto responseDto = itemMapper.toItemResponseDto(itemSaved); - mapResponseDto(itemSaved, responseDto); - return responseDto; + return itemMapper.toItemResponseDto(itemSaved); } - public ItemResponseDtoWithComments getItemById(Long id) { - ItemResponseDto item = itemMapper.toItemResponseDto(itemRepository.getItemByItemId(id) - .orElseThrow(() -> new NotFoundException("Item with id " + id + " not found"))); + public ItemResponseDtoWithComments getItemById(Long itemId, Long ownerId) { + ItemResponseDto item = itemMapper.toItemResponseDto(itemRepository.getItemByItemId(itemId) + .orElseThrow(() -> new NotFoundException("Item with id " + itemId + " not found"))); - List comments = commentRepository.getCommentsByItem_ItemId(id).stream() + List comments = commentRepository.getCommentsByItem_ItemId(itemId).stream() .map(commentMapper::toCommentResponseDto) .collect(Collectors.toList()); ItemResponseDtoWithComments itemDto = itemMapper.toItemResponseDtoWithComments( - itemRepository.getItemByItemId(id).get()); + itemRepository.getItemByItemId(itemId).get()); itemDto.setComments(comments); + if (item.getOwnerId().equals(ownerId)) { + List bookingsLast= bookingRepository.getBookingsByItem_ItemId(itemId).stream() + .filter(booking -> booking.getEnd().isBefore(LocalDateTime.now())) + .toList(); + if (!bookingsLast.isEmpty()) { + BookingResponseDto lastBooking = bookingMapper.bookingToBookingResponseDto(bookingsLast.stream() + .sorted(Comparator.comparing(Booking::getEnd)) + .toList() + .getLast()); + itemDto.setLastBooking(lastBooking); + } + + List bookingsNext = bookingRepository.getBookingsByItem_ItemId(itemId).stream() + .filter(booking -> booking.getStart().isAfter(LocalDateTime.now())) + .toList(); + + if (!bookingsNext.isEmpty()) { + BookingResponseDto nextBooking = bookingMapper.bookingToBookingResponseDto(bookingsNext.stream() + .sorted(Comparator.comparing(Booking::getStart)) + .toList() + .getFirst()); + itemDto.setNextBooking(nextBooking); + } + } return itemDto; + } public ItemResponseDto updateItem(Long itemId, @@ -98,10 +126,7 @@ public ItemResponseDto updateItem(Long itemId, throw new AnotherUserException("User with id " + ownerId + " is not owner of this Item"); } - ItemResponseDto responseDto = itemMapper.toItemResponseDto(foundItem); - mapResponseDto(foundItem, responseDto); - - return responseDto; + return itemMapper.toItemResponseDto(foundItem); } public Collection getAllItemsForOwner(Long ownerId) { @@ -133,27 +158,15 @@ public CommentResponseCreatedDto addComment(Long commentatorId, .findFirst() .orElseThrow(() -> new NotFoundException("Booking with bookerId " + commentatorId + " not found")); - if (!booking.getEnd().isBefore(commentDto.getDate())) { - throw new ValidationException("Booking end date cannot be before comment date"); - } - - if (booking.getStatus().equals(BookingStatus.APPROVED)) { - throw new ValidationException("Booking status cannot be APPROVED"); - } + if (booking.getEnd().isBefore(commentDto.getDate()) && booking.getStatus().equals(BookingStatus.APPROVED)) { + Comment comment = commentMapper.toComment(commentDto); + comment.setItem(itemRepository.getItemByItemId(itemId).get()); + comment.setAuthor(userRepository.getUserByUserId(commentatorId).get()); - Comment comment = commentMapper.toComment(commentDto); - comment.setItem(itemRepository.getItemByItemId(itemId).get()); - comment.setAuthor(userRepository.getUserByUserId(commentatorId).get()); + return commentMapper.toCommentResponseCreatedDto(commentRepository.save(comment)); - return commentMapper.toCommentResponseCreatedDto( - commentRepository.save(comment)); - } - - private void mapResponseDto(Item item, ItemResponseDto itemResponseDto) { - itemResponseDto.setOwnerId(item.getOwner().getUserId()); - - if (item.getItemRequest() != null) { - itemResponseDto.setRequestId(item.getItemRequest().getItemRequestId()); + } else { + throw new ValidationException("Comment cannot be added to the booking"); } } diff --git a/src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java b/src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java index 53e00e3..63d3bd6 100644 --- a/src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java +++ b/src/main/java/ru/practicum/shareit/item/dto/ItemResponseDtoWithComments.java @@ -5,8 +5,8 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import ru.practicum.shareit.booking.dto.BookingResponseDto; -import java.time.LocalDateTime; import java.util.List; @Data @@ -32,9 +32,9 @@ public class ItemResponseDtoWithComments { private Long requestId; - private LocalDateTime lastBooking; + private BookingResponseDto lastBooking; - private LocalDateTime nextBooking; + private BookingResponseDto nextBooking; private List comments; } diff --git a/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java b/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java index f09f8d5..722ac82 100644 --- a/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java +++ b/src/main/java/ru/practicum/shareit/item/interfaces/ItemServiceInterface.java @@ -9,7 +9,7 @@ public interface ItemServiceInterface { ItemResponseDto createItem(ItemRequestDto item, Long ownerId); - ItemResponseDtoWithComments getItemById(Long id); + ItemResponseDtoWithComments getItemById(Long id, Long ownerId); ItemResponseDto updateItem(Long itemId, ItemRequestDto item, Long ownerId); From 697315ba71471bde056d52bdf90f7edf4709bc45 Mon Sep 17 00:00:00 2001 From: NadezhdaTA Date: Sun, 29 Jun 2025 15:31:06 +0400 Subject: [PATCH 9/9] =?UTF-8?q?=D0=A4=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=2015?= =?UTF-8?q?=D0=B3=D0=BE=20(=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=20=D1=81=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=BD?= =?UTF-8?q?=D0=BE=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=D0=BC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/ru/practicum/shareit/booking/BookingServiceImpl.java | 2 +- src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java b/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java index 829b7dd..4bc3009 100644 --- a/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/booking/BookingServiceImpl.java @@ -89,7 +89,7 @@ public BookingResponseDto getBookingByBookingId(Long bookingId, Long userId) { Booking booking = bookingRepository.getBookingByBookingId(bookingId) .orElseThrow(() -> new NotFoundException("Booking not found")); - if(booking.getBooker().getUserId().equals(userId) || + if (booking.getBooker().getUserId().equals(userId) || booking.getItem().getOwner().getUserId().equals(userId)) { return mapBookerAndItemToBooking(booking); } else { diff --git a/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java b/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java index 9f6d1d7..3b77efe 100644 --- a/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java +++ b/src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java @@ -72,7 +72,7 @@ public ItemResponseDtoWithComments getItemById(Long itemId, Long ownerId) { itemDto.setComments(comments); if (item.getOwnerId().equals(ownerId)) { - List bookingsLast= bookingRepository.getBookingsByItem_ItemId(itemId).stream() + List bookingsLast = bookingRepository.getBookingsByItem_ItemId(itemId).stream() .filter(booking -> booking.getEnd().isBefore(LocalDateTime.now())) .toList(); if (!bookingsLast.isEmpty()) {