From b34621051b6fdf061f28dabb3465f751ef35a454 Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 18:46:34 +0330 Subject: [PATCH 01/18] Upgrade to go 1.22 --- .github/workflows/go.yml | 2 +- src/go.mod | 2 +- src/go.sum | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 8b44a43..f5398ae 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: 1.22 - name: Build run: cd src && go mod download && go build -v cmd/main.go diff --git a/src/go.mod b/src/go.mod index 39dfdbd..60b24fa 100644 --- a/src/go.mod +++ b/src/go.mod @@ -1,6 +1,6 @@ module github.com/naeemaei/golang-clean-web-api -go 1.19 +go 1.22 require ( github.com/didip/tollbooth v4.0.2+incompatible diff --git a/src/go.sum b/src/go.sum index 3c5f633..6a1a881 100644 --- a/src/go.sum +++ b/src/go.sum @@ -19,15 +19,18 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/didip/tollbooth v4.0.2+incompatible h1:fVSa33JzSz0hoh2NxpwZtksAzAgd7zjmGO20HCZtF4M= github.com/didip/tollbooth v4.0.2+incompatible/go.mod h1:A9b0665CE6l1KmzpDws2++elm/CsuWBMa5Jv4WY0PEY= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= @@ -43,6 +46,7 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh 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-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -59,6 +63,7 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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= @@ -85,6 +90,7 @@ github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZX github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -123,6 +129,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= @@ -132,6 +139,7 @@ github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5E github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -174,6 +182,7 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= @@ -189,6 +198,7 @@ golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjs golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -242,6 +252,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= From 3e41b29f29f639fed513d295be66dd55a91295ae Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 18:47:00 +0330 Subject: [PATCH 02/18] Remove services --- src/services/base_service.go | 263 ------------------ src/services/car_model_color_service.go | 52 ---- src/services/car_model_comment_service.go | 54 ---- src/services/car_model_image_service.go | 52 ---- .../car_model_price_history_service.go | 49 ---- src/services/car_model_property_service.go | 52 ---- src/services/car_model_service.go | 60 ---- src/services/car_model_year_service.go | 52 ---- src/services/car_type_service.go | 49 ---- src/services/city_service.go | 52 ---- src/services/color_service.go | 49 ---- src/services/company_service.go | 52 ---- src/services/country_service.go | 50 ---- src/services/file_service.go | 50 ---- src/services/gearbox_service.go | 49 ---- src/services/otp_Service.go | 69 ----- src/services/property_category_service.go | 50 ---- src/services/property_service.go | 50 ---- src/services/token_service.go | 107 ------- src/services/user_service.go | 258 ----------------- src/services/year_service.go | 49 ---- 21 files changed, 1568 deletions(-) delete mode 100644 src/services/base_service.go delete mode 100644 src/services/car_model_color_service.go delete mode 100644 src/services/car_model_comment_service.go delete mode 100644 src/services/car_model_image_service.go delete mode 100644 src/services/car_model_price_history_service.go delete mode 100644 src/services/car_model_property_service.go delete mode 100644 src/services/car_model_service.go delete mode 100644 src/services/car_model_year_service.go delete mode 100644 src/services/car_type_service.go delete mode 100644 src/services/city_service.go delete mode 100644 src/services/color_service.go delete mode 100644 src/services/company_service.go delete mode 100644 src/services/country_service.go delete mode 100644 src/services/file_service.go delete mode 100644 src/services/gearbox_service.go delete mode 100644 src/services/otp_Service.go delete mode 100644 src/services/property_category_service.go delete mode 100644 src/services/property_service.go delete mode 100644 src/services/token_service.go delete mode 100644 src/services/user_service.go delete mode 100644 src/services/year_service.go diff --git a/src/services/base_service.go b/src/services/base_service.go deleted file mode 100644 index 3720fec..0000000 --- a/src/services/base_service.go +++ /dev/null @@ -1,263 +0,0 @@ -package services - -import ( - "context" - "database/sql" - "fmt" - "math" - "reflect" - "strings" - "time" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/common" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/constants" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" - "github.com/naeemaei/golang-clean-web-api/pkg/metrics" - "github.com/naeemaei/golang-clean-web-api/pkg/service_errors" - "gorm.io/gorm" -) - -const softDeleteExp string = "id = ? and deleted_by is null" -type preload struct { - string -} - -type BaseService[T any, Tc any, Tu any, Tr any] struct { - Database *gorm.DB - Logger logging.Logger - Preloads []preload -} - -func NewBaseService[T any, Tc any, Tu any, Tr any](cfg *config.Config) *BaseService[T, Tc, Tu, Tr] { - return &BaseService[T, Tc, Tu, Tr]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - } -} - -func (s *BaseService[T, Tc, Tu, Tr]) Create(ctx context.Context, req *Tc) (*Tr, error) { - - model, _ := common.TypeConverter[T](req) - tx := s.Database.WithContext(ctx).Begin() - err := tx. - Create(model). - Error - if err != nil { - tx.Rollback() - s.Logger.Error(logging.Postgres, logging.Insert, err.Error(), nil) - metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "Create", "Failed").Inc() - return nil, err - } - tx.Commit() - bm, _ := common.TypeConverter[models.BaseModel](model) - metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "Create", "Success").Inc() - return s.GetById(ctx, bm.Id) -} - -func (s *BaseService[T, Tc, Tu, Tr]) Update(ctx context.Context, id int, req *Tu) (*Tr, error) { - - updateMap, _ := common.TypeConverter[map[string]interface{}](req) - snakeMap := map[string]interface{}{} - for k, v := range *updateMap { - snakeMap[common.ToSnakeCase(k)] = v - } - snakeMap["modified_by"] = &sql.NullInt64{Int64: int64(ctx.Value(constants.UserIdKey).(float64)), Valid: true} - snakeMap["modified_at"] = sql.NullTime{Valid: true, Time: time.Now().UTC()} - model := new(T) - tx := s.Database.WithContext(ctx).Begin() - if err := tx.Model(model). - Where(softDeleteExp, id). - Updates(snakeMap). - Error; err != nil { - tx.Rollback() - s.Logger.Error(logging.Postgres, logging.Update, err.Error(), nil) - metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "Update", "Failed").Inc() - return nil, err - } - tx.Commit() - metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "Update", "Success").Inc() - return s.GetById(ctx, id) - -} - -func (s *BaseService[T, Tc, Tu, Tr]) Delete(ctx context.Context, id int) error { - tx := s.Database.WithContext(ctx).Begin() - - model := new(T) - - deleteMap := map[string]interface{}{ - "deleted_by": &sql.NullInt64{Int64: int64(ctx.Value(constants.UserIdKey).(float64)), Valid: true}, - "deleted_at": sql.NullTime{Valid: true, Time: time.Now().UTC()}, - } - - if ctx.Value(constants.UserIdKey) == nil { - return &service_errors.ServiceError{EndUserMessage: service_errors.PermissionDenied} - } - if cnt := tx. - Model(model). - Where(softDeleteExp, id). - Updates(deleteMap). - RowsAffected; cnt == 0 { - tx.Rollback() - s.Logger.Error(logging.Postgres, logging.Update, service_errors.RecordNotFound, nil) - metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "Delete", "Failed").Inc() - return &service_errors.ServiceError{EndUserMessage: service_errors.RecordNotFound} - } - tx.Commit() - metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "Delete", "Success").Inc() - return nil -} - -func (s *BaseService[T, Tc, Tu, Tr]) GetById(ctx context.Context, id int) (*Tr, error) { - model := new(T) - db := Preload(s.Database, s.Preloads) - err := db. - Where(softDeleteExp, id). - First(model). - Error - if err != nil { - metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "GetById", "Failed").Inc() - return nil, err - } - metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "GetById", "Success").Inc() - return common.TypeConverter[Tr](model) -} - -func (s *BaseService[T, Tc, Tu, Tr]) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[Tr], error) { - res, err := Paginate[T, Tr](req, s.Preloads, s.Database) - if err != nil { - metrics.DbCall.WithLabelValues(reflect.TypeOf(*new(T)).String(), "GetByFilter", "Failed").Inc() - return nil, err - } - metrics.DbCall.WithLabelValues(reflect.TypeOf(*new(T)).String(), "GetByFilter", "Success").Inc() - return res, nil -} - -func NewPagedList[T any](items *[]T, count int64, pageNumber int, pageSize int64) *dto.PagedList[T] { - pl := &dto.PagedList[T]{ - PageNumber: pageNumber, - TotalRows: count, - Items: items, - } - pl.TotalPages = int(math.Ceil(float64(count) / float64(pageSize))) - pl.HasNextPage = pl.PageNumber < pl.TotalPages - pl.HasPreviousPage = pl.PageNumber > 1 - - return pl -} - -// Paginate -func Paginate[T any, Tr any](pagination *dto.PaginationInputWithFilter, preloads []preload, db *gorm.DB) (*dto.PagedList[Tr], error) { - model := new(T) - var items *[]T - var rItems *[]Tr - db = Preload(db, preloads) - query := getQuery[T](&pagination.DynamicFilter) - sort := getSort[T](&pagination.DynamicFilter) - - var totalRows int64 = 0 - - db. - Model(model). - Where(query). - Count(&totalRows) - - err := db. - Where(query). - Offset(pagination.GetOffset()). - Limit(pagination.GetPageSize()). - Order(sort). - Find(&items). - Error - - if err != nil { - return nil, err - } - rItems, err = common.TypeConverter[[]Tr](items) - if err != nil { - return nil, err - } - return NewPagedList(rItems, totalRows, pagination.PageNumber, int64(pagination.PageSize)), err - -} - -// getQuery -func getQuery[T any](filter *dto.DynamicFilter) string { - t := new(T) - typeT := reflect.TypeOf(*t) - query := make([]string, 0) - query = append(query, "deleted_by is null") - if filter.Filter != nil { - for name, filter := range filter.Filter { - if fld, ok := typeT.FieldByName(name); ok{ - query = append(query, generateDynamicFilter(fld, filter)) - } - } - } - return strings.Join(query, " AND ") -} - -func generateDynamicFilter(fld reflect.StructField, filter dto.Filter) string { - conditionQuery := "" - fld.Name = common.ToSnakeCase(fld.Name) - switch filter.Type { - case "contains": - conditionQuery = fmt.Sprintf("%s ILike '%%%s%%'", fld.Name, filter.From) - case "notContains": - conditionQuery = fmt.Sprintf("%s not ILike '%%%s%%'", fld.Name, filter.From) - case "startsWith": - conditionQuery = fmt.Sprintf("%s ILike '%s%%'", fld.Name, filter.From) - case "endsWith": - conditionQuery = fmt.Sprintf("%s ILike '%%%s'", fld.Name, filter.From) - case "equals": - conditionQuery = fmt.Sprintf("%s = '%s'", fld.Name, filter.From) - case "notEqual": - conditionQuery = fmt.Sprintf("%s != '%s'", fld.Name, filter.From) - case "lessThan": - conditionQuery = fmt.Sprintf("%s < %s", fld.Name, filter.From) - case "lessThanOrEqual": - conditionQuery = fmt.Sprintf("%s <= %s", fld.Name, filter.From) - case "greaterThan": - conditionQuery = fmt.Sprintf("%s > %s", fld.Name, filter.From) - case "greaterThanOrEqual": - conditionQuery = fmt.Sprintf("%s >= %s", fld.Name, filter.From) - case "inRange": - if fld.Type.Kind() == reflect.String { - conditionQuery = fmt.Sprintf("%s >= '%s%%' AND ", fld.Name, filter.From) - conditionQuery += fmt.Sprintf("%s <= '%%%s'", fld.Name, filter.To) - } else { - conditionQuery = fmt.Sprintf("%s >= %s AND ", fld.Name, filter.From) - conditionQuery += fmt.Sprintf("%s <= %s", fld.Name, filter.To) - } - } - return conditionQuery -} - -// getSort -func getSort[T any](filter *dto.DynamicFilter) string { - t := new(T) - typeT := reflect.TypeOf(*t) - sort := make([]string, 0) - if filter.Sort != nil { - for _, tp := range *filter.Sort { - fld, ok := typeT.FieldByName(tp.ColId) - if ok && (tp.Sort == "asc" || tp.Sort == "desc") { - fld.Name = common.ToSnakeCase(fld.Name) - sort = append(sort, fmt.Sprintf("%s %s", fld.Name, tp.Sort)) - } - } - } - return strings.Join(sort, ", ") -} - -// Preload -func Preload(db *gorm.DB, preloads []preload) *gorm.DB { - for _, item := range preloads { - db = db.Preload(item.string) - } - return db -} diff --git a/src/services/car_model_color_service.go b/src/services/car_model_color_service.go deleted file mode 100644 index 3b77a2f..0000000 --- a/src/services/car_model_color_service.go +++ /dev/null @@ -1,52 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CarModelColorService struct { - base *BaseService[models.CarModelColor, dto.CreateCarModelColorRequest, dto.UpdateCarModelColorRequest, dto.CarModelColorResponse] -} - -func NewCarModelColorService(cfg *config.Config) *CarModelColorService { - return &CarModelColorService{ - base: &BaseService[models.CarModelColor, dto.CreateCarModelColorRequest, dto.UpdateCarModelColorRequest, dto.CarModelColorResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{ - {string: "Color"}, - }, - }, - } -} - -// Create -func (s *CarModelColorService) Create(ctx context.Context, req *dto.CreateCarModelColorRequest) (*dto.CarModelColorResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *CarModelColorService) Update(ctx context.Context, id int, req *dto.UpdateCarModelColorRequest) (*dto.CarModelColorResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CarModelColorService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CarModelColorService) GetById(ctx context.Context, id int) (*dto.CarModelColorResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CarModelColorService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CarModelColorResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/car_model_comment_service.go b/src/services/car_model_comment_service.go deleted file mode 100644 index 0623b0b..0000000 --- a/src/services/car_model_comment_service.go +++ /dev/null @@ -1,54 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/constants" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CarModelCommentService struct { - base *BaseService[models.CarModelComment, dto.CreateCarModelCommentRequest, dto.UpdateCarModelCommentRequest, dto.CarModelCommentResponse] -} - -func NewCarModelCommentService(cfg *config.Config) *CarModelCommentService { - return &CarModelCommentService{ - base: &BaseService[models.CarModelComment, dto.CreateCarModelCommentRequest, dto.UpdateCarModelCommentRequest, dto.CarModelCommentResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{ - {string: "User"}, - }, - }, - } -} - -// Create -func (s *CarModelCommentService) Create(ctx context.Context, req *dto.CreateCarModelCommentRequest) (*dto.CarModelCommentResponse, error) { - req.UserId = int(ctx.Value(constants.UserIdKey).(float64)) - return s.base.Create(ctx, req) -} - -// Update -func (s *CarModelCommentService) Update(ctx context.Context, id int, req *dto.UpdateCarModelCommentRequest) (*dto.CarModelCommentResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CarModelCommentService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CarModelCommentService) GetById(ctx context.Context, id int) (*dto.CarModelCommentResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CarModelCommentService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CarModelCommentResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/car_model_image_service.go b/src/services/car_model_image_service.go deleted file mode 100644 index 0ed1c7f..0000000 --- a/src/services/car_model_image_service.go +++ /dev/null @@ -1,52 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CarModelImageService struct { - base *BaseService[models.CarModelImage, dto.CreateCarModelImageRequest, dto.UpdateCarModelImageRequest, dto.CarModelImageResponse] -} - -func NewCarModelImageService(cfg *config.Config) *CarModelImageService { - return &CarModelImageService{ - base: &BaseService[models.CarModelImage, dto.CreateCarModelImageRequest, dto.UpdateCarModelImageRequest, dto.CarModelImageResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{ - {string: "Image"}, - }, - }, - } -} - -// Create -func (s *CarModelImageService) Create(ctx context.Context, req *dto.CreateCarModelImageRequest) (*dto.CarModelImageResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *CarModelImageService) Update(ctx context.Context, id int, req *dto.UpdateCarModelImageRequest) (*dto.CarModelImageResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CarModelImageService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CarModelImageService) GetById(ctx context.Context, id int) (*dto.CarModelImageResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CarModelImageService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CarModelImageResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/car_model_price_history_service.go b/src/services/car_model_price_history_service.go deleted file mode 100644 index a10c9ef..0000000 --- a/src/services/car_model_price_history_service.go +++ /dev/null @@ -1,49 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CarModelPriceHistoryService struct { - base *BaseService[models.CarModelPriceHistory, dto.CreateCarModelPriceHistoryRequest, dto.UpdateCarModelPriceHistoryRequest, dto.CarModelPriceHistoryResponse] -} - -func NewCarModelPriceHistoryService(cfg *config.Config) *CarModelPriceHistoryService { - return &CarModelPriceHistoryService{ - base: &BaseService[models.CarModelPriceHistory, dto.CreateCarModelPriceHistoryRequest, dto.UpdateCarModelPriceHistoryRequest, dto.CarModelPriceHistoryResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - }, - } -} - -// Create -func (s *CarModelPriceHistoryService) Create(ctx context.Context, req *dto.CreateCarModelPriceHistoryRequest) (*dto.CarModelPriceHistoryResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *CarModelPriceHistoryService) Update(ctx context.Context, id int, req *dto.UpdateCarModelPriceHistoryRequest) (*dto.CarModelPriceHistoryResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CarModelPriceHistoryService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CarModelPriceHistoryService) GetById(ctx context.Context, id int) (*dto.CarModelPriceHistoryResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CarModelPriceHistoryService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CarModelPriceHistoryResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/car_model_property_service.go b/src/services/car_model_property_service.go deleted file mode 100644 index f5aa409..0000000 --- a/src/services/car_model_property_service.go +++ /dev/null @@ -1,52 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CarModelPropertyService struct { - base *BaseService[models.CarModelProperty, dto.CreateCarModelPropertyRequest, dto.UpdateCarModelPropertyRequest, dto.CarModelPropertyResponse] -} - -func NewCarModelPropertyService(cfg *config.Config) *CarModelPropertyService { - return &CarModelPropertyService{ - base: &BaseService[models.CarModelProperty, dto.CreateCarModelPropertyRequest, dto.UpdateCarModelPropertyRequest, dto.CarModelPropertyResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{ - {string: "Property.Category"}, - }, - }, - } -} - -// Create -func (s *CarModelPropertyService) Create(ctx context.Context, req *dto.CreateCarModelPropertyRequest) (*dto.CarModelPropertyResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *CarModelPropertyService) Update(ctx context.Context, id int, req *dto.UpdateCarModelPropertyRequest) (*dto.CarModelPropertyResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CarModelPropertyService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CarModelPropertyService) GetById(ctx context.Context, id int) (*dto.CarModelPropertyResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CarModelPropertyService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CarModelPropertyResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/car_model_service.go b/src/services/car_model_service.go deleted file mode 100644 index 1e34273..0000000 --- a/src/services/car_model_service.go +++ /dev/null @@ -1,60 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CarModelService struct { - base *BaseService[models.CarModel, dto.CreateCarModelRequest, dto.UpdateCarModelRequest, dto.CarModelResponse] -} - -func NewCarModelService(cfg *config.Config) *CarModelService { - return &CarModelService{ - base: &BaseService[models.CarModel, dto.CreateCarModelRequest, dto.UpdateCarModelRequest, dto.CarModelResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{ - {string: "Company.Country"}, - {string: "CarType"}, - {string: "Gearbox"}, - {string: "CarModelColors.Color"}, - {string: "CarModelYears.PersianYear"}, - {string: "CarModelYears.CarModelPriceHistories"}, - {string: "CarModelProperties.Property.Category"}, - {string: "CarModelImages.Image"}, - {string: "CarModelComments.User"}, - }, - }, - } -} - -// Create -func (s *CarModelService) Create(ctx context.Context, req *dto.CreateCarModelRequest) (*dto.CarModelResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *CarModelService) Update(ctx context.Context, id int, req *dto.UpdateCarModelRequest) (*dto.CarModelResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CarModelService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CarModelService) GetById(ctx context.Context, id int) (*dto.CarModelResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CarModelService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CarModelResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/car_model_year_service.go b/src/services/car_model_year_service.go deleted file mode 100644 index 63e8355..0000000 --- a/src/services/car_model_year_service.go +++ /dev/null @@ -1,52 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CarModelYearService struct { - base *BaseService[models.CarModelYear, dto.CreateCarModelYearRequest, dto.UpdateCarModelYearRequest, dto.CarModelYearResponse] -} - -func NewCarModelYearService(cfg *config.Config) *CarModelYearService { - return &CarModelYearService{ - base: &BaseService[models.CarModelYear, dto.CreateCarModelYearRequest, dto.UpdateCarModelYearRequest, dto.CarModelYearResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{ - {string: "PersianYear"}, - }, - }, - } -} - -// Create -func (s *CarModelYearService) Create(ctx context.Context, req *dto.CreateCarModelYearRequest) (*dto.CarModelYearResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *CarModelYearService) Update(ctx context.Context, id int, req *dto.UpdateCarModelYearRequest) (*dto.CarModelYearResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CarModelYearService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CarModelYearService) GetById(ctx context.Context, id int) (*dto.CarModelYearResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CarModelYearService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CarModelYearResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/car_type_service.go b/src/services/car_type_service.go deleted file mode 100644 index 3128a55..0000000 --- a/src/services/car_type_service.go +++ /dev/null @@ -1,49 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CarTypeService struct { - base *BaseService[models.CarType, dto.CreateCarTypeRequest, dto.UpdateCarTypeRequest, dto.CarTypeResponse] -} - -func NewCarTypeService(cfg *config.Config) *CarTypeService { - return &CarTypeService{ - base: &BaseService[models.CarType, dto.CreateCarTypeRequest, dto.UpdateCarTypeRequest, dto.CarTypeResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - }, - } -} - -// Create -func (s *CarTypeService) Create(ctx context.Context, req *dto.CreateCarTypeRequest) (*dto.CarTypeResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *CarTypeService) Update(ctx context.Context, id int, req *dto.UpdateCarTypeRequest) (*dto.CarTypeResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CarTypeService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CarTypeService) GetById(ctx context.Context, id int) (*dto.CarTypeResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CarTypeService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CarTypeResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/city_service.go b/src/services/city_service.go deleted file mode 100644 index 546f4fa..0000000 --- a/src/services/city_service.go +++ /dev/null @@ -1,52 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CityService struct { - base *BaseService[models.City, dto.CreateCityRequest, dto.UpdateCityRequest, dto.CityResponse] -} - -func NewCityService(cfg *config.Config) *CityService { - return &CityService{ - base: &BaseService[models.City, dto.CreateCityRequest, dto.UpdateCityRequest, dto.CityResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{ - {string: "Country"}, - }, - }, - } -} - -// Create -func (s *CityService) Create(ctx context.Context, req *dto.CreateCityRequest) (*dto.CityResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *CityService) Update(ctx context.Context, id int, req *dto.UpdateCityRequest) (*dto.CityResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CityService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CityService) GetById(ctx context.Context, id int) (*dto.CityResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CityService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CityResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/color_service.go b/src/services/color_service.go deleted file mode 100644 index 0261e32..0000000 --- a/src/services/color_service.go +++ /dev/null @@ -1,49 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type ColorService struct { - base *BaseService[models.Color, dto.CreateColorRequest, dto.UpdateColorRequest, dto.ColorResponse] -} - -func NewColorService(cfg *config.Config) *ColorService { - return &ColorService{ - base: &BaseService[models.Color, dto.CreateColorRequest, dto.UpdateColorRequest, dto.ColorResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - }, - } -} - -// Create -func (s *ColorService) Create(ctx context.Context, req *dto.CreateColorRequest) (*dto.ColorResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *ColorService) Update(ctx context.Context, id int, req *dto.UpdateColorRequest) (*dto.ColorResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *ColorService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *ColorService) GetById(ctx context.Context, id int) (*dto.ColorResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *ColorService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.ColorResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/company_service.go b/src/services/company_service.go deleted file mode 100644 index 5903fb6..0000000 --- a/src/services/company_service.go +++ /dev/null @@ -1,52 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CompanyService struct { - base *BaseService[models.Company, dto.CreateCompanyRequest, dto.UpdateCompanyRequest, dto.CompanyResponse] -} - -func NewCompanyService(cfg *config.Config) *CompanyService { - return &CompanyService{ - base: &BaseService[models.Company, dto.CreateCompanyRequest, dto.UpdateCompanyRequest, dto.CompanyResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{ - {string: "Country"}, - }, - }, - } -} - -// Create -func (s *CompanyService) Create(ctx context.Context, req *dto.CreateCompanyRequest) (*dto.CompanyResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *CompanyService) Update(ctx context.Context, id int, req *dto.UpdateCompanyRequest) (*dto.CompanyResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CompanyService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CompanyService) GetById(ctx context.Context, id int) (*dto.CompanyResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CompanyService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CompanyResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/country_service.go b/src/services/country_service.go deleted file mode 100644 index 31d7c9f..0000000 --- a/src/services/country_service.go +++ /dev/null @@ -1,50 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type CountryService struct { - base *BaseService[models.Country, dto.CreateUpdateCountryRequest, dto.CreateUpdateCountryRequest, dto.CountryResponse] -} - -func NewCountryService(cfg *config.Config) *CountryService { - return &CountryService{ - base: &BaseService[models.Country, dto.CreateUpdateCountryRequest, dto.CreateUpdateCountryRequest, dto.CountryResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{{string: "Cities"}, {string: "Companies"}}, - }, - } -} - -// Create -func (s *CountryService) Create(ctx context.Context, req *dto.CreateUpdateCountryRequest) (*dto.CountryResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *CountryService) Update(ctx context.Context, id int, req *dto.CreateUpdateCountryRequest) (*dto.CountryResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *CountryService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *CountryService) GetById(ctx context.Context, id int) (*dto.CountryResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *CountryService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.CountryResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/file_service.go b/src/services/file_service.go deleted file mode 100644 index 73df88f..0000000 --- a/src/services/file_service.go +++ /dev/null @@ -1,50 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type FileService struct { - base *BaseService[models.File,dto.CreateFileRequest, dto.UpdateFileRequest,dto.FileResponse] -} - -func NewFileService(cfg *config.Config) *FileService { - return &FileService{ - base: &BaseService[models.File, dto.CreateFileRequest, dto.UpdateFileRequest, dto.FileResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - }, - } -} - - -// Create -func (s *FileService) Create(ctx context.Context, req *dto.CreateFileRequest) (*dto.FileResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *FileService) Update(ctx context.Context, id int, req *dto.UpdateFileRequest) (*dto.FileResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *FileService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *FileService) GetById(ctx context.Context, id int) (*dto.FileResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *FileService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.FileResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/gearbox_service.go b/src/services/gearbox_service.go deleted file mode 100644 index e052e31..0000000 --- a/src/services/gearbox_service.go +++ /dev/null @@ -1,49 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type GearboxService struct { - base *BaseService[models.Gearbox, dto.CreateGearboxRequest, dto.UpdateGearboxRequest, dto.GearboxResponse] -} - -func NewGearboxService(cfg *config.Config) *GearboxService { - return &GearboxService{ - base: &BaseService[models.Gearbox, dto.CreateGearboxRequest, dto.UpdateGearboxRequest, dto.GearboxResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - }, - } -} - -// Create -func (s *GearboxService) Create(ctx context.Context, req *dto.CreateGearboxRequest) (*dto.GearboxResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *GearboxService) Update(ctx context.Context, id int, req *dto.UpdateGearboxRequest) (*dto.GearboxResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *GearboxService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *GearboxService) GetById(ctx context.Context, id int) (*dto.GearboxResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *GearboxService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.GearboxResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/otp_Service.go b/src/services/otp_Service.go deleted file mode 100644 index 2554412..0000000 --- a/src/services/otp_Service.go +++ /dev/null @@ -1,69 +0,0 @@ -package services - -import ( - "fmt" - "time" - - "github.com/go-redis/redis/v7" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/constants" - "github.com/naeemaei/golang-clean-web-api/data/cache" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" - "github.com/naeemaei/golang-clean-web-api/pkg/service_errors" -) - -type OtpService struct { - logger logging.Logger - cfg *config.Config - redisClient *redis.Client -} - -type OtpDto struct { - Value string - Used bool -} - -func NewOtpService(cfg *config.Config) *OtpService { - logger := logging.NewLogger(cfg) - redis := cache.GetRedis() - return &OtpService{logger: logger, cfg: cfg, redisClient: redis} -} - -func (s *OtpService) SetOtp(mobileNumber string, otp string) error { - key := fmt.Sprintf("%s:%s", constants.RedisOtpDefaultKey, mobileNumber) - val := &OtpDto{ - Value: otp, - Used: false, - } - - res, err := cache.Get[OtpDto](s.redisClient, key) - if err == nil && !res.Used { - return &service_errors.ServiceError{EndUserMessage: service_errors.OptExists} - } else if err == nil && res.Used { - return &service_errors.ServiceError{EndUserMessage: service_errors.OtpUsed} - } - err = cache.Set(s.redisClient, key, val, s.cfg.Otp.ExpireTime*time.Second) - if err != nil { - return err - } - return nil -} - -func (s *OtpService) ValidateOtp(mobileNumber string, otp string) error { - key := fmt.Sprintf("%s:%s", constants.RedisOtpDefaultKey, mobileNumber) - res, err := cache.Get[OtpDto](s.redisClient, key) - if err != nil { - return err - } else if res.Used { - return &service_errors.ServiceError{EndUserMessage: service_errors.OtpUsed} - } else if !res.Used && res.Value != otp { - return &service_errors.ServiceError{EndUserMessage: service_errors.OtpNotValid} - } else if !res.Used && res.Value == otp { - res.Used = true - err = cache.Set(s.redisClient, key, res, s.cfg.Otp.ExpireTime*time.Second) - if err != nil { - return err - } - } - return nil -} diff --git a/src/services/property_category_service.go b/src/services/property_category_service.go deleted file mode 100644 index 487cfad..0000000 --- a/src/services/property_category_service.go +++ /dev/null @@ -1,50 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type PropertyCategoryService struct { - base *BaseService[models.PropertyCategory, dto.CreatePropertyCategoryRequest, dto.UpdatePropertyCategoryRequest, dto.PropertyCategoryResponse] -} - -func NewPropertyCategoryService(cfg *config.Config) *PropertyCategoryService { - return &PropertyCategoryService{ - base: &BaseService[models.PropertyCategory, dto.CreatePropertyCategoryRequest, dto.UpdatePropertyCategoryRequest, dto.PropertyCategoryResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{{string: "Properties"}}, - }, - } -} - -// Create -func (s *PropertyCategoryService) Create(ctx context.Context, req *dto.CreatePropertyCategoryRequest) (*dto.PropertyCategoryResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *PropertyCategoryService) Update(ctx context.Context, id int, req *dto.UpdatePropertyCategoryRequest) (*dto.PropertyCategoryResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *PropertyCategoryService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *PropertyCategoryService) GetById(ctx context.Context, id int) (*dto.PropertyCategoryResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *PropertyCategoryService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.PropertyCategoryResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/property_service.go b/src/services/property_service.go deleted file mode 100644 index ca2f422..0000000 --- a/src/services/property_service.go +++ /dev/null @@ -1,50 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type PropertyService struct { - base *BaseService[models.Property, dto.CreatePropertyRequest, dto.UpdatePropertyRequest, dto.PropertyResponse] -} - -func NewPropertyService(cfg *config.Config) *PropertyService { - return &PropertyService{ - base: &BaseService[models.Property, dto.CreatePropertyRequest, dto.UpdatePropertyRequest, dto.PropertyResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - Preloads: []preload{{string: "Category"}}, - }, - } -} - -// Create -func (s *PropertyService) Create(ctx context.Context, req *dto.CreatePropertyRequest) (*dto.PropertyResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *PropertyService) Update(ctx context.Context, id int, req *dto.UpdatePropertyRequest) (*dto.PropertyResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *PropertyService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *PropertyService) GetById(ctx context.Context, id int) (*dto.PropertyResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *PropertyService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.PropertyResponse], error) { - return s.base.GetByFilter(ctx, req) -} diff --git a/src/services/token_service.go b/src/services/token_service.go deleted file mode 100644 index ba4eadf..0000000 --- a/src/services/token_service.go +++ /dev/null @@ -1,107 +0,0 @@ -package services - -import ( - "time" - - "github.com/golang-jwt/jwt" - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/constants" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" - "github.com/naeemaei/golang-clean-web-api/pkg/service_errors" -) - -type TokenService struct { - logger logging.Logger - cfg *config.Config -} - -type tokenDto struct { - UserId int - FirstName string - LastName string - Username string - MobileNumber string - Email string - Roles []string -} - -func NewTokenService(cfg *config.Config) *TokenService { - logger := logging.NewLogger(cfg) - return &TokenService{ - cfg: cfg, - logger: logger, - } -} - -func (s *TokenService) GenerateToken(token *tokenDto) (*dto.TokenDetail, error) { - td := &dto.TokenDetail{} - td.AccessTokenExpireTime = time.Now().Add(s.cfg.JWT.AccessTokenExpireDuration * time.Minute).Unix() - td.RefreshTokenExpireTime = time.Now().Add(s.cfg.JWT.RefreshTokenExpireDuration * time.Minute).Unix() - - atc := jwt.MapClaims{} - - atc[constants.UserIdKey] = token.UserId - atc[constants.FirstNameKey] = token.FirstName - atc[constants.LastNameKey] = token.LastName - atc[constants.UsernameKey] = token.Username - atc[constants.EmailKey] = token.Email - atc[constants.MobileNumberKey] = token.MobileNumber - atc[constants.RolesKey] = token.Roles - atc[constants.ExpireTimeKey] = td.AccessTokenExpireTime - - at := jwt.NewWithClaims(jwt.SigningMethodHS256, atc) - - var err error - td.AccessToken, err = at.SignedString([]byte(s.cfg.JWT.Secret)) - - if err != nil { - return nil, err - } - - rtc := jwt.MapClaims{} - - rtc[constants.UserIdKey] = token.UserId - rtc[constants.ExpireTimeKey] = td.RefreshTokenExpireTime - - rt := jwt.NewWithClaims(jwt.SigningMethodHS256, rtc) - - td.RefreshToken, err = rt.SignedString([]byte(s.cfg.JWT.RefreshSecret)) - - if err != nil { - return nil, err - } - - return td, nil -} - -func (s *TokenService) VerifyToken(token string) (*jwt.Token, error) { - at, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { - _, ok := token.Method.(*jwt.SigningMethodHMAC) - if !ok { - return nil, &service_errors.ServiceError{EndUserMessage: service_errors.UnExpectedError} - } - return []byte(s.cfg.JWT.Secret), nil - }) - if err != nil { - return nil, err - } - return at, nil -} - -func (s *TokenService) GetClaims(token string) (claimMap map[string]interface{}, err error) { - claimMap = map[string]interface{}{} - - verifyToken, err := s.VerifyToken(token) - if err != nil { - return nil, err - } - claims, ok := verifyToken.Claims.(jwt.MapClaims) - if ok && verifyToken.Valid { - for k, v := range claims { - claimMap[k] = v - } - return claimMap, nil - } - return nil, &service_errors.ServiceError{EndUserMessage: service_errors.ClaimsNotFound} -} diff --git a/src/services/user_service.go b/src/services/user_service.go deleted file mode 100644 index 8dc16df..0000000 --- a/src/services/user_service.go +++ /dev/null @@ -1,258 +0,0 @@ -package services - -import ( - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/common" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/constants" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" - "github.com/naeemaei/golang-clean-web-api/pkg/service_errors" - "golang.org/x/crypto/bcrypt" - "gorm.io/gorm" -) - -const userFilterExp string = "username = ?" -const countFilterExp string = "count(*) > 0" - -type UserService struct { - logger logging.Logger - cfg *config.Config - otpService *OtpService - tokenService *TokenService - database *gorm.DB -} - -func NewUserService(cfg *config.Config) *UserService { - database := db.GetDb() - logger := logging.NewLogger(cfg) - return &UserService{ - cfg: cfg, - database: database, - logger: logger, - otpService: NewOtpService(cfg), - tokenService: NewTokenService(cfg), - } -} - -// Login by username -func (s *UserService) LoginByUsername(req *dto.LoginByUsernameRequest) (*dto.TokenDetail, error) { - var user models.User - err := s.database. - Model(&models.User{}). - Where(userFilterExp, req.Username). - Preload("UserRoles", func(tx *gorm.DB) *gorm.DB { - return tx.Preload("Role") - }). - Find(&user).Error - if err != nil { - return nil, err - } - err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)) - if err != nil { - return nil, err - } - tokenDto := tokenDto{UserId: user.Id, FirstName: user.FirstName, LastName: user.LastName, - Email: user.Email, MobileNumber: user.MobileNumber} - - if len(*user.UserRoles) > 0 { - for _, ur := range *user.UserRoles { - tokenDto.Roles = append(tokenDto.Roles, ur.Role.Name) - } - } - - token, err := s.tokenService.GenerateToken(&tokenDto) - if err != nil { - return nil, err - } - return token, nil - -} - -// Register by username -func (s *UserService) RegisterByUsername(req *dto.RegisterUserByUsernameRequest) error { - u := models.User{Username: req.Username, FirstName: req.FirstName, LastName: req.LastName, Email: req.Email} - - exists, err := s.existsByEmail(req.Email) - if err != nil { - return err - } - if exists { - return &service_errors.ServiceError{EndUserMessage: service_errors.EmailExists} - } - exists, err = s.existsByUsername(req.Username) - if err != nil { - return err - } - if exists { - return &service_errors.ServiceError{EndUserMessage: service_errors.UsernameExists} - } - - bp := []byte(req.Password) - hp, err := bcrypt.GenerateFromPassword(bp, bcrypt.DefaultCost) - if err != nil { - s.logger.Error(logging.General, logging.HashPassword, err.Error(), nil) - return err - } - u.Password = string(hp) - roleId, err := s.getDefaultRole() - if err != nil { - s.logger.Error(logging.Postgres, logging.DefaultRoleNotFound, err.Error(), nil) - return err - } - - tx := s.database.Begin() - err = tx.Create(&u).Error - if err != nil { - tx.Rollback() - s.logger.Error(logging.Postgres, logging.Rollback, err.Error(), nil) - return err - } - err = tx.Create(&models.UserRole{RoleId: roleId, UserId: u.Id}).Error - if err != nil { - tx.Rollback() - s.logger.Error(logging.Postgres, logging.Rollback, err.Error(), nil) - return err - } - tx.Commit() - return nil - -} - -// Register/login by mobile number -func (s *UserService) RegisterLoginByMobileNumber(req *dto.RegisterLoginByMobileRequest) (*dto.TokenDetail, error) { - err := s.otpService.ValidateOtp(req.MobileNumber, req.Otp) - if err != nil { - return nil, err - } - exists, err := s.existsByMobileNumber(req.MobileNumber) - if err != nil { - return nil, err - } - - u := models.User{MobileNumber: req.MobileNumber, Username: req.MobileNumber} - - if exists { - return s.loginByMobileNumber(u.Username) - } - - // Register and login - bp := []byte(common.GeneratePassword()) - hp, err := bcrypt.GenerateFromPassword(bp, bcrypt.DefaultCost) - if err != nil { - s.logger.Error(logging.General, logging.HashPassword, err.Error(), nil) - return nil, err - } - u.Password = string(hp) - roleId, err := s.getDefaultRole() - if err != nil { - s.logger.Error(logging.Postgres, logging.DefaultRoleNotFound, err.Error(), nil) - return nil, err - } - - tx := s.database.Begin() - err = tx.Create(&u).Error - if err != nil { - tx.Rollback() - s.logger.Error(logging.Postgres, logging.Rollback, err.Error(), nil) - return nil, err - } - err = tx.Create(&models.UserRole{RoleId: roleId, UserId: u.Id}).Error - if err != nil { - tx.Rollback() - s.logger.Error(logging.Postgres, logging.Rollback, err.Error(), nil) - return nil, err - } - tx.Commit() - - return s.loginByMobileNumber(u.Username) - -} - -func (s *UserService) loginByMobileNumber(username string) (*dto.TokenDetail, error) { - var user models.User - err := s.database. - Model(&models.User{}). - Where(userFilterExp, username). - Preload("UserRoles", func(tx *gorm.DB) *gorm.DB { - return tx.Preload("Role") - }). - Find(&user).Error - if err != nil { - return nil, err - } - tokenDto := tokenDto{UserId: user.Id, FirstName: user.FirstName, LastName: user.LastName, - Email: user.Email, MobileNumber: user.MobileNumber} - - if len(*user.UserRoles) > 0 { - for _, ur := range *user.UserRoles { - tokenDto.Roles = append(tokenDto.Roles, ur.Role.Name) - } - } - - token, err := s.tokenService.GenerateToken(&tokenDto) - if err != nil { - return nil, err - } - return token, nil -} - -func (s *UserService) SendOtp(req *dto.GetOtpRequest) error { - otp := common.GenerateOtp() - err := s.otpService.SetOtp(req.MobileNumber, otp) - if err != nil { - return err - } - return nil -} - -func (s *UserService) existsByEmail(email string) (bool, error) { - var exists bool - if err := s.database.Model(&models.User{}). - Select(countFilterExp). - Where("email = ?", email). - Find(&exists). - Error; err != nil { - s.logger.Error(logging.Postgres, logging.Select, err.Error(), nil) - return false, err - } - return exists, nil -} - -func (s *UserService) existsByUsername(username string) (bool, error) { - var exists bool - if err := s.database.Model(&models.User{}). - Select(countFilterExp). - Where(userFilterExp, username). - Find(&exists). - Error; err != nil { - s.logger.Error(logging.Postgres, logging.Select, err.Error(), nil) - return false, err - } - return exists, nil -} - -func (s *UserService) existsByMobileNumber(mobileNumber string) (bool, error) { - var exists bool - if err := s.database.Model(&models.User{}). - Select(countFilterExp). - Where("mobile_number = ?", mobileNumber). - Find(&exists). - Error; err != nil { - s.logger.Error(logging.Postgres, logging.Select, err.Error(), nil) - return false, err - } - return exists, nil -} - -func (s *UserService) getDefaultRole() (roleId int, err error) { - - if err = s.database.Model(&models.Role{}). - Select("id"). - Where("name = ?", constants.DefaultRoleName). - First(&roleId).Error; err != nil { - return 0, err - } - return roleId, nil -} diff --git a/src/services/year_service.go b/src/services/year_service.go deleted file mode 100644 index a932168..0000000 --- a/src/services/year_service.go +++ /dev/null @@ -1,49 +0,0 @@ -package services - -import ( - "context" - - "github.com/naeemaei/golang-clean-web-api/api/dto" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - -type PersianYearService struct { - base *BaseService[models.PersianYear, dto.CreatePersianYearRequest, dto.UpdatePersianYearRequest, dto.PersianYearResponse] -} - -func NewPersianYearService(cfg *config.Config) *PersianYearService { - return &PersianYearService{ - base: &BaseService[models.PersianYear, dto.CreatePersianYearRequest, dto.UpdatePersianYearRequest, dto.PersianYearResponse]{ - Database: db.GetDb(), - Logger: logging.NewLogger(cfg), - }, - } -} - -// Create -func (s *PersianYearService) Create(ctx context.Context, req *dto.CreatePersianYearRequest) (*dto.PersianYearResponse, error) { - return s.base.Create(ctx, req) -} - -// Update -func (s *PersianYearService) Update(ctx context.Context, id int, req *dto.UpdatePersianYearRequest) (*dto.PersianYearResponse, error) { - return s.base.Update(ctx, id, req) -} - -// Delete -func (s *PersianYearService) Delete(ctx context.Context, id int) error { - return s.base.Delete(ctx, id) -} - -// Get By Id -func (s *PersianYearService) GetById(ctx context.Context, id int) (*dto.PersianYearResponse, error) { - return s.base.GetById(ctx, id) -} - -// Get By Filter -func (s *PersianYearService) GetByFilter(ctx context.Context, req *dto.PaginationInputWithFilter) (*dto.PagedList[dto.PersianYearResponse], error) { - return s.base.GetByFilter(ctx, req) -} From ee433b7eed8173ed7b38e9786f9151f21ab12ad0 Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 18:50:45 +0330 Subject: [PATCH 03/18] Update dockerfile and docker compose file --- docker/docker-compose.yml | 17 +++++++++-------- src/Dockerfile | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 07d5fac..7cd2f30 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -21,7 +21,7 @@ services: - webapi_network depends_on: - elasticsearch - + ####################### ELK ####################### elasticsearch: build: @@ -77,7 +77,7 @@ services: #- ../prod/logs:/var/log/filebeat/service:ro - logs:/var/log/filebeat - logs:/app:ro - + environment: FILEBEAT_INTERNAL_PASSWORD: ${FILEBEAT_INTERNAL_PASSWORD:-} BEATS_SYSTEM_PASSWORD: ${FILEBEAT_INTERNAL_PASSWORD:-} @@ -118,15 +118,15 @@ services: restart: unless-stopped depends_on: - postgres - + ####################### REDIS ####################### redis: image: redis:latest container_name: redis_container - command: ["redis-server", "/etc/redis/redis.conf"] + command: [ "redis-server", "/etc/redis/redis.conf" ] volumes: - ./redis/redis.conf:/etc/redis/redis.conf - - redis:/etc/redis + - redis:/etc/redis ports: - "6379:6379" networks: @@ -182,7 +182,7 @@ services: command: - "--config.file=/etc/alertmanager/config.yml" - "--storage.path=/alertmanager" - + grafana: image: grafana/grafana user: "472" @@ -196,7 +196,7 @@ services: env_file: - ./grafana/config.monitoring networks: - - webapi_network + - webapi_network restart: always car-api1: build: ../src/ @@ -241,6 +241,7 @@ volumes: prometheus_data: grafana_data: + networks: webapi_network: - driver: bridge \ No newline at end of file + driver: bridge diff --git a/src/Dockerfile b/src/Dockerfile index 809faaf..7956aef 100644 --- a/src/Dockerfile +++ b/src/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19-buster as builder +FROM golang:1.19-buster AS builder WORKDIR /app From b08482285041ff4f66098a3cd39f514e1f13737c Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 18:54:16 +0330 Subject: [PATCH 04/18] Remove data layer Create domain layer Move data model to domain layer and create repository contracts in domain layer --- src/domain/filter/dynamic_filter.go | 20 ++++ src/domain/filter/pagination.go | 72 +++++++++++++ src/{data/models => domain/model}/base.go | 2 +- .../models => domain/model}/base_model.go | 2 +- src/{data/models => domain/model}/car.go | 3 +- src/{data/models => domain/model}/property.go | 2 +- src/{data/models => domain/model}/user.go | 2 +- src/domain/repository/repository.go | 101 ++++++++++++++++++ 8 files changed, 199 insertions(+), 5 deletions(-) create mode 100644 src/domain/filter/dynamic_filter.go create mode 100644 src/domain/filter/pagination.go rename src/{data/models => domain/model}/base.go (98%) rename src/{data/models => domain/model}/base_model.go (98%) rename src/{data/models => domain/model}/car.go (99%) rename src/{data/models => domain/model}/property.go (98%) rename src/{data/models => domain/model}/user.go (98%) create mode 100644 src/domain/repository/repository.go diff --git a/src/domain/filter/dynamic_filter.go b/src/domain/filter/dynamic_filter.go new file mode 100644 index 0000000..4b3066a --- /dev/null +++ b/src/domain/filter/dynamic_filter.go @@ -0,0 +1,20 @@ +package filter + +type Sort struct { + ColId string `json:"colId"` + Sort string `json:"sort"` +} + +type Filter struct { + // contains notContains equals notEqual startsWith lessThan lessThanOrEqual greaterThan greaterThanOrEqual inRange endsWith + Type string `json:"type"` + From string `json:"from"` + To string `json:"to"` + // text number + FilterType string `json:"filterType"` +} + +type DynamicFilter struct { + Sort *[]Sort `json:"sort"` + Filter map[string]Filter `json:"filter"` +} diff --git a/src/domain/filter/pagination.go b/src/domain/filter/pagination.go new file mode 100644 index 0000000..04d5153 --- /dev/null +++ b/src/domain/filter/pagination.go @@ -0,0 +1,72 @@ +package filter + +import ( + "math" + + "github.com/naeemaei/golang-clean-web-api/common" +) + +func NewPagedList[T any](items *[]T, count int64, pageNumber int, pageSize int64) *PagedList[T] { + pl := &PagedList[T]{ + PageNumber: pageNumber, + PageSize: pageSize, + TotalRows: count, + Items: items, + } + pl.TotalPages = int(math.Ceil(float64(count) / float64(pageSize))) + pl.HasNextPage = pl.PageNumber < pl.TotalPages + pl.HasPreviousPage = pl.PageNumber > 1 + + return pl +} + +// Paginate +func Paginate[TInput any, TOutput any](totalRows int64, items *[]TInput, pageNumber int, pageSize int64) (*PagedList[TOutput], error) { + var rItems []TOutput + + rItems, err := common.TypeConverter[[]TOutput](items) + if err != nil { + return nil, err + } + return NewPagedList(&rItems, totalRows, pageNumber, pageSize), err + +} + +type PagedList[T any] struct { + PageNumber int `json:"pageNumber"` + PageSize int64 `json:"pageSize"` + TotalRows int64 `json:"totalRows"` + TotalPages int `json:"totalPages"` + HasPreviousPage bool `json:"hasPreviousPage"` + HasNextPage bool `json:"hasNextPage"` + Items *[]T `json:"items"` +} + +type PaginationInput struct { + PageSize int `json:"pageSize"` + PageNumber int `json:"pageNumber"` +} + +type PaginationInputWithFilter struct { + PaginationInput + DynamicFilter +} + +func (p *PaginationInputWithFilter) GetOffset() int { + // 2 , 10 => 11-20 + return (p.GetPageNumber() - 1) * p.GetPageSize() +} + +func (p *PaginationInputWithFilter) GetPageSize() int { + if p.PageSize == 0 { + p.PageSize = 10 + } + return p.PageSize +} + +func (p *PaginationInputWithFilter) GetPageNumber() int { + if p.PageNumber == 0 { + p.PageNumber = 1 + } + return p.PageNumber +} diff --git a/src/data/models/base.go b/src/domain/model/base.go similarity index 98% rename from src/data/models/base.go rename to src/domain/model/base.go index c6abed3..1cc35e3 100644 --- a/src/data/models/base.go +++ b/src/domain/model/base.go @@ -1,4 +1,4 @@ -package models +package model import "time" diff --git a/src/data/models/base_model.go b/src/domain/model/base_model.go similarity index 98% rename from src/data/models/base_model.go rename to src/domain/model/base_model.go index c081dec..53e939c 100644 --- a/src/data/models/base_model.go +++ b/src/domain/model/base_model.go @@ -1,4 +1,4 @@ -package models +package model import ( "database/sql" diff --git a/src/data/models/car.go b/src/domain/model/car.go similarity index 99% rename from src/data/models/car.go rename to src/domain/model/car.go index 6dd54a1..bd69184 100644 --- a/src/data/models/car.go +++ b/src/domain/model/car.go @@ -1,4 +1,4 @@ -package models +package model import "time" @@ -89,3 +89,4 @@ type CarModelComment struct { UserId int Message string `gorm:"size:500,type:string;not null"` } + diff --git a/src/data/models/property.go b/src/domain/model/property.go similarity index 98% rename from src/data/models/property.go rename to src/domain/model/property.go index 0fa7935..3af9a4e 100644 --- a/src/data/models/property.go +++ b/src/domain/model/property.go @@ -1,4 +1,4 @@ -package models +package model type PropertyCategory struct { BaseModel diff --git a/src/data/models/user.go b/src/domain/model/user.go similarity index 98% rename from src/data/models/user.go rename to src/domain/model/user.go index 1b69525..ccbf3be 100644 --- a/src/data/models/user.go +++ b/src/domain/model/user.go @@ -1,4 +1,4 @@ -package models +package model type User struct { BaseModel diff --git a/src/domain/repository/repository.go b/src/domain/repository/repository.go new file mode 100644 index 0000000..bb2131c --- /dev/null +++ b/src/domain/repository/repository.go @@ -0,0 +1,101 @@ +package repository + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/domain/model" +) + +type BaseRepository[TEntity any] interface { + Create(ctx context.Context, entity TEntity) (TEntity, error) + Update(ctx context.Context, id int, entity map[string]interface{}) (TEntity, error) + Delete(ctx context.Context, id int) error + GetById(ctx context.Context, id int) (TEntity, error) + GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (int64, *[]TEntity, error) +} +type CountryRepository interface { + BaseRepository[model.Country] +} + +type CityRepository interface { + BaseRepository[model.City] + // Create(ctx context.Context, City model.City) (model.City, error) + // Update(ctx context.Context, id int, City model.City) (model.City, error) + // Delete(ctx context.Context, id int) error + // GetById(ctx context.Context, id int) (model.City, error) + // GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (int64, *[]model.City, error) +} + +type PersianYearRepository interface { + BaseRepository[model.PersianYear] +} + +type ColorRepository interface { + BaseRepository[model.Color] +} + +type FileRepository interface { + BaseRepository[model.File] +} + +type GearboxRepository interface { + BaseRepository[model.Gearbox] +} + +type CarTypeRepository interface { + BaseRepository[model.CarType] +} + +type CompanyRepository interface { + BaseRepository[model.Company] +} + +type CarModelRepository interface { + BaseRepository[model.CarModel] +} + +type CarModelColorRepository interface { + BaseRepository[model.CarModelColor] +} + +type CarModelYearRepository interface { + BaseRepository[model.CarModelYear] +} + +type CarModelImageRepository interface { + BaseRepository[model.CarModelImage] +} + +type CarModelPriceHistoryRepository interface { + BaseRepository[model.CarModelPriceHistory] +} + +type CarModelPropertyRepository interface { + BaseRepository[model.CarModelProperty] +} + +type CarModelCommentRepository interface { + BaseRepository[model.CarModelComment] +} + +type PropertyCategoryRepository interface { + BaseRepository[model.PropertyCategory] +} + +type PropertyRepository interface { + BaseRepository[model.Property] +} + +type UserRepository interface { + ExistsMobileNumber(ctx context.Context, mobileNumber string) (bool, error) + ExistsUsername(ctx context.Context, username string) (bool, error) + ExistsEmail(ctx context.Context, email string) (bool, error) + FetchUserInfo(ctx context.Context, username string, password string) (model.User, error) + GetDefaultRole(ctx context.Context) (roleId int, err error) + CreateUser(ctx context.Context, u model.User) (model.User, error) +} + +type RoleRepository interface { + BaseRepository[model.Role] +} From fad050846b40d81e842e40a5d763556f266226b4 Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 18:55:13 +0330 Subject: [PATCH 05/18] Move redis and repository implementation to infra --- src/{data => infra}/cache/redis.go | 0 .../persistence/database}/postgres.go | 2 +- .../persistence/database/query_builder.go | 93 +++++++++++ .../persistence/migration}/1_Init.go | 16 +- .../persistence/migration}/default_values.go | 4 +- .../repository/postgres_repository.go | 146 ++++++++++++++++++ .../repository/postgres_user_repository.go | 121 +++++++++++++++ 7 files changed, 371 insertions(+), 11 deletions(-) rename src/{data => infra}/cache/redis.go (100%) rename src/{data/db => infra/persistence/database}/postgres.go (98%) create mode 100644 src/infra/persistence/database/query_builder.go rename src/{data/db/migrations => infra/persistence/migration}/1_Init.go (95%) rename src/{data/db/migrations => infra/persistence/migration}/default_values.go (98%) create mode 100644 src/infra/persistence/repository/postgres_repository.go create mode 100644 src/infra/persistence/repository/postgres_user_repository.go diff --git a/src/data/cache/redis.go b/src/infra/cache/redis.go similarity index 100% rename from src/data/cache/redis.go rename to src/infra/cache/redis.go diff --git a/src/data/db/postgres.go b/src/infra/persistence/database/postgres.go similarity index 98% rename from src/data/db/postgres.go rename to src/infra/persistence/database/postgres.go index f2f7ef7..d0b53d5 100644 --- a/src/data/db/postgres.go +++ b/src/infra/persistence/database/postgres.go @@ -1,4 +1,4 @@ -package db +package database import ( "fmt" diff --git a/src/infra/persistence/database/query_builder.go b/src/infra/persistence/database/query_builder.go new file mode 100644 index 0000000..0e57f29 --- /dev/null +++ b/src/infra/persistence/database/query_builder.go @@ -0,0 +1,93 @@ +package database + +import ( + "fmt" + "reflect" + "strings" + + "github.com/naeemaei/golang-clean-web-api/common" + "gorm.io/gorm" + + filter "github.com/naeemaei/golang-clean-web-api/domain/filter" +) + +type PreloadEntity struct { + Entity string +} + +// GenerateDynamicQuery +func GenerateDynamicQuery[T any](filter *filter.DynamicFilter) string { + t := new(T) + typeT := reflect.TypeOf(*t) + query := make([]string, 0) + query = append(query, "deleted_by is null") + if filter.Filter != nil { + for name, filter := range filter.Filter { + if fld, ok := typeT.FieldByName(name); ok { + query = append(query, GenerateDynamicFilter(fld, filter)) + } + } + } + return strings.Join(query, " AND ") +} + +func GenerateDynamicFilter(fld reflect.StructField, filter filter.Filter) string { + conditionQuery := "" + fld.Name = common.ToSnakeCase(fld.Name) + switch filter.Type { + case "contains": + conditionQuery = fmt.Sprintf("%s ILike '%%%s%%'", fld.Name, filter.From) + case "notContains": + conditionQuery = fmt.Sprintf("%s not ILike '%%%s%%'", fld.Name, filter.From) + case "startsWith": + conditionQuery = fmt.Sprintf("%s ILike '%s%%'", fld.Name, filter.From) + case "endsWith": + conditionQuery = fmt.Sprintf("%s ILike '%%%s'", fld.Name, filter.From) + case "equals": + conditionQuery = fmt.Sprintf("%s = '%s'", fld.Name, filter.From) + case "notEqual": + conditionQuery = fmt.Sprintf("%s != '%s'", fld.Name, filter.From) + case "lessThan": + conditionQuery = fmt.Sprintf("%s < %s", fld.Name, filter.From) + case "lessThanOrEqual": + conditionQuery = fmt.Sprintf("%s <= %s", fld.Name, filter.From) + case "greaterThan": + conditionQuery = fmt.Sprintf("%s > %s", fld.Name, filter.From) + case "greaterThanOrEqual": + conditionQuery = fmt.Sprintf("%s >= %s", fld.Name, filter.From) + case "inRange": + if fld.Type.Kind() == reflect.String { + conditionQuery = fmt.Sprintf("%s >= '%s%%' AND ", fld.Name, filter.From) + conditionQuery += fmt.Sprintf("%s <= '%%%s'", fld.Name, filter.To) + } else { + conditionQuery = fmt.Sprintf("%s >= %s AND ", fld.Name, filter.From) + conditionQuery += fmt.Sprintf("%s <= %s", fld.Name, filter.To) + } + } + return conditionQuery +} + +// generateDynamicSort +func GenerateDynamicSort[T any](filter *filter.DynamicFilter) string { + t := new(T) + typeT := reflect.TypeOf(*t) + sort := make([]string, 0) + if filter.Sort != nil { + for _, tp := range *filter.Sort { + fld, ok := typeT.FieldByName(tp.ColId) + if ok && (tp.Sort == "asc" || tp.Sort == "desc") { + fld.Name = common.ToSnakeCase(fld.Name) + sort = append(sort, fmt.Sprintf("%s %s", fld.Name, tp.Sort)) + } + } + } + return strings.Join(sort, ", ") +} + +// Preload +func Preload(db *gorm.DB, preloads []PreloadEntity) *gorm.DB { + for _, item := range preloads { + db = db.Preload(item.Entity) + } + return db +} diff --git a/src/data/db/migrations/1_Init.go b/src/infra/persistence/migration/1_Init.go similarity index 95% rename from src/data/db/migrations/1_Init.go rename to src/infra/persistence/migration/1_Init.go index e394855..679488c 100644 --- a/src/data/db/migrations/1_Init.go +++ b/src/infra/persistence/migration/1_Init.go @@ -1,12 +1,12 @@ -package migrations +package migration import ( "time" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/constants" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/models" + "github.com/naeemaei/golang-clean-web-api/constant" + models "github.com/naeemaei/golang-clean-web-api/domain/model" + database "github.com/naeemaei/golang-clean-web-api/infra/persistence/database" "github.com/naeemaei/golang-clean-web-api/pkg/logging" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" @@ -17,7 +17,7 @@ const countStarExp = "count(*)" var logger = logging.NewLogger(config.GetConfig()) func Up1() { - database := db.GetDb() + database := database.GetDb() createTables(database) createDefaultUserInformation(database) @@ -77,13 +77,13 @@ func addNewTable(database *gorm.DB, model interface{}, tables []interface{}) []i func createDefaultUserInformation(database *gorm.DB) { - adminRole := models.Role{Name: constants.AdminRoleName} + adminRole := models.Role{Name: constant.AdminRoleName} createRoleIfNotExists(database, &adminRole) - defaultRole := models.Role{Name: constants.DefaultRoleName} + defaultRole := models.Role{Name: constant.DefaultRoleName} createRoleIfNotExists(database, &defaultRole) - u := models.User{Username: constants.DefaultUserName, FirstName: "Test", LastName: "Test", + u := models.User{Username: constant.DefaultUserName, FirstName: "Test", LastName: "Test", MobileNumber: "09111112222", Email: "admin@admin.com"} pass := "12345678" hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) diff --git a/src/data/db/migrations/default_values.go b/src/infra/persistence/migration/default_values.go similarity index 98% rename from src/data/db/migrations/default_values.go rename to src/infra/persistence/migration/default_values.go index 8056bcb..9d57615 100644 --- a/src/data/db/migrations/default_values.go +++ b/src/infra/persistence/migration/default_values.go @@ -1,6 +1,6 @@ -package migrations +package migration -import "github.com/naeemaei/golang-clean-web-api/data/models" +import models "github.com/naeemaei/golang-clean-web-api/domain/model" func getBodyProperties(cat int) *[]models.Property { var props []models.Property = []models.Property{ diff --git a/src/infra/persistence/repository/postgres_repository.go b/src/infra/persistence/repository/postgres_repository.go new file mode 100644 index 0000000..f51bb98 --- /dev/null +++ b/src/infra/persistence/repository/postgres_repository.go @@ -0,0 +1,146 @@ +package repository + +import ( + "context" + "database/sql" + "reflect" + "time" + + "github.com/naeemaei/golang-clean-web-api/common" + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/constant" + filter "github.com/naeemaei/golang-clean-web-api/domain/filter" + database "github.com/naeemaei/golang-clean-web-api/infra/persistence/database" + "github.com/naeemaei/golang-clean-web-api/pkg/logging" + "github.com/naeemaei/golang-clean-web-api/pkg/metrics" + "github.com/naeemaei/golang-clean-web-api/pkg/service_errors" + "gorm.io/gorm" +) + +const softDeleteExp string = "id = ? and deleted_by is null" + +type BaseRepository[TEntity any] struct { + database *gorm.DB + logger logging.Logger + preloads []database.PreloadEntity +} + +func NewBaseRepository[TEntity any](cfg *config.Config, preloads []database.PreloadEntity) *BaseRepository[TEntity] { + return &BaseRepository[TEntity]{ + database: database.GetDb(), + logger: logging.NewLogger(cfg), + preloads: preloads, + } +} + +func (r BaseRepository[TEntity]) Create(ctx context.Context, entity TEntity) (TEntity, error) { + tx := r.database.WithContext(ctx).Begin() + err := tx. + Create(&entity). + Error + if err != nil { + tx.Rollback() + r.logger.Error(logging.Postgres, logging.Insert, err.Error(), nil) + metrics.DbCall.WithLabelValues(reflect.TypeOf(entity).String(), "Create", "Failed").Inc() + return entity, err + } + tx.Commit() + + metrics.DbCall.WithLabelValues(reflect.TypeOf(entity).String(), "Create", "Success").Inc() + return entity, nil +} + +func (r BaseRepository[TEntity]) Update(ctx context.Context, id int, entity map[string]interface{}) (TEntity, error) { + snakeMap := map[string]interface{}{} + for k, v := range entity { + snakeMap[common.ToSnakeCase(k)] = v + } + snakeMap["modified_by"] = &sql.NullInt64{Int64: int64(ctx.Value(constant.UserIdKey).(float64)), Valid: true} + snakeMap["modified_at"] = sql.NullTime{Valid: true, Time: time.Now().UTC()} + model := new(TEntity) + tx := r.database.WithContext(ctx).Begin() + if err := tx.Model(model). + Where(softDeleteExp, id). + Updates(snakeMap). + Error; err != nil { + tx.Rollback() + r.logger.Error(logging.Postgres, logging.Update, err.Error(), nil) + metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "Update", "Failed").Inc() + return *model, err + } + tx.Commit() + metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "Update", "Success").Inc() + return *model, nil +} + +func (r BaseRepository[TEntity]) Delete(ctx context.Context, id int) error { + tx := r.database.WithContext(ctx).Begin() + + model := new(TEntity) + + deleteMap := map[string]interface{}{ + "deleted_by": &sql.NullInt64{Int64: int64(ctx.Value(constant.UserIdKey).(float64)), Valid: true}, + "deleted_at": sql.NullTime{Valid: true, Time: time.Now().UTC()}, + } + + if ctx.Value(constant.UserIdKey) == nil { + return &service_errors.ServiceError{EndUserMessage: service_errors.PermissionDenied} + } + if cnt := tx. + Model(model). + Where(softDeleteExp, id). + Updates(deleteMap). + RowsAffected; cnt == 0 { + tx.Rollback() + r.logger.Error(logging.Postgres, logging.Update, service_errors.RecordNotFound, nil) + metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "Delete", "Failed").Inc() + return &service_errors.ServiceError{EndUserMessage: service_errors.RecordNotFound} + } + tx.Commit() + metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "Delete", "Success").Inc() + return nil +} + +func (r BaseRepository[TEntity]) GetById(ctx context.Context, id int) (TEntity, error) { + model := new(TEntity) + db := database.Preload(r.database, r.preloads) + err := db. + Where(softDeleteExp, id). + First(model). + Error + if err != nil { + metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "GetById", "Failed").Inc() + return *model, err + } + metrics.DbCall.WithLabelValues(reflect.TypeOf(*model).String(), "GetById", "Success").Inc() + return *model, nil +} + +func (r BaseRepository[TEntity]) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (int64, *[]TEntity, error) { + model := new(TEntity) + var items *[]TEntity + + db := database.Preload(r.database, r.preloads) + query := database.GenerateDynamicQuery[TEntity](&req.DynamicFilter) + sort := database.GenerateDynamicSort[TEntity](&req.DynamicFilter) + var totalRows int64 = 0 + + db. + Model(model). + Where(query). + Count(&totalRows) + + err := db. + Where(query). + Offset(req.GetOffset()). + Limit(req.GetPageSize()). + Order(sort). + Find(&items). + Error + + if err != nil { + return 0, &[]TEntity{}, err + } + return totalRows, items, err + +} diff --git a/src/infra/persistence/repository/postgres_user_repository.go b/src/infra/persistence/repository/postgres_user_repository.go new file mode 100644 index 0000000..1e4afc2 --- /dev/null +++ b/src/infra/persistence/repository/postgres_user_repository.go @@ -0,0 +1,121 @@ +package repository + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/constant" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + database "github.com/naeemaei/golang-clean-web-api/infra/persistence/database" + "github.com/naeemaei/golang-clean-web-api/pkg/logging" + "golang.org/x/crypto/bcrypt" + "gorm.io/gorm" +) + +const userFilterExp string = "username = ?" +const countFilterExp string = "count(*) > 0" + +type PostgresUserRepository struct { + *BaseRepository[model.User] +} + +func NewUserRepository(cfg *config.Config) *PostgresUserRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{} + return &PostgresUserRepository{BaseRepository: NewBaseRepository[model.User](cfg, preloads)} +} + +func (r *PostgresUserRepository) CreateUser(ctx context.Context, u model.User) (model.User, error) { + + roleId, err := r.GetDefaultRole(ctx) + if err != nil { + r.logger.Error(logging.Postgres, logging.DefaultRoleNotFound, err.Error(), nil) + return u, err + } + tx := r.database.WithContext(ctx).Begin() + err = tx.Create(&u).Error + if err != nil { + tx.Rollback() + r.logger.Error(logging.Postgres, logging.Rollback, err.Error(), nil) + return u, err + } + err = tx.Create(&model.UserRole{RoleId: roleId, UserId: u.Id}).Error + if err != nil { + tx.Rollback() + r.logger.Error(logging.Postgres, logging.Rollback, err.Error(), nil) + return u, err + } + tx.Commit() + return u, nil +} + +func (r *PostgresUserRepository) FetchUserInfo(ctx context.Context, username string, password string) (model.User, error) { + var user model.User + err := r.database.WithContext(ctx). + Model(&model.User{}). + Where(userFilterExp, username). + Preload("UserRoles", func(tx *gorm.DB) *gorm.DB { + return tx.Preload("Role") + }). + Find(&user).Error + + if err != nil { + return user, err + } + + err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) + if err != nil { + return user, err + } + + return user, nil +} + +func (r *PostgresUserRepository) ExistsEmail(ctx context.Context, email string) (bool, error) { + var exists bool + if err := r.database.WithContext(ctx).Model(&model.User{}). + Select(countFilterExp). + Where("email = ?", email). + Find(&exists). + Error; err != nil { + r.logger.Error(logging.Postgres, logging.Select, err.Error(), nil) + return false, err + } + return exists, nil +} + +func (r *PostgresUserRepository) ExistsUsername(ctx context.Context, username string) (bool, error) { + var exists bool + if err := r.database.WithContext(ctx).Model(&model.User{}). + Select(countFilterExp). + Where(userFilterExp, username). + Find(&exists). + Error; err != nil { + r.logger.Error(logging.Postgres, logging.Select, err.Error(), nil) + return false, err + } + return exists, nil +} + +func (r *PostgresUserRepository) ExistsMobileNumber(ctx context.Context, mobileNumber string) (bool, error) { + var exists bool + if err := r.database.WithContext(ctx).Model(&model.User{}). + Select(countFilterExp). + Where("mobile_number = ?", mobileNumber). + Find(&exists). + Error; err != nil { + r.logger.Error(logging.Postgres, logging.Select, err.Error(), nil) + return false, err + } + return exists, nil +} + +func (r *PostgresUserRepository) GetDefaultRole(ctx context.Context) (roleId int, err error) { + + if err = r.database.WithContext(ctx).Model(&model.Role{}). + Select("id"). + Where("name = ?", constant.DefaultRoleName). + First(&roleId).Error; err != nil { + return 0, err + } + return roleId, nil +} From 1936883ba9a2e1baddaaefa475b6c6a77da314ee Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 18:57:30 +0330 Subject: [PATCH 06/18] Change constant directory location --- src/{constants => constant}/constanst.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/{constants => constant}/constanst.go (96%) diff --git a/src/constants/constanst.go b/src/constant/constanst.go similarity index 96% rename from src/constants/constanst.go rename to src/constant/constanst.go index 13b0c41..d41e2d3 100644 --- a/src/constants/constanst.go +++ b/src/constant/constanst.go @@ -1,4 +1,4 @@ -package constants +package constant const ( // User From fd7d2dbbce7e67f7f6909f98a987f10c70deee95 Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 18:58:04 +0330 Subject: [PATCH 07/18] Change validation directory location --- src/api/{validations => validation}/custom.go | 0 src/api/{validations => validation}/mobile.go | 0 src/api/{validations => validation}/password.go | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/api/{validations => validation}/custom.go (100%) rename src/api/{validations => validation}/mobile.go (100%) rename src/api/{validations => validation}/password.go (100%) diff --git a/src/api/validations/custom.go b/src/api/validation/custom.go similarity index 100% rename from src/api/validations/custom.go rename to src/api/validation/custom.go diff --git a/src/api/validations/mobile.go b/src/api/validation/mobile.go similarity index 100% rename from src/api/validations/mobile.go rename to src/api/validation/mobile.go diff --git a/src/api/validations/password.go b/src/api/validation/password.go similarity index 100% rename from src/api/validations/password.go rename to src/api/validation/password.go From 0623ece4e08acab2f8f77a12d2909c682009a1a7 Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 18:58:55 +0330 Subject: [PATCH 08/18] Change middleware directory location --- src/api/{middlewares => middleware}/auth.go | 30 +++++++++---------- src/api/{middlewares => middleware}/cors.go | 2 +- .../custom_recovery.go | 2 +- .../{middlewares => middleware}/limiter.go | 2 +- src/api/{middlewares => middleware}/logger.go | 2 +- .../otp_limiter.go | 4 +-- .../{middlewares => middleware}/prometheus.go | 2 +- .../test_middleware.go | 2 +- 8 files changed, 23 insertions(+), 23 deletions(-) rename src/api/{middlewares => middleware}/auth.go (68%) rename src/api/{middlewares => middleware}/cors.go (97%) rename src/api/{middlewares => middleware}/custom_recovery.go (96%) rename src/api/{middlewares => middleware}/limiter.go (96%) rename src/api/{middlewares => middleware}/logger.go (99%) rename src/api/{middlewares => middleware}/otp_limiter.go (93%) rename src/api/{middlewares => middleware}/prometheus.go (95%) rename src/api/{middlewares => middleware}/test_middleware.go (93%) diff --git a/src/api/middlewares/auth.go b/src/api/middleware/auth.go similarity index 68% rename from src/api/middlewares/auth.go rename to src/api/middleware/auth.go index cce871a..53139b6 100644 --- a/src/api/middlewares/auth.go +++ b/src/api/middleware/auth.go @@ -1,4 +1,4 @@ -package middlewares +package middleware import ( "fmt" @@ -9,23 +9,23 @@ import ( "github.com/golang-jwt/jwt" "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/constants" + constant "github.com/naeemaei/golang-clean-web-api/constant" "github.com/naeemaei/golang-clean-web-api/pkg/service_errors" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/usecase" ) func Authentication(cfg *config.Config) gin.HandlerFunc { - var tokenService = services.NewTokenService(cfg) + var tokenUsecase = usecase.NewTokenUsecase(cfg) return func(c *gin.Context) { var err error claimMap := map[string]interface{}{} - auth := c.GetHeader(constants.AuthorizationHeaderKey) + auth := c.GetHeader(constant.AuthorizationHeaderKey) token := strings.Split(auth, " ") if auth == "" || len(token) < 2 { err = &service_errors.ServiceError{EndUserMessage: service_errors.TokenRequired} } else { - claimMap, err = tokenService.GetClaims(token[1]) + claimMap, err = tokenUsecase.GetClaims(token[1]) if err != nil { switch err.(*jwt.ValidationError).Errors { case jwt.ValidationErrorExpired: @@ -42,14 +42,14 @@ func Authentication(cfg *config.Config) gin.HandlerFunc { return } - c.Set(constants.UserIdKey, claimMap[constants.UserIdKey]) - c.Set(constants.FirstNameKey, claimMap[constants.FirstNameKey]) - c.Set(constants.LastNameKey, claimMap[constants.LastNameKey]) - c.Set(constants.UsernameKey, claimMap[constants.UsernameKey]) - c.Set(constants.EmailKey, claimMap[constants.EmailKey]) - c.Set(constants.MobileNumberKey, claimMap[constants.MobileNumberKey]) - c.Set(constants.RolesKey, claimMap[constants.RolesKey]) - c.Set(constants.ExpireTimeKey, claimMap[constants.ExpireTimeKey]) + c.Set(constant.UserIdKey, claimMap[constant.UserIdKey]) + c.Set(constant.FirstNameKey, claimMap[constant.FirstNameKey]) + c.Set(constant.LastNameKey, claimMap[constant.LastNameKey]) + c.Set(constant.UsernameKey, claimMap[constant.UsernameKey]) + c.Set(constant.EmailKey, claimMap[constant.EmailKey]) + c.Set(constant.MobileNumberKey, claimMap[constant.MobileNumberKey]) + c.Set(constant.RolesKey, claimMap[constant.RolesKey]) + c.Set(constant.ExpireTimeKey, claimMap[constant.ExpireTimeKey]) c.Next() } @@ -61,7 +61,7 @@ func Authorization(validRoles []string) gin.HandlerFunc { c.AbortWithStatusJSON(http.StatusForbidden, helper.GenerateBaseResponse(nil, false, helper.ForbiddenError)) return } - rolesVal := c.Keys[constants.RolesKey] + rolesVal := c.Keys[constant.RolesKey] fmt.Println(rolesVal) if rolesVal == nil { c.AbortWithStatusJSON(http.StatusForbidden, helper.GenerateBaseResponse(nil, false, helper.ForbiddenError)) diff --git a/src/api/middlewares/cors.go b/src/api/middleware/cors.go similarity index 97% rename from src/api/middlewares/cors.go rename to src/api/middleware/cors.go index c683d0c..1c91fc5 100644 --- a/src/api/middlewares/cors.go +++ b/src/api/middleware/cors.go @@ -1,4 +1,4 @@ -package middlewares +package middleware import ( "github.com/gin-gonic/gin" diff --git a/src/api/middlewares/custom_recovery.go b/src/api/middleware/custom_recovery.go similarity index 96% rename from src/api/middlewares/custom_recovery.go rename to src/api/middleware/custom_recovery.go index 962529c..e9c1033 100644 --- a/src/api/middlewares/custom_recovery.go +++ b/src/api/middleware/custom_recovery.go @@ -1,4 +1,4 @@ -package middlewares +package middleware import ( "net/http" diff --git a/src/api/middlewares/limiter.go b/src/api/middleware/limiter.go similarity index 96% rename from src/api/middlewares/limiter.go rename to src/api/middleware/limiter.go index b635d12..d771e85 100644 --- a/src/api/middlewares/limiter.go +++ b/src/api/middleware/limiter.go @@ -1,4 +1,4 @@ -package middlewares +package middleware import ( "net/http" diff --git a/src/api/middlewares/logger.go b/src/api/middleware/logger.go similarity index 99% rename from src/api/middlewares/logger.go rename to src/api/middleware/logger.go index 1093ff7..a3e0b1f 100644 --- a/src/api/middlewares/logger.go +++ b/src/api/middleware/logger.go @@ -1,4 +1,4 @@ -package middlewares +package middleware import ( "bytes" diff --git a/src/api/middlewares/otp_limiter.go b/src/api/middleware/otp_limiter.go similarity index 93% rename from src/api/middlewares/otp_limiter.go rename to src/api/middleware/otp_limiter.go index a366404..0d2d3fb 100644 --- a/src/api/middlewares/otp_limiter.go +++ b/src/api/middleware/otp_limiter.go @@ -1,4 +1,4 @@ -package middlewares +package middleware import ( "errors" @@ -17,7 +17,7 @@ func OtpLimiter(cfg *config.Config) gin.HandlerFunc { return func(c *gin.Context) { limiter := limiter.GetLimiter(c.Request.RemoteAddr) if !limiter.Allow() { - c.AbortWithStatusJSON(http.StatusTooManyRequests, helper.GenerateBaseResponseWithError(nil, false, helper.OtpLimiterError, errors.New("Not allowed"))) + c.AbortWithStatusJSON(http.StatusTooManyRequests, helper.GenerateBaseResponseWithError(nil, false, helper.OtpLimiterError, errors.New("not allowed"))) c.Abort() } else { c.Next() diff --git a/src/api/middlewares/prometheus.go b/src/api/middleware/prometheus.go similarity index 95% rename from src/api/middlewares/prometheus.go rename to src/api/middleware/prometheus.go index 6d7bbb1..3ddd0e0 100644 --- a/src/api/middlewares/prometheus.go +++ b/src/api/middleware/prometheus.go @@ -1,4 +1,4 @@ -package middlewares +package middleware import ( "strconv" diff --git a/src/api/middlewares/test_middleware.go b/src/api/middleware/test_middleware.go similarity index 93% rename from src/api/middlewares/test_middleware.go rename to src/api/middleware/test_middleware.go index ea4a831..d30c1e5 100644 --- a/src/api/middlewares/test_middleware.go +++ b/src/api/middleware/test_middleware.go @@ -1,4 +1,4 @@ -package middlewares +package middleware import ( "net/http" From c00846e72bcc7c7b8605fa560968ca7f4a81935e Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 18:59:44 +0330 Subject: [PATCH 09/18] Add new items to log category and error constants --- src/pkg/logging/category.go | 1 + src/pkg/service_errors/error_code.go | 1 + 2 files changed, 2 insertions(+) diff --git a/src/pkg/logging/category.go b/src/pkg/logging/category.go index 1b25127..682cca6 100644 --- a/src/pkg/logging/category.go +++ b/src/pkg/logging/category.go @@ -32,6 +32,7 @@ const ( Api SubCategory = "Api" HashPassword SubCategory = "HashPassword" DefaultRoleNotFound SubCategory = "DefaultRoleNotFound" + FailedToCreateUser SubCategory = "FailedToCreateUser" // Validation MobileValidation SubCategory = "MobileValidation" diff --git a/src/pkg/service_errors/error_code.go b/src/pkg/service_errors/error_code.go index b944e1c..1b12e94 100644 --- a/src/pkg/service_errors/error_code.go +++ b/src/pkg/service_errors/error_code.go @@ -17,6 +17,7 @@ const ( EmailExists = "Email exists" UsernameExists = "Username exists" PermissionDenied = "Permission denied" + UsernameOrPasswordInvalid = "username or password invalid" // DB RecordNotFound = "record not found" From d70d3671606c8f3dc77d90e524864e2f04b4e627 Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 19:00:22 +0330 Subject: [PATCH 10/18] Add some mapper functions to data transfer objects --- src/api/api.go | 98 +++++++------- src/api/dto/base.go | 120 ----------------- src/api/dto/car.go | 276 +++++++++++++++++++++++++++++++++++++++- src/api/dto/city.go | 40 ++++++ src/api/dto/color.go | 41 ++++++ src/api/dto/company.go | 40 ++++++ src/api/dto/country.go | 27 ++++ src/api/dto/file.go | 60 +++++++++ src/api/dto/filter.go | 58 --------- src/api/dto/property.go | 63 +++++++++ src/api/dto/user.go | 12 ++ src/api/dto/year.go | 71 +++++++++++ 12 files changed, 678 insertions(+), 228 deletions(-) delete mode 100644 src/api/dto/base.go create mode 100644 src/api/dto/city.go create mode 100644 src/api/dto/color.go create mode 100644 src/api/dto/company.go create mode 100644 src/api/dto/country.go create mode 100644 src/api/dto/file.go delete mode 100644 src/api/dto/filter.go create mode 100644 src/api/dto/year.go diff --git a/src/api/api.go b/src/api/api.go index 4ce3d31..4ccd9c7 100644 --- a/src/api/api.go +++ b/src/api/api.go @@ -6,9 +6,9 @@ import ( "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/go-playground/validator/v10" - "github.com/naeemaei/golang-clean-web-api/api/middlewares" - "github.com/naeemaei/golang-clean-web-api/api/routers" - validation "github.com/naeemaei/golang-clean-web-api/api/validations" + "github.com/naeemaei/golang-clean-web-api/api/middleware" + "github.com/naeemaei/golang-clean-web-api/api/router" + validation "github.com/naeemaei/golang-clean-web-api/api/validation" "github.com/naeemaei/golang-clean-web-api/config" "github.com/naeemaei/golang-clean-web-api/docs" "github.com/naeemaei/golang-clean-web-api/pkg/logging" @@ -27,10 +27,10 @@ func InitServer(cfg *config.Config) { RegisterValidators() RegisterPrometheus() - r.Use(middlewares.DefaultStructuredLogger(cfg)) - r.Use(middlewares.Cors(cfg)) - r.Use(middlewares.Prometheus()) - r.Use(gin.Logger(), gin.CustomRecovery(middlewares.ErrorHandler) /*middlewares.TestMiddleware()*/, middlewares.LimitByRequest()) + r.Use(middleware.DefaultStructuredLogger(cfg)) + r.Use(middleware.Cors(cfg)) + r.Use(middleware.Prometheus()) + r.Use(gin.Logger(), gin.CustomRecovery(middleware.ErrorHandler) /*middleware.TestMiddleware()*/, middleware.LimitByRequest()) RegisterRoutes(r, cfg) RegisterSwagger(r, cfg) @@ -49,63 +49,63 @@ func RegisterRoutes(r *gin.Engine, cfg *config.Config) { { // Test health := v1.Group("/health") - testRouter := v1.Group("/test" /*middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})*/) + testRouter := v1.Group("/test" /*middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})*/) // User users := v1.Group("/users") // Base - countries := v1.Group("/countries", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - cities := v1.Group("/cities", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - files := v1.Group("/files", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - companies := v1.Group("/companies", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - colors := v1.Group("/colors", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - years := v1.Group("/years", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) + countries := v1.Group("/countries", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + cities := v1.Group("/cities", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + files := v1.Group("/files", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + companies := v1.Group("/companies", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + colors := v1.Group("/colors", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + years := v1.Group("/years", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) // Property - properties := v1.Group("/properties", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - propertyCategories := v1.Group("/property-categories", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) + properties := v1.Group("/properties", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + propertyCategories := v1.Group("/property-categories", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) // Car - carTypes := v1.Group("/car-types", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - gearboxes := v1.Group("/gearboxes", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - carModels := v1.Group("/car-models", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - carModelColors := v1.Group("/car-model-colors", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - carModelYears := v1.Group("/car-model-years", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - carModelPriceHistories := v1.Group("/car-model-price-histories", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - carModelImages := v1.Group("/car-model-images", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - carModelProperties := v1.Group("/car-model-properties", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin"})) - carModelComments := v1.Group("/car-model-comments", middlewares.Authentication(cfg), middlewares.Authorization([]string{"admin", "default"})) + carTypes := v1.Group("/car-types", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + gearboxes := v1.Group("/gearboxes", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + carModels := v1.Group("/car-models", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + carModelColors := v1.Group("/car-model-colors", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + carModelYears := v1.Group("/car-model-years", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + carModelPriceHistories := v1.Group("/car-model-price-histories", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + carModelImages := v1.Group("/car-model-images", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + carModelProperties := v1.Group("/car-model-properties", middleware.Authentication(cfg), middleware.Authorization([]string{"admin"})) + carModelComments := v1.Group("/car-model-comments", middleware.Authentication(cfg), middleware.Authorization([]string{"admin", "default"})) // Test - routers.Health(health) - routers.TestRouter(testRouter) + router.Health(health) + router.TestRouter(testRouter) // User - routers.User(users, cfg) + router.User(users, cfg) // Base - routers.Country(countries, cfg) - routers.City(cities, cfg) - routers.File(files, cfg) - routers.Company(companies, cfg) - routers.Color(colors, cfg) - routers.Year(years, cfg) + router.Country(countries, cfg) + router.City(cities, cfg) + router.File(files, cfg) + router.Company(companies, cfg) + router.Color(colors, cfg) + router.Year(years, cfg) // Property - routers.Property(properties, cfg) - routers.PropertyCategory(propertyCategories, cfg) + router.Property(properties, cfg) + router.PropertyCategory(propertyCategories, cfg) // Car - routers.CarType(carTypes, cfg) - routers.Gearbox(gearboxes, cfg) - routers.CarModel(carModels, cfg) - routers.CarModelColor(carModelColors, cfg) - routers.CarModelYear(carModelYears, cfg) - routers.CarModelPriceHistory(carModelPriceHistories, cfg) - routers.CarModelImage(carModelImages, cfg) - routers.CarModelProperty(carModelProperties, cfg) - routers.CarModelComment(carModelComments, cfg) + router.CarType(carTypes, cfg) + router.Gearbox(gearboxes, cfg) + router.CarModel(carModels, cfg) + router.CarModelColor(carModelColors, cfg) + router.CarModelYear(carModelYears, cfg) + router.CarModelPriceHistory(carModelPriceHistories, cfg) + router.CarModelImage(carModelImages, cfg) + router.CarModelProperty(carModelProperties, cfg) + router.CarModelComment(carModelComments, cfg) r.Static("/static", "./uploads") @@ -115,7 +115,7 @@ func RegisterRoutes(r *gin.Engine, cfg *config.Config) { v2 := api.Group("/v2") { health := v2.Group("/health") - routers.Health(health) + router.Health(health) } } @@ -144,14 +144,14 @@ func RegisterSwagger(r *gin.Engine, cfg *config.Config) { r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) } -func RegisterPrometheus(){ +func RegisterPrometheus() { err := prometheus.Register(metrics.DbCall) if err != nil { logger.Error(logging.Prometheus, logging.Startup, err.Error(), nil) } - + err = prometheus.Register(metrics.HttpDuration) if err != nil { logger.Error(logging.Prometheus, logging.Startup, err.Error(), nil) } -} \ No newline at end of file +} diff --git a/src/api/dto/base.go b/src/api/dto/base.go deleted file mode 100644 index 991d2ae..0000000 --- a/src/api/dto/base.go +++ /dev/null @@ -1,120 +0,0 @@ -package dto - -import ( - "mime/multipart" - "time" -) - -type CreateUpdateCountryRequest struct { - Name string `json:"name" binding:"required,alpha,min=3,max=20"` -} - -type CountryResponse struct { - Id int `json:"id"` - Name string `json:"name"` - Cities []CityResponse `json:"cities,omitempty"` - Companies []CompanyResponse `json:"companies,omitempty"` -} - -type CreateCityRequest struct { - Name string `json:"name" binding:"required,alpha,min=3,max=20"` - CountryId int `json:"countryId" binding:"required"` -} - -type UpdateCityRequest struct { - Name string `json:"name,omitempty" binding:"alpha,min=3,max=20"` - CountryId int `json:"countryId,omitempty"` -} -type CityResponse struct { - Id int `json:"id"` - Name string `json:"name"` - Country CountryResponse `json:"country,omitempty"` -} - -// File -type FileFormRequest struct { - File *multipart.FileHeader `json:"file" form:"file" binding:"required" swaggerignoer:"true"` -} - -type UploadFileRequest struct { - FileFormRequest - Description string `json:"description" form:"description" binding:"required"` -} - -type CreateFileRequest struct { - Name string `json:"name"` - Directory string `json:"directory"` - Description string `json:"description"` - MimeType string `json:"mimeType"` -} - -type UpdateFileRequest struct { - Description string `json:"description"` -} - -type FileResponse struct { - Id int `json:"id"` - Name string `json:"name"` - Directory string `json:"directory"` - Description string `json:"description"` - MimeType string `json:"mimeType"` -} - -type CreateCompanyRequest struct { - Name string `json:"name" binding:"required,alpha,min=3,max=20"` - CountryId int `json:"countryId" binding:"required"` -} - -type UpdateCompanyRequest struct { - Name string `json:"name,omitempty" binding:"alpha,min=3,max=20"` - CountryId int `json:"countryId,omitempty"` -} -type CompanyResponse struct { - Id int `json:"id"` - Name string `json:"name"` - Country CountryResponse `json:"country,omitempty"` -} - -type CreateColorRequest struct { - Name string `json:"name" binding:"alpha,min=3,max=15"` - HexCode string `json:"hexCode" binding:"min=7,max=7"` -} - -type UpdateColorRequest struct { - Name string `json:"name,omitempty" binding:"alpha,min=3,max=15"` - HexCode string `json:"hexCode,omitempty" binding:"min=7,max=7"` -} - -type ColorResponse struct { - Id int `json:"id"` - Name string `json:"name,omitempty"` - HexCode string `json:"hexCode,omitempty"` -} - -type CreatePersianYearRequest struct { - PersianTitle string `json:"persianTitle" binding:"min=4,max=4"` - Year int `json:"year"` - StartAt time.Time `json:"startAt"` - EndAt time.Time `json:"endAt"` -} - -type UpdatePersianYearRequest struct { - PersianTitle string `json:"persianTitle,omitempty" binding:"min=4,max=4"` - Year int `json:"year,omitempty"` - StartAt time.Time `json:"startAt,omitempty"` - EndAt time.Time `json:"endAt,omitempty"` -} - -type PersianYearResponse struct { - Id int `json:"id"` - PersianTitle string `json:"persianTitle,omitempty"` - Year int `json:"year,omitempty"` - StartAt time.Time `json:"startAt,omitempty"` - EndAt time.Time `json:"endAt,omitempty"` -} - -type PersianYearWithoutDateResponse struct { - Id int `json:"id"` - PersianTitle string `json:"persianTitle,omitempty"` - Year int `json:"year,omitempty"` -} diff --git a/src/api/dto/car.go b/src/api/dto/car.go index 21c7cd5..09ac4bb 100644 --- a/src/api/dto/car.go +++ b/src/api/dto/car.go @@ -1,6 +1,11 @@ package dto -import "time" +import ( + "sync" + "time" + + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) type CreateCarTypeRequest struct { Name string `json:"name" binding:"required,alpha,min=3,max=15"` @@ -163,3 +168,272 @@ type UserResponse struct { LastName string `json:"lastName"` Email string `json:"email"` } + +func ToCarTypeResponse(from dto.IdName) CarTypeResponse { + return CarTypeResponse{ + Id: from.Id, + Name: from.Name, + } +} + +func ToCreateCarType(from CreateCarTypeRequest) dto.Name { + return dto.Name{ + Name: from.Name, + } +} + +func ToUpdateCarType(from UpdateCarTypeRequest) dto.Name { + return dto.Name{ + Name: from.Name, + } +} + +func ToGearboxResponse(from dto.IdName) GearboxResponse { + return GearboxResponse{ + Id: from.Id, + Name: from.Name, + } +} + +func ToCreateGearbox(from CreateGearboxRequest) dto.Name { + return dto.Name{ + Name: from.Name, + } +} + +func ToUpdateGearbox(from UpdateGearboxRequest) dto.Name { + return dto.Name{ + Name: from.Name, + } +} + +func ToCarModelResponse(from dto.CarModel) CarModelResponse { + colors := []CarModelColorResponse{} + years := []CarModelYearResponse{} + images := []CarModelImageResponse{} + properties := []CarModelPropertyResponse{} + comments := []CarModelCommentResponse{} + + var wg sync.WaitGroup + wg.Add(5) + + go func() { + for _, item := range from.CarModelColors { + colors = append(colors, ToCarModelColorResponse(item)) + } + wg.Done() + }() + + go func() { + for _, item := range from.CarModelYears { + years = append(years, ToCarModelYearResponse(item)) + } + wg.Done() + }() + + go func() { + for _, item := range from.CarModelComments { + comments = append(comments, ToCarModelCommentResponse(item)) + } + wg.Done() + }() + + go func() { + for _, item := range from.CarModelImages { + images = append(images, ToCarModelImageResponse(item)) + } + wg.Done() + }() + + go func() { + for _, item := range from.CarModelProperties { + properties = append(properties, ToCarModelPropertyResponse(item)) + } + wg.Done() + }() + + wg.Wait() + + return CarModelResponse{ + Id: from.Id, + Name: from.Name, + CarType: ToCarTypeResponse(from.CarType), + Company: ToCompanyResponse(from.Company), + Gearbox: ToGearboxResponse(from.Gearbox), + CarModelColors: colors, + CarModelYears: years, + CarModelImages: images, + CarModelProperties: properties, + CarModelComments: comments, + } +} + +func ToCreateCarModel(from CreateCarModelRequest) dto.CreateCarModel { + return dto.CreateCarModel{ + Name: from.Name, + CompanyId: from.CompanyId, + CarTypeId: from.CarTypeId, + GearboxId: from.GearboxId, + } +} + +func ToUpdateCarModel(from UpdateCarModelRequest) dto.UpdateCarModel { + return dto.UpdateCarModel{ + Name: from.Name, + CompanyId: from.CompanyId, + CarTypeId: from.CarTypeId, + GearboxId: from.GearboxId, + } +} + +func ToCarModelColorResponse(from dto.CarModelColor) CarModelColorResponse { + return CarModelColorResponse{ + Id: from.Id, + Color: ToColorResponse(from.Color), + } +} + +func ToCreateCarModelColor(from CreateCarModelColorRequest) dto.CreateCarModelColor { + return dto.CreateCarModelColor{ + CarModelId: from.CarModelId, + ColorId: from.ColorId, + } +} + +func ToUpdateCarModelColor(from UpdateCarModelColorRequest) dto.UpdateCarModelColor { + return dto.UpdateCarModelColor{ + CarModelId: from.CarModelId, + ColorId: from.ColorId, + } +} + +func ToCarModelYearResponse(from dto.CarModelYear) CarModelYearResponse { + var histories []CarModelPriceHistoryResponse = []CarModelPriceHistoryResponse{} + + for _, item := range from.CarModelPriceHistories { + histories = append(histories, ToCarModelPriceHistoryResponse(item)) + } + return CarModelYearResponse{ + Id: from.Id, + PersianYear: ToPersianYearWithoutDateResponse(from.PersianYear), + CarModelId: from.CarModelId, + CarModelPriceHistories: histories, + } +} + +func ToCreateCarModelYear(from CreateCarModelYearRequest) dto.CreateCarModelYear { + return dto.CreateCarModelYear{ + CarModelId: from.CarModelId, + PersianYearId: from.PersianYearId, + } +} + +func ToUpdateCarModelYear(from UpdateCarModelYearRequest) dto.UpdateCarModelYear { + return dto.UpdateCarModelYear{ + CarModelId: from.CarModelId, + PersianYearId: from.PersianYearId, + } +} + +func ToCarModelPriceHistoryResponse(from dto.CarModelPriceHistory) CarModelPriceHistoryResponse { + return CarModelPriceHistoryResponse{ + Id: from.Id, + CarModelYearId: from.CarModelYearId, + PriceAt: from.PriceAt, + Price: from.Price, + } +} + +func ToCreateCarModelPriceHistory(from CreateCarModelPriceHistoryRequest) dto.CreateCarModelPriceHistory { + return dto.CreateCarModelPriceHistory{ + CarModelYearId: from.CarModelYearId, + PriceAt: from.PriceAt, + Price: from.Price, + } +} + +func ToUpdateCarModelPriceHistory(from UpdateCarModelPriceHistoryRequest) dto.UpdateCarModelPriceHistory { + return dto.UpdateCarModelPriceHistory{ + PriceAt: from.PriceAt, + Price: from.Price, + } +} + +func ToCarModelImageResponse(from dto.CarModelImage) CarModelImageResponse { + return CarModelImageResponse{ + Id: from.Id, + CarModelId: from.CarModelId, + IsMainImage: from.IsMainImage, + Image: ToFileResponse(from.Image), + } +} + +func ToCreateCarModelImage(from CreateCarModelImageRequest) dto.CreateCarModelImage { + return dto.CreateCarModelImage{ + CarModelId: from.CarModelId, + ImageId: from.ImageId, + IsMainImage: from.IsMainImage, + } +} + +func ToUpdateCarModelImage(from UpdateCarModelImageRequest) dto.UpdateCarModelImage { + return dto.UpdateCarModelImage{ + IsMainImage: from.IsMainImage, + } +} + +func ToCarModelPropertyResponse(from dto.CarModelProperty) CarModelPropertyResponse { + return CarModelPropertyResponse{ + Id: from.Id, + CarModelId: from.CarModelId, + Property: ToPropertyResponse(from.Property), + Value: from.Value, + } +} + +func ToCreateCarModelProperty(from CreateCarModelPropertyRequest) dto.CreateCarModelProperty { + return dto.CreateCarModelProperty{ + CarModelId: from.CarModelId, + PropertyId: from.PropertyId, + Value: from.Value, + } +} + +func ToUpdateCarModelProperty(from UpdateCarModelPropertyRequest) dto.UpdateCarModelProperty { + return dto.UpdateCarModelProperty{ + Value: from.Value, + } +} + +func ToCarModelCommentResponse(from dto.CarModelComment) CarModelCommentResponse { + return CarModelCommentResponse{ + Id: from.Id, + CarModelId: from.CarModelId, + Message: from.Message, + User: ToUserResponse(from.User), + } +} + +func ToCreateCarModelComment(from CreateCarModelCommentRequest) dto.CreateCarModelComment { + return dto.CreateCarModelComment{ + CarModelId: from.CarModelId, + UserId: from.UserId, + Message: from.Message, + } +} + +func ToUpdateCarModelComment(from UpdateCarModelCommentRequest) dto.UpdateCarModelComment { + return dto.UpdateCarModelComment{ + Message: from.Message, + } +} + +func ToUserResponse(from dto.User) UserResponse { + return UserResponse{ + Id: from.Id, + Username: from.Username, + FirstName: from.FirstName, + LastName: from.LastName, + Email: from.Email, + } +} diff --git a/src/api/dto/city.go b/src/api/dto/city.go new file mode 100644 index 0000000..c613029 --- /dev/null +++ b/src/api/dto/city.go @@ -0,0 +1,40 @@ +package dto + +import "github.com/naeemaei/golang-clean-web-api/usecase/dto" + +type CreateCityRequest struct { + Name string `json:"name" binding:"required,alpha,min=3,max=20"` + CountryId int `json:"countryId" binding:"required"` +} + +type UpdateCityRequest struct { + Name string `json:"name,omitempty" binding:"alpha,min=3,max=20"` + CountryId int `json:"countryId,omitempty"` +} +type CityResponse struct { + Id int `json:"id"` + Name string `json:"name"` + Country CountryResponse `json:"country,omitempty"` +} + +func ToCityResponse(from dto.City) CityResponse { + return CityResponse{ + Id: from.Id, + Name: from.Name, + Country: ToCountryResponse(from.Country), + } +} + +func ToCreateCity(from CreateCityRequest) dto.CreateCity { + return dto.CreateCity{ + Name: from.Name, + CountryId: from.CountryId, + } +} + +func ToUpdateCity(from UpdateCityRequest) dto.UpdateCity { + return dto.UpdateCity{ + Name: from.Name, + CountryId: from.CountryId, + } +} diff --git a/src/api/dto/color.go b/src/api/dto/color.go new file mode 100644 index 0000000..87f4524 --- /dev/null +++ b/src/api/dto/color.go @@ -0,0 +1,41 @@ +package dto + +import "github.com/naeemaei/golang-clean-web-api/usecase/dto" + +type CreateColorRequest struct { + Name string `json:"name" binding:"alpha,min=3,max=15"` + HexCode string `json:"hexCode" binding:"min=7,max=7"` +} + +type UpdateColorRequest struct { + Name string `json:"name,omitempty" binding:"alpha,min=3,max=15"` + HexCode string `json:"hexCode,omitempty" binding:"min=7,max=7"` +} + +type ColorResponse struct { + Id int `json:"id"` + Name string `json:"name,omitempty"` + HexCode string `json:"hexCode,omitempty"` +} + +func ToColorResponse(from dto.Color) ColorResponse { + return ColorResponse{ + Id: from.Id, + Name: from.Name, + HexCode: from.HexCode, + } +} + +func ToCreateColor(from CreateColorRequest) dto.CreateColor { + return dto.CreateColor{ + Name: from.Name, + HexCode: from.HexCode, + } +} + +func ToUpdateColor(from CreateColorRequest) dto.UpdateColor { + return dto.UpdateColor{ + Name: from.Name, + HexCode: from.HexCode, + } +} diff --git a/src/api/dto/company.go b/src/api/dto/company.go new file mode 100644 index 0000000..3a8e938 --- /dev/null +++ b/src/api/dto/company.go @@ -0,0 +1,40 @@ +package dto + +import "github.com/naeemaei/golang-clean-web-api/usecase/dto" + +type CreateCompanyRequest struct { + Name string `json:"name" binding:"required,alpha,min=3,max=20"` + CountryId int `json:"countryId" binding:"required"` +} + +type UpdateCompanyRequest struct { + Name string `json:"name,omitempty" binding:"alpha,min=3,max=20"` + CountryId int `json:"countryId,omitempty"` +} +type CompanyResponse struct { + Id int `json:"id"` + Name string `json:"name"` + Country CountryResponse `json:"country,omitempty"` +} + +func ToCompanyResponse(from dto.Company) CompanyResponse { + return CompanyResponse{ + Id: from.Id, + Name: from.Name, + Country: ToCountryResponse(from.Country), + } +} + +func ToCreateCompany(from CreateCompanyRequest) dto.CreateCompany { + return dto.CreateCompany{ + Name: from.Name, + CountryId: from.CountryId, + } +} + +func ToUpdateCompany(from UpdateCompanyRequest) dto.UpdateCompany { + return dto.UpdateCompany{ + Name: from.Name, + CountryId: from.CountryId, + } +} diff --git a/src/api/dto/country.go b/src/api/dto/country.go new file mode 100644 index 0000000..579d1a7 --- /dev/null +++ b/src/api/dto/country.go @@ -0,0 +1,27 @@ +package dto + +import "github.com/naeemaei/golang-clean-web-api/usecase/dto" + +type CreateUpdateCountryRequest struct { + Name string `json:"name" binding:"required,alpha,min=3,max=20"` +} + +type CountryResponse struct { + Id int `json:"id"` + Name string `json:"name"` + Cities []CityResponse `json:"cities,omitempty"` + Companies []CompanyResponse `json:"companies,omitempty"` +} + +func ToCountryResponse(from dto.Country) CountryResponse { + return CountryResponse{ + Id: from.Id, + Name: from.Name, + } +} + +func ToCreateUpdateCountry(from CreateUpdateCountryRequest) dto.Name { + return dto.Name{ + Name: from.Name, + } +} diff --git a/src/api/dto/file.go b/src/api/dto/file.go new file mode 100644 index 0000000..e9b6246 --- /dev/null +++ b/src/api/dto/file.go @@ -0,0 +1,60 @@ +package dto + +import ( + "mime/multipart" + + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type FileFormRequest struct { + File *multipart.FileHeader `json:"file" form:"file" binding:"required" swaggerignore:"true"` +} + +type UploadFileRequest struct { + FileFormRequest + Description string `json:"description" form:"description" binding:"required"` +} + +type CreateFileRequest struct { + Name string `json:"name"` + Directory string `json:"directory"` + Description string `json:"description"` + MimeType string `json:"mimeType"` +} + +type UpdateFileRequest struct { + Description string `json:"description"` +} + +type FileResponse struct { + Id int `json:"id"` + Name string `json:"name"` + Directory string `json:"directory"` + Description string `json:"description"` + MimeType string `json:"mimeType"` +} + +func ToFileResponse(from dto.File) FileResponse { + return FileResponse{ + Id: from.Id, + Name: from.Name, + Directory: from.Directory, + Description: from.Description, + MimeType: from.MimeType, + } +} + +func ToCreateFile(from CreateFileRequest) dto.CreateFile { + return dto.CreateFile{ + Name: from.Name, + Directory: from.Directory, + Description: from.Description, + MimeType: from.MimeType, + } +} + +func ToUpdateFile(from UpdateFileRequest) dto.UpdateFile { + return dto.UpdateFile{ + Description: from.Description, + } +} diff --git a/src/api/dto/filter.go b/src/api/dto/filter.go deleted file mode 100644 index a1c3c37..0000000 --- a/src/api/dto/filter.go +++ /dev/null @@ -1,58 +0,0 @@ -package dto - -type Sort struct { - ColId string `json:"colId"` - Sort string `json:"sort"` -} - -type Filter struct { - // contains notContains equals notEqual startsWith lessThan lessThanOrEqual greaterThan greaterThanOrEqual inRange endsWith - Type string `json:"type"` - From string `json:"from"` - To string `json:"to"` - // text number - FilterType string `json:"filterType"` -} - -type DynamicFilter struct { - Sort *[]Sort `json:"sort"` - Filter map[string]Filter `json:"filter"` -} - -type PagedList[T any] struct { - PageNumber int `json:"pageNumber"` - TotalRows int64 `json:"totalRows"` - TotalPages int `json:"totalPages"` - HasPreviousPage bool `json:"hasPreviousPage"` - HasNextPage bool `json:"hasNextPage"` - Items *[]T `json:"items"` -} - -type PaginationInput struct { - PageSize int `json:"pageSize"` - PageNumber int `json:"pageNumber"` -} - -type PaginationInputWithFilter struct { - PaginationInput - DynamicFilter -} - -func (p *PaginationInputWithFilter) GetOffset() int { - // 2 , 10 => 11-20 - return (p.GetPageNumber() - 1) * p.GetPageSize() -} - -func (p *PaginationInputWithFilter) GetPageSize() int { - if p.PageSize == 0 { - p.PageSize = 10 - } - return p.PageSize -} - -func (p *PaginationInputWithFilter) GetPageNumber() int { - if p.PageNumber == 0 { - p.PageNumber = 1 - } - return p.PageNumber -} diff --git a/src/api/dto/property.go b/src/api/dto/property.go index 7ba769b..02eaec6 100644 --- a/src/api/dto/property.go +++ b/src/api/dto/property.go @@ -1,5 +1,7 @@ package dto +import "github.com/naeemaei/golang-clean-web-api/usecase/dto" + type CreatePropertyCategoryRequest struct { Name string `json:"name" binding:"required,alpha,min=3,max=50"` Icon string `json:"icon" binding:"max=1000"` @@ -44,3 +46,64 @@ type PropertyResponse struct { Unit string `json:"unit"` Category PropertyCategoryResponse `json:"category,omitempty"` } + +func ToPropertyResponse(from dto.Property) PropertyResponse { + return PropertyResponse{ + Id: from.Id, + Name: from.Name, + Icon: from.Icon, + DataType: from.DataType, + Unit: from.Unit, + Category: ToPropertyCategoryResponse(from.Category), + Description: from.Description, + } +} + +func ToCreateProperty(from CreatePropertyRequest) dto.CreateProperty { + return dto.CreateProperty{ + Name: from.Name, + Icon: from.Icon, + DataType: from.DataType, + Unit: from.Unit, + CategoryId: from.CategoryId, + Description: from.Description, + } +} + +func ToUpdateProperty(from UpdatePropertyRequest) dto.UpdateProperty { + return dto.UpdateProperty{ + Name: from.Name, + Icon: from.Icon, + DataType: from.DataType, + Unit: from.Unit, + CategoryId: from.CategoryId, + Description: from.Description, + } +} + +func ToPropertyCategoryResponse(from dto.PropertyCategory) PropertyCategoryResponse { + properties := []PropertyResponse{} + for _, item := range from.Properties { + properties = append(properties, ToPropertyResponse(item)) + } + return PropertyCategoryResponse{ + Id: from.Id, + Name: from.Name, + Icon: from.Icon, + Properties: properties, + } +} + +func ToCreatePropertyCategory(from CreatePropertyCategoryRequest) dto.CreatePropertyCategory { + return dto.CreatePropertyCategory{ + Name: from.Name, + Icon: from.Icon, + } +} + +func ToUpdatePropertyCategory(from UpdatePropertyCategoryRequest) dto.UpdatePropertyCategory { + return dto.UpdatePropertyCategory{ + Name: from.Name, + Icon: from.Icon, + } +} diff --git a/src/api/dto/user.go b/src/api/dto/user.go index 40bad7c..760cbe8 100644 --- a/src/api/dto/user.go +++ b/src/api/dto/user.go @@ -1,5 +1,7 @@ package dto +import usecase "github.com/naeemaei/golang-clean-web-api/usecase/dto" + type GetOtpRequest struct { MobileNumber string `json:"mobileNumber" binding:"required,mobile,min=11,max=11"` } @@ -28,3 +30,13 @@ type LoginByUsernameRequest struct { Username string `json:"username" binding:"required,min=5"` Password string `json:"password" binding:"required,min=6"` } + +func (from RegisterUserByUsernameRequest) ToRegisterUserByUsername() usecase.RegisterUserByUsername { + return usecase.RegisterUserByUsername{ + Username: from.Username, + FirstName: from.FirstName, + LastName: from.LastName, + Email: from.Email, + Password: from.Password, + } +} diff --git a/src/api/dto/year.go b/src/api/dto/year.go new file mode 100644 index 0000000..20bb790 --- /dev/null +++ b/src/api/dto/year.go @@ -0,0 +1,71 @@ +package dto + +import ( + "time" + + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CreatePersianYearRequest struct { + PersianTitle string `json:"persianTitle" binding:"min=4,max=4"` + Year int `json:"year"` + StartAt time.Time `json:"startAt"` + EndAt time.Time `json:"endAt"` +} + +type UpdatePersianYearRequest struct { + PersianTitle string `json:"persianTitle,omitempty" binding:"min=4,max=4"` + Year int `json:"year,omitempty"` + StartAt time.Time `json:"startAt,omitempty"` + EndAt time.Time `json:"endAt,omitempty"` +} + +type PersianYearResponse struct { + Id int `json:"id"` + PersianTitle string `json:"persianTitle,omitempty"` + Year int `json:"year,omitempty"` + StartAt time.Time `json:"startAt,omitempty"` + EndAt time.Time `json:"endAt,omitempty"` +} + +type PersianYearWithoutDateResponse struct { + Id int `json:"id"` + PersianTitle string `json:"persianTitle,omitempty"` + Year int `json:"year,omitempty"` +} + +func ToPersianYearResponse(from dto.PersianYear) PersianYearResponse { + return PersianYearResponse{ + Id: from.Id, + PersianTitle: from.PersianTitle, + Year: from.Year, + StartAt: from.StartAt, + EndAt: from.EndAt, + } +} + +func ToPersianYearWithoutDateResponse(from dto.PersianYearWithoutDate) PersianYearWithoutDateResponse { + return PersianYearWithoutDateResponse{ + Id: from.Id, + PersianTitle: from.PersianTitle, + Year: from.Year, + } +} + +func ToCreatePersianYear(from CreatePersianYearRequest) dto.CreatePersianYear { + return dto.CreatePersianYear{ + PersianTitle: from.PersianTitle, + Year: from.Year, + StartAt: from.StartAt, + EndAt: from.EndAt, + } +} + +func ToUpdatePersianYear(from UpdatePersianYearRequest) dto.UpdatePersianYear { + return dto.UpdatePersianYear{ + PersianTitle: from.PersianTitle, + Year: from.Year, + StartAt: from.StartAt, + EndAt: from.EndAt, + } +} From a9af0cdd3800eefcb6dc3e7a578e00f43a3cfc6d Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 19:00:55 +0330 Subject: [PATCH 11/18] Update validation reference in base response --- src/api/helper/base_response.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/helper/base_response.go b/src/api/helper/base_response.go index f612263..1af19ae 100644 --- a/src/api/helper/base_response.go +++ b/src/api/helper/base_response.go @@ -1,11 +1,11 @@ package helper -import validation "github.com/naeemaei/golang-clean-web-api/api/validations" +import validation "github.com/naeemaei/golang-clean-web-api/api/validation" type BaseHttpResponse struct { Result any `json:"result"` Success bool `json:"success"` - ResultCode ResultCode `json:"resultCode"` + ResultCode ResultCode `json:"resultCode"` ValidationErrors *[]validation.ValidationError `json:"validationErrors"` Error any `json:"error"` } From 9a8686dca18882ae4080d3dd6e8466c86dc8cd5f Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 19:03:07 +0330 Subject: [PATCH 12/18] Change mapper input from --- src/common/mapper.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/common/mapper.go b/src/common/mapper.go index 0ae1ff7..cb644bd 100644 --- a/src/common/mapper.go +++ b/src/common/mapper.go @@ -2,15 +2,16 @@ package common import "encoding/json" -func TypeConverter[T any](data any) (*T, error) { +// TODO: must write struct to struct mapper instead of this function +func TypeConverter[T any](data any) (T, error) { var result T dataJson, err := json.Marshal(&data) if err != nil { - return nil, err + return result, err } err = json.Unmarshal(dataJson, &result) if err != nil { - return nil, err + return result, err } - return &result, nil + return result, nil } From 2958db8de34e2b53fb6cf2d13419dba103aa73ac Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 19:03:47 +0330 Subject: [PATCH 13/18] Create dependency manager to create repositories based its contracts --- src/dependency/dependency.go | 113 +++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/dependency/dependency.go diff --git a/src/dependency/dependency.go b/src/dependency/dependency.go new file mode 100644 index 0000000..a6c1f7d --- /dev/null +++ b/src/dependency/dependency.go @@ -0,0 +1,113 @@ +package dependency + +import ( + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/model" + contractRepository "github.com/naeemaei/golang-clean-web-api/domain/repository" + database "github.com/naeemaei/golang-clean-web-api/infra/persistence/database" + infraRepository "github.com/naeemaei/golang-clean-web-api/infra/persistence/repository" +) + +func GetUserRepository(cfg *config.Config) contractRepository.UserRepository { + return infraRepository.NewUserRepository(cfg) +} + +func GetPersianYearRepository(cfg *config.Config) contractRepository.PersianYearRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{} + return infraRepository.NewBaseRepository[model.PersianYear](cfg, preloads) +} + +func GetCountryRepository(cfg *config.Config) contractRepository.CountryRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{{Entity: "Cities"}, {Entity: "Companies"}} + return infraRepository.NewBaseRepository[model.Country](cfg, preloads) +} + +func GetCarModelColorRepository(cfg *config.Config) contractRepository.CarModelColorRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{{Entity: "Color"}} + return infraRepository.NewBaseRepository[model.CarModelColor](cfg, preloads) +} + +func GetCarModelCommentRepository(cfg *config.Config) contractRepository.CarModelCommentRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{{Entity: "User"}} + return infraRepository.NewBaseRepository[model.CarModelComment](cfg, preloads) +} + +func GetCarModelImageRepository(cfg *config.Config) contractRepository.CarModelImageRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{{Entity: "Image"}} + return infraRepository.NewBaseRepository[model.CarModelImage](cfg, preloads) +} + +func GetCarModelPriceHistoryRepository(cfg *config.Config) contractRepository.CarModelPriceHistoryRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{} + return infraRepository.NewBaseRepository[model.CarModelPriceHistory](cfg, preloads) +} + +func GetCarModelPropertyRepository(cfg *config.Config) contractRepository.CarModelPropertyRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{{Entity: "Property.Category"}} + return infraRepository.NewBaseRepository[model.CarModelProperty](cfg, preloads) +} + +func GetCarModelRepository(cfg *config.Config) contractRepository.CarModelRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{ + {Entity: "Company.Country"}, + {Entity: "CarType"}, + {Entity: "Gearbox"}, + {Entity: "CarModelColors.Color"}, + {Entity: "CarModelYears.PersianYear"}, + {Entity: "CarModelYears.CarModelPriceHistories"}, + {Entity: "CarModelProperties.Property.Category"}, + {Entity: "CarModelImages.Image"}, + {Entity: "CarModelComments.User"}, + } + return infraRepository.NewBaseRepository[model.CarModel](cfg, preloads) +} + +func GetCarModelYearRepository(cfg *config.Config) contractRepository.CarModelYearRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{{Entity: "PersianYear"}} + return infraRepository.NewBaseRepository[model.CarModelYear](cfg, preloads) +} + +func GetCarTypeRepository(cfg *config.Config) contractRepository.CarTypeRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{} + return infraRepository.NewBaseRepository[model.CarType](cfg, preloads) +} + +func GetCityRepository(cfg *config.Config) contractRepository.CityRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{{Entity: "Country"}} + return infraRepository.NewBaseRepository[model.City](cfg, preloads) +} + +func GetColorRepository(cfg *config.Config) contractRepository.ColorRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{} + return infraRepository.NewBaseRepository[model.Color](cfg, preloads) +} + +func GetCompanyRepository(cfg *config.Config) contractRepository.CompanyRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{{Entity: "Country"}} + return infraRepository.NewBaseRepository[model.Company](cfg, preloads) +} + +func GetFileRepository(cfg *config.Config) contractRepository.FileRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{} + return infraRepository.NewBaseRepository[model.File](cfg, preloads) +} + +func GetGearboxRepository(cfg *config.Config) contractRepository.GearboxRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{} + return infraRepository.NewBaseRepository[model.Gearbox](cfg, preloads) +} + +func GetPropertyCategoryRepository(cfg *config.Config) contractRepository.PropertyCategoryRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{{Entity: "Properties"}} + return infraRepository.NewBaseRepository[model.PropertyCategory](cfg, preloads) +} + +func GetPropertyRepository(cfg *config.Config) contractRepository.PropertyRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{{Entity: "Category"}} + return infraRepository.NewBaseRepository[model.Property](cfg, preloads) +} + +func GetRoleRepository(cfg *config.Config) contractRepository.RoleRepository { + var preloads []database.PreloadEntity = []database.PreloadEntity{} + return infraRepository.NewBaseRepository[model.Role](cfg, preloads) +} From e9ba84aa777b8e13418ebbfc98cae9b57c4c08f6 Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 19:04:15 +0330 Subject: [PATCH 14/18] Write usecases --- src/usecase/base_usecase.go | 74 ++++++++++ src/usecase/carModelColor_usecase.go | 46 +++++++ src/usecase/carModelComment_usecase.go | 46 +++++++ src/usecase/carModelImage_usecase.go | 46 +++++++ src/usecase/carModelPriceHistory_usecase.go | 46 +++++++ src/usecase/carModelProperty_usecase.go | 46 +++++++ src/usecase/carModelYear_usecase.go | 46 +++++++ src/usecase/carModel_usecase.go | 46 +++++++ src/usecase/carType_usecase.go | 46 +++++++ src/usecase/city_usecase.go | 46 +++++++ src/usecase/color_usecase.go | 46 +++++++ src/usecase/company_usecase.go | 46 +++++++ src/usecase/country_usecase.go | 46 +++++++ src/usecase/dto/base.go | 108 +++++++++++++++ src/usecase/dto/car.go | 138 +++++++++++++++++++ src/usecase/dto/property.go | 44 ++++++ src/usecase/dto/user.go | 36 +++++ src/usecase/file_usecase.go | 46 +++++++ src/usecase/gearbox_usecase.go | 46 +++++++ src/usecase/otp_usecase.go | 79 +++++++++++ src/usecase/propertyCategory_usecase.go | 46 +++++++ src/usecase/property_usecase.go | 46 +++++++ src/usecase/token_usecase.go | 107 +++++++++++++++ src/usecase/user_usecase.go | 145 ++++++++++++++++++++ src/usecase/year_usecase.go | 46 +++++++ 25 files changed, 1513 insertions(+) create mode 100644 src/usecase/base_usecase.go create mode 100644 src/usecase/carModelColor_usecase.go create mode 100644 src/usecase/carModelComment_usecase.go create mode 100644 src/usecase/carModelImage_usecase.go create mode 100644 src/usecase/carModelPriceHistory_usecase.go create mode 100644 src/usecase/carModelProperty_usecase.go create mode 100644 src/usecase/carModelYear_usecase.go create mode 100644 src/usecase/carModel_usecase.go create mode 100644 src/usecase/carType_usecase.go create mode 100644 src/usecase/city_usecase.go create mode 100644 src/usecase/color_usecase.go create mode 100644 src/usecase/company_usecase.go create mode 100644 src/usecase/country_usecase.go create mode 100644 src/usecase/dto/base.go create mode 100644 src/usecase/dto/car.go create mode 100644 src/usecase/dto/property.go create mode 100644 src/usecase/dto/user.go create mode 100644 src/usecase/file_usecase.go create mode 100644 src/usecase/gearbox_usecase.go create mode 100644 src/usecase/otp_usecase.go create mode 100644 src/usecase/propertyCategory_usecase.go create mode 100644 src/usecase/property_usecase.go create mode 100644 src/usecase/token_usecase.go create mode 100644 src/usecase/user_usecase.go create mode 100644 src/usecase/year_usecase.go diff --git a/src/usecase/base_usecase.go b/src/usecase/base_usecase.go new file mode 100644 index 0000000..3b68095 --- /dev/null +++ b/src/usecase/base_usecase.go @@ -0,0 +1,74 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/common" + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/pkg/logging" +) + +type BaseUsecase[TEntity any, TCreate any, TUpdate any, TResponse any] struct { + logger logging.Logger + repository repository.BaseRepository[TEntity] +} + +func NewBaseUsecase[TEntity any, TCreate any, TUpdate any, TResponse any](cfg *config.Config, repository repository.BaseRepository[TEntity]) *BaseUsecase[TEntity, TCreate, TUpdate, TResponse] { + logger := logging.NewLogger(cfg) + return &BaseUsecase[TEntity, TCreate, TUpdate, TResponse]{ + repository: repository, + logger: logger, + } +} + +func (u *BaseUsecase[TEntity, TCreate, TUpdate, TResponse]) Create(ctx context.Context, req TCreate) (TResponse, error) { + var response TResponse + entity, _ := common.TypeConverter[TEntity](req) + + entity, err := u.repository.Create(ctx, entity) + if err != nil { + return response, err + } + + response, _ = common.TypeConverter[TResponse](entity) + return response, nil +} + +func (u *BaseUsecase[TEntity, TCreate, TUpdate, TResponse]) Update(ctx context.Context, id int, req TUpdate) (TResponse, error) { + var response TResponse + updateMap, _ := common.TypeConverter[map[string]interface{}](req) + + entity, err := u.repository.Update(ctx, id, updateMap) + if err != nil { + return response, err + } + response, _ = common.TypeConverter[TResponse](entity) + + return response, nil +} + +func (u *BaseUsecase[TEntity, TCreate, TUpdate, TResponse]) Delete(ctx context.Context, id int) error { + + return u.repository.Delete(ctx, id) +} + +func (u *BaseUsecase[TEntity, TCreate, TUpdate, TResponse]) GetById(ctx context.Context, id int) (TResponse, error) { + var response TResponse + entity, err := u.repository.GetById(ctx, id) + if err != nil { + return response, err + } + return common.TypeConverter[TResponse](entity) +} + +func (u *BaseUsecase[TEntity, TCreate, TUpdate, TResponse]) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[TResponse], error) { + var response *filter.PagedList[TResponse] + count, entities, err := u.repository.GetByFilter(ctx, req) + if err != nil { + return response, err + } + + return filter.Paginate[TEntity, TResponse](count, entities, req.PageNumber, int64(req.PageSize)) +} diff --git a/src/usecase/carModelColor_usecase.go b/src/usecase/carModelColor_usecase.go new file mode 100644 index 0000000..b277860 --- /dev/null +++ b/src/usecase/carModelColor_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CarModelColorUsecase struct { + base *BaseUsecase[model.CarModelColor, dto.CreateCarModelColor, dto.UpdateCarModelColor, dto.CarModelColor] +} + +func NewCarModelColorUsecase(cfg *config.Config, repository repository.CarModelColorRepository) *CarModelColorUsecase { + return &CarModelColorUsecase{ + base: NewBaseUsecase[model.CarModelColor, dto.CreateCarModelColor, dto.UpdateCarModelColor, dto.CarModelColor](cfg, repository), + } +} + +// Create +func (u *CarModelColorUsecase) Create(ctx context.Context, req dto.CreateCarModelColor) (dto.CarModelColor, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CarModelColorUsecase) Update(ctx context.Context, id int, req dto.UpdateCarModelColor) (dto.CarModelColor, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CarModelColorUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CarModelColorUsecase) GetById(ctx context.Context, id int) (dto.CarModelColor, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CarModelColorUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.CarModelColor], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/carModelComment_usecase.go b/src/usecase/carModelComment_usecase.go new file mode 100644 index 0000000..5c0bfcc --- /dev/null +++ b/src/usecase/carModelComment_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CarModelCommentUsecase struct { + base *BaseUsecase[model.CarModelComment, dto.CreateCarModelComment, dto.UpdateCarModelComment, dto.CarModelComment] +} + +func NewCarModelCommentUsecase(cfg *config.Config, repository repository.CarModelCommentRepository) *CarModelCommentUsecase { + return &CarModelCommentUsecase{ + base: NewBaseUsecase[model.CarModelComment, dto.CreateCarModelComment, dto.UpdateCarModelComment, dto.CarModelComment](cfg, repository), + } +} + +// Create +func (u *CarModelCommentUsecase) Create(ctx context.Context, req dto.CreateCarModelComment) (dto.CarModelComment, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CarModelCommentUsecase) Update(ctx context.Context, id int, req dto.UpdateCarModelComment) (dto.CarModelComment, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CarModelCommentUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CarModelCommentUsecase) GetById(ctx context.Context, id int) (dto.CarModelComment, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CarModelCommentUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.CarModelComment], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/carModelImage_usecase.go b/src/usecase/carModelImage_usecase.go new file mode 100644 index 0000000..29609cc --- /dev/null +++ b/src/usecase/carModelImage_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CarModelImageUsecase struct { + base *BaseUsecase[model.CarModelImage, dto.CreateCarModelImage, dto.UpdateCarModelImage, dto.CarModelImage] +} + +func NewCarModelImageUsecase(cfg *config.Config, repository repository.CarModelImageRepository) *CarModelImageUsecase { + return &CarModelImageUsecase{ + base: NewBaseUsecase[model.CarModelImage, dto.CreateCarModelImage, dto.UpdateCarModelImage, dto.CarModelImage](cfg, repository), + } +} + +// Create +func (u *CarModelImageUsecase) Create(ctx context.Context, req dto.CreateCarModelImage) (dto.CarModelImage, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CarModelImageUsecase) Update(ctx context.Context, id int, req dto.UpdateCarModelImage) (dto.CarModelImage, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CarModelImageUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CarModelImageUsecase) GetById(ctx context.Context, id int) (dto.CarModelImage, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CarModelImageUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.CarModelImage], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/carModelPriceHistory_usecase.go b/src/usecase/carModelPriceHistory_usecase.go new file mode 100644 index 0000000..db4cdb2 --- /dev/null +++ b/src/usecase/carModelPriceHistory_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CarModelPriceHistoryUsecase struct { + base *BaseUsecase[model.CarModelPriceHistory, dto.CreateCarModelPriceHistory, dto.UpdateCarModelPriceHistory, dto.CarModelPriceHistory] +} + +func NewCarModelPriceHistoryUsecase(cfg *config.Config, repository repository.CarModelPriceHistoryRepository) *CarModelPriceHistoryUsecase { + return &CarModelPriceHistoryUsecase{ + base: NewBaseUsecase[model.CarModelPriceHistory, dto.CreateCarModelPriceHistory, dto.UpdateCarModelPriceHistory, dto.CarModelPriceHistory](cfg, repository), + } +} + +// Create +func (u *CarModelPriceHistoryUsecase) Create(ctx context.Context, req dto.CreateCarModelPriceHistory) (dto.CarModelPriceHistory, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CarModelPriceHistoryUsecase) Update(ctx context.Context, id int, req dto.UpdateCarModelPriceHistory) (dto.CarModelPriceHistory, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CarModelPriceHistoryUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CarModelPriceHistoryUsecase) GetById(ctx context.Context, id int) (dto.CarModelPriceHistory, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CarModelPriceHistoryUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.CarModelPriceHistory], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/carModelProperty_usecase.go b/src/usecase/carModelProperty_usecase.go new file mode 100644 index 0000000..986d4d3 --- /dev/null +++ b/src/usecase/carModelProperty_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CarModelPropertyUsecase struct { + base *BaseUsecase[model.CarModelProperty, dto.CreateCarModelProperty, dto.UpdateCarModelProperty, dto.CarModelProperty] +} + +func NewCarModelPropertyUsecase(cfg *config.Config, repository repository.CarModelPropertyRepository) *CarModelPropertyUsecase { + return &CarModelPropertyUsecase{ + base: NewBaseUsecase[model.CarModelProperty, dto.CreateCarModelProperty, dto.UpdateCarModelProperty, dto.CarModelProperty](cfg, repository), + } +} + +// Create +func (u *CarModelPropertyUsecase) Create(ctx context.Context, req dto.CreateCarModelProperty) (dto.CarModelProperty, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CarModelPropertyUsecase) Update(ctx context.Context, id int, req dto.UpdateCarModelProperty) (dto.CarModelProperty, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CarModelPropertyUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CarModelPropertyUsecase) GetById(ctx context.Context, id int) (dto.CarModelProperty, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CarModelPropertyUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.CarModelProperty], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/carModelYear_usecase.go b/src/usecase/carModelYear_usecase.go new file mode 100644 index 0000000..759fba3 --- /dev/null +++ b/src/usecase/carModelYear_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CarModelYearUsecase struct { + base *BaseUsecase[model.CarModelYear, dto.CreateCarModelYear, dto.UpdateCarModelYear, dto.CarModelYear] +} + +func NewCarModelYearUsecase(cfg *config.Config, repository repository.CarModelYearRepository) *CarModelYearUsecase { + return &CarModelYearUsecase{ + base: NewBaseUsecase[model.CarModelYear, dto.CreateCarModelYear, dto.UpdateCarModelYear, dto.CarModelYear](cfg, repository), + } +} + +// Create +func (u *CarModelYearUsecase) Create(ctx context.Context, req dto.CreateCarModelYear) (dto.CarModelYear, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CarModelYearUsecase) Update(ctx context.Context, id int, req dto.UpdateCarModelYear) (dto.CarModelYear, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CarModelYearUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CarModelYearUsecase) GetById(ctx context.Context, id int) (dto.CarModelYear, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CarModelYearUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.CarModelYear], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/carModel_usecase.go b/src/usecase/carModel_usecase.go new file mode 100644 index 0000000..2630cd4 --- /dev/null +++ b/src/usecase/carModel_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CarModelUsecase struct { + base *BaseUsecase[model.CarModel, dto.CreateCarModel, dto.UpdateCarModel, dto.CarModel] +} + +func NewCarModelUsecase(cfg *config.Config, repository repository.CarModelRepository) *CarModelUsecase { + return &CarModelUsecase{ + base: NewBaseUsecase[model.CarModel, dto.CreateCarModel, dto.UpdateCarModel, dto.CarModel](cfg, repository), + } +} + +// Create +func (u *CarModelUsecase) Create(ctx context.Context, req dto.CreateCarModel) (dto.CarModel, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CarModelUsecase) Update(ctx context.Context, id int, req dto.UpdateCarModel) (dto.CarModel, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CarModelUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CarModelUsecase) GetById(ctx context.Context, id int) (dto.CarModel, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CarModelUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.CarModel], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/carType_usecase.go b/src/usecase/carType_usecase.go new file mode 100644 index 0000000..f069bcb --- /dev/null +++ b/src/usecase/carType_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CarTypeUsecase struct { + base *BaseUsecase[model.CarType, dto.Name, dto.Name, dto.IdName] +} + +func NewCarTypeUsecase(cfg *config.Config, repository repository.CarTypeRepository) *CarTypeUsecase { + return &CarTypeUsecase{ + base: NewBaseUsecase[model.CarType, dto.Name, dto.Name, dto.IdName](cfg, repository), + } +} + +// Create +func (u *CarTypeUsecase) Create(ctx context.Context, req dto.Name) (dto.IdName, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CarTypeUsecase) Update(ctx context.Context, id int, req dto.Name) (dto.IdName, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CarTypeUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CarTypeUsecase) GetById(ctx context.Context, id int) (dto.IdName, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CarTypeUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.IdName], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/city_usecase.go b/src/usecase/city_usecase.go new file mode 100644 index 0000000..be3679c --- /dev/null +++ b/src/usecase/city_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CityUsecase struct { + base *BaseUsecase[model.City, dto.CreateCity, dto.UpdateCity, dto.City] +} + +func NewCityUsecase(cfg *config.Config, repository repository.CityRepository) *CityUsecase { + return &CityUsecase{ + base: NewBaseUsecase[model.City, dto.CreateCity, dto.UpdateCity, dto.City](cfg, repository), + } +} + +// Create +func (u *CityUsecase) Create(ctx context.Context, req dto.CreateCity) (dto.City, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CityUsecase) Update(ctx context.Context, id int, req dto.UpdateCity) (dto.City, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CityUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CityUsecase) GetById(ctx context.Context, id int) (dto.City, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CityUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.City], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/color_usecase.go b/src/usecase/color_usecase.go new file mode 100644 index 0000000..3d0010e --- /dev/null +++ b/src/usecase/color_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type ColorUsecase struct { + base *BaseUsecase[model.Color, dto.CreateColor, dto.UpdateColor, dto.Color] +} + +func NewColorUsecase(cfg *config.Config, repository repository.ColorRepository) *ColorUsecase { + return &ColorUsecase{ + base: NewBaseUsecase[model.Color, dto.CreateColor, dto.UpdateColor, dto.Color](cfg, repository), + } +} + +// Create +func (u *ColorUsecase) Create(ctx context.Context, req dto.CreateColor) (dto.Color, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *ColorUsecase) Update(ctx context.Context, id int, req dto.UpdateColor) (dto.Color, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *ColorUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *ColorUsecase) GetById(ctx context.Context, id int) (dto.Color, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *ColorUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.Color], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/company_usecase.go b/src/usecase/company_usecase.go new file mode 100644 index 0000000..125e439 --- /dev/null +++ b/src/usecase/company_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CompanyUsecase struct { + base *BaseUsecase[model.Company, dto.CreateCompany, dto.UpdateCompany, dto.Company] +} + +func NewCompanyUsecase(cfg *config.Config, repository repository.CompanyRepository) *CompanyUsecase { + return &CompanyUsecase{ + base: NewBaseUsecase[model.Company, dto.CreateCompany, dto.UpdateCompany, dto.Company](cfg, repository), + } +} + +// Create +func (u *CompanyUsecase) Create(ctx context.Context, req dto.CreateCompany) (dto.Company, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CompanyUsecase) Update(ctx context.Context, id int, req dto.UpdateCompany) (dto.Company, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CompanyUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CompanyUsecase) GetById(ctx context.Context, id int) (dto.Company, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CompanyUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.Company], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/country_usecase.go b/src/usecase/country_usecase.go new file mode 100644 index 0000000..8d8be0d --- /dev/null +++ b/src/usecase/country_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type CountryUsecase struct { + base *BaseUsecase[model.Country, dto.Name, dto.Name, dto.Country] +} + +func NewCountryUsecase(cfg *config.Config, repository repository.CountryRepository) *CountryUsecase { + return &CountryUsecase{ + base: NewBaseUsecase[model.Country, dto.Name, dto.Name, dto.Country](cfg, repository), + } +} + +// Create +func (u *CountryUsecase) Create(ctx context.Context, req dto.Name) (dto.Country, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *CountryUsecase) Update(ctx context.Context, id int, req dto.Name) (dto.Country, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *CountryUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *CountryUsecase) GetById(ctx context.Context, id int) (dto.Country, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *CountryUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.Country], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/dto/base.go b/src/usecase/dto/base.go new file mode 100644 index 0000000..71d5373 --- /dev/null +++ b/src/usecase/dto/base.go @@ -0,0 +1,108 @@ +package dto + +import ( + "time" +) + +type IdName struct { + Id int + Name string +} +type Name struct { + Name string +} + +type Country struct { + IdName + Cities []City + Companies []Company +} + +type CreateCity struct { + Name string + CountryId int +} + +type UpdateCity struct { + Name string + CountryId int +} +type City struct { + IdName + Country Country +} + +type CreateFile struct { + Name string + Directory string + Description string + MimeType string +} + +type UpdateFile struct { + Description string +} + +type File struct { + IdName + Directory string + Description string + MimeType string +} + +type CreateCompany struct { + Name string + CountryId int +} + +type UpdateCompany struct { + Name string + CountryId int +} +type Company struct { + IdName + Country Country +} + +type CreateColor struct { + Name string + HexCode string +} + +type UpdateColor struct { + Name string + HexCode string +} + +type Color struct { + IdName + HexCode string +} + +type CreatePersianYear struct { + PersianTitle string + Year int + StartAt time.Time + EndAt time.Time +} + +type UpdatePersianYear struct { + PersianTitle string + Year int + StartAt time.Time + EndAt time.Time +} + +type PersianYear struct { + Id int + PersianTitle string + Year int + StartAt time.Time + EndAt time.Time +} + +type PersianYearWithoutDate struct { + Id int + PersianTitle string + Year int +} diff --git a/src/usecase/dto/car.go b/src/usecase/dto/car.go new file mode 100644 index 0000000..f3f7afa --- /dev/null +++ b/src/usecase/dto/car.go @@ -0,0 +1,138 @@ +package dto + +import "time" + +type CreateCarModel struct { + Name string + CompanyId int + CarTypeId int + GearboxId int +} + +type UpdateCarModel struct { + Name string + CompanyId int + CarTypeId int + GearboxId int +} + +type CarModel struct { + IdName + CarType IdName + Company Company + Gearbox IdName + CarModelColors []CarModelColor + CarModelYears []CarModelYear + CarModelImages []CarModelImage + CarModelProperties []CarModelProperty + CarModelComments []CarModelComment +} + +type CreateCarModelColor struct { + CarModelId int + ColorId int +} + +type UpdateCarModelColor struct { + CarModelId int + ColorId int +} + +type CarModelColor struct { + Id int + Color Color +} + +type CreateCarModelYear struct { + CarModelId int + PersianYearId int +} + +type UpdateCarModelYear struct { + CarModelId int + PersianYearId int +} + +type CarModelYear struct { + Id int + PersianYear PersianYearWithoutDate + CarModelId int + CarModelPriceHistories []CarModelPriceHistory +} + +type CreateCarModelPriceHistory struct { + CarModelYearId int + PriceAt time.Time + Price float64 +} + +type UpdateCarModelPriceHistory struct { + PriceAt time.Time + Price float64 +} + +type CarModelPriceHistory struct { + Id int + CarModelYearId int + PriceAt time.Time + Price float64 +} + +type CreateCarModelImage struct { + CarModelId int + ImageId int + IsMainImage bool +} + +type UpdateCarModelImage struct { + IsMainImage bool +} + +type CarModelImage struct { + Id int + CarModelId int + Image File + IsMainImage bool +} + +type CreateCarModelProperty struct { + CarModelId int + PropertyId int + Value string +} + +type UpdateCarModelProperty struct { + Value string +} + +type CarModelProperty struct { + Id int + CarModelId int + Property Property + Value string +} + +type CreateCarModelComment struct { + CarModelId int + UserId int + Message string +} + +type UpdateCarModelComment struct { + Message string +} + +type CarModelComment struct { + Id int + CarModelId int + User User + Message string +} + +type User struct { + Id int + Username string + FirstName string + LastName string + Email string +} diff --git a/src/usecase/dto/property.go b/src/usecase/dto/property.go new file mode 100644 index 0000000..75ba66f --- /dev/null +++ b/src/usecase/dto/property.go @@ -0,0 +1,44 @@ +package dto + +type CreatePropertyCategory struct { + Name string + Icon string +} + +type UpdatePropertyCategory struct { + Name string + Icon string +} + +type PropertyCategory struct { + IdName + Icon string + Properties []Property +} + +type CreateProperty struct { + Name string + CategoryId int + Icon string + Description string + DataType string + Unit string +} + +type UpdateProperty struct { + Name string + CategoryId int + Icon string + Description string + DataType string + Unit string +} + +type Property struct { + IdName + Icon string + Description string + DataType string + Unit string + Category PropertyCategory +} diff --git a/src/usecase/dto/user.go b/src/usecase/dto/user.go new file mode 100644 index 0000000..926ddb8 --- /dev/null +++ b/src/usecase/dto/user.go @@ -0,0 +1,36 @@ +package dto + +import model "github.com/naeemaei/golang-clean-web-api/domain/model" + +type TokenDetail struct { + AccessToken string + RefreshToken string + AccessTokenExpireTime int64 + RefreshTokenExpireTime int64 +} + +type RegisterUserByUsername struct { + FirstName string + LastName string + Username string + Email string + Password string +} + +func ToUserModel(from RegisterUserByUsername) model.User { + return model.User{Username: from.Username, + FirstName: from.FirstName, + LastName: from.LastName, + Email: from.Email, + } +} + +type RegisterLoginByMobile struct { + MobileNumber string + Otp string +} + +type LoginByUsername struct { + Username string + Password string +} diff --git a/src/usecase/file_usecase.go b/src/usecase/file_usecase.go new file mode 100644 index 0000000..a46b29f --- /dev/null +++ b/src/usecase/file_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type FileUsecase struct { + base *BaseUsecase[model.File, dto.CreateFile, dto.UpdateFile, dto.File] +} + +func NewFileUsecase(cfg *config.Config, repository repository.FileRepository) *FileUsecase { + return &FileUsecase{ + base: NewBaseUsecase[model.File, dto.CreateFile, dto.UpdateFile, dto.File](cfg, repository), + } +} + +// Create +func (u *FileUsecase) Create(ctx context.Context, req dto.CreateFile) (dto.File, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *FileUsecase) Update(ctx context.Context, id int, req dto.UpdateFile) (dto.File, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *FileUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *FileUsecase) GetById(ctx context.Context, id int) (dto.File, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *FileUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.File], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/gearbox_usecase.go b/src/usecase/gearbox_usecase.go new file mode 100644 index 0000000..9bd6636 --- /dev/null +++ b/src/usecase/gearbox_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type GearboxUsecase struct { + base *BaseUsecase[model.Gearbox, dto.Name, dto.Name, dto.IdName] +} + +func NewGearboxUsecase(cfg *config.Config, repository repository.GearboxRepository) *GearboxUsecase { + return &GearboxUsecase{ + base: NewBaseUsecase[model.Gearbox, dto.Name, dto.Name, dto.IdName](cfg, repository), + } +} + +// Create +func (u *GearboxUsecase) Create(ctx context.Context, req dto.Name) (dto.IdName, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *GearboxUsecase) Update(ctx context.Context, id int, req dto.Name) (dto.IdName, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *GearboxUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *GearboxUsecase) GetById(ctx context.Context, id int) (dto.IdName, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *GearboxUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.IdName], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/otp_usecase.go b/src/usecase/otp_usecase.go new file mode 100644 index 0000000..ffc20b0 --- /dev/null +++ b/src/usecase/otp_usecase.go @@ -0,0 +1,79 @@ +package usecase + +import ( + "fmt" + "time" + + "github.com/go-redis/redis/v7" + "github.com/naeemaei/golang-clean-web-api/common" + "github.com/naeemaei/golang-clean-web-api/config" + constant "github.com/naeemaei/golang-clean-web-api/constant" + "github.com/naeemaei/golang-clean-web-api/infra/cache" + "github.com/naeemaei/golang-clean-web-api/pkg/logging" + "github.com/naeemaei/golang-clean-web-api/pkg/service_errors" +) + +type OtpUsecase struct { + logger logging.Logger + cfg *config.Config + redisClient *redis.Client +} + +type otpDto struct { + Value string + Used bool +} + +func NewOtpUsecase(cfg *config.Config) *OtpUsecase { + logger := logging.NewLogger(cfg) + redis := cache.GetRedis() + return &OtpUsecase{logger: logger, cfg: cfg, redisClient: redis} +} + +func (u *OtpUsecase) SendOtp(mobileNumber string) error { + otp := common.GenerateOtp() + err := u.SetOtp(mobileNumber, otp) + if err != nil { + return err + } + return nil +} + +func (s *OtpUsecase) SetOtp(mobileNumber string, otp string) error { + key := fmt.Sprintf("%s:%s", constant.RedisOtpDefaultKey, mobileNumber) + val := &otpDto{ + Value: otp, + Used: false, + } + + res, err := cache.Get[otpDto](s.redisClient, key) + if err == nil && !res.Used { + return &service_errors.ServiceError{EndUserMessage: service_errors.OptExists} + } else if err == nil && res.Used { + return &service_errors.ServiceError{EndUserMessage: service_errors.OtpUsed} + } + err = cache.Set(s.redisClient, key, val, s.cfg.Otp.ExpireTime*time.Second) + if err != nil { + return err + } + return nil +} + +func (s *OtpUsecase) ValidateOtp(mobileNumber string, otp string) error { + key := fmt.Sprintf("%s:%s", constant.RedisOtpDefaultKey, mobileNumber) + res, err := cache.Get[otpDto](s.redisClient, key) + if err != nil { + return err + } else if res.Used { + return &service_errors.ServiceError{EndUserMessage: service_errors.OtpUsed} + } else if !res.Used && res.Value != otp { + return &service_errors.ServiceError{EndUserMessage: service_errors.OtpNotValid} + } else if !res.Used && res.Value == otp { + res.Used = true + err = cache.Set(s.redisClient, key, res, s.cfg.Otp.ExpireTime*time.Second) + if err != nil { + return err + } + } + return nil +} diff --git a/src/usecase/propertyCategory_usecase.go b/src/usecase/propertyCategory_usecase.go new file mode 100644 index 0000000..cad6f4c --- /dev/null +++ b/src/usecase/propertyCategory_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type PropertyCategoryUsecase struct { + base *BaseUsecase[model.PropertyCategory, dto.CreatePropertyCategory, dto.UpdatePropertyCategory, dto.PropertyCategory] +} + +func NewPropertyCategoryUsecase(cfg *config.Config, repository repository.PropertyCategoryRepository) *PropertyCategoryUsecase { + return &PropertyCategoryUsecase{ + base: NewBaseUsecase[model.PropertyCategory, dto.CreatePropertyCategory, dto.UpdatePropertyCategory, dto.PropertyCategory](cfg, repository), + } +} + +// Create +func (u *PropertyCategoryUsecase) Create(ctx context.Context, req dto.CreatePropertyCategory) (dto.PropertyCategory, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *PropertyCategoryUsecase) Update(ctx context.Context, id int, req dto.UpdatePropertyCategory) (dto.PropertyCategory, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *PropertyCategoryUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *PropertyCategoryUsecase) GetById(ctx context.Context, id int) (dto.PropertyCategory, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *PropertyCategoryUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.PropertyCategory], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/property_usecase.go b/src/usecase/property_usecase.go new file mode 100644 index 0000000..59ff240 --- /dev/null +++ b/src/usecase/property_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type PropertyUsecase struct { + base *BaseUsecase[model.Property, dto.CreateProperty, dto.UpdateProperty, dto.Property] +} + +func NewPropertyUsecase(cfg *config.Config, repository repository.PropertyRepository) *PropertyUsecase { + return &PropertyUsecase{ + base: NewBaseUsecase[model.Property, dto.CreateProperty, dto.UpdateProperty, dto.Property](cfg, repository), + } +} + +// Create +func (u *PropertyUsecase) Create(ctx context.Context, req dto.CreateProperty) (dto.Property, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *PropertyUsecase) Update(ctx context.Context, id int, req dto.UpdateProperty) (dto.Property, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *PropertyUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *PropertyUsecase) GetById(ctx context.Context, id int) (dto.Property, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *PropertyUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.Property], error) { + return s.base.GetByFilter(ctx, req) +} diff --git a/src/usecase/token_usecase.go b/src/usecase/token_usecase.go new file mode 100644 index 0000000..48981c7 --- /dev/null +++ b/src/usecase/token_usecase.go @@ -0,0 +1,107 @@ +package usecase + +import ( + "time" + + "github.com/golang-jwt/jwt" + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/constant" + "github.com/naeemaei/golang-clean-web-api/pkg/logging" + "github.com/naeemaei/golang-clean-web-api/pkg/service_errors" + dto "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type TokenUsecase struct { + logger logging.Logger + cfg *config.Config +} + +type tokenDto struct { + UserId int + FirstName string + LastName string + Username string + MobileNumber string + Email string + Roles []string +} + +func NewTokenUsecase(cfg *config.Config) *TokenUsecase { + logger := logging.NewLogger(cfg) + return &TokenUsecase{ + cfg: cfg, + logger: logger, + } +} + +func (s *TokenUsecase) GenerateToken(token tokenDto) (*dto.TokenDetail, error) { + td := &dto.TokenDetail{} + td.AccessTokenExpireTime = time.Now().Add(s.cfg.JWT.AccessTokenExpireDuration * time.Minute).Unix() + td.RefreshTokenExpireTime = time.Now().Add(s.cfg.JWT.RefreshTokenExpireDuration * time.Minute).Unix() + + atc := jwt.MapClaims{} + + atc[constant.UserIdKey] = token.UserId + atc[constant.FirstNameKey] = token.FirstName + atc[constant.LastNameKey] = token.LastName + atc[constant.UsernameKey] = token.Username + atc[constant.EmailKey] = token.Email + atc[constant.MobileNumberKey] = token.MobileNumber + atc[constant.RolesKey] = token.Roles + atc[constant.ExpireTimeKey] = td.AccessTokenExpireTime + + at := jwt.NewWithClaims(jwt.SigningMethodHS256, atc) + + var err error + td.AccessToken, err = at.SignedString([]byte(s.cfg.JWT.Secret)) + + if err != nil { + return nil, err + } + + rtc := jwt.MapClaims{} + + rtc[constant.UserIdKey] = token.UserId + rtc[constant.ExpireTimeKey] = td.RefreshTokenExpireTime + + rt := jwt.NewWithClaims(jwt.SigningMethodHS256, rtc) + + td.RefreshToken, err = rt.SignedString([]byte(s.cfg.JWT.RefreshSecret)) + + if err != nil { + return nil, err + } + + return td, nil +} + +func (s *TokenUsecase) VerifyToken(token string) (*jwt.Token, error) { + at, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { + _, ok := token.Method.(*jwt.SigningMethodHMAC) + if !ok { + return nil, &service_errors.ServiceError{EndUserMessage: service_errors.UnExpectedError} + } + return []byte(s.cfg.JWT.Secret), nil + }) + if err != nil { + return nil, err + } + return at, nil +} + +func (s *TokenUsecase) GetClaims(token string) (claimMap map[string]interface{}, err error) { + claimMap = map[string]interface{}{} + + verifyToken, err := s.VerifyToken(token) + if err != nil { + return nil, err + } + claims, ok := verifyToken.Claims.(jwt.MapClaims) + if ok && verifyToken.Valid { + for k, v := range claims { + claimMap[k] = v + } + return claimMap, nil + } + return nil, &service_errors.ServiceError{EndUserMessage: service_errors.ClaimsNotFound} +} diff --git a/src/usecase/user_usecase.go b/src/usecase/user_usecase.go new file mode 100644 index 0000000..bde9e9c --- /dev/null +++ b/src/usecase/user_usecase.go @@ -0,0 +1,145 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/common" + "github.com/naeemaei/golang-clean-web-api/config" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/pkg/logging" + "github.com/naeemaei/golang-clean-web-api/pkg/service_errors" + dto "github.com/naeemaei/golang-clean-web-api/usecase/dto" + "golang.org/x/crypto/bcrypt" +) + +type UserUsecase struct { + logger logging.Logger + cfg *config.Config + otpUsecase *OtpUsecase + tokenUsecase *TokenUsecase + repository repository.UserRepository +} + +func NewUserUsecase(cfg *config.Config, repository repository.UserRepository) *UserUsecase { + logger := logging.NewLogger(cfg) + return &UserUsecase{ + cfg: cfg, + repository: repository, + logger: logger, + otpUsecase: NewOtpUsecase(cfg), + tokenUsecase: NewTokenUsecase(cfg), + } +} + +// Login by username +func (u *UserUsecase) LoginByUsername(ctx context.Context, username string, password string) (*dto.TokenDetail, error) { + user, err := u.repository.FetchUserInfo(ctx, username, password) + + if err != nil { + return nil, err + } + tokenDto := tokenDto{UserId: user.Id, FirstName: user.FirstName, LastName: user.LastName, + Email: user.Email, MobileNumber: user.MobileNumber} + + if len(*user.UserRoles) > 0 { + for _, ur := range *user.UserRoles { + tokenDto.Roles = append(tokenDto.Roles, ur.Role.Name) + } + } + + token, err := u.tokenUsecase.GenerateToken(tokenDto) + + if err != nil { + return nil, err + } + return token, nil + +} + +// Register by username +func (u *UserUsecase) RegisterByUsername(ctx context.Context, req dto.RegisterUserByUsername) error { + user := dto.ToUserModel(req) + + exists, err := u.repository.ExistsEmail(ctx, req.Email) + if err != nil { + return err + } + if exists { + return &service_errors.ServiceError{EndUserMessage: service_errors.EmailExists} + } + exists, err = u.repository.ExistsUsername(ctx, req.Username) + if err != nil { + return err + } + if exists { + return &service_errors.ServiceError{EndUserMessage: service_errors.UsernameExists} + } + + bp := []byte(req.Password) + hp, err := bcrypt.GenerateFromPassword(bp, bcrypt.DefaultCost) + if err != nil { + u.logger.Error(logging.General, logging.HashPassword, err.Error(), nil) + return err + } + user.Password = string(hp) + _, err = u.repository.CreateUser(ctx, user) + return err + +} + +// Register/login by mobile number +func (u *UserUsecase) RegisterAndLoginByMobileNumber(ctx context.Context, mobileNumber string, otp string) (*dto.TokenDetail, error) { + err := u.otpUsecase.ValidateOtp(mobileNumber, otp) + if err != nil { + return nil, err + } + exists, err := u.repository.ExistsMobileNumber(ctx, mobileNumber) + if err != nil { + return nil, err + } + + user := model.User{MobileNumber: mobileNumber, Username: mobileNumber} + + if exists { + user, err = u.repository.FetchUserInfo(ctx, user.Username, user.Password) + if err != nil { + return nil, err + } + + return u.generateToken(user) + } + + // Register and login + bp := []byte(common.GeneratePassword()) + hp, err := bcrypt.GenerateFromPassword(bp, bcrypt.DefaultCost) + if err != nil { + u.logger.Error(logging.General, logging.HashPassword, err.Error(), nil) + return nil, err + } + user.Password = string(hp) + + user, err = u.repository.CreateUser(ctx, user) + if err != nil { + return nil, err + } + return u.generateToken(user) + +} + +func (u *UserUsecase) generateToken(user model.User) (*dto.TokenDetail, error) { + tokenDto := tokenDto{UserId: user.Id, FirstName: user.FirstName, LastName: user.LastName, + Email: user.Email, MobileNumber: user.MobileNumber} + + if len(*user.UserRoles) > 0 { + for _, ur := range *user.UserRoles { + tokenDto.Roles = append(tokenDto.Roles, ur.Role.Name) + } + } + + token, err := u.tokenUsecase.GenerateToken(tokenDto) + if err != nil { + return nil, err + } + return token, nil +} diff --git a/src/usecase/year_usecase.go b/src/usecase/year_usecase.go new file mode 100644 index 0000000..51981c8 --- /dev/null +++ b/src/usecase/year_usecase.go @@ -0,0 +1,46 @@ +package usecase + +import ( + "context" + + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + model "github.com/naeemaei/golang-clean-web-api/domain/model" + "github.com/naeemaei/golang-clean-web-api/domain/repository" + "github.com/naeemaei/golang-clean-web-api/usecase/dto" +) + +type PersianYearUsecase struct { + base *BaseUsecase[model.PersianYear, dto.CreatePersianYear, dto.UpdatePersianYear, dto.PersianYear] +} + +func NewPersianYearUsecase(cfg *config.Config, repository repository.PersianYearRepository) *PersianYearUsecase { + return &PersianYearUsecase{ + base: NewBaseUsecase[model.PersianYear, dto.CreatePersianYear, dto.UpdatePersianYear, dto.PersianYear](cfg, repository), + } +} + +// Create +func (u *PersianYearUsecase) Create(ctx context.Context, req dto.CreatePersianYear) (dto.PersianYear, error) { + return u.base.Create(ctx, req) +} + +// Update +func (s *PersianYearUsecase) Update(ctx context.Context, id int, req dto.UpdatePersianYear) (dto.PersianYear, error) { + return s.base.Update(ctx, id, req) +} + +// Delete +func (s *PersianYearUsecase) Delete(ctx context.Context, id int) error { + return s.base.Delete(ctx, id) +} + +// Get By Id +func (s *PersianYearUsecase) GetById(ctx context.Context, id int) (dto.PersianYear, error) { + return s.base.GetById(ctx, id) +} + +// Get By Filter +func (s *PersianYearUsecase) GetByFilter(ctx context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[dto.PersianYear], error) { + return s.base.GetByFilter(ctx, req) +} From 32bb07e2116ce7f1a82dce922d64f9924b9e8743 Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 19:05:20 +0330 Subject: [PATCH 15/18] Change handlers directory location --- src/api/handler/base_generic_crud.go | 190 ++++++++++++++++ .../car_models.go => handler/car_model.go} | 26 ++- .../car_model_color.go} | 26 ++- .../car_model_comment.go} | 26 ++- .../car_model_image.go} | 26 ++- .../car_model_price_history.go} | 26 ++- .../car_model_property.go} | 26 ++- .../car_model_year.go} | 26 ++- .../car_types.go => handler/car_type.go} | 26 ++- .../{handlers/cities.go => handler/city.go} | 26 ++- .../{handlers/colors.go => handler/color.go} | 26 ++- .../companies.go => handler/company.go} | 26 ++- .../countries.go => handler/country.go} | 27 ++- .../{handlers/files.go => handler/file.go} | 62 +++--- .../gearboxes.go => handler/gearbox.go} | 26 ++- src/api/{handlers => handler}/health.go | 2 +- .../properties.go => handler/property.go} | 26 ++- .../property_category.go} | 26 ++- src/api/handler/property_simple.go | 208 ++++++++++++++++++ src/api/{handlers => handler}/test_handler.go | 2 +- .../{handlers/users.go => handler/user.go} | 24 +- .../{handlers/years.go => handler/year.go} | 28 ++- src/api/handlers/base.go | 106 --------- 23 files changed, 670 insertions(+), 343 deletions(-) create mode 100644 src/api/handler/base_generic_crud.go rename src/api/{handlers/car_models.go => handler/car_model.go} (76%) rename src/api/{handlers/car_model_colors.go => handler/car_model_color.go} (76%) rename src/api/{handlers/car_model_comments.go => handler/car_model_comment.go} (76%) rename src/api/{handlers/car_model_images.go => handler/car_model_image.go} (76%) rename src/api/{handlers/car_model_price_histories.go => handler/car_model_price_history.go} (76%) rename src/api/{handlers/car_model_properties.go => handler/car_model_property.go} (76%) rename src/api/{handlers/car_model_years.go => handler/car_model_year.go} (76%) rename src/api/{handlers/car_types.go => handler/car_type.go} (75%) rename src/api/{handlers/cities.go => handler/city.go} (75%) rename src/api/{handlers/colors.go => handler/color.go} (75%) rename src/api/{handlers/companies.go => handler/company.go} (76%) rename src/api/{handlers/countries.go => handler/country.go} (73%) rename src/api/{handlers/files.go => handler/file.go} (77%) rename src/api/{handlers/gearboxes.go => handler/gearbox.go} (76%) rename src/api/{handlers => handler}/health.go (97%) rename src/api/{handlers/properties.go => handler/property.go} (76%) rename src/api/{handlers/property_categories.go => handler/property_category.go} (76%) create mode 100644 src/api/handler/property_simple.go rename src/api/{handlers => handler}/test_handler.go (99%) rename src/api/{handlers/users.go => handler/user.go} (86%) rename src/api/{handlers/years.go => handler/year.go} (75%) delete mode 100644 src/api/handlers/base.go diff --git a/src/api/handler/base_generic_crud.go b/src/api/handler/base_generic_crud.go new file mode 100644 index 0000000..1ccf822 --- /dev/null +++ b/src/api/handler/base_generic_crud.go @@ -0,0 +1,190 @@ +// A generic base handler can that we can use for CRUD operations +// +// To use simple crud can see user handler and year handler + +package handler + +import ( + "context" + "net/http" + "strconv" + + "github.com/gin-gonic/gin" + "github.com/naeemaei/golang-clean-web-api/api/helper" + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/pkg/logging" +) + +var logger = logging.NewLogger(config.GetConfig()) + +// Create an entity +// TRequest: Http request body +// TUInput: Usecase method input that mapped from TRequest with TUInput := mapper(TRequest) +// TUOutput: Usecase function output +// TResponse: Http response body that mapped from TUOutput with TResponse := mapper(TUOutput) +// requestMapper: this function map endpoint input to usecase input +// responseMapper: this function map usecase output to endpoint output +// usecaseCreate: usecase Create method +func Create[TRequest any, TUInput any, TUOutput any, TResponse any](c *gin.Context, + requestMapper func(req TRequest) (res TUInput), + responseMapper func(req TUOutput) (res TResponse), + usecaseCreate func(ctx context.Context, + req TUInput) (TUOutput, error)) { + + // bind http request + request := new(TRequest) + err := c.ShouldBindJSON(&request) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, + helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) + return + } + + // map http request body to usecase input + usecaseInput := requestMapper(*request) + + // call use case method + usecaseResult, err := usecaseCreate(c, usecaseInput) + if err != nil { + c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), + helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) + return + } + + // map usecase response to http response + response := responseMapper(usecaseResult) + + c.JSON(http.StatusCreated, helper.GenerateBaseResponse(response, true, 0)) +} + +// Update an entity +// TRequest: Http request body +// TUInput: Use case method input that mapped from TRequest with TUInput := mapper(TRequest) +// TUOutput: Use case function output +// TResponse: Http response body that mapped from TUOutput with TResponse := mapper(TUOutput) +// requestMapper: this function map endpoint input to usecase input +// responseMapper: this function map usecase output to endpoint output +// usecaseUpdate: usecase Update method +func Update[TRequest any, TUInput any, TUOutput any, TResponse any](c *gin.Context, + requestMapper func(req TRequest) (res TUInput), + responseMapper func(req TUOutput) (res TResponse), + usecaseUpdate func(ctx context.Context, + id int, req TUInput) (TUOutput, error)) { + + // bind http request + id, _ := strconv.Atoi(c.Params.ByName("id")) + request := new(TRequest) + err := c.ShouldBindJSON(&request) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, + helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) + return + + } + // map http request body to usecase input + usecaseInput := requestMapper(*request) + + // call use case method + usecaseResult, err := usecaseUpdate(c, id, usecaseInput) + if err != nil { + c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), + helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) + return + } + + // map usecase response to http response + response := responseMapper(usecaseResult) + + c.JSON(http.StatusOK, helper.GenerateBaseResponse(response, true, 0)) +} + +func Delete(c *gin.Context, usecaseDelete func(ctx context.Context, id int) error) { + id, _ := strconv.Atoi(c.Params.ByName("id")) + if id == 0 { + c.AbortWithStatusJSON(http.StatusNotFound, + helper.GenerateBaseResponse(nil, false, helper.ValidationError)) + return + } + + err := usecaseDelete(c, id) + if err != nil { + c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), + helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) + return + } + c.JSON(http.StatusOK, helper.GenerateBaseResponse(nil, true, 0)) +} + +// Get an entity +// TUOutput: Usecase function output +// TResponse: Http response body that mapped from TUOutput with TResponse := mapper(TUOutput) +// responseMapper: this function map usecase output to endpoint output +// usecaseGet: usecase Get method +func GetById[TUOutput any, TResponse any](c *gin.Context, + responseMapper func(req TUOutput) (res TResponse), + usecaseGet func(c context.Context, id int) (TUOutput, error)) { + id, _ := strconv.Atoi(c.Params.ByName("id")) + if id == 0 { + c.AbortWithStatusJSON(http.StatusNotFound, + helper.GenerateBaseResponse(nil, false, helper.ValidationError)) + return + } + + // call use case method + usecaseResult, err := usecaseGet(c, id) + if err != nil { + c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), + helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) + return + } + + // map usecase response to http response + response := responseMapper(usecaseResult) + + c.JSON(http.StatusOK, helper.GenerateBaseResponse(response, true, 0)) +} + +// Get entities by filter +// TUOutput: Usecase function output +// TResponse: Http response body that mapped from TUOutput with TResponse := mapper(TUOutput) +// responseMapper: this function map usecase output to endpoint output +// usecaseList: usecase GetByFilter method +func GetByFilter[TUOutput any, TResponse any](c *gin.Context, + responseMapper func(req TUOutput) (res TResponse), + usecaseList func(c context.Context, req filter.PaginationInputWithFilter) (*filter.PagedList[TUOutput], error)) { + + req := new(filter.PaginationInputWithFilter) + err := c.ShouldBindJSON(&req) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, + helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) + return + } + + // call use case method + usecaseResult, err := usecaseList(c, *req) + if err != nil { + c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), + helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) + return + } + response := filter.PagedList[TResponse]{ + PageNumber: usecaseResult.PageNumber, + PageSize: usecaseResult.PageSize, + TotalRows: usecaseResult.TotalRows, + TotalPages: usecaseResult.TotalPages, + HasPreviousPage: usecaseResult.HasPreviousPage, + HasNextPage: usecaseResult.HasNextPage, + } + + // map usecase response to http response + items := []TResponse{} + for _, item := range *usecaseResult.Items { + + items = append(items, responseMapper(item)) + } + response.Items = &items + + c.JSON(http.StatusOK, helper.GenerateBaseResponse(response, true, 0)) +} diff --git a/src/api/handlers/car_models.go b/src/api/handler/car_model.go similarity index 76% rename from src/api/handlers/car_models.go rename to src/api/handler/car_model.go index 4c66a2a..9a3174d 100644 --- a/src/api/handlers/car_models.go +++ b/src/api/handler/car_model.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CarModelHandler struct { - service *services.CarModelService + usecase *usecase.CarModelUsecase } func NewCarModelHandler(cfg *config.Config) *CarModelHandler { return &CarModelHandler{ - service: services.NewCarModelService(cfg), + usecase: usecase.NewCarModelUsecase(cfg, dependency.GetCarModelRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewCarModelHandler(cfg *config.Config) *CarModelHandler { // @Router /v1/car-models/ [post] // @Security AuthBearer func (h *CarModelHandler) Create(c *gin.Context) { - Create(c, h.service.Create) + Create(c, dto.ToCreateCarModel, dto.ToCarModelResponse, h.usecase.Create) } // UpdateCarModel godoc @@ -47,7 +49,7 @@ func (h *CarModelHandler) Create(c *gin.Context) { // @Router /v1/car-models/{id} [put] // @Security AuthBearer func (h *CarModelHandler) Update(c *gin.Context) { - Update(c, h.service.Update) + Update(c, dto.ToUpdateCarModel, dto.ToCarModelResponse, h.usecase.Update) } // DeleteCarModel godoc @@ -63,7 +65,7 @@ func (h *CarModelHandler) Update(c *gin.Context) { // @Router /v1/car-models/{id} [delete] // @Security AuthBearer func (h *CarModelHandler) Delete(c *gin.Context) { - Delete(c, h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCarModel godoc @@ -79,7 +81,7 @@ func (h *CarModelHandler) Delete(c *gin.Context) { // @Router /v1/car-models/{id} [get] // @Security AuthBearer func (h *CarModelHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCarModelResponse, h.usecase.GetById) } // GetCarModels godoc @@ -88,11 +90,11 @@ func (h *CarModelHandler) GetById(c *gin.Context) { // @Tags CarModels // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CarModelResponse]} "CarModel response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CarModelResponse]} "CarModel response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/car-models/get-by-filter [post] // @Security AuthBearer func (h *CarModelHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCarModelResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/car_model_colors.go b/src/api/handler/car_model_color.go similarity index 76% rename from src/api/handlers/car_model_colors.go rename to src/api/handler/car_model_color.go index bb1861d..f07caf1 100644 --- a/src/api/handlers/car_model_colors.go +++ b/src/api/handler/car_model_color.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CarModelColorHandler struct { - service *services.CarModelColorService + usecase *usecase.CarModelColorUsecase } func NewCarModelColorHandler(cfg *config.Config) *CarModelColorHandler { return &CarModelColorHandler{ - service: services.NewCarModelColorService(cfg), + usecase: usecase.NewCarModelColorUsecase(cfg, dependency.GetCarModelColorRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewCarModelColorHandler(cfg *config.Config) *CarModelColorHandler { // @Router /v1/car-model-colors/ [post] // @Security AuthBearer func (h *CarModelColorHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + Create(c, dto.ToCreateCarModelColor, dto.ToCarModelColorResponse, h.usecase.Create) } // UpdateCarModelColor godoc @@ -47,7 +49,7 @@ func (h *CarModelColorHandler) Create(c *gin.Context) { // @Router /v1/car-model-colors/{id} [put] // @Security AuthBearer func (h *CarModelColorHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToUpdateCarModelColor, dto.ToCarModelColorResponse, h.usecase.Update) } // DeleteCarModelColor godoc @@ -63,7 +65,7 @@ func (h *CarModelColorHandler) Update(c *gin.Context) { // @Router /v1/car-model-colors/{id} [delete] // @Security AuthBearer func (h *CarModelColorHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCarModelColor godoc @@ -79,7 +81,7 @@ func (h *CarModelColorHandler) Delete(c *gin.Context) { // @Router /v1/car-model-colors/{id} [get] // @Security AuthBearer func (h *CarModelColorHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCarModelColorResponse, h.usecase.GetById) } // GetCarModelColors godoc @@ -88,11 +90,11 @@ func (h *CarModelColorHandler) GetById(c *gin.Context) { // @Tags CarModelColors // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CarModelColorResponse]} "CarModelColor response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CarModelColorResponse]} "CarModelColor response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/car-model-colors/get-by-filter [post] // @Security AuthBearer func (h *CarModelColorHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCarModelColorResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/car_model_comments.go b/src/api/handler/car_model_comment.go similarity index 76% rename from src/api/handlers/car_model_comments.go rename to src/api/handler/car_model_comment.go index 3f4a238..df79e06 100644 --- a/src/api/handlers/car_model_comments.go +++ b/src/api/handler/car_model_comment.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CarModelCommentHandler struct { - service *services.CarModelCommentService + usecase *usecase.CarModelCommentUsecase } func NewCarModelCommentHandler(cfg *config.Config) *CarModelCommentHandler { return &CarModelCommentHandler{ - service: services.NewCarModelCommentService(cfg), + usecase: usecase.NewCarModelCommentUsecase(cfg, dependency.GetCarModelCommentRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewCarModelCommentHandler(cfg *config.Config) *CarModelCommentHandler { // @Router /v1/car-model-comments/ [post] // @Security AuthBearer func (h *CarModelCommentHandler) Create(c *gin.Context) { - Create(c, h.service.Create) + Create(c, dto.ToCreateCarModelComment, dto.ToCarModelCommentResponse, h.usecase.Create) } // UpdateCarModelComment godoc @@ -47,7 +49,7 @@ func (h *CarModelCommentHandler) Create(c *gin.Context) { // @Router /v1/car-model-comments/{id} [put] // @Security AuthBearer func (h *CarModelCommentHandler) Update(c *gin.Context) { - Update(c, h.service.Update) + Update(c, dto.ToUpdateCarModelComment, dto.ToCarModelCommentResponse, h.usecase.Update) } // DeleteCarModelComment godoc @@ -63,7 +65,7 @@ func (h *CarModelCommentHandler) Update(c *gin.Context) { // @Router /v1/car-model-comments/{id} [delete] // @Security AuthBearer func (h *CarModelCommentHandler) Delete(c *gin.Context) { - Delete(c, h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCarModelComment godoc @@ -79,7 +81,7 @@ func (h *CarModelCommentHandler) Delete(c *gin.Context) { // @Router /v1/car-model-comments/{id} [get] // @Security AuthBearer func (h *CarModelCommentHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCarModelCommentResponse, h.usecase.GetById) } // GetCarModelComments godoc @@ -88,11 +90,11 @@ func (h *CarModelCommentHandler) GetById(c *gin.Context) { // @Tags CarModelComments // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CarModelCommentResponse]} "CarModelComment response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CarModelCommentResponse]} "CarModelComment response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/car-model-comments/get-by-filter [post] // @Security AuthBearer func (h *CarModelCommentHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCarModelCommentResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/car_model_images.go b/src/api/handler/car_model_image.go similarity index 76% rename from src/api/handlers/car_model_images.go rename to src/api/handler/car_model_image.go index 89e255d..5781074 100644 --- a/src/api/handlers/car_model_images.go +++ b/src/api/handler/car_model_image.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CarModelImageHandler struct { - service *services.CarModelImageService + usecase *usecase.CarModelImageUsecase } func NewCarModelImageHandler(cfg *config.Config) *CarModelImageHandler { return &CarModelImageHandler{ - service: services.NewCarModelImageService(cfg), + usecase: usecase.NewCarModelImageUsecase(cfg, dependency.GetCarModelImageRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewCarModelImageHandler(cfg *config.Config) *CarModelImageHandler { // @Router /v1/car-model-images/ [post] // @Security AuthBearer func (h *CarModelImageHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + Create(c, dto.ToCreateCarModelImage, dto.ToCarModelImageResponse, h.usecase.Create) } // UpdateCarModelImage godoc @@ -47,7 +49,7 @@ func (h *CarModelImageHandler) Create(c *gin.Context) { // @Router /v1/car-model-images/{id} [put] // @Security AuthBearer func (h *CarModelImageHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToUpdateCarModelImage, dto.ToCarModelImageResponse, h.usecase.Update) } // DeleteCarModelImage godoc @@ -63,7 +65,7 @@ func (h *CarModelImageHandler) Update(c *gin.Context) { // @Router /v1/car-model-images/{id} [delete] // @Security AuthBearer func (h *CarModelImageHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCarModelImage godoc @@ -79,7 +81,7 @@ func (h *CarModelImageHandler) Delete(c *gin.Context) { // @Router /v1/car-model-images/{id} [get] // @Security AuthBearer func (h *CarModelImageHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCarModelImageResponse, h.usecase.GetById) } // GetCarModelImages godoc @@ -88,11 +90,11 @@ func (h *CarModelImageHandler) GetById(c *gin.Context) { // @Tags CarModelImages // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CarModelImageResponse]} "CarModelImage response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CarModelImageResponse]} "CarModelImage response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/car-model-images/get-by-filter [post] // @Security AuthBearer func (h *CarModelImageHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCarModelImageResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/car_model_price_histories.go b/src/api/handler/car_model_price_history.go similarity index 76% rename from src/api/handlers/car_model_price_histories.go rename to src/api/handler/car_model_price_history.go index c40eec4..ad56f78 100644 --- a/src/api/handlers/car_model_price_histories.go +++ b/src/api/handler/car_model_price_history.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CarModelPriceHistoryHandler struct { - service *services.CarModelPriceHistoryService + usecase *usecase.CarModelPriceHistoryUsecase } func NewCarModelPriceHistoryHandler(cfg *config.Config) *CarModelPriceHistoryHandler { return &CarModelPriceHistoryHandler{ - service: services.NewCarModelPriceHistoryService(cfg), + usecase: usecase.NewCarModelPriceHistoryUsecase(cfg, dependency.GetCarModelPriceHistoryRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewCarModelPriceHistoryHandler(cfg *config.Config) *CarModelPriceHistoryHan // @Router /v1/car-model-price-histories/ [post] // @Security AuthBearer func (h *CarModelPriceHistoryHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + Create(c, dto.ToCreateCarModelPriceHistory, dto.ToCarModelPriceHistoryResponse, h.usecase.Create) } // UpdateCarModelPriceHistory godoc @@ -47,7 +49,7 @@ func (h *CarModelPriceHistoryHandler) Create(c *gin.Context) { // @Router /v1/car-model-price-histories/{id} [put] // @Security AuthBearer func (h *CarModelPriceHistoryHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToUpdateCarModelPriceHistory, dto.ToCarModelPriceHistoryResponse, h.usecase.Update) } // DeleteCarModelPriceHistory godoc @@ -63,7 +65,7 @@ func (h *CarModelPriceHistoryHandler) Update(c *gin.Context) { // @Router /v1/car-model-price-histories/{id} [delete] // @Security AuthBearer func (h *CarModelPriceHistoryHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCarModelPriceHistory godoc @@ -79,7 +81,7 @@ func (h *CarModelPriceHistoryHandler) Delete(c *gin.Context) { // @Router /v1/car-model-price-histories/{id} [get] // @Security AuthBearer func (h *CarModelPriceHistoryHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCarModelPriceHistoryResponse, h.usecase.GetById) } // GetCarModelPriceHistories godoc @@ -88,11 +90,11 @@ func (h *CarModelPriceHistoryHandler) GetById(c *gin.Context) { // @Tags CarModelPriceHistories // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CarModelPriceHistoryResponse]} "CarModelPriceHistory response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CarModelPriceHistoryResponse]} "CarModelPriceHistory response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/car-model-price-histories/get-by-filter [post] // @Security AuthBearer func (h *CarModelPriceHistoryHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCarModelPriceHistoryResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/car_model_properties.go b/src/api/handler/car_model_property.go similarity index 76% rename from src/api/handlers/car_model_properties.go rename to src/api/handler/car_model_property.go index 1f898c4..e9eedcc 100644 --- a/src/api/handlers/car_model_properties.go +++ b/src/api/handler/car_model_property.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CarModelPropertyHandler struct { - service *services.CarModelPropertyService + usecase *usecase.CarModelPropertyUsecase } func NewCarModelPropertyHandler(cfg *config.Config) *CarModelPropertyHandler { return &CarModelPropertyHandler{ - service: services.NewCarModelPropertyService(cfg), + usecase: usecase.NewCarModelPropertyUsecase(cfg, dependency.GetCarModelPropertyRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewCarModelPropertyHandler(cfg *config.Config) *CarModelPropertyHandler { // @Router /v1/car-model-properties/ [post] // @Security AuthBearer func (h *CarModelPropertyHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + Create(c, dto.ToCreateCarModelProperty, dto.ToCarModelPropertyResponse, h.usecase.Create) } // UpdateCarModelProperty godoc @@ -47,7 +49,7 @@ func (h *CarModelPropertyHandler) Create(c *gin.Context) { // @Router /v1/car-model-properties/{id} [put] // @Security AuthBearer func (h *CarModelPropertyHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToUpdateCarModelProperty, dto.ToCarModelPropertyResponse, h.usecase.Update) } // DeleteCarModelProperty godoc @@ -63,7 +65,7 @@ func (h *CarModelPropertyHandler) Update(c *gin.Context) { // @Router /v1/car-model-properties/{id} [delete] // @Security AuthBearer func (h *CarModelPropertyHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCarModelProperty godoc @@ -79,7 +81,7 @@ func (h *CarModelPropertyHandler) Delete(c *gin.Context) { // @Router /v1/car-model-properties/{id} [get] // @Security AuthBearer func (h *CarModelPropertyHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCarModelPropertyResponse, h.usecase.GetById) } // GetCarModelProperties godoc @@ -88,11 +90,11 @@ func (h *CarModelPropertyHandler) GetById(c *gin.Context) { // @Tags CarModelProperties // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CarModelPropertyResponse]} "CarModelProperty response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CarModelPropertyResponse]} "CarModelProperty response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/car-model-properties/get-by-filter [post] // @Security AuthBearer func (h *CarModelPropertyHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCarModelPropertyResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/car_model_years.go b/src/api/handler/car_model_year.go similarity index 76% rename from src/api/handlers/car_model_years.go rename to src/api/handler/car_model_year.go index 219558a..2208fc6 100644 --- a/src/api/handlers/car_model_years.go +++ b/src/api/handler/car_model_year.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CarModelYearHandler struct { - service *services.CarModelYearService + usecase *usecase.CarModelYearUsecase } func NewCarModelYearHandler(cfg *config.Config) *CarModelYearHandler { return &CarModelYearHandler{ - service: services.NewCarModelYearService(cfg), + usecase: usecase.NewCarModelYearUsecase(cfg, dependency.GetCarModelYearRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewCarModelYearHandler(cfg *config.Config) *CarModelYearHandler { // @Router /v1/car-model-years/ [post] // @Security AuthBearer func (h *CarModelYearHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + Create(c, dto.ToCreateCarModelYear, dto.ToCarModelYearResponse, h.usecase.Create) } // UpdateCarModelYear godoc @@ -47,7 +49,7 @@ func (h *CarModelYearHandler) Create(c *gin.Context) { // @Router /v1/car-model-years/{id} [put] // @Security AuthBearer func (h *CarModelYearHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToUpdateCarModelYear, dto.ToCarModelYearResponse, h.usecase.Update) } // DeleteCarModelYear godoc @@ -63,7 +65,7 @@ func (h *CarModelYearHandler) Update(c *gin.Context) { // @Router /v1/car-model-years/{id} [delete] // @Security AuthBearer func (h *CarModelYearHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCarModelYear godoc @@ -79,7 +81,7 @@ func (h *CarModelYearHandler) Delete(c *gin.Context) { // @Router /v1/car-model-years/{id} [get] // @Security AuthBearer func (h *CarModelYearHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCarModelYearResponse, h.usecase.GetById) } // GetCarModelYears godoc @@ -88,11 +90,11 @@ func (h *CarModelYearHandler) GetById(c *gin.Context) { // @Tags CarModelYears // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CarModelYearResponse]} "CarModelYear response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CarModelYearResponse]} "CarModelYear response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/car-model-years/get-by-filter [post] // @Security AuthBearer func (h *CarModelYearHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCarModelYearResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/car_types.go b/src/api/handler/car_type.go similarity index 75% rename from src/api/handlers/car_types.go rename to src/api/handler/car_type.go index cdf5bbf..4620a8f 100644 --- a/src/api/handlers/car_types.go +++ b/src/api/handler/car_type.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CarTypeHandler struct { - service *services.CarTypeService + usecase *usecase.CarTypeUsecase } func NewCarTypeHandler(cfg *config.Config) *CarTypeHandler { return &CarTypeHandler{ - service: services.NewCarTypeService(cfg), + usecase: usecase.NewCarTypeUsecase(cfg, dependency.GetCarTypeRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewCarTypeHandler(cfg *config.Config) *CarTypeHandler { // @Router /v1/car-types/ [post] // @Security AuthBearer func (h *CarTypeHandler) Create(c *gin.Context) { - Create(c, h.service.Create) + Create(c, dto.ToCreateCarType, dto.ToCarTypeResponse, h.usecase.Create) } // UpdateCarType godoc @@ -47,7 +49,7 @@ func (h *CarTypeHandler) Create(c *gin.Context) { // @Router /v1/car-types/{id} [put] // @Security AuthBearer func (h *CarTypeHandler) Update(c *gin.Context) { - Update(c, h.service.Update) + Update(c, dto.ToUpdateCarType, dto.ToCarTypeResponse, h.usecase.Update) } // DeleteCarType godoc @@ -63,7 +65,7 @@ func (h *CarTypeHandler) Update(c *gin.Context) { // @Router /v1/car-types/{id} [delete] // @Security AuthBearer func (h *CarTypeHandler) Delete(c *gin.Context) { - Delete(c, h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCarType godoc @@ -79,7 +81,7 @@ func (h *CarTypeHandler) Delete(c *gin.Context) { // @Router /v1/car-types/{id} [get] // @Security AuthBearer func (h *CarTypeHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCarTypeResponse, h.usecase.GetById) } // GetCarTypes godoc @@ -88,11 +90,11 @@ func (h *CarTypeHandler) GetById(c *gin.Context) { // @Tags CarTypes // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CarTypeResponse]} "CarType response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CarTypeResponse]} "CarType response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/car-types/get-by-filter [post] // @Security AuthBearer func (h *CarTypeHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCarTypeResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/cities.go b/src/api/handler/city.go similarity index 75% rename from src/api/handlers/cities.go rename to src/api/handler/city.go index b9350ee..c29b1b3 100644 --- a/src/api/handlers/cities.go +++ b/src/api/handler/city.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CityHandler struct { - service *services.CityService + usecase *usecase.CityUsecase } func NewCityHandler(cfg *config.Config) *CityHandler { return &CityHandler{ - service: services.NewCityService(cfg), + usecase: usecase.NewCityUsecase(cfg, dependency.GetCityRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewCityHandler(cfg *config.Config) *CityHandler { // @Router /v1/cities/ [post] // @Security AuthBearer func (h *CityHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + Create(c, dto.ToCreateCity, dto.ToCityResponse, h.usecase.Create) } // UpdateCity godoc @@ -47,7 +49,7 @@ func (h *CityHandler) Create(c *gin.Context) { // @Router /v1/cities/{id} [put] // @Security AuthBearer func (h *CityHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToUpdateCity, dto.ToCityResponse, h.usecase.Update) } // DeleteCity godoc @@ -63,7 +65,7 @@ func (h *CityHandler) Update(c *gin.Context) { // @Router /v1/cities/{id} [delete] // @Security AuthBearer func (h *CityHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCity godoc @@ -79,7 +81,7 @@ func (h *CityHandler) Delete(c *gin.Context) { // @Router /v1/cities/{id} [get] // @Security AuthBearer func (h *CityHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCityResponse, h.usecase.GetById) } // GetCities godoc @@ -88,11 +90,11 @@ func (h *CityHandler) GetById(c *gin.Context) { // @Tags Cities // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CityResponse]} "City response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CityResponse]} "City response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/cities/get-by-filter [post] // @Security AuthBearer func (h *CityHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCityResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/colors.go b/src/api/handler/color.go similarity index 75% rename from src/api/handlers/colors.go rename to src/api/handler/color.go index f1f2f33..3f436cb 100644 --- a/src/api/handlers/colors.go +++ b/src/api/handler/color.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type ColorHandler struct { - service *services.ColorService + usecase *usecase.ColorUsecase } func NewColorHandler(cfg *config.Config) *ColorHandler { return &ColorHandler{ - service: services.NewColorService(cfg), + usecase: usecase.NewColorUsecase(cfg, dependency.GetColorRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewColorHandler(cfg *config.Config) *ColorHandler { // @Router /v1/colors/ [post] // @Security AuthBearer func (h *ColorHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + Create(c, dto.ToCreateColor, dto.ToColorResponse, h.usecase.Create) } // UpdateColor godoc @@ -47,7 +49,7 @@ func (h *ColorHandler) Create(c *gin.Context) { // @Router /v1/colors/{id} [put] // @Security AuthBearer func (h *ColorHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToUpdateColor, dto.ToColorResponse, h.usecase.Update) } // DeleteColor godoc @@ -63,7 +65,7 @@ func (h *ColorHandler) Update(c *gin.Context) { // @Router /v1/colors/{id} [delete] // @Security AuthBearer func (h *ColorHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetColor godoc @@ -79,7 +81,7 @@ func (h *ColorHandler) Delete(c *gin.Context) { // @Router /v1/colors/{id} [get] // @Security AuthBearer func (h *ColorHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToColorResponse, h.usecase.GetById) } // GetColors godoc @@ -88,11 +90,11 @@ func (h *ColorHandler) GetById(c *gin.Context) { // @Tags Colors // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.ColorResponse]} "Color response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.ColorResponse]} "Color response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/colors/get-by-filter [post] // @Security AuthBearer func (h *ColorHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToColorResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/companies.go b/src/api/handler/company.go similarity index 76% rename from src/api/handlers/companies.go rename to src/api/handler/company.go index fb823e5..daa9dd0 100644 --- a/src/api/handlers/companies.go +++ b/src/api/handler/company.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CompanyHandler struct { - service *services.CompanyService + usecase *usecase.CompanyUsecase } func NewCompanyHandler(cfg *config.Config) *CompanyHandler { return &CompanyHandler{ - service: services.NewCompanyService(cfg), + usecase: usecase.NewCompanyUsecase(cfg, dependency.GetCompanyRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewCompanyHandler(cfg *config.Config) *CompanyHandler { // @Router /v1/companies/ [post] // @Security AuthBearer func (h *CompanyHandler) Create(c *gin.Context) { - Create(c, h.service.Create) + Create(c, dto.ToCreateCompany, dto.ToCompanyResponse, h.usecase.Create) } // UpdateCompany godoc @@ -47,7 +49,7 @@ func (h *CompanyHandler) Create(c *gin.Context) { // @Router /v1/companies/{id} [put] // @Security AuthBearer func (h *CompanyHandler) Update(c *gin.Context) { - Update(c, h.service.Update) + Update(c, dto.ToUpdateCompany, dto.ToCompanyResponse, h.usecase.Update) } // DeleteCompany godoc @@ -63,7 +65,7 @@ func (h *CompanyHandler) Update(c *gin.Context) { // @Router /v1/companies/{id} [delete] // @Security AuthBearer func (h *CompanyHandler) Delete(c *gin.Context) { - Delete(c, h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCompany godoc @@ -79,7 +81,7 @@ func (h *CompanyHandler) Delete(c *gin.Context) { // @Router /v1/companies/{id} [get] // @Security AuthBearer func (h *CompanyHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCompanyResponse, h.usecase.GetById) } // GetCompanies godoc @@ -88,11 +90,11 @@ func (h *CompanyHandler) GetById(c *gin.Context) { // @Tags Companies // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CompanyResponse]} "Company response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CompanyResponse]} "Company response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/companies/get-by-filter [post] // @Security AuthBearer func (h *CompanyHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCompanyResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/countries.go b/src/api/handler/country.go similarity index 73% rename from src/api/handlers/countries.go rename to src/api/handler/country.go index 21682ce..522afbc 100644 --- a/src/api/handlers/countries.go +++ b/src/api/handler/country.go @@ -1,19 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type CountryHandler struct { - service *services.CountryService + usecase *usecase.CountryUsecase } func NewCountryHandler(cfg *config.Config) *CountryHandler { - return &CountryHandler{service: services.NewCountryService(cfg)} + return &CountryHandler{ + usecase: usecase.NewCountryUsecase(cfg, dependency.GetCountryRepository(cfg))} } // CreateCountry godoc @@ -28,7 +31,7 @@ func NewCountryHandler(cfg *config.Config) *CountryHandler { // @Router /v1/countries/ [post] // @Security AuthBearer func (h *CountryHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + Create(c, dto.ToCreateUpdateCountry, dto.ToCountryResponse, h.usecase.Create) } // UpdateCountry godoc @@ -44,7 +47,7 @@ func (h *CountryHandler) Create(c *gin.Context) { // @Router /v1/countries/{id} [put] // @Security AuthBearer func (h *CountryHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToCreateUpdateCountry, dto.ToCountryResponse, h.usecase.Update) } // DeleteCountry godoc @@ -59,7 +62,7 @@ func (h *CountryHandler) Update(c *gin.Context) { // @Router /v1/countries/{id} [delete] // @Security AuthBearer func (h *CountryHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetCountry godoc @@ -74,7 +77,7 @@ func (h *CountryHandler) Delete(c *gin.Context) { // @Router /v1/countries/{id} [get] // @Security AuthBearer func (h *CountryHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToCountryResponse, h.usecase.GetById) } // GetCountries godoc @@ -83,11 +86,11 @@ func (h *CountryHandler) GetById(c *gin.Context) { // @Tags Countries // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.CountryResponse]} "Country response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.CountryResponse]} "Country response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/countries/get-by-filter [post] // @Security AuthBearer func (h *CountryHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToCountryResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/files.go b/src/api/handler/file.go similarity index 77% rename from src/api/handlers/files.go rename to src/api/handler/file.go index 55b95af..48965d1 100644 --- a/src/api/handlers/files.go +++ b/src/api/handler/file.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "fmt" @@ -9,8 +9,9 @@ import ( "strconv" "strings" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" - _ "github.com/naeemaei/golang-clean-web-api/api/helper" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" "github.com/gin-gonic/gin" "github.com/google/uuid" @@ -18,16 +19,15 @@ import ( "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" "github.com/naeemaei/golang-clean-web-api/pkg/logging" - "github.com/naeemaei/golang-clean-web-api/services" ) type FileHandler struct { - service *services.FileService + usecase *usecase.FileUsecase } func NewFileHandler(cfg *config.Config) *FileHandler { return &FileHandler{ - service: services.NewFileService(cfg), + usecase: usecase.NewFileUsecase(cfg, dependency.GetFileRepository(cfg)), } } @@ -43,26 +43,26 @@ func NewFileHandler(cfg *config.Config) *FileHandler { // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/files/ [post] // @Security AuthBearer -func (h *FileHandler) Create(c *gin.Context){ - upload:= dto.UploadFileRequest{} +func (h *FileHandler) Create(c *gin.Context) { + upload := dto.UploadFileRequest{} err := c.ShouldBind(&upload) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) return } - req:=dto.CreateFileRequest{} + req := dto.CreateFileRequest{} req.Description = upload.Description req.MimeType = upload.File.Header.Get("Content-Type") - req.Directory ="uploads" - req.Name, err = saveUploadFile(upload.File, req.Directory) + req.Directory = "uploads" + req.Name, err = saveUploadedFile(upload.File, req.Directory) if err != nil { c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) return } - res, err := h.service.Create(c, &req) + res, err := h.usecase.Create(c, dto.ToCreateFile(req)) if err != nil { c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) @@ -70,7 +70,6 @@ func (h *FileHandler) Create(c *gin.Context){ } c.JSON(http.StatusCreated, helper.GenerateBaseResponse(res, true, helper.Success)) - } // UpdateFile godoc @@ -86,7 +85,7 @@ func (h *FileHandler) Create(c *gin.Context){ // @Router /v1/files/{id} [put] // @Security AuthBearer func (h *FileHandler) Update(c *gin.Context) { - Update(c, h.service.Update) + Update(c, dto.ToUpdateFile, dto.ToFileResponse, h.usecase.Update) } // DeleteFile godoc @@ -107,7 +106,7 @@ func (h *FileHandler) Delete(c *gin.Context) { helper.GenerateBaseResponse(nil, false, helper.ValidationError)) return } - file,err := h.service.GetById(c,id) + file, err := h.usecase.GetById(c, id) if err != nil { logger.Error(logging.IO, logging.RemoveFile, err.Error(), nil) c.AbortWithStatusJSON(http.StatusNotFound, @@ -119,9 +118,9 @@ func (h *FileHandler) Delete(c *gin.Context) { logger.Error(logging.IO, logging.RemoveFile, err.Error(), nil) c.AbortWithStatusJSON(http.StatusNotFound, helper.GenerateBaseResponse(nil, false, helper.InternalError)) - return + return } - err = h.service.Delete(c, id) + err = h.usecase.Delete(c, id) if err != nil { c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) @@ -142,7 +141,7 @@ func (h *FileHandler) Delete(c *gin.Context) { // @Router /v1/files/{id} [get] // @Security AuthBearer func (h *FileHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToFileResponse, h.usecase.GetById) } // GetFiles godoc @@ -151,44 +150,43 @@ func (h *FileHandler) GetById(c *gin.Context) { // @Tags Files // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.FileResponse]} "File response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.FileResponse]} "File response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/files/get-by-filter [post] // @Security AuthBearer func (h *FileHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToFileResponse, h.usecase.GetByFilter) } - -func saveUploadFile(file *multipart.FileHeader, directory string) (string, error){ +func saveUploadedFile(file *multipart.FileHeader, directory string) (string, error) { // test.txt -> 95239855629856.txt randFileName := uuid.New() - err:= os.MkdirAll(directory,os.ModePerm) - if err != nil{ + err := os.MkdirAll(directory, os.ModePerm) + if err != nil { return "", err } fileName := file.Filename fileNameArr := strings.Split(fileName, ".") - fileExt := fileNameArr[len(fileNameArr) - 1] - fileName = fmt.Sprintf("%s.%s",randFileName,fileExt) - dst := fmt.Sprintf("%s/%s",directory,fileName) + fileExt := fileNameArr[len(fileNameArr)-1] + fileName = fmt.Sprintf("%s.%s", randFileName, fileExt) + dst := fmt.Sprintf("%s/%s", directory, fileName) src, err := file.Open() - if err != nil{ + if err != nil { return "", err } defer src.Close() out, err := os.Create(dst) - if err != nil{ + if err != nil { return "", err } defer out.Close() _, err = io.Copy(out, src) - if err != nil{ + if err != nil { return "", err } return fileName, nil -} \ No newline at end of file +} diff --git a/src/api/handlers/gearboxes.go b/src/api/handler/gearbox.go similarity index 76% rename from src/api/handlers/gearboxes.go rename to src/api/handler/gearbox.go index 205080a..219eff3 100644 --- a/src/api/handlers/gearboxes.go +++ b/src/api/handler/gearbox.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type GearboxHandler struct { - service *services.GearboxService + usecase *usecase.GearboxUsecase } func NewGearboxHandler(cfg *config.Config) *GearboxHandler { return &GearboxHandler{ - service: services.NewGearboxService(cfg), + usecase: usecase.NewGearboxUsecase(cfg, dependency.GetGearboxRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewGearboxHandler(cfg *config.Config) *GearboxHandler { // @Router /v1/gearboxes/ [post] // @Security AuthBearer func (h *GearboxHandler) Create(c *gin.Context) { - Create(c, h.service.Create) + Create(c, dto.ToCreateGearbox, dto.ToGearboxResponse, h.usecase.Create) } // UpdateGearbox godoc @@ -47,7 +49,7 @@ func (h *GearboxHandler) Create(c *gin.Context) { // @Router /v1/gearboxes/{id} [put] // @Security AuthBearer func (h *GearboxHandler) Update(c *gin.Context) { - Update(c, h.service.Update) + Update(c, dto.ToUpdateGearbox, dto.ToGearboxResponse, h.usecase.Update) } // DeleteGearbox godoc @@ -63,7 +65,7 @@ func (h *GearboxHandler) Update(c *gin.Context) { // @Router /v1/gearboxes/{id} [delete] // @Security AuthBearer func (h *GearboxHandler) Delete(c *gin.Context) { - Delete(c, h.service.Delete) + Delete(c, h.usecase.Delete) } // GetGearbox godoc @@ -79,7 +81,7 @@ func (h *GearboxHandler) Delete(c *gin.Context) { // @Router /v1/gearboxes/{id} [get] // @Security AuthBearer func (h *GearboxHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToGearboxResponse, h.usecase.GetById) } // GetGearboxes godoc @@ -88,11 +90,11 @@ func (h *GearboxHandler) GetById(c *gin.Context) { // @Tags Gearboxes // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.GearboxResponse]} "Gearbox response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.GearboxResponse]} "Gearbox response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/gearboxes/get-by-filter [post] // @Security AuthBearer func (h *GearboxHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToGearboxResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/health.go b/src/api/handler/health.go similarity index 97% rename from src/api/handlers/health.go rename to src/api/handler/health.go index ef0ca19..cac2326 100644 --- a/src/api/handlers/health.go +++ b/src/api/handler/health.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "net/http" diff --git a/src/api/handlers/properties.go b/src/api/handler/property.go similarity index 76% rename from src/api/handlers/properties.go rename to src/api/handler/property.go index ca4f09a..1af73cf 100644 --- a/src/api/handlers/properties.go +++ b/src/api/handler/property.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type PropertyHandler struct { - service *services.PropertyService + usecase *usecase.PropertyUsecase } func NewPropertyHandler(cfg *config.Config) *PropertyHandler { return &PropertyHandler{ - service: services.NewPropertyService(cfg), + usecase: usecase.NewPropertyUsecase(cfg, dependency.GetPropertyRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewPropertyHandler(cfg *config.Config) *PropertyHandler { // @Router /v1/properties/ [post] // @Security AuthBearer func (h *PropertyHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + Create(c, dto.ToCreateProperty, dto.ToPropertyResponse, h.usecase.Create) } // UpdateProperty godoc @@ -47,7 +49,7 @@ func (h *PropertyHandler) Create(c *gin.Context) { // @Router /v1/properties/{id} [put] // @Security AuthBearer func (h *PropertyHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToUpdateProperty, dto.ToPropertyResponse, h.usecase.Update) } // DeleteProperty godoc @@ -63,7 +65,7 @@ func (h *PropertyHandler) Update(c *gin.Context) { // @Router /v1/properties/{id} [delete] // @Security AuthBearer func (h *PropertyHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetProperty godoc @@ -79,7 +81,7 @@ func (h *PropertyHandler) Delete(c *gin.Context) { // @Router /v1/properties/{id} [get] // @Security AuthBearer func (h *PropertyHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToPropertyResponse, h.usecase.GetById) } // GetProperties godoc @@ -88,11 +90,11 @@ func (h *PropertyHandler) GetById(c *gin.Context) { // @Tags Properties // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.PropertyResponse]} "Property response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.PropertyResponse]} "Property response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/properties/get-by-filter [post] // @Security AuthBearer func (h *PropertyHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToPropertyResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/property_categories.go b/src/api/handler/property_category.go similarity index 76% rename from src/api/handlers/property_categories.go rename to src/api/handler/property_category.go index cb6a748..f046de8 100644 --- a/src/api/handlers/property_categories.go +++ b/src/api/handler/property_category.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type PropertyCategoryHandler struct { - service *services.PropertyCategoryService + usecase *usecase.PropertyCategoryUsecase } func NewPropertyCategoryHandler(cfg *config.Config) *PropertyCategoryHandler { return &PropertyCategoryHandler{ - service: services.NewPropertyCategoryService(cfg), + usecase: usecase.NewPropertyCategoryUsecase(cfg, dependency.GetPropertyCategoryRepository(cfg)), } } @@ -30,7 +32,7 @@ func NewPropertyCategoryHandler(cfg *config.Config) *PropertyCategoryHandler { // @Router /v1/property-categories/ [post] // @Security AuthBearer func (h *PropertyCategoryHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + Create(c, dto.ToCreatePropertyCategory, dto.ToPropertyCategoryResponse, h.usecase.Create) } // UpdatePropertyCategory godoc @@ -47,7 +49,7 @@ func (h *PropertyCategoryHandler) Create(c *gin.Context) { // @Router /v1/property-categories/{id} [put] // @Security AuthBearer func (h *PropertyCategoryHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToUpdatePropertyCategory, dto.ToPropertyCategoryResponse, h.usecase.Update) } // DeletePropertyCategory godoc @@ -63,7 +65,7 @@ func (h *PropertyCategoryHandler) Update(c *gin.Context) { // @Router /v1/property-categories/{id} [delete] // @Security AuthBearer func (h *PropertyCategoryHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetPropertyCategory godoc @@ -79,7 +81,7 @@ func (h *PropertyCategoryHandler) Delete(c *gin.Context) { // @Router /v1/property-categories/{id} [get] // @Security AuthBearer func (h *PropertyCategoryHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToPropertyCategoryResponse, h.usecase.GetById) } // GetPropertyCategories godoc @@ -88,11 +90,11 @@ func (h *PropertyCategoryHandler) GetById(c *gin.Context) { // @Tags PropertyCategories // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.PropertyCategoryResponse]} "PropertyCategory response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.PropertyCategoryResponse]} "PropertyCategory response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/property-categories/get-by-filter [post] // @Security AuthBearer func (h *PropertyCategoryHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + GetByFilter(c, dto.ToPropertyCategoryResponse, h.usecase.GetByFilter) } diff --git a/src/api/handler/property_simple.go b/src/api/handler/property_simple.go new file mode 100644 index 0000000..4e6af1b --- /dev/null +++ b/src/api/handler/property_simple.go @@ -0,0 +1,208 @@ +package handler + +import ( + "net/http" + "strconv" + + "github.com/gin-gonic/gin" + "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/helper" + "github.com/naeemaei/golang-clean-web-api/config" + "github.com/naeemaei/golang-clean-web-api/dependency" + "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" +) + +type PropertySimpleHandler struct { + usecase *usecase.PropertyUsecase +} + +func NewPropertySimpleHandler(cfg *config.Config) *PropertySimpleHandler { + return &PropertySimpleHandler{ + usecase: usecase.NewPropertyUsecase(cfg, dependency.GetPropertyRepository(cfg)), + } +} + +// CreateProperty godoc +// @Summary Create a Property +// @Description Create a Property +// @Tags Properties +// @Accept json +// @produces json +// @Param Request body dto.CreatePropertyRequest true "Create a Property" +// @Success 201 {object} helper.BaseHttpResponse{result=dto.PropertyResponse} "Property response" +// @Failure 400 {object} helper.BaseHttpResponse "Bad request" +// @Router /v1/properties/ [post] +// @Security AuthBearer +func (h *PropertySimpleHandler) Create(c *gin.Context) { + request := new(dto.CreatePropertyRequest) + err := c.ShouldBindJSON(&request) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, + helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) + return + } + + // map http request body to usecase input and call use case method + property, err := h.usecase.Create(c, dto.ToCreateProperty(*request)) + + if err != nil { + c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), + helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) + return + } + + // map usecase response to http response + response := dto.ToPropertyResponse(property) + + c.JSON(http.StatusCreated, helper.GenerateBaseResponse(response, true, 0)) +} + +// UpdateProperty godoc +// @Summary Update a Property +// @Description Update a Property +// @Tags Properties +// @Accept json +// @produces json +// @Param id path int true "Id" +// @Param Request body dto.UpdatePropertyRequest true "Update a Property" +// @Success 200 {object} helper.BaseHttpResponse{result=dto.PropertyResponse} "Property response" +// @Failure 400 {object} helper.BaseHttpResponse "Bad request" +// @Failure 404 {object} helper.BaseHttpResponse "Not found" +// @Router /v1/properties/{id} [put] +// @Security AuthBearer +func (h *PropertySimpleHandler) Update(c *gin.Context) { + // bind http request + id, _ := strconv.Atoi(c.Params.ByName("id")) + request := new(dto.UpdatePropertyRequest) + err := c.ShouldBindJSON(&request) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, + helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) + return + + } + // map http request body to usecase input and call use case method + property, err := h.usecase.Update(c, id, dto.ToUpdateProperty(*request)) + + if err != nil { + c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), + helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) + return + } + + // map usecase response to http response + response := dto.ToPropertyResponse(property) + + c.JSON(http.StatusOK, helper.GenerateBaseResponse(response, true, 0)) +} + +// DeleteProperty godoc +// @Summary Delete a Property +// @Description Delete a Property +// @Tags Properties +// @Accept json +// @produces json +// @Param id path int true "Id" +// @Success 200 {object} helper.BaseHttpResponse "response" +// @Failure 400 {object} helper.BaseHttpResponse "Bad request" +// @Failure 404 {object} helper.BaseHttpResponse "Not found" +// @Router /v1/properties/{id} [delete] +// @Security AuthBearer +func (h *PropertySimpleHandler) Delete(c *gin.Context) { + id, _ := strconv.Atoi(c.Params.ByName("id")) + if id == 0 { + c.AbortWithStatusJSON(http.StatusNotFound, + helper.GenerateBaseResponse(nil, false, helper.ValidationError)) + return + } + + err := h.usecase.Delete(c, id) + if err != nil { + c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), + helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) + return + } + c.JSON(http.StatusOK, helper.GenerateBaseResponse(nil, true, 0)) +} + +// GetProperty godoc +// @Summary Get a Property +// @Description Get a Property +// @Tags Properties +// @Accept json +// @produces json +// @Param id path int true "Id" +// @Success 200 {object} helper.BaseHttpResponse{result=dto.PropertyResponse} "Property response" +// @Failure 400 {object} helper.BaseHttpResponse "Bad request" +// @Failure 404 {object} helper.BaseHttpResponse "Not found" +// @Router /v1/properties/{id} [get] +// @Security AuthBearer +func (h *PropertySimpleHandler) GetById(c *gin.Context) { + id, _ := strconv.Atoi(c.Params.ByName("id")) + if id == 0 { + c.AbortWithStatusJSON(http.StatusNotFound, + helper.GenerateBaseResponse(nil, false, helper.ValidationError)) + return + } + + // call use case method + property, err := h.usecase.GetById(c, id) + if err != nil { + c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), + helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) + return + } + + // map usecase response to http response + response := dto.ToPropertyResponse(property) + + c.JSON(http.StatusOK, helper.GenerateBaseResponse(response, true, 0)) +} + +// GetProperties godoc +// @Summary Get Properties +// @Description Get Properties +// @Tags Properties +// @Accept json +// @produces json +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.PropertyResponse]} "Property response" +// @Failure 400 {object} helper.BaseHttpResponse "Bad request" +// @Router /v1/properties/get-by-filter [post] +// @Security AuthBearer +func (h *PropertySimpleHandler) GetByFilter(c *gin.Context) { + req := new(filter.PaginationInputWithFilter) + err := c.ShouldBindJSON(&req) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, + helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) + return + } + + // call use case method + properties, err := h.usecase.GetByFilter(c, *req) + if err != nil { + c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), + helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) + return + } + response := filter.PagedList[dto.PropertyResponse]{ + PageNumber: properties.PageNumber, + PageSize: properties.PageSize, + TotalRows: properties.TotalRows, + TotalPages: properties.TotalPages, + HasPreviousPage: properties.HasPreviousPage, + HasNextPage: properties.HasNextPage, + } + + // map usecase response to http response + items := []dto.PropertyResponse{} + for _, item := range *properties.Items { + + items = append(items, dto.ToPropertyResponse(item)) + } + response.Items = &items + + c.JSON(http.StatusOK, helper.GenerateBaseResponse(response, true, 0)) +} diff --git a/src/api/handlers/test_handler.go b/src/api/handler/test_handler.go similarity index 99% rename from src/api/handlers/test_handler.go rename to src/api/handler/test_handler.go index f958531..d3194b9 100644 --- a/src/api/handlers/test_handler.go +++ b/src/api/handler/test_handler.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "net/http" diff --git a/src/api/handlers/users.go b/src/api/handler/user.go similarity index 86% rename from src/api/handlers/users.go rename to src/api/handler/user.go index 46f8cbc..9d6329a 100644 --- a/src/api/handlers/users.go +++ b/src/api/handler/user.go @@ -1,4 +1,4 @@ -package handlers +package handler import ( "net/http" @@ -7,16 +7,18 @@ import ( "github.com/naeemaei/golang-clean-web-api/api/dto" "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type UsersHandler struct { - service *services.UserService + usecase *usecase.UserUsecase + otpUsecase *usecase.OtpUsecase } -func NewUsersHandler(cfg *config.Config) *UsersHandler { - service := services.NewUserService(cfg) - return &UsersHandler{service: service} +func NewUserHandler(cfg *config.Config) *UsersHandler { + usecase := usecase.NewUserUsecase(cfg, dependency.GetUserRepository(cfg)) + return &UsersHandler{usecase: usecase} } // LoginByUsername godoc @@ -38,7 +40,7 @@ func (h *UsersHandler) LoginByUsername(c *gin.Context) { helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) return } - token, err := h.service.LoginByUsername(req) + token, err := h.usecase.LoginByUsername(c, req.Username, req.Password) if err != nil { c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) @@ -67,7 +69,7 @@ func (h *UsersHandler) RegisterByUsername(c *gin.Context) { helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) return } - err = h.service.RegisterByUsername(req) + err = h.usecase.RegisterByUsername(c, req.ToRegisterUserByUsername()) if err != nil { c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) @@ -96,7 +98,7 @@ func (h *UsersHandler) RegisterLoginByMobileNumber(c *gin.Context) { helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) return } - token, err := h.service.RegisterLoginByMobileNumber(req) + token, err := h.usecase.RegisterAndLoginByMobileNumber(c, req.MobileNumber, req.Otp) if err != nil { c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) @@ -125,12 +127,12 @@ func (h *UsersHandler) SendOtp(c *gin.Context) { helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) return } - err = h.service.SendOtp(req) + err = h.otpUsecase.SendOtp(req.MobileNumber) if err != nil { c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) return } - // Call internal SMS service + // TODO: Call internal SMS service c.JSON(http.StatusCreated, helper.GenerateBaseResponse(nil, true, helper.Success)) } diff --git a/src/api/handlers/years.go b/src/api/handler/year.go similarity index 75% rename from src/api/handlers/years.go rename to src/api/handler/year.go index c2ee6db..4349c8e 100644 --- a/src/api/handlers/years.go +++ b/src/api/handler/year.go @@ -1,20 +1,22 @@ -package handlers +package handler import ( "github.com/gin-gonic/gin" - _ "github.com/naeemaei/golang-clean-web-api/api/dto" + "github.com/naeemaei/golang-clean-web-api/api/dto" _ "github.com/naeemaei/golang-clean-web-api/api/helper" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/services" + "github.com/naeemaei/golang-clean-web-api/dependency" + _ "github.com/naeemaei/golang-clean-web-api/domain/filter" + "github.com/naeemaei/golang-clean-web-api/usecase" ) type PersianYearHandler struct { - service *services.PersianYearService + usecase *usecase.PersianYearUsecase } func NewPersianYearHandler(cfg *config.Config) *PersianYearHandler { return &PersianYearHandler{ - service: services.NewPersianYearService(cfg), + usecase: usecase.NewPersianYearUsecase(cfg, dependency.GetPersianYearRepository(cfg)), } } @@ -30,7 +32,8 @@ func NewPersianYearHandler(cfg *config.Config) *PersianYearHandler { // @Router /v1/years/ [post] // @Security AuthBearer func (h *PersianYearHandler) Create(c *gin.Context) { - Create(c,h.service.Create) + + Create(c, dto.ToCreatePersianYear, dto.ToPersianYearResponse, h.usecase.Create) } // UpdatePersianYear godoc @@ -47,7 +50,7 @@ func (h *PersianYearHandler) Create(c *gin.Context) { // @Router /v1/years/{id} [put] // @Security AuthBearer func (h *PersianYearHandler) Update(c *gin.Context) { - Update(c,h.service.Update) + Update(c, dto.ToUpdatePersianYear, dto.ToPersianYearResponse, h.usecase.Update) } // DeletePersianYear godoc @@ -63,7 +66,7 @@ func (h *PersianYearHandler) Update(c *gin.Context) { // @Router /v1/years/{id} [delete] // @Security AuthBearer func (h *PersianYearHandler) Delete(c *gin.Context) { - Delete(c,h.service.Delete) + Delete(c, h.usecase.Delete) } // GetPersianYear godoc @@ -79,7 +82,7 @@ func (h *PersianYearHandler) Delete(c *gin.Context) { // @Router /v1/years/{id} [get] // @Security AuthBearer func (h *PersianYearHandler) GetById(c *gin.Context) { - GetById(c, h.service.GetById) + GetById(c, dto.ToPersianYearResponse, h.usecase.GetById) } // GetPersianYears godoc @@ -88,11 +91,12 @@ func (h *PersianYearHandler) GetById(c *gin.Context) { // @Tags PersianYears // @Accept json // @produces json -// @Param Request body dto.PaginationInputWithFilter true "Request" -// @Success 200 {object} helper.BaseHttpResponse{result=dto.PagedList[dto.PersianYearResponse]} "PersianYear response" +// @Param Request body filter.PaginationInputWithFilter true "Request" +// @Success 200 {object} helper.BaseHttpResponse{result=filter.PagedList[dto.PersianYearResponse]} "PersianYear response" // @Failure 400 {object} helper.BaseHttpResponse "Bad request" // @Router /v1/years/get-by-filter [post] // @Security AuthBearer func (h *PersianYearHandler) GetByFilter(c *gin.Context) { - GetByFilter(c, h.service.GetByFilter) + + GetByFilter(c, dto.ToPersianYearResponse, h.usecase.GetByFilter) } diff --git a/src/api/handlers/base.go b/src/api/handlers/base.go deleted file mode 100644 index b1d887b..0000000 --- a/src/api/handlers/base.go +++ /dev/null @@ -1,106 +0,0 @@ -package handlers - -import ( - "context" - "net/http" - "strconv" - - "github.com/gin-gonic/gin" - "github.com/naeemaei/golang-clean-web-api/api/helper" - "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/pkg/logging" -) - - - -var logger = logging.NewLogger(config.GetConfig()) - - -func Create[Ti any,To any](c *gin.Context, caller func(ctx context.Context, req *Ti)(*To, error)){ - req := new(Ti) - err := c.ShouldBindJSON(&req) - if err != nil { - c.AbortWithStatusJSON(http.StatusBadRequest, - helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) - return - } - - res, err := caller(c, req) - if err != nil { - c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), - helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) - return - } - c.JSON(http.StatusCreated, helper.GenerateBaseResponse(res, true, 0)) -} - -func Update[Ti any,To any](c *gin.Context, caller func(ctx context.Context,id int, req *Ti)(*To, error)){ - id, _ := strconv.Atoi(c.Params.ByName("id")) - req :=new(Ti) - err := c.ShouldBindJSON(&req) - if err != nil { - c.AbortWithStatusJSON(http.StatusBadRequest, - helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) - return - } - - res, err := caller(c, id, req) - if err != nil { - c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), - helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) - return - } - c.JSON(http.StatusOK, helper.GenerateBaseResponse(res, true, 0)) -} - -func Delete(c *gin.Context, caller func(ctx context.Context,id int)error){ - id, _ := strconv.Atoi(c.Params.ByName("id")) - if id == 0 { - c.AbortWithStatusJSON(http.StatusNotFound, - helper.GenerateBaseResponse(nil, false, helper.ValidationError)) - return - } - - err := caller(c, id) - if err != nil { - c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), - helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) - return - } - c.JSON(http.StatusOK, helper.GenerateBaseResponse(nil, true, 0)) -} - -func GetById[To any](c *gin.Context,caller func(c context.Context, id int) (*To, error)){ - id, _ := strconv.Atoi(c.Params.ByName("id")) - if id == 0 { - c.AbortWithStatusJSON(http.StatusNotFound, - helper.GenerateBaseResponse(nil, false, helper.ValidationError)) - return - } - - res, err := caller(c, id) - if err != nil { - c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), - helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) - return - } - c.JSON(http.StatusOK, helper.GenerateBaseResponse(res, true, 0)) -} - -func GetByFilter[Ti any, To any](c *gin.Context, caller func(c context.Context, req *Ti)(*To, error)){ - req := new(Ti) - err := c.ShouldBindJSON(&req) - if err != nil { - c.AbortWithStatusJSON(http.StatusBadRequest, - helper.GenerateBaseResponseWithValidationError(nil, false, helper.ValidationError, err)) - return - } - - res, err := caller(c, req) - if err != nil { - c.AbortWithStatusJSON(helper.TranslateErrorToStatusCode(err), - helper.GenerateBaseResponseWithError(nil, false, helper.InternalError, err)) - return - } - c.JSON(http.StatusOK, helper.GenerateBaseResponse(res, true, 0)) -} \ No newline at end of file From 0cbfc7a7fa2458cfe0479b76910a6fd5160ad8d0 Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 19:05:31 +0330 Subject: [PATCH 16/18] Change routers directory location --- src/api/{routers => router}/basic.go | 17 +++++++------- src/api/{routers => router}/cars.go | 22 +++++++++---------- src/api/router/health.go | 12 ++++++++++ .../properties.go => router/property.go} | 8 +++---- src/api/{routers => router}/test_router.go | 6 ++--- src/api/{routers => router}/users.go | 10 ++++----- src/api/routers/health.go | 12 ---------- 7 files changed, 44 insertions(+), 43 deletions(-) rename src/api/{routers => router}/basic.go (81%) rename src/api/{routers => router}/cars.go (80%) create mode 100644 src/api/router/health.go rename src/api/{routers/properties.go => router/property.go} (75%) rename src/api/{routers => router}/test_router.go (85%) rename src/api/{routers => router}/users.go (58%) delete mode 100644 src/api/routers/health.go diff --git a/src/api/routers/basic.go b/src/api/router/basic.go similarity index 81% rename from src/api/routers/basic.go rename to src/api/router/basic.go index ec928a5..db2485e 100644 --- a/src/api/routers/basic.go +++ b/src/api/router/basic.go @@ -1,14 +1,15 @@ -package routers +package router import ( "github.com/gin-gonic/gin" - "github.com/naeemaei/golang-clean-web-api/api/handlers" + "github.com/naeemaei/golang-clean-web-api/api/handler" "github.com/naeemaei/golang-clean-web-api/config" ) const GetByFilterExp string = "/get-by-filter" + func Country(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCountryHandler(cfg) + h := handler.NewCountryHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -18,7 +19,7 @@ func Country(r *gin.RouterGroup, cfg *config.Config) { } func City(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCityHandler(cfg) + h := handler.NewCityHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -28,7 +29,7 @@ func City(r *gin.RouterGroup, cfg *config.Config) { } func File(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewFileHandler(cfg) + h := handler.NewFileHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -38,7 +39,7 @@ func File(r *gin.RouterGroup, cfg *config.Config) { } func Company(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCompanyHandler(cfg) + h := handler.NewCompanyHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -48,7 +49,7 @@ func Company(r *gin.RouterGroup, cfg *config.Config) { } func Color(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewColorHandler(cfg) + h := handler.NewColorHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -58,7 +59,7 @@ func Color(r *gin.RouterGroup, cfg *config.Config) { } func Year(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewPersianYearHandler(cfg) + h := handler.NewPersianYearHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) diff --git a/src/api/routers/cars.go b/src/api/router/cars.go similarity index 80% rename from src/api/routers/cars.go rename to src/api/router/cars.go index af342ca..385546b 100644 --- a/src/api/routers/cars.go +++ b/src/api/router/cars.go @@ -1,13 +1,13 @@ -package routers +package router import ( "github.com/gin-gonic/gin" - "github.com/naeemaei/golang-clean-web-api/api/handlers" + "github.com/naeemaei/golang-clean-web-api/api/handler" "github.com/naeemaei/golang-clean-web-api/config" ) func CarType(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCarTypeHandler(cfg) + h := handler.NewCarTypeHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -17,7 +17,7 @@ func CarType(r *gin.RouterGroup, cfg *config.Config) { } func Gearbox(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewGearboxHandler(cfg) + h := handler.NewGearboxHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -27,7 +27,7 @@ func Gearbox(r *gin.RouterGroup, cfg *config.Config) { } func CarModel(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCarModelHandler(cfg) + h := handler.NewCarModelHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -37,7 +37,7 @@ func CarModel(r *gin.RouterGroup, cfg *config.Config) { } func CarModelColor(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCarModelColorHandler(cfg) + h := handler.NewCarModelColorHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -47,7 +47,7 @@ func CarModelColor(r *gin.RouterGroup, cfg *config.Config) { } func CarModelYear(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCarModelYearHandler(cfg) + h := handler.NewCarModelYearHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -57,7 +57,7 @@ func CarModelYear(r *gin.RouterGroup, cfg *config.Config) { } func CarModelPriceHistory(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCarModelPriceHistoryHandler(cfg) + h := handler.NewCarModelPriceHistoryHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -67,7 +67,7 @@ func CarModelPriceHistory(r *gin.RouterGroup, cfg *config.Config) { } func CarModelImage(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCarModelImageHandler(cfg) + h := handler.NewCarModelImageHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -77,7 +77,7 @@ func CarModelImage(r *gin.RouterGroup, cfg *config.Config) { } func CarModelProperty(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCarModelPropertyHandler(cfg) + h := handler.NewCarModelPropertyHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -87,7 +87,7 @@ func CarModelProperty(r *gin.RouterGroup, cfg *config.Config) { } func CarModelComment(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewCarModelCommentHandler(cfg) + h := handler.NewCarModelCommentHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) diff --git a/src/api/router/health.go b/src/api/router/health.go new file mode 100644 index 0000000..ef8e42f --- /dev/null +++ b/src/api/router/health.go @@ -0,0 +1,12 @@ +package router + +import ( + "github.com/gin-gonic/gin" + "github.com/naeemaei/golang-clean-web-api/api/handler" +) + +func Health(r *gin.RouterGroup) { + handler := handler.NewHealthHandler() + + r.GET("/", handler.Health) +} diff --git a/src/api/routers/properties.go b/src/api/router/property.go similarity index 75% rename from src/api/routers/properties.go rename to src/api/router/property.go index 8dcc59e..8a18be8 100644 --- a/src/api/routers/properties.go +++ b/src/api/router/property.go @@ -1,13 +1,13 @@ -package routers +package router import ( "github.com/gin-gonic/gin" - "github.com/naeemaei/golang-clean-web-api/api/handlers" + "github.com/naeemaei/golang-clean-web-api/api/handler" "github.com/naeemaei/golang-clean-web-api/config" ) func PropertyCategory(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewPropertyCategoryHandler(cfg) + h := handler.NewPropertyCategoryHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) @@ -17,7 +17,7 @@ func PropertyCategory(r *gin.RouterGroup, cfg *config.Config) { } func Property(r *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewPropertyHandler(cfg) + h := handler.NewPropertyHandler(cfg) r.POST("/", h.Create) r.PUT("/:id", h.Update) diff --git a/src/api/routers/test_router.go b/src/api/router/test_router.go similarity index 85% rename from src/api/routers/test_router.go rename to src/api/router/test_router.go index c838b32..84b9414 100644 --- a/src/api/routers/test_router.go +++ b/src/api/router/test_router.go @@ -1,12 +1,12 @@ -package routers +package router import ( "github.com/gin-gonic/gin" - "github.com/naeemaei/golang-clean-web-api/api/handlers" + "github.com/naeemaei/golang-clean-web-api/api/handler" ) func TestRouter(r *gin.RouterGroup) { - h := handlers.NewTestHandler() + h := handler.NewTestHandler() r.GET("/", h.Test) r.GET("/users", h.Users) diff --git a/src/api/routers/users.go b/src/api/router/users.go similarity index 58% rename from src/api/routers/users.go rename to src/api/router/users.go index a93cf30..52444dd 100644 --- a/src/api/routers/users.go +++ b/src/api/router/users.go @@ -1,16 +1,16 @@ -package routers +package router import ( "github.com/gin-gonic/gin" - "github.com/naeemaei/golang-clean-web-api/api/handlers" - "github.com/naeemaei/golang-clean-web-api/api/middlewares" + "github.com/naeemaei/golang-clean-web-api/api/handler" + "github.com/naeemaei/golang-clean-web-api/api/middleware" "github.com/naeemaei/golang-clean-web-api/config" ) func User(router *gin.RouterGroup, cfg *config.Config) { - h := handlers.NewUsersHandler(cfg) + h := handler.NewUserHandler(cfg) - router.POST("/send-otp", middlewares.OtpLimiter(cfg), h.SendOtp) + router.POST("/send-otp", middleware.OtpLimiter(cfg), h.SendOtp) router.POST("/login-by-username", h.LoginByUsername) router.POST("/register-by-username", h.RegisterByUsername) router.POST("/login-by-mobile", h.RegisterLoginByMobileNumber) diff --git a/src/api/routers/health.go b/src/api/routers/health.go deleted file mode 100644 index f0c5140..0000000 --- a/src/api/routers/health.go +++ /dev/null @@ -1,12 +0,0 @@ -package routers - -import ( - "github.com/gin-gonic/gin" - "github.com/naeemaei/golang-clean-web-api/api/handlers" -) - -func Health(r *gin.RouterGroup) { - handler := handlers.NewHealthHandler() - - r.GET("/", handler.Health) -} From f696b038eea9bafcfdeb024729e03740fc3ab434 Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 19:05:46 +0330 Subject: [PATCH 17/18] Update main file references --- src/cmd/main.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/main.go b/src/cmd/main.go index 8e31e5b..367ff51 100644 --- a/src/cmd/main.go +++ b/src/cmd/main.go @@ -3,9 +3,9 @@ package main import ( "github.com/naeemaei/golang-clean-web-api/api" "github.com/naeemaei/golang-clean-web-api/config" - "github.com/naeemaei/golang-clean-web-api/data/cache" - "github.com/naeemaei/golang-clean-web-api/data/db" - "github.com/naeemaei/golang-clean-web-api/data/db/migrations" + "github.com/naeemaei/golang-clean-web-api/infra/cache" + database "github.com/naeemaei/golang-clean-web-api/infra/persistence/database" + "github.com/naeemaei/golang-clean-web-api/infra/persistence/migration" "github.com/naeemaei/golang-clean-web-api/pkg/logging" ) @@ -23,12 +23,12 @@ func main() { logger.Fatal(logging.Redis, logging.Startup, err.Error(), nil) } - err = db.InitDb(cfg) - defer db.CloseDb() + err = database.InitDb(cfg) + defer database.CloseDb() if err != nil { logger.Fatal(logging.Postgres, logging.Startup, err.Error(), nil) } - migrations.Up1() + migration.Up1() api.InitServer(cfg) } From 8e64beabaf41c2dea0c2a86d66b79e14f5cecd6c Mon Sep 17 00:00:00 2001 From: hamed naeemaei Date: Mon, 29 Apr 2024 19:05:54 +0330 Subject: [PATCH 18/18] Update docs --- src/docs/docs.go | 1310 +++++++++++++++++++++-------------------- src/docs/swagger.json | 1310 +++++++++++++++++++++-------------------- src/docs/swagger.yaml | 1005 +++++++++++++++---------------- 3 files changed, 1850 insertions(+), 1775 deletions(-) diff --git a/src/docs/docs.go b/src/docs/docs.go index 968020d..c9eb776 100644 --- a/src/docs/docs.go +++ b/src/docs/docs.go @@ -91,7 +91,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -107,7 +107,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse" } } } @@ -366,7 +366,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -382,7 +382,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse" } } } @@ -641,7 +641,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -657,7 +657,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse" } } } @@ -916,7 +916,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -932,7 +932,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse" } } } @@ -1191,7 +1191,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -1207,7 +1207,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse" } } } @@ -1466,7 +1466,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -1482,7 +1482,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse" } } } @@ -1741,7 +1741,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -1757,7 +1757,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse" } } } @@ -2016,7 +2016,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -2032,7 +2032,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse" } } } @@ -2291,7 +2291,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -2307,7 +2307,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse" } } } @@ -2566,7 +2566,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -2582,7 +2582,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse" } } } @@ -2841,7 +2841,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -2857,7 +2857,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse" } } } @@ -3116,7 +3116,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -3132,7 +3132,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse" } } } @@ -3377,7 +3377,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -3393,7 +3393,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse" } } } @@ -3634,7 +3634,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -3650,7 +3650,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse" } } } @@ -3938,7 +3938,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -3954,7 +3954,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse" } } } @@ -4213,7 +4213,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -4229,7 +4229,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse" } } } @@ -4437,7 +4437,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/api_handlers.personData" + "$ref": "#/definitions/api_handler.personData" } } ], @@ -4829,7 +4829,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -4845,7 +4845,7 @@ const docTemplate = `{ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse" } } } @@ -5030,7 +5030,7 @@ const docTemplate = `{ } }, "definitions": { - "api_handlers.personData": { + "api_handler.personData": { "type": "object", "required": [ "first_name", @@ -5588,25 +5588,6 @@ const docTemplate = `{ } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.Filter": { - "type": "object", - "properties": { - "filterType": { - "description": "text number", - "type": "string" - }, - "from": { - "type": "string" - }, - "to": { - "type": "string" - }, - "type": { - "description": "contains notContains equals notEqual startsWith lessThan lessThanOrEqual greaterThan greaterThanOrEqual inRange endsWith", - "type": "string" - } - } - }, "github_com_naeemaei_golang-clean-web-api_api_dto.GearboxResponse": { "type": "object", "properties": { @@ -5648,482 +5629,303 @@ const docTemplate = `{ } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelColorResponse" - } + "endAt": { + "type": "string" }, - "pageNumber": { + "id": { "type": "integer" }, - "totalPages": { - "type": "integer" + "persianTitle": { + "type": "string" }, - "totalRows": { + "startAt": { + "type": "string" + }, + "year": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearWithoutDateResponse": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelCommentResponse" - } - }, - "pageNumber": { + "id": { "type": "integer" }, - "totalPages": { - "type": "integer" + "persianTitle": { + "type": "string" }, - "totalRows": { + "year": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" + "icon": { + "type": "string" }, - "hasPreviousPage": { - "type": "boolean" + "id": { + "type": "integer" }, - "items": { + "name": { + "type": "string" + }, + "properties": { "type": "array", "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelImageResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse" } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" + "category": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse" }, - "hasPreviousPage": { - "type": "boolean" + "dataType": { + "type": "string" }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPriceHistoryResponse" - } + "description": { + "type": "string" }, - "pageNumber": { - "type": "integer" + "icon": { + "type": "string" }, - "totalPages": { + "id": { "type": "integer" }, - "totalRows": { - "type": "integer" + "name": { + "type": "string" + }, + "unit": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.RegisterLoginByMobileRequest": { "type": "object", + "required": [ + "mobileNumber", + "otp" + ], "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPropertyResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" + "mobileNumber": { + "type": "string", + "maxLength": 11, + "minLength": 11 }, - "totalRows": { - "type": "integer" + "otp": { + "type": "string", + "maxLength": 6, + "minLength": 6 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.RegisterUserByUsernameRequest": { "type": "object", + "required": [ + "firstName", + "lastName", + "password", + "username" + ], "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" + "email": { + "type": "string", + "minLength": 6 }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelResponse" - } + "firstName": { + "type": "string", + "minLength": 3 }, - "pageNumber": { - "type": "integer" + "lastName": { + "type": "string", + "minLength": 6 }, - "totalPages": { - "type": "integer" + "password": { + "type": "string", + "minLength": 6 }, - "totalRows": { - "type": "integer" + "username": { + "type": "string", + "minLength": 5 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelColorRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelYearResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { + "carModelId": { "type": "integer" }, - "totalRows": { + "colorId": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelCommentRequest": { "type": "object", + "required": [ + "message" + ], "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarTypeResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" + "message": { + "type": "string", + "maxLength": 100 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelImageRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { + "isMainImage": { "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CityResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPriceHistoryRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.ColorResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" + "price": { + "type": "number" }, - "totalRows": { - "type": "integer" + "priceAt": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPropertyRequest": { "type": "object", + "required": [ + "value" + ], "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CompanyResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" + "value": { + "type": "string", + "maxLength": 100 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CountryResponse" - } - }, - "pageNumber": { + "carTypeId": { "type": "integer" }, - "totalPages": { + "companyId": { "type": "integer" }, - "totalRows": { + "gearboxId": { "type": "integer" + }, + "name": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelYearRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.FileResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { + "carModelId": { "type": "integer" }, - "totalRows": { + "persianYearId": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarTypeRequest": { "type": "object", + "required": [ + "name" + ], "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.GearboxResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" + "name": { + "type": "string", + "maxLength": 15, + "minLength": 3 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCityRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { + "countryId": { "type": "integer" }, - "totalRows": { - "type": "integer" + "name": { + "type": "string", + "maxLength": 20, + "minLength": 3 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateColorRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" + "hexCode": { + "type": "string", + "maxLength": 7, + "minLength": 7 }, - "totalRows": { - "type": "integer" + "name": { + "type": "string", + "maxLength": 15, + "minLength": 3 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCompanyRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { + "countryId": { "type": "integer" }, - "totalRows": { - "type": "integer" + "name": { + "type": "string", + "maxLength": 20, + "minLength": 3 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateFileRequest": { "type": "object", "properties": { - "filter": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.Filter" - } - }, - "pageNumber": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "sort": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.Sort" - } + "description": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateGearboxRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "maxLength": 15, + "minLength": 3 + } + } + }, + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePersianYearRequest": { "type": "object", "properties": { "endAt": { "type": "string" }, - "id": { - "type": "integer" - }, "persianTitle": { - "type": "string" + "type": "string", + "maxLength": 4, + "minLength": 4 }, "startAt": { "type": "string" @@ -6133,441 +5935,667 @@ const docTemplate = `{ } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearWithoutDateResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyCategoryRequest": { "type": "object", "properties": { - "id": { - "type": "integer" - }, - "persianTitle": { + "icon": { "type": "string" }, - "year": { - "type": "integer" + "name": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyRequest": { "type": "object", "properties": { - "icon": { - "type": "string" - }, - "id": { + "categoryId": { "type": "integer" }, - "name": { + "dataType": { + "type": "string", + "maxLength": 15 + }, + "description": { + "type": "string", + "maxLength": 1000 + }, + "icon": { + "type": "string", + "maxLength": 1000 + }, + "name": { "type": "string" }, - "properties": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse" - } + "unit": { + "type": "string", + "maxLength": 15 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UserResponse": { "type": "object", "properties": { - "category": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse" - }, - "dataType": { - "type": "string" - }, - "description": { + "email": { "type": "string" }, - "icon": { + "firstName": { "type": "string" }, "id": { "type": "integer" }, - "name": { + "lastName": { "type": "string" }, - "unit": { + "username": { "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.RegisterLoginByMobileRequest": { + "github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse": { "type": "object", - "required": [ - "mobileNumber", - "otp" - ], "properties": { - "mobileNumber": { - "type": "string", - "maxLength": 11, - "minLength": 11 + "error": {}, + "result": {}, + "resultCode": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode" }, - "otp": { - "type": "string", - "maxLength": 6, - "minLength": 6 + "success": { + "type": "boolean" + }, + "validationErrors": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_validation.ValidationError" + } } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.RegisterUserByUsernameRequest": { - "type": "object", - "required": [ - "firstName", - "lastName", - "password", - "username" + "github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode": { + "type": "integer", + "enum": [ + 0, + 40001, + 40101, + 40301, + 40401, + 42901, + 42902, + 50001, + 50002 ], + "x-enum-varnames": [ + "Success", + "ValidationError", + "AuthError", + "ForbiddenError", + "NotFoundError", + "LimiterError", + "OtpLimiterError", + "CustomRecovery", + "InternalError" + ] + }, + "github_com_naeemaei_golang-clean-web-api_api_validation.ValidationError": { + "type": "object", "properties": { - "email": { - "type": "string", - "minLength": 6 - }, - "firstName": { - "type": "string", - "minLength": 3 + "message": { + "type": "string" }, - "lastName": { - "type": "string", - "minLength": 6 + "property": { + "type": "string" }, - "password": { - "type": "string", - "minLength": 6 + "tag": { + "type": "string" }, - "username": { - "type": "string", - "minLength": 5 + "value": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.Sort": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.Filter": { "type": "object", "properties": { - "colId": { + "filterType": { + "description": "text number", "type": "string" }, - "sort": { + "from": { + "type": "string" + }, + "to": { + "type": "string" + }, + "type": { + "description": "contains notContains equals notEqual startsWith lessThan lessThanOrEqual greaterThan greaterThanOrEqual inRange endsWith", "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelColorRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse": { "type": "object", "properties": { - "carModelId": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelColorResponse" + } + }, + "pageNumber": { "type": "integer" }, - "colorId": { + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelCommentRequest": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string", - "maxLength": 100 - } - } - }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelImageRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse": { "type": "object", "properties": { - "isMainImage": { + "hasNextPage": { "type": "boolean" - } - } - }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPriceHistoryRequest": { - "type": "object", - "properties": { - "price": { - "type": "number" }, - "priceAt": { - "type": "string" - } - } - }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPropertyRequest": { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string", - "maxLength": 100 + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelCommentResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse": { "type": "object", "properties": { - "carTypeId": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelImageResponse" + } + }, + "pageNumber": { "type": "integer" }, - "companyId": { + "pageSize": { "type": "integer" }, - "gearboxId": { + "totalPages": { "type": "integer" }, - "name": { - "type": "string" + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelYearRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse": { "type": "object", "properties": { - "carModelId": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPriceHistoryResponse" + } + }, + "pageNumber": { "type": "integer" }, - "persianYearId": { + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarTypeRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse": { "type": "object", - "required": [ - "name" - ], "properties": { - "name": { - "type": "string", - "maxLength": 15, - "minLength": 3 + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPropertyResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCityRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse": { "type": "object", "properties": { - "countryId": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelResponse" + } + }, + "pageNumber": { "type": "integer" }, - "name": { - "type": "string", - "maxLength": 20, - "minLength": 3 + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateColorRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse": { "type": "object", "properties": { - "hexCode": { - "type": "string", - "maxLength": 7, - "minLength": 7 + "hasNextPage": { + "type": "boolean" }, - "name": { - "type": "string", - "maxLength": 15, - "minLength": 3 + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelYearResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCompanyRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse": { "type": "object", "properties": { - "countryId": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarTypeResponse" + } + }, + "pageNumber": { "type": "integer" }, - "name": { - "type": "string", - "maxLength": 20, - "minLength": 3 + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateFileRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse": { "type": "object", "properties": { - "description": { - "type": "string" + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CityResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateGearboxRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse": { "type": "object", - "required": [ - "name" - ], "properties": { - "name": { - "type": "string", - "maxLength": 15, - "minLength": 3 + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.ColorResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePersianYearRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse": { "type": "object", "properties": { - "endAt": { - "type": "string" + "hasNextPage": { + "type": "boolean" }, - "persianTitle": { - "type": "string", - "maxLength": 4, - "minLength": 4 + "hasPreviousPage": { + "type": "boolean" }, - "startAt": { - "type": "string" + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CompanyResponse" + } }, - "year": { + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyCategoryRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse": { "type": "object", "properties": { - "icon": { - "type": "string" + "hasNextPage": { + "type": "boolean" }, - "name": { - "type": "string" + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CountryResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse": { "type": "object", "properties": { - "categoryId": { - "type": "integer" + "hasNextPage": { + "type": "boolean" }, - "dataType": { - "type": "string", - "maxLength": 15 + "hasPreviousPage": { + "type": "boolean" }, - "description": { - "type": "string", - "maxLength": 1000 + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.FileResponse" + } }, - "icon": { - "type": "string", - "maxLength": 1000 + "pageNumber": { + "type": "integer" }, - "name": { - "type": "string" + "pageSize": { + "type": "integer" }, - "unit": { - "type": "string", - "maxLength": 15 + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UserResponse": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse": { "type": "object", "properties": { - "email": { - "type": "string" + "hasNextPage": { + "type": "boolean" }, - "firstName": { - "type": "string" + "hasPreviousPage": { + "type": "boolean" }, - "id": { + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.GearboxResponse" + } + }, + "pageNumber": { "type": "integer" }, - "lastName": { - "type": "string" + "pageSize": { + "type": "integer" }, - "username": { - "type": "string" + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse": { "type": "object", "properties": { - "error": {}, - "result": {}, - "resultCode": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode" + "hasNextPage": { + "type": "boolean" }, - "success": { + "hasPreviousPage": { "type": "boolean" }, - "validationErrors": { + "items": { "type": "array", "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_validations.ValidationError" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse" } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode": { - "type": "integer", - "enum": [ - 0, - 40001, - 40101, - 40301, - 40401, - 42901, - 42902, - 50001, - 50002 - ], - "x-enum-varnames": [ - "Success", - "ValidationError", - "AuthError", - "ForbiddenError", - "NotFoundError", - "LimiterError", - "OtpLimiterError", - "CustomRecovery", - "InternalError" - ] + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse": { + "type": "object", + "properties": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" + } + } }, - "github_com_naeemaei_golang-clean-web-api_api_validations.ValidationError": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse": { "type": "object", "properties": { - "message": { - "type": "string" + "hasNextPage": { + "type": "boolean" }, - "property": { - "type": "string" + "hasPreviousPage": { + "type": "boolean" }, - "tag": { - "type": "string" + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse" + } }, - "value": { - "type": "string" + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "multipart.FileHeader": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter": { "type": "object", "properties": { - "filename": { - "type": "string" + "filter": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.Filter" + } }, - "header": { - "$ref": "#/definitions/textproto.MIMEHeader" + "pageNumber": { + "type": "integer" }, - "size": { + "pageSize": { "type": "integer" + }, + "sort": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.Sort" + } } } }, - "textproto.MIMEHeader": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.Sort": { "type": "object", - "additionalProperties": { - "type": "array", - "items": { + "properties": { + "colId": { + "type": "string" + }, + "sort": { "type": "string" } } diff --git a/src/docs/swagger.json b/src/docs/swagger.json index 4af10ef..2e4d6db 100644 --- a/src/docs/swagger.json +++ b/src/docs/swagger.json @@ -80,7 +80,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -96,7 +96,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse" } } } @@ -355,7 +355,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -371,7 +371,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse" } } } @@ -630,7 +630,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -646,7 +646,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse" } } } @@ -905,7 +905,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -921,7 +921,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse" } } } @@ -1180,7 +1180,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -1196,7 +1196,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse" } } } @@ -1455,7 +1455,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -1471,7 +1471,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse" } } } @@ -1730,7 +1730,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -1746,7 +1746,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse" } } } @@ -2005,7 +2005,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -2021,7 +2021,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse" } } } @@ -2280,7 +2280,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -2296,7 +2296,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse" } } } @@ -2555,7 +2555,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -2571,7 +2571,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse" } } } @@ -2830,7 +2830,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -2846,7 +2846,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse" } } } @@ -3105,7 +3105,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -3121,7 +3121,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse" } } } @@ -3366,7 +3366,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -3382,7 +3382,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse" } } } @@ -3623,7 +3623,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -3639,7 +3639,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse" } } } @@ -3927,7 +3927,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -3943,7 +3943,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse" } } } @@ -4202,7 +4202,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -4218,7 +4218,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse" } } } @@ -4426,7 +4426,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/api_handlers.personData" + "$ref": "#/definitions/api_handler.personData" } } ], @@ -4818,7 +4818,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter" } } ], @@ -4834,7 +4834,7 @@ "type": "object", "properties": { "result": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse" } } } @@ -5019,7 +5019,7 @@ } }, "definitions": { - "api_handlers.personData": { + "api_handler.personData": { "type": "object", "required": [ "first_name", @@ -5577,25 +5577,6 @@ } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.Filter": { - "type": "object", - "properties": { - "filterType": { - "description": "text number", - "type": "string" - }, - "from": { - "type": "string" - }, - "to": { - "type": "string" - }, - "type": { - "description": "contains notContains equals notEqual startsWith lessThan lessThanOrEqual greaterThan greaterThanOrEqual inRange endsWith", - "type": "string" - } - } - }, "github_com_naeemaei_golang-clean-web-api_api_dto.GearboxResponse": { "type": "object", "properties": { @@ -5637,482 +5618,303 @@ } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelColorResponse" - } + "endAt": { + "type": "string" }, - "pageNumber": { + "id": { "type": "integer" }, - "totalPages": { - "type": "integer" + "persianTitle": { + "type": "string" }, - "totalRows": { + "startAt": { + "type": "string" + }, + "year": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearWithoutDateResponse": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelCommentResponse" - } - }, - "pageNumber": { + "id": { "type": "integer" }, - "totalPages": { - "type": "integer" + "persianTitle": { + "type": "string" }, - "totalRows": { + "year": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" + "icon": { + "type": "string" }, - "hasPreviousPage": { - "type": "boolean" + "id": { + "type": "integer" }, - "items": { + "name": { + "type": "string" + }, + "properties": { "type": "array", "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelImageResponse" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse" } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" + "category": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse" }, - "hasPreviousPage": { - "type": "boolean" + "dataType": { + "type": "string" }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPriceHistoryResponse" - } + "description": { + "type": "string" }, - "pageNumber": { - "type": "integer" + "icon": { + "type": "string" }, - "totalPages": { + "id": { "type": "integer" }, - "totalRows": { - "type": "integer" + "name": { + "type": "string" + }, + "unit": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.RegisterLoginByMobileRequest": { "type": "object", + "required": [ + "mobileNumber", + "otp" + ], "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPropertyResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" + "mobileNumber": { + "type": "string", + "maxLength": 11, + "minLength": 11 }, - "totalRows": { - "type": "integer" + "otp": { + "type": "string", + "maxLength": 6, + "minLength": 6 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.RegisterUserByUsernameRequest": { "type": "object", + "required": [ + "firstName", + "lastName", + "password", + "username" + ], "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" + "email": { + "type": "string", + "minLength": 6 }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelResponse" - } + "firstName": { + "type": "string", + "minLength": 3 }, - "pageNumber": { - "type": "integer" + "lastName": { + "type": "string", + "minLength": 6 }, - "totalPages": { - "type": "integer" + "password": { + "type": "string", + "minLength": 6 }, - "totalRows": { - "type": "integer" + "username": { + "type": "string", + "minLength": 5 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelColorRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelYearResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { + "carModelId": { "type": "integer" }, - "totalRows": { + "colorId": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelCommentRequest": { "type": "object", + "required": [ + "message" + ], "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarTypeResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" + "message": { + "type": "string", + "maxLength": 100 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelImageRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { + "isMainImage": { "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CityResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPriceHistoryRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.ColorResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" + "price": { + "type": "number" }, - "totalRows": { - "type": "integer" + "priceAt": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPropertyRequest": { "type": "object", + "required": [ + "value" + ], "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CompanyResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" + "value": { + "type": "string", + "maxLength": 100 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CountryResponse" - } - }, - "pageNumber": { + "carTypeId": { "type": "integer" }, - "totalPages": { + "companyId": { "type": "integer" }, - "totalRows": { + "gearboxId": { "type": "integer" + }, + "name": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelYearRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.FileResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { + "carModelId": { "type": "integer" }, - "totalRows": { + "persianYearId": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarTypeRequest": { "type": "object", + "required": [ + "name" + ], "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.GearboxResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" - }, - "totalRows": { - "type": "integer" + "name": { + "type": "string", + "maxLength": 15, + "minLength": 3 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCityRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { + "countryId": { "type": "integer" }, - "totalRows": { - "type": "integer" + "name": { + "type": "string", + "maxLength": 20, + "minLength": 3 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateColorRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { - "type": "integer" + "hexCode": { + "type": "string", + "maxLength": 7, + "minLength": 7 }, - "totalRows": { - "type": "integer" + "name": { + "type": "string", + "maxLength": 15, + "minLength": 3 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCompanyRequest": { "type": "object", "properties": { - "hasNextPage": { - "type": "boolean" - }, - "hasPreviousPage": { - "type": "boolean" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse" - } - }, - "pageNumber": { - "type": "integer" - }, - "totalPages": { + "countryId": { "type": "integer" }, - "totalRows": { - "type": "integer" + "name": { + "type": "string", + "maxLength": 20, + "minLength": 3 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateFileRequest": { "type": "object", "properties": { - "filter": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.Filter" - } - }, - "pageNumber": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "sort": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.Sort" - } + "description": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateGearboxRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "maxLength": 15, + "minLength": 3 + } + } + }, + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePersianYearRequest": { "type": "object", "properties": { "endAt": { "type": "string" }, - "id": { - "type": "integer" - }, "persianTitle": { - "type": "string" + "type": "string", + "maxLength": 4, + "minLength": 4 }, "startAt": { "type": "string" @@ -6122,441 +5924,667 @@ } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearWithoutDateResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyCategoryRequest": { "type": "object", "properties": { - "id": { - "type": "integer" - }, - "persianTitle": { + "icon": { "type": "string" }, - "year": { - "type": "integer" + "name": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyRequest": { "type": "object", "properties": { - "icon": { - "type": "string" - }, - "id": { + "categoryId": { "type": "integer" }, - "name": { + "dataType": { + "type": "string", + "maxLength": 15 + }, + "description": { + "type": "string", + "maxLength": 1000 + }, + "icon": { + "type": "string", + "maxLength": 1000 + }, + "name": { "type": "string" }, - "properties": { - "type": "array", - "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse" - } + "unit": { + "type": "string", + "maxLength": 15 } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse": { + "github_com_naeemaei_golang-clean-web-api_api_dto.UserResponse": { "type": "object", "properties": { - "category": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse" - }, - "dataType": { - "type": "string" - }, - "description": { + "email": { "type": "string" }, - "icon": { + "firstName": { "type": "string" }, "id": { "type": "integer" }, - "name": { + "lastName": { "type": "string" }, - "unit": { + "username": { "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.RegisterLoginByMobileRequest": { + "github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse": { "type": "object", - "required": [ - "mobileNumber", - "otp" - ], "properties": { - "mobileNumber": { - "type": "string", - "maxLength": 11, - "minLength": 11 + "error": {}, + "result": {}, + "resultCode": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode" }, - "otp": { - "type": "string", - "maxLength": 6, - "minLength": 6 + "success": { + "type": "boolean" + }, + "validationErrors": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_validation.ValidationError" + } } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.RegisterUserByUsernameRequest": { - "type": "object", - "required": [ - "firstName", - "lastName", - "password", - "username" + "github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode": { + "type": "integer", + "enum": [ + 0, + 40001, + 40101, + 40301, + 40401, + 42901, + 42902, + 50001, + 50002 ], + "x-enum-varnames": [ + "Success", + "ValidationError", + "AuthError", + "ForbiddenError", + "NotFoundError", + "LimiterError", + "OtpLimiterError", + "CustomRecovery", + "InternalError" + ] + }, + "github_com_naeemaei_golang-clean-web-api_api_validation.ValidationError": { + "type": "object", "properties": { - "email": { - "type": "string", - "minLength": 6 - }, - "firstName": { - "type": "string", - "minLength": 3 + "message": { + "type": "string" }, - "lastName": { - "type": "string", - "minLength": 6 + "property": { + "type": "string" }, - "password": { - "type": "string", - "minLength": 6 + "tag": { + "type": "string" }, - "username": { - "type": "string", - "minLength": 5 + "value": { + "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.Sort": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.Filter": { "type": "object", "properties": { - "colId": { + "filterType": { + "description": "text number", "type": "string" }, - "sort": { + "from": { + "type": "string" + }, + "to": { + "type": "string" + }, + "type": { + "description": "contains notContains equals notEqual startsWith lessThan lessThanOrEqual greaterThan greaterThanOrEqual inRange endsWith", "type": "string" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelColorRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse": { "type": "object", "properties": { - "carModelId": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelColorResponse" + } + }, + "pageNumber": { "type": "integer" }, - "colorId": { + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelCommentRequest": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string", - "maxLength": 100 - } - } - }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelImageRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse": { "type": "object", "properties": { - "isMainImage": { + "hasNextPage": { "type": "boolean" - } - } - }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPriceHistoryRequest": { - "type": "object", - "properties": { - "price": { - "type": "number" }, - "priceAt": { - "type": "string" - } - } - }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPropertyRequest": { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string", - "maxLength": 100 + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelCommentResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse": { "type": "object", "properties": { - "carTypeId": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelImageResponse" + } + }, + "pageNumber": { "type": "integer" }, - "companyId": { + "pageSize": { "type": "integer" }, - "gearboxId": { + "totalPages": { "type": "integer" }, - "name": { - "type": "string" + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelYearRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse": { "type": "object", "properties": { - "carModelId": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPriceHistoryResponse" + } + }, + "pageNumber": { "type": "integer" }, - "persianYearId": { + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarTypeRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse": { "type": "object", - "required": [ - "name" - ], "properties": { - "name": { - "type": "string", - "maxLength": 15, - "minLength": 3 + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPropertyResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCityRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse": { "type": "object", "properties": { - "countryId": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelResponse" + } + }, + "pageNumber": { "type": "integer" }, - "name": { - "type": "string", - "maxLength": 20, - "minLength": 3 + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateColorRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse": { "type": "object", "properties": { - "hexCode": { - "type": "string", - "maxLength": 7, - "minLength": 7 + "hasNextPage": { + "type": "boolean" }, - "name": { - "type": "string", - "maxLength": 15, - "minLength": 3 + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelYearResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCompanyRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse": { "type": "object", "properties": { - "countryId": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarTypeResponse" + } + }, + "pageNumber": { "type": "integer" }, - "name": { - "type": "string", - "maxLength": 20, - "minLength": 3 + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateFileRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse": { "type": "object", "properties": { - "description": { - "type": "string" + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CityResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdateGearboxRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse": { "type": "object", - "required": [ - "name" - ], "properties": { - "name": { - "type": "string", - "maxLength": 15, - "minLength": 3 + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.ColorResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePersianYearRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse": { "type": "object", "properties": { - "endAt": { - "type": "string" + "hasNextPage": { + "type": "boolean" }, - "persianTitle": { - "type": "string", - "maxLength": 4, - "minLength": 4 + "hasPreviousPage": { + "type": "boolean" }, - "startAt": { - "type": "string" + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CompanyResponse" + } }, - "year": { + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyCategoryRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse": { "type": "object", "properties": { - "icon": { - "type": "string" + "hasNextPage": { + "type": "boolean" }, - "name": { - "type": "string" + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CountryResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyRequest": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse": { "type": "object", "properties": { - "categoryId": { - "type": "integer" + "hasNextPage": { + "type": "boolean" }, - "dataType": { - "type": "string", - "maxLength": 15 + "hasPreviousPage": { + "type": "boolean" }, - "description": { - "type": "string", - "maxLength": 1000 + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.FileResponse" + } }, - "icon": { - "type": "string", - "maxLength": 1000 + "pageNumber": { + "type": "integer" }, - "name": { - "type": "string" + "pageSize": { + "type": "integer" }, - "unit": { - "type": "string", - "maxLength": 15 + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_dto.UserResponse": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse": { "type": "object", "properties": { - "email": { - "type": "string" + "hasNextPage": { + "type": "boolean" }, - "firstName": { - "type": "string" + "hasPreviousPage": { + "type": "boolean" }, - "id": { + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.GearboxResponse" + } + }, + "pageNumber": { "type": "integer" }, - "lastName": { - "type": "string" + "pageSize": { + "type": "integer" }, - "username": { - "type": "string" + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse": { "type": "object", "properties": { - "error": {}, - "result": {}, - "resultCode": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode" + "hasNextPage": { + "type": "boolean" }, - "success": { + "hasPreviousPage": { "type": "boolean" }, - "validationErrors": { + "items": { "type": "array", "items": { - "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_validations.ValidationError" + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse" } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode": { - "type": "integer", - "enum": [ - 0, - 40001, - 40101, - 40301, - 40401, - 42901, - 42902, - 50001, - 50002 - ], - "x-enum-varnames": [ - "Success", - "ValidationError", - "AuthError", - "ForbiddenError", - "NotFoundError", - "LimiterError", - "OtpLimiterError", - "CustomRecovery", - "InternalError" - ] + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse": { + "type": "object", + "properties": { + "hasNextPage": { + "type": "boolean" + }, + "hasPreviousPage": { + "type": "boolean" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse" + } + }, + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" + } + } }, - "github_com_naeemaei_golang-clean-web-api_api_validations.ValidationError": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse": { "type": "object", "properties": { - "message": { - "type": "string" + "hasNextPage": { + "type": "boolean" }, - "property": { - "type": "string" + "hasPreviousPage": { + "type": "boolean" }, - "tag": { - "type": "string" + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse" + } }, - "value": { - "type": "string" + "pageNumber": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "totalPages": { + "type": "integer" + }, + "totalRows": { + "type": "integer" } } }, - "multipart.FileHeader": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter": { "type": "object", "properties": { - "filename": { - "type": "string" + "filter": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.Filter" + } }, - "header": { - "$ref": "#/definitions/textproto.MIMEHeader" + "pageNumber": { + "type": "integer" }, - "size": { + "pageSize": { "type": "integer" + }, + "sort": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.Sort" + } } } }, - "textproto.MIMEHeader": { + "github_com_naeemaei_golang-clean-web-api_domain_filter.Sort": { "type": "object", - "additionalProperties": { - "type": "array", - "items": { + "properties": { + "colId": { + "type": "string" + }, + "sort": { "type": "string" } } diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index 0df8817..369d5a1 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -1,5 +1,5 @@ definitions: - api_handlers.personData: + api_handler.personData: properties: first_name: maxLength: 10 @@ -378,20 +378,6 @@ definitions: name: type: string type: object - github_com_naeemaei_golang-clean-web-api_api_dto.Filter: - properties: - filterType: - description: text number - type: string - from: - type: string - to: - type: string - type: - description: contains notContains equals notEqual startsWith lessThan lessThanOrEqual - greaterThan greaterThanOrEqual inRange endsWith - type: string - type: object github_com_naeemaei_golang-clean-web-api_api_dto.GearboxResponse: properties: id: @@ -420,262 +406,408 @@ definitions: - password - username type: object - ? github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse - : properties: - hasNextPage: - type: boolean - hasPreviousPage: - type: boolean - items: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelColorResponse' - type: array - pageNumber: - type: integer - totalPages: + github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse: + properties: + endAt: + type: string + id: type: integer - totalRows: + persianTitle: + type: string + startAt: + type: string + year: type: integer type: object - ? github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse - : properties: - hasNextPage: - type: boolean - hasPreviousPage: - type: boolean - items: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelCommentResponse' - type: array - pageNumber: - type: integer - totalPages: + github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearWithoutDateResponse: + properties: + id: type: integer - totalRows: + persianTitle: + type: string + year: type: integer type: object - ? github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse - : properties: - hasNextPage: - type: boolean - hasPreviousPage: - type: boolean - items: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelImageResponse' - type: array - pageNumber: - type: integer - totalPages: - type: integer - totalRows: + github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse: + properties: + icon: + type: string + id: type: integer - type: object - ? github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse - : properties: - hasNextPage: - type: boolean - hasPreviousPage: - type: boolean - items: + name: + type: string + properties: items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPriceHistoryResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse' type: array - pageNumber: - type: integer - totalPages: - type: integer - totalRows: - type: integer type: object - ? github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse - : properties: - hasNextPage: - type: boolean - hasPreviousPage: - type: boolean - items: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPropertyResponse' - type: array - pageNumber: - type: integer - totalPages: - type: integer - totalRows: + github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse: + properties: + category: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse' + dataType: + type: string + description: + type: string + icon: + type: string + id: type: integer + name: + type: string + unit: + type: string type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse: + github_com_naeemaei_golang-clean-web-api_api_dto.RegisterLoginByMobileRequest: properties: - hasNextPage: - type: boolean - hasPreviousPage: - type: boolean - items: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelResponse' - type: array - pageNumber: - type: integer - totalPages: - type: integer - totalRows: - type: integer + mobileNumber: + maxLength: 11 + minLength: 11 + type: string + otp: + maxLength: 6 + minLength: 6 + type: string + required: + - mobileNumber + - otp type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse: + github_com_naeemaei_golang-clean-web-api_api_dto.RegisterUserByUsernameRequest: properties: - hasNextPage: - type: boolean - hasPreviousPage: - type: boolean - items: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelYearResponse' - type: array - pageNumber: - type: integer - totalPages: - type: integer - totalRows: - type: integer + email: + minLength: 6 + type: string + firstName: + minLength: 3 + type: string + lastName: + minLength: 6 + type: string + password: + minLength: 6 + type: string + username: + minLength: 5 + type: string + required: + - firstName + - lastName + - password + - username type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse: + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelColorRequest: properties: - hasNextPage: - type: boolean - hasPreviousPage: - type: boolean - items: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarTypeResponse' - type: array - pageNumber: - type: integer - totalPages: + carModelId: type: integer - totalRows: + colorId: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse: + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelCommentRequest: properties: - hasNextPage: - type: boolean - hasPreviousPage: + message: + maxLength: 100 + type: string + required: + - message + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelImageRequest: + properties: + isMainImage: type: boolean - items: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CityResponse' - type: array - pageNumber: + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPriceHistoryRequest: + properties: + price: + type: number + priceAt: + type: string + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPropertyRequest: + properties: + value: + maxLength: 100 + type: string + required: + - value + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelRequest: + properties: + carTypeId: type: integer - totalPages: + companyId: type: integer - totalRows: + gearboxId: type: integer + name: + type: string type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse: + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelYearRequest: properties: - hasNextPage: - type: boolean - hasPreviousPage: - type: boolean - items: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.ColorResponse' - type: array - pageNumber: - type: integer - totalPages: + carModelId: type: integer - totalRows: + persianYearId: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse: + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarTypeRequest: properties: + name: + maxLength: 15 + minLength: 3 + type: string + required: + - name + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCityRequest: + properties: + countryId: + type: integer + name: + maxLength: 20 + minLength: 3 + type: string + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateColorRequest: + properties: + hexCode: + maxLength: 7 + minLength: 7 + type: string + name: + maxLength: 15 + minLength: 3 + type: string + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCompanyRequest: + properties: + countryId: + type: integer + name: + maxLength: 20 + minLength: 3 + type: string + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateFileRequest: + properties: + description: + type: string + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdateGearboxRequest: + properties: + name: + maxLength: 15 + minLength: 3 + type: string + required: + - name + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePersianYearRequest: + properties: + endAt: + type: string + persianTitle: + maxLength: 4 + minLength: 4 + type: string + startAt: + type: string + year: + type: integer + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyCategoryRequest: + properties: + icon: + type: string + name: + type: string + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyRequest: + properties: + categoryId: + type: integer + dataType: + maxLength: 15 + type: string + description: + maxLength: 1000 + type: string + icon: + maxLength: 1000 + type: string + name: + type: string + unit: + maxLength: 15 + type: string + type: object + github_com_naeemaei_golang-clean-web-api_api_dto.UserResponse: + properties: + email: + type: string + firstName: + type: string + id: + type: integer + lastName: + type: string + username: + type: string + type: object + github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse: + properties: + error: {} + result: {} + resultCode: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode' + success: + type: boolean + validationErrors: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_validation.ValidationError' + type: array + type: object + github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode: + enum: + - 0 + - 40001 + - 40101 + - 40301 + - 40401 + - 42901 + - 42902 + - 50001 + - 50002 + type: integer + x-enum-varnames: + - Success + - ValidationError + - AuthError + - ForbiddenError + - NotFoundError + - LimiterError + - OtpLimiterError + - CustomRecovery + - InternalError + github_com_naeemaei_golang-clean-web-api_api_validation.ValidationError: + properties: + message: + type: string + property: + type: string + tag: + type: string + value: + type: string + type: object + github_com_naeemaei_golang-clean-web-api_domain_filter.Filter: + properties: + filterType: + description: text number + type: string + from: + type: string + to: + type: string + type: + description: contains notContains equals notEqual startsWith lessThan lessThanOrEqual + greaterThan greaterThanOrEqual inRange endsWith + type: string + type: object + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse + : properties: hasNextPage: type: boolean hasPreviousPage: type: boolean items: items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CompanyResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelColorResponse' type: array pageNumber: type: integer + pageSize: + type: integer totalPages: type: integer totalRows: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse: - properties: + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse + : properties: hasNextPage: type: boolean hasPreviousPage: type: boolean items: items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CountryResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelCommentResponse' type: array pageNumber: type: integer + pageSize: + type: integer totalPages: type: integer totalRows: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse: - properties: + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse + : properties: hasNextPage: type: boolean hasPreviousPage: type: boolean items: items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.FileResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelImageResponse' type: array pageNumber: type: integer + pageSize: + type: integer totalPages: type: integer totalRows: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse: - properties: + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse + : properties: hasNextPage: type: boolean hasPreviousPage: type: boolean items: items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.GearboxResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPriceHistoryResponse' type: array pageNumber: type: integer + pageSize: + type: integer totalPages: type: integer totalRows: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse: - properties: + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse + : properties: hasNextPage: type: boolean hasPreviousPage: type: boolean items: items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelPropertyResponse' type: array pageNumber: type: integer + pageSize: + type: integer totalPages: type: integer totalRows: type: integer type: object - ? github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse : properties: hasNextPage: type: boolean @@ -683,360 +815,247 @@ definitions: type: boolean items: items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelResponse' type: array pageNumber: type: integer + pageSize: + type: integer totalPages: type: integer totalRows: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse: - properties: + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse + : properties: hasNextPage: type: boolean hasPreviousPage: type: boolean items: items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarModelYearResponse' type: array pageNumber: type: integer + pageSize: + type: integer totalPages: type: integer totalRows: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter: - properties: - filter: - additionalProperties: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.Filter' - type: object + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse + : properties: + hasNextPage: + type: boolean + hasPreviousPage: + type: boolean + items: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CarTypeResponse' + type: array pageNumber: type: integer pageSize: type: integer - sort: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.Sort' - type: array - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse: - properties: - endAt: - type: string - id: + totalPages: type: integer - persianTitle: - type: string - startAt: - type: string - year: + totalRows: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearWithoutDateResponse: + github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse: properties: - id: + hasNextPage: + type: boolean + hasPreviousPage: + type: boolean + items: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CityResponse' + type: array + pageNumber: type: integer - persianTitle: - type: string - year: + pageSize: + type: integer + totalPages: + type: integer + totalRows: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse: + github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse: properties: - icon: - type: string - id: - type: integer - name: - type: string - properties: - items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse' + hasNextPage: + type: boolean + hasPreviousPage: + type: boolean + items: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.ColorResponse' type: array - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse: - properties: - category: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse' - dataType: - type: string - description: - type: string - icon: - type: string - id: + pageNumber: type: integer - name: - type: string - unit: - type: string - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.RegisterLoginByMobileRequest: - properties: - mobileNumber: - maxLength: 11 - minLength: 11 - type: string - otp: - maxLength: 6 - minLength: 6 - type: string - required: - - mobileNumber - - otp - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.RegisterUserByUsernameRequest: - properties: - email: - minLength: 6 - type: string - firstName: - minLength: 3 - type: string - lastName: - minLength: 6 - type: string - password: - minLength: 6 - type: string - username: - minLength: 5 - type: string - required: - - firstName - - lastName - - password - - username - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.Sort: - properties: - colId: - type: string - sort: - type: string - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelColorRequest: - properties: - carModelId: + pageSize: type: integer - colorId: + totalPages: + type: integer + totalRows: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelCommentRequest: - properties: - message: - maxLength: 100 - type: string - required: - - message - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelImageRequest: - properties: - isMainImage: + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse + : properties: + hasNextPage: type: boolean - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPriceHistoryRequest: - properties: - price: - type: number - priceAt: - type: string - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelPropertyRequest: - properties: - value: - maxLength: 100 - type: string - required: - - value - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelRequest: - properties: - carTypeId: + hasPreviousPage: + type: boolean + items: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CompanyResponse' + type: array + pageNumber: type: integer - companyId: + pageSize: type: integer - gearboxId: + totalPages: + type: integer + totalRows: type: integer - name: - type: string type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarModelYearRequest: - properties: - carModelId: + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse + : properties: + hasNextPage: + type: boolean + hasPreviousPage: + type: boolean + items: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.CountryResponse' + type: array + pageNumber: type: integer - persianYearId: + pageSize: type: integer - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCarTypeRequest: - properties: - name: - maxLength: 15 - minLength: 3 - type: string - required: - - name - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCityRequest: - properties: - countryId: + totalPages: type: integer - name: - maxLength: 20 - minLength: 3 - type: string - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateColorRequest: - properties: - hexCode: - maxLength: 7 - minLength: 7 - type: string - name: - maxLength: 15 - minLength: 3 - type: string - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateCompanyRequest: - properties: - countryId: + totalRows: type: integer - name: - maxLength: 20 - minLength: 3 - type: string type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateFileRequest: + github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse: properties: - description: - type: string - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdateGearboxRequest: - properties: - name: - maxLength: 15 - minLength: 3 - type: string - required: - - name - type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePersianYearRequest: - properties: - endAt: - type: string - persianTitle: - maxLength: 4 - minLength: 4 - type: string - startAt: - type: string - year: + hasNextPage: + type: boolean + hasPreviousPage: + type: boolean + items: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.FileResponse' + type: array + pageNumber: + type: integer + pageSize: + type: integer + totalPages: + type: integer + totalRows: type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyCategoryRequest: - properties: - icon: - type: string - name: - type: string + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse + : properties: + hasNextPage: + type: boolean + hasPreviousPage: + type: boolean + items: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.GearboxResponse' + type: array + pageNumber: + type: integer + pageSize: + type: integer + totalPages: + type: integer + totalRows: + type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UpdatePropertyRequest: - properties: - categoryId: + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse + : properties: + hasNextPage: + type: boolean + hasPreviousPage: + type: boolean + items: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PersianYearResponse' + type: array + pageNumber: + type: integer + pageSize: + type: integer + totalPages: + type: integer + totalRows: type: integer - dataType: - maxLength: 15 - type: string - description: - maxLength: 1000 - type: string - icon: - maxLength: 1000 - type: string - name: - type: string - unit: - maxLength: 15 - type: string type: object - github_com_naeemaei_golang-clean-web-api_api_dto.UserResponse: - properties: - email: - type: string - firstName: - type: string - id: + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse + : properties: + hasNextPage: + type: boolean + hasPreviousPage: + type: boolean + items: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyCategoryResponse' + type: array + pageNumber: + type: integer + pageSize: + type: integer + totalPages: + type: integer + totalRows: type: integer - lastName: - type: string - username: - type: string type: object - github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse: - properties: - error: {} - result: {} - resultCode: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode' - success: + ? github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse + : properties: + hasNextPage: type: boolean - validationErrors: + hasPreviousPage: + type: boolean + items: items: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_validations.ValidationError' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PropertyResponse' type: array + pageNumber: + type: integer + pageSize: + type: integer + totalPages: + type: integer + totalRows: + type: integer type: object - github_com_naeemaei_golang-clean-web-api_api_helper.ResultCode: - enum: - - 0 - - 40001 - - 40101 - - 40301 - - 40401 - - 42901 - - 42902 - - 50001 - - 50002 - type: integer - x-enum-varnames: - - Success - - ValidationError - - AuthError - - ForbiddenError - - NotFoundError - - LimiterError - - OtpLimiterError - - CustomRecovery - - InternalError - github_com_naeemaei_golang-clean-web-api_api_validations.ValidationError: + github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter: properties: - message: - type: string - property: - type: string - tag: - type: string - value: - type: string + filter: + additionalProperties: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.Filter' + type: object + pageNumber: + type: integer + pageSize: + type: integer + sort: + items: + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.Sort' + type: array type: object - multipart.FileHeader: + github_com_naeemaei_golang-clean-web-api_domain_filter.Sort: properties: - filename: + colId: type: string - header: - $ref: '#/definitions/textproto.MIMEHeader' - size: - type: integer - type: object - textproto.MIMEHeader: - additionalProperties: - items: + sort: type: string - type: array type: object info: contact: {} @@ -1184,7 +1203,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: CarModelColor response @@ -1193,7 +1212,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelColorResponse' type: object "400": description: Bad request @@ -1347,7 +1366,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: CarModelComment response @@ -1356,7 +1375,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelCommentResponse' type: object "400": description: Bad request @@ -1510,7 +1529,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: CarModelImage response @@ -1519,7 +1538,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelImageResponse' type: object "400": description: Bad request @@ -1673,7 +1692,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: CarModelPriceHistory response @@ -1682,7 +1701,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPriceHistoryResponse' type: object "400": description: Bad request @@ -1836,7 +1855,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: CarModelProperty response @@ -1845,7 +1864,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelPropertyResponse' type: object "400": description: Bad request @@ -1999,7 +2018,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: CarModelYear response @@ -2008,7 +2027,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelYearResponse' type: object "400": description: Bad request @@ -2162,7 +2181,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: CarModel response @@ -2171,7 +2190,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarModelResponse' type: object "400": description: Bad request @@ -2325,7 +2344,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: CarType response @@ -2334,7 +2353,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CarTypeResponse' type: object "400": description: Bad request @@ -2488,7 +2507,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: City response @@ -2497,7 +2516,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CityResponse' type: object "400": description: Bad request @@ -2651,7 +2670,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: Color response @@ -2660,7 +2679,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_ColorResponse' type: object "400": description: Bad request @@ -2814,7 +2833,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: Company response @@ -2823,7 +2842,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CompanyResponse' type: object "400": description: Bad request @@ -2965,7 +2984,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: Country response @@ -2974,7 +2993,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_CountryResponse' type: object "400": description: Bad request @@ -3119,7 +3138,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: File response @@ -3128,7 +3147,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_FileResponse' type: object "400": description: Bad request @@ -3282,7 +3301,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: Gearbox response @@ -3291,7 +3310,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_GearboxResponse' type: object "400": description: Bad request @@ -3464,7 +3483,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: Property response @@ -3473,7 +3492,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyResponse' type: object "400": description: Bad request @@ -3627,7 +3646,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: PropertyCategory response @@ -3636,7 +3655,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PropertyCategoryResponse' type: object "400": description: Bad request @@ -3658,7 +3677,7 @@ paths: name: person required: true schema: - $ref: '#/definitions/api_handlers.personData' + $ref: '#/definitions/api_handler.personData' produces: - application/json responses: @@ -4005,7 +4024,7 @@ paths: name: Request required: true schema: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PaginationInputWithFilter' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PaginationInputWithFilter' responses: "200": description: PersianYear response @@ -4014,7 +4033,7 @@ paths: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_helper.BaseHttpResponse' - properties: result: - $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_api_dto.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse' + $ref: '#/definitions/github_com_naeemaei_golang-clean-web-api_domain_filter.PagedList-github_com_naeemaei_golang-clean-web-api_api_dto_PersianYearResponse' type: object "400": description: Bad request