Repository: BuldakovMikhail/bmstu_team_development
Pull request #32: Feature/22 create api
Author: login: needsomesleeptd
Created: 2025-04-10T20:56:48Z | Merged: 2025-04-11T19:24:33Z

Не заметил что мердж из #27 идет в таску #22  а не в мастер, желательно долить изменения 


Diff:
diff --git a/go.mod b/go.mod
index 1263e10..53cade0 100644
--- a/go.mod
+++ b/go.mod
@@ -4,23 +4,27 @@ go 1.23.8
 
 require (
 	github.com/go-chi/chi/v5 v5.2.1
+	github.com/go-chi/render v1.0.3
+	github.com/google/uuid v1.6.0
 	github.com/swaggo/http-swagger v1.3.4
 	github.com/swaggo/swag v1.16.4
+	gorm.io/gorm v1.25.12
 )
 
 require (
 	github.com/KyleBanks/depth v1.2.1 // indirect
+	github.com/ajg/form v1.5.1 // indirect
 	github.com/go-openapi/jsonpointer v0.21.1 // indirect
 	github.com/go-openapi/jsonreference v0.21.0 // indirect
 	github.com/go-openapi/spec v0.21.0 // indirect
 	github.com/go-openapi/swag v0.23.1 // indirect
-	github.com/google/uuid v1.6.0 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/mailru/easyjson v0.9.0 // indirect
 	github.com/swaggo/files v1.0.1 // indirect
 	golang.org/x/net v0.39.0 // indirect
-	golang.org/x/sys v0.32.0 // indirect
+	golang.org/x/text v0.24.0 // indirect
 	golang.org/x/tools v0.32.0 // indirect
-	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/go.sum b/go.sum
index e7f44a2..d24072a 100644
--- a/go.sum
+++ b/go.sum
@@ -1,89 +1,69 @@
 github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
 github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
-github.com/agiledragon/gomonkey/v2 v2.3.1 h1:k+UnUY0EMNYUFUAQVETGY9uUTxjMdnUkP0ARyJS1zzs=
-github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
+github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
 github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
-github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
-github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
+github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
 github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
 github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
-github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
-github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
 github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
 github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
-github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ=
-github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
 github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
 github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
-github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
-github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
-github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
 github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
 github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
-github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
 github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
 github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE=
-github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
+github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
 github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
 github.com/swaggo/http-swagger v1.3.4 h1:q7t/XLx0n15H1Q9/tk3Y9L4n210XzJF5WtnDX64a5ww=
 github.com/swaggo/http-swagger v1.3.4/go.mod h1:9dAh0unqMBAlbp1uE2Uc2mQTxNMU/ha4UbucIg1MFkQ=
-github.com/swaggo/swag v1.8.1 h1:JuARzFX1Z1njbCGz+ZytBR15TFJwF2Q7fu8puJHhQYI=
-github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ=
 github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
 github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
+golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
 golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
 golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
+golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
-golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -91,22 +71,18 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
+golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
 golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
-gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
+gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
diff --git a/internal/api/handlers/category.go b/internal/api/handlers/category.go
index 03b0441..ccdeb64 100644
--- a/internal/api/handlers/category.go
+++ b/internal/api/handlers/category.go
@@ -10,12 +10,8 @@ type CategoryBody struct {
 	Name string `json:"name"`
 }
 
-type CategoryId struct {
-	Id uuid.UUID `json:"id"`
-}
-
 type CategoryResponse struct {
-	CategoryId
+	ID uuid.UUID `json:"id"`
 	CategoryBody
 }
 
diff --git a/internal/api/handlers/task.go b/internal/api/handlers/task.go
index 4d12e77..48e0d7a 100644
--- a/internal/api/handlers/task.go
+++ b/internal/api/handlers/task.go
@@ -1,8 +1,14 @@
 package handlers
 
 import (
+	"context"
 	"net/http"
+	"time"
+	"todolist/internal/models"
+	"todolist/internal/pkg/response"
 
+	"github.com/go-chi/chi/v5"
+	"github.com/go-chi/render"
 	"github.com/google/uuid"
 )
 
@@ -12,13 +18,13 @@ type TaskBody struct {
 }
 
 type TaskMeta struct {
-	Id     uuid.UUID `json:"id"`
+	ID     uuid.UUID `json:"id"`
 	IsDone bool      `json:"is_done"`
 }
 
 type TaskRequest struct {
 	TaskBody
-	CategoryIds []CategoryId `json:"category_ids"`
+	CategoryIds []uuid.UUID `json:"category_ids"`
 }
 
 type TaskResponse struct {
@@ -27,11 +33,22 @@ type TaskResponse struct {
 	CategoriesResponse
 }
 
+type TaskShortResponse struct {
+	TaskMeta
+	Title string `json:"title"`
+}
+
 type TasksList struct {
-	List []struct {
-		TaskMeta
-		Title string `json:"title"`
-	} `json:"list"`
+	List []TaskShortResponse `json:"list"`
+}
+
+type TaskProvider interface {
+	CreateTask(ctx context.Context, body *models.TaskBody) error
+	Update(ctx context.Context, id uuid.UUID, body *models.TaskBody) error
+	GetByID(ctx context.Context, id uuid.UUID) (*models.TaskFullInfo, error)
+	GetAll(ctx context.Context, pageIndex, recordsPerPage int) ([]models.TaskShortInfo, error)
+	Delete(ctx context.Context, id uuid.UUID) error
+	ToggleDone(ctx context.Context, id uuid.UUID) error
 }
 
 // @Summary CreateTask
@@ -43,13 +60,32 @@ type TasksList struct {
 // @Produce  json
 // @Param input body TaskRequest true "task info"
 // @Success 200
-// @Failure 400,404 {object} response.Response
+// @Failure 400 {object} response.Response
 // @Failure 500 {object} response.Response
 // @Failure default {object} response.Response
 // @Router /api/v1/task [post]
-func CreateTask() http.HandlerFunc {
+func CreateTask(taskProvider TaskProvider, timeout time.Duration) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
+		var req TaskRequest
+		err := render.DecodeJSON(r.Body, &req)
+		if err != nil {
+			render.Status(r, http.StatusBadRequest)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
+
+		ctx := r.Context()
+		ctx, cancel := context.WithTimeout(ctx, timeout)
+		defer cancel()
+
+		err = taskProvider.CreateTask(ctx, toModelTaskBody(req))
+		if err != nil {
+			render.Status(r, http.StatusInternalServerError)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
 
+		render.Status(r, http.StatusOK)
 	}
 }
 
@@ -63,13 +99,41 @@ func CreateTask() http.HandlerFunc {
 // @Param input body TaskRequest true "task info"
 // @Param id   path      string  true  "Task ID (UUID)"
 // @Success 200
-// @Failure 400,404 {object} response.Response
+// @Failure 400 {object} response.Response
 // @Failure 500 {object} response.Response
 // @Failure default {object} response.Response
 // @Router /api/v1/task/{id} [put]
-func EditTask() http.HandlerFunc {
+func EditTask(taskProvider TaskProvider, timeout time.Duration) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
+		id := chi.URLParam(r, "id")
+
+		uuid, err := uuid.Parse(id)
+		if err != nil {
+			render.Status(r, http.StatusBadRequest)
+			render.JSON(w, r, response.Error("invalid UUID"))
+			return
+		}
 
+		var req TaskRequest
+		err = render.DecodeJSON(r.Body, &req)
+		if err != nil {
+			render.Status(r, http.StatusBadRequest)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
+
+		ctx := r.Context()
+		ctx, cancel := context.WithTimeout(ctx, timeout)
+		defer cancel()
+
+		err = taskProvider.Update(ctx, uuid, toModelTaskBody(req))
+		if err != nil {
+			render.Status(r, http.StatusInternalServerError)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
+
+		render.Status(r, http.StatusOK)
 	}
 }
 
@@ -82,13 +146,32 @@ func EditTask() http.HandlerFunc {
 // @Produce  json
 // @Param id   path      string  true  "Task ID (UUID)"
 // @Success 200 {object} TaskResponse
-// @Failure 400,404 {object} response.Response
+// @Failure 400 {object} response.Response
 // @Failure 500 {object} response.Response
 // @Failure default {object} response.Response
 // @Router /api/v1/task/{id} [get]
-func GetTask() http.HandlerFunc {
+func GetTask(taskProvider TaskProvider, timeout time.Duration) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
+		id := chi.URLParam(r, "id")
+		uuid, err := uuid.Parse(id)
+		if err != nil {
+			render.Status(r, http.StatusBadRequest)
+			render.JSON(w, r, response.Error("invalid UUID"))
+			return
+		}
+
+		ctx := r.Context()
+		ctx, cancel := context.WithTimeout(ctx, timeout)
+		defer cancel()
 
+		task, err := taskProvider.GetByID(ctx, uuid)
+		if err != nil {
+			render.Status(r, http.StatusInternalServerError)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
+
+		render.JSON(w, r, toTaskResponse(task))
 	}
 }
 
@@ -101,13 +184,32 @@ func GetTask() http.HandlerFunc {
 // @Produce  json
 // @Param input body Pagination true "pagination info"
 // @Success 200 {object} TasksList
-// @Failure 400,404 {object} response.Response
+// @Failure 400 {object} response.Response
 // @Failure 500 {object} response.Response
 // @Failure default {object} response.Response
 // @Router /api/v1/task/all [post]
-func GetAllTasks() http.HandlerFunc {
+func GetAllTasks(taskProvider TaskProvider, timeout time.Duration) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
+		var req Pagination
+		err := render.DecodeJSON(r.Body, &req)
+		if err != nil {
+			render.Status(r, http.StatusBadRequest)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
+
+		ctx := r.Context()
+		ctx, cancel := context.WithTimeout(ctx, timeout)
+		defer cancel()
+
+		tasks, err := taskProvider.GetAll(ctx, req.PageIndex, req.RecordsPerPage)
+		if err != nil {
+			render.Status(r, http.StatusInternalServerError)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
 
+		render.JSON(w, r, toTaskList(tasks))
 	}
 }
 
@@ -120,13 +222,32 @@ func GetAllTasks() http.HandlerFunc {
 // @Produce  json
 // @Param id   path      string  true  "Task ID (UUID)"
 // @Success 200
-// @Failure 400,404 {object} response.Response
+// @Failure 400 {object} response.Response
 // @Failure 500 {object} response.Response
 // @Failure default {object} response.Response
 // @Router /api/v1/task/{id} [post]
-func ToggleReadinessTask() http.HandlerFunc {
+func ToggleReadinessTask(taskProvider TaskProvider, timeout time.Duration) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
+		id := chi.URLParam(r, "id")
+		uuid, err := uuid.Parse(id)
+		if err != nil {
+			render.Status(r, http.StatusBadRequest)
+			render.JSON(w, r, response.Error("invalid UUID"))
+			return
+		}
+
+		ctx := r.Context()
+		ctx, cancel := context.WithTimeout(ctx, timeout)
+		defer cancel()
+
+		err = taskProvider.ToggleDone(ctx, uuid)
+		if err != nil {
+			render.Status(r, http.StatusInternalServerError)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
 
+		render.Status(r, http.StatusOK)
 	}
 }
 
@@ -143,8 +264,77 @@ func ToggleReadinessTask() http.HandlerFunc {
 // @Failure 500 {object} response.Response
 // @Failure default {object} response.Response
 // @Router /api/v1/task/{id} [delete]
-func DeleteTask() http.HandlerFunc {
+func DeleteTask(taskProvider TaskProvider, timeout time.Duration) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
+		id := chi.URLParam(r, "id")
+		uuid, err := uuid.Parse(id)
+		if err != nil {
+			render.Status(r, http.StatusBadRequest)
+			render.JSON(w, r, response.Error("invalid UUID"))
+			return
+		}
+
+		ctx := r.Context()
+		ctx, cancel := context.WithTimeout(ctx, timeout)
+		defer cancel()
+
+		err = taskProvider.Delete(ctx, uuid)
+		if err != nil {
+			render.Status(r, http.StatusInternalServerError)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
+
+		render.Status(r, http.StatusOK)
+	}
+}
+
+func toModelTaskBody(task TaskRequest) *models.TaskBody {
+	return &models.TaskBody{
+		Title:       task.Title,
+		Description: task.Description,
+	}
+}
+
+func toTaskResponse(task *models.TaskFullInfo) *TaskResponse {
+	categoryResponse := make([]CategoryResponse, len(task.Categories))
+	for i, category := range task.Categories {
+		categoryResponse[i] = CategoryResponse{
+			ID: category.ID,
+			CategoryBody: CategoryBody{
+				Name: category.Name,
+			},
+		}
+	}
+
+	return &TaskResponse{
+		TaskMeta: TaskMeta{
+			ID:     task.ID,
+			IsDone: task.IsDone,
+		},
+		TaskBody: TaskBody{
+			Title:       task.Title,
+			Description: task.Description,
+		},
+		CategoriesResponse: CategoriesResponse{
+			Categories: categoryResponse,
+		},
+	}
+}
+
+func toTaskList(tasks []models.TaskShortInfo) TasksList {
+	list := make([]TaskShortResponse, 0, len(tasks))
+	for _, task := range tasks {
+		list = append(list, TaskShortResponse{
+			Title: task.Title,
+			TaskMeta: TaskMeta{
+				ID:     task.ID,
+				IsDone: task.IsDone,
+			},
+		})
+	}
 
+	return TasksList{
+		List: list,
 	}
 }
diff --git a/internal/models/category.go b/internal/models/category.go
new file mode 100644
index 0000000..4c53ccf
--- /dev/null
+++ b/internal/models/category.go
@@ -0,0 +1,8 @@
+package models
+
+import "github.com/google/uuid"
+
+type Category struct {
+	ID   uuid.UUID
+	Name string
+}
diff --git a/internal/models/task.go b/internal/models/task.go
new file mode 100644
index 0000000..3929018
--- /dev/null
+++ b/internal/models/task.go
@@ -0,0 +1,22 @@
+package models
+
+import "github.com/google/uuid"
+
+type TaskBody struct {
+	Title       string
+	Description string
+}
+
+type TaskShortInfo struct {
+	ID     uuid.UUID
+	IsDone bool
+	Title  string
+}
+
+type TaskFullInfo struct {
+	ID          uuid.UUID
+	Title       string
+	Description string
+	IsDone      bool
+	Categories  []Category
+}


Reviews:
user: login: needsomesleeptd
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T10:00:26Z
user: login: needsomesleeptd
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T10:01:07Z
user: login: BuldakovMikhail
state: COMMENTED
author_association: OWNER
submitted_at: 2025-04-11T19:22:28Z
user: login: BuldakovMikhail
state: APPROVED
author_association: OWNER
submitted_at: 2025-04-11T19:22:52Z

Review comments:
diff_hunk: @@ -101,13 +184,32 @@ func GetTask() http.HandlerFunc {
 // @Produce  json
 // @Param input body Pagination true "pagination info"
 // @Success 200 {object} TasksList
-// @Failure 400,404 {object} response.Response
+// @Failure 400 {object} response.Response
 // @Failure 500 {object} response.Response
 // @Failure default {object} response.Response
 // @Router /api/v1/task/all [post]
-func GetAllTasks() http.HandlerFunc {
+func GetAllTasks(taskProvider TaskProvider, timeout time.Duration) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
+		var req Pagination
+		err := render.DecodeJSON(r.Body, &req)
+		if err != nil {
+			render.Status(r, http.StatusBadRequest)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
+
+		ctx := r.Context()
+		ctx, cancel := context.WithTimeout(ctx, timeout)
+		defer cancel()
+
+		tasks, err := taskProvider.GetAll(ctx, req.PageIndex, req.RecordsPerPage)
+		if err != nil {
+			render.Status(r, http.StatusInternalServerError)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
 
+		render.JSON(w, r, tasks)
path: internal/api/handlers/task.go
user: login: needsomesleeptd
body: Полагаю вот здесь нужно привести tasks все таки к DTO объекту с json тэгами
created_at: 2025-04-11T10:00:26Z
author_association: COLLABORATOR
diff_hunk: @@ -101,13 +184,32 @@ func GetTask() http.HandlerFunc {
 // @Produce  json
 // @Param input body Pagination true "pagination info"
 // @Success 200 {object} TasksList
-// @Failure 400,404 {object} response.Response
+// @Failure 400 {object} response.Response
 // @Failure 500 {object} response.Response
 // @Failure default {object} response.Response
 // @Router /api/v1/task/all [post]
-func GetAllTasks() http.HandlerFunc {
+func GetAllTasks(taskProvider TaskProvider, timeout time.Duration) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
+		var req Pagination
+		err := render.DecodeJSON(r.Body, &req)
+		if err != nil {
+			render.Status(r, http.StatusBadRequest)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
+
+		ctx := r.Context()
+		ctx, cancel := context.WithTimeout(ctx, timeout)
+		defer cancel()
+
+		tasks, err := taskProvider.GetAll(ctx, req.PageIndex, req.RecordsPerPage)
+		if err != nil {
+			render.Status(r, http.StatusInternalServerError)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
 
+		render.JSON(w, r, tasks)
path: internal/api/handlers/task.go
user: login: needsomesleeptd
body: Забыл заюзать toTaskList
created_at: 2025-04-11T10:01:07Z
author_association: COLLABORATOR
diff_hunk: @@ -101,13 +184,32 @@ func GetTask() http.HandlerFunc {
 // @Produce  json
 // @Param input body Pagination true "pagination info"
 // @Success 200 {object} TasksList
-// @Failure 400,404 {object} response.Response
+// @Failure 400 {object} response.Response
 // @Failure 500 {object} response.Response
 // @Failure default {object} response.Response
 // @Router /api/v1/task/all [post]
-func GetAllTasks() http.HandlerFunc {
+func GetAllTasks(taskProvider TaskProvider, timeout time.Duration) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
+		var req Pagination
+		err := render.DecodeJSON(r.Body, &req)
+		if err != nil {
+			render.Status(r, http.StatusBadRequest)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
+
+		ctx := r.Context()
+		ctx, cancel := context.WithTimeout(ctx, timeout)
+		defer cancel()
+
+		tasks, err := taskProvider.GetAll(ctx, req.PageIndex, req.RecordsPerPage)
+		if err != nil {
+			render.Status(r, http.StatusInternalServerError)
+			render.JSON(w, r, response.Error(err.Error()))
+			return
+		}
 
+		render.JSON(w, r, tasks)
path: internal/api/handlers/task.go
user: login: BuldakovMikhail
body: поправил
created_at: 2025-04-11T19:22:28Z
author_association: OWNER

PR comments:
user: login: BuldakovMikhail
created_at: 2025-04-11T18:53:03Z
body: > Не заметил что мердж из #27 идет в таску #22 а не в мастер, желательно долить изменения

не совсем понял что ты имеешь ввиду? 
author_association: OWNER
user: login: needsomesleeptd
created_at: 2025-04-11T19:05:59Z
body: Я сначала влил эту ветку в мастер, а потом твои юзаем в в нее , то есть в подбил в неверной последовательности. Поэтому сейчас нужно всерджить эту, измененную ветку
author_association: COLLABORATOR