├── .github └── workflows │ └── YoursStore.yml ├── .gitignore ├── CNAME ├── Dockerfile ├── README.md ├── cmd └── api │ ├── docs │ ├── docs.go │ ├── swagger.json │ └── swagger.yaml │ └── main.go ├── docker-compose.yml ├── go.mod ├── go.sum ├── makefile └── pkg ├── api ├── handlers │ ├── admin.go │ ├── cart.go │ ├── category.go │ ├── coupon.go │ ├── inventory.go │ ├── offer.go │ ├── order.go │ ├── otp.go │ ├── payment.go │ ├── user.go │ └── wishlist.go ├── middleware │ ├── auth.go │ └── userAuth.go └── server.go ├── config └── config.go ├── db └── connection.go ├── di ├── wire.go └── wire_gen.go ├── domain ├── admin.go ├── cart.go ├── coupon.go ├── inventory.go ├── offer.go ├── orders.go ├── user.go ├── wallet.go └── wishlist.go ├── helper ├── helper.go └── pdf │ ├── invoice.go │ ├── invoiceData.go │ └── invoicePdf.go ├── repository ├── admin.go ├── cart.go ├── category.go ├── coupon.go ├── interfaces │ ├── admin.go │ ├── cart.go │ ├── category.go │ ├── coupon.go │ ├── inventory.go │ ├── offer.go │ ├── order.go │ ├── otp.go │ ├── payment.go │ ├── user.go │ └── wishlist.go ├── inventory.go ├── offer.go ├── order.go ├── otp.go ├── payment.go ├── user.go └── wishlist.go ├── routes ├── admin.go ├── inventory.go └── user.go ├── templates └── razorpay.html ├── usecase ├── admin.go ├── cart.go ├── category.go ├── coupon.go ├── interfaces │ ├── admin.go │ ├── cart.go │ ├── category.go │ ├── coupon.go │ ├── inventory.go │ ├── offer.go │ ├── order.go │ ├── otp.go │ ├── payment.go │ ├── user.go │ └── wishlist.go ├── inventory.go ├── offer.go ├── order.go ├── otp.go ├── payment.go ├── user.go └── wishlist.go └── utils ├── models ├── admin.go ├── category.go ├── inventory.go ├── offer.go ├── order.go ├── otp.go ├── user.go └── wishlis.go └── response └── response.go /.github/workflows/YoursStore.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a golang project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go 3 | 4 | name: YoursStore project ci/cd 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | 12 | jobs: 13 | 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - name: Set up Go 20 | uses: actions/setup-go@v4 21 | with: 22 | go-version: '1.20' 23 | 24 | - name: Build 25 | run: go build -v ./... 26 | 27 | - name: Test 28 | run: go test -v ./... 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.pdf 3 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | ecommerce.in -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.20.6-alpine3.18 AS build-stage 2 | WORKDIR /app 3 | COPY . ./ 4 | RUN go mod download 5 | RUN go build -v -o /api ./cmd/api 6 | 7 | 8 | FROM gcr.io/distroless/static-debian11 9 | COPY --from=build-stage /api /api 10 | COPY --from=build-stage /app/.env / 11 | EXPOSE 8080 12 | CMD [ "/api" ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yours Store E-Commerce Backend Rest API 2 | *** 3 | Yours Store E-Commerce Backend Rest API is a feature-rich backend solution for E-commerce applications developed using Golang with the Gin web framework. This API is designed to efficiently handle routing and HTTP requests while following best practices in code architecture and dependency management. 4 | 5 | # Key Features 6 | *** 7 | - Clean Code Architecture: The project follows clean code architecture principles, making it maintainable and scalable. 8 | - Dependency Injection: Utilizes the Dependency Injection design pattern for flexible component integration. 9 | - Compile-Time Dependency Injection: Dependencies are managed using Wire for compile-time injection. 10 | - Database: Leverages PostgreSQL for efficient and relational data storage. 11 | - AWS Integration: Integrates with AWS S3 for cloud-based storage solutions. 12 | - E-Commerce Features: Implements a wide range of features commonly found in e-commerce applications, including cart management, wishlist, wallet, offers, and coupon management. 13 | - Code Quality: Implements Continuous Integration(CI) with GitHub Actions. 14 | *** 15 | # API Documentation 16 | *** 17 | For interactive API documentation, Swagger is implemented. You can explore and test the API endpoints in real-time. 18 | *** 19 | # Getting Started 20 | *** 21 | To run the project locally, you can follow these steps: 22 | 23 | 1. Clone the repository. 24 | 2. Set up your environment with the required dependencies, including Golang, PostgreSQL, Docker, and Wire. 25 | 3. Configure your environment variables (e.g., database credentials, AWS keys, Twilio credentials). 26 | 4. Build and run the project. 27 | *** 28 | # Environment Variables 29 | *** 30 | Before running the project, you need to set the following environment variables with your corresponding values: 31 | 32 | # PostgreSQL 33 | *** 34 | - `DB_HOST`: Database host 35 | - `DB_NAME`: Database name 36 | - `DB_USER`: Database user 37 | - `DB_PORT`: Database port 38 | - `DB_PASSWORD`: Database password 39 | *** 40 | # Twilio 41 | *** 42 | - `DB_AUTHTOKEN`: Twilio authentication token 43 | - `DB_ACCOUNTSID`: Twilio account SID 44 | - `DB_SERVICESID`: Twilio services ID 45 | *** 46 | # AWS 47 | *** 48 | - `AWS_REGION`: AWS region 49 | - `AWS_ACCESS_KEY_ID`: AWS access key ID 50 | - `AWS_SECRET_ACCESS_KEY`: AWS secret access key 51 | 52 | Make sure to provide the appropriate values for these environment variables to configure the project correctly. 53 | -------------------------------------------------------------------------------- /cmd/api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/Anandhu4456/go-Ecommerce/cmd/api/docs" 7 | di "github.com/Anandhu4456/go-Ecommerce/pkg/di" 8 | 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/config" 10 | ) 11 | 12 | func main() { 13 | config, configErr := config.LoadConfig() 14 | if configErr != nil { 15 | log.Fatal("cannot load config", configErr) 16 | } 17 | 18 | docs.SwaggerInfo.Title = "YoursStore" 19 | docs.SwaggerInfo.Description = "An Ecommerce Application" 20 | docs.SwaggerInfo.Version = "1.0" 21 | // docs.SwaggerInfo.Host = config.BASE_URL 22 | docs.SwaggerInfo.BasePath = "" 23 | docs.SwaggerInfo.Schemes = []string{"http"} 24 | 25 | server, err := di.InitializeAPI(config) 26 | if err != nil { 27 | log.Fatal("couldn't start server", err) 28 | } else { 29 | server.Start() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | postgres: 4 | image: postgres:latest 5 | restart: always 6 | environment: 7 | POSTGRES_USER: "postgres10" 8 | POSTGRES_PASSWORD: "newpass" 9 | POSTGRES_DB: "ecommerce10" 10 | networks: 11 | - mydb 12 | volumes: 13 | - pgdata:/var/lib/postgresql/data 14 | 15 | yoursstore: 16 | image: app 17 | restart: on-failure 18 | environment: 19 | DB_HOST: "postgres" 20 | DB_USER: "postgres10" 21 | DB_PASSWORD: "newpass" 22 | DB_PORT: "5432" 23 | DB_NAME: "ecommerce10" 24 | depends_on: 25 | - postgres 26 | networks: 27 | - mydb 28 | ports: 29 | - "8082:8082" 30 | 31 | volumes: 32 | pgdata: 33 | 34 | networks: 35 | mydb: 36 | driver: bridge -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Anandhu4456/go-Ecommerce 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/aws/aws-sdk-go-v2 v1.23.5 7 | github.com/aws/aws-sdk-go-v2/config v1.25.11 8 | github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.4 9 | github.com/aws/aws-sdk-go-v2/service/s3 v1.47.2 10 | github.com/gin-gonic/gin v1.9.1 11 | github.com/golang-jwt/jwt v3.2.2+incompatible 12 | github.com/google/wire v0.5.0 13 | github.com/jinzhu/copier v0.4.0 14 | github.com/joho/godotenv v1.5.1 15 | github.com/razorpay/razorpay-go v1.2.0 16 | github.com/spf13/viper v1.17.0 17 | github.com/swaggo/files v1.0.1 18 | github.com/swaggo/gin-swagger v1.6.0 19 | github.com/swaggo/swag v1.8.12 20 | github.com/twilio/twilio-go v1.15.3 21 | github.com/unidoc/unipdf/v3 v3.52.0 22 | golang.org/x/crypto v0.16.0 23 | gorm.io/driver/postgres v1.5.3 24 | gorm.io/gorm v1.25.5 25 | ) 26 | 27 | require ( 28 | github.com/KyleBanks/depth v1.2.1 // indirect 29 | github.com/PuerkitoBio/purell v1.1.1 // indirect 30 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 31 | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.3 // indirect 32 | github.com/aws/aws-sdk-go-v2/credentials v1.16.9 // indirect 33 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.9 // indirect 34 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.8 // indirect 35 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.8 // indirect 36 | github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect 37 | github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.8 // indirect 38 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.3 // indirect 39 | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.8 // indirect 40 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.8 // indirect 41 | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.8 // indirect 42 | github.com/aws/aws-sdk-go-v2/service/sso v1.18.2 // indirect 43 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.2 // indirect 44 | github.com/aws/aws-sdk-go-v2/service/sts v1.26.2 // indirect 45 | github.com/aws/smithy-go v1.18.1 // indirect 46 | github.com/bytedance/sonic v1.9.1 // indirect 47 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect 48 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 49 | github.com/fsnotify/fsnotify v1.6.0 // indirect 50 | github.com/gabriel-vasile/mimetype v1.4.2 // indirect 51 | github.com/gin-contrib/sse v0.1.0 // indirect 52 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 53 | github.com/go-openapi/jsonreference v0.19.6 // indirect 54 | github.com/go-openapi/spec v0.20.4 // indirect 55 | github.com/go-openapi/swag v0.19.15 // indirect 56 | github.com/go-playground/locales v0.14.1 // indirect 57 | github.com/go-playground/universal-translator v0.18.1 // indirect 58 | github.com/go-playground/validator/v10 v10.14.0 // indirect 59 | github.com/goccy/go-json v0.10.2 // indirect 60 | github.com/golang/mock v1.6.0 // indirect 61 | // github.com/google/subcommands v1.0.1 // indirect 62 | github.com/gorilla/i18n v0.0.0-20150820051429-8b358169da46 // indirect 63 | github.com/hashicorp/hcl v1.0.0 // indirect 64 | github.com/jackc/pgpassfile v1.0.0 // indirect 65 | github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect 66 | github.com/jackc/pgx/v5 v5.4.3 // indirect 67 | github.com/jinzhu/inflection v1.0.0 // indirect 68 | github.com/jinzhu/now v1.1.5 // indirect 69 | github.com/jmespath/go-jmespath v0.4.0 // indirect 70 | github.com/josharian/intern v1.0.0 // indirect 71 | github.com/json-iterator/go v1.1.12 // indirect 72 | github.com/klauspost/cpuid/v2 v2.2.4 // indirect 73 | github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect 74 | github.com/leodido/go-urn v1.2.4 // indirect 75 | github.com/magiconair/properties v1.8.7 // indirect 76 | github.com/mailru/easyjson v0.7.6 // indirect 77 | github.com/mattn/go-isatty v0.0.19 // indirect 78 | github.com/mitchellh/mapstructure v1.5.0 // indirect 79 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 80 | github.com/modern-go/reflect2 v1.0.2 // indirect 81 | github.com/pelletier/go-toml/v2 v2.1.0 // indirect 82 | github.com/pkg/errors v0.9.1 // indirect 83 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 84 | github.com/sagikazarmark/locafero v0.3.0 // indirect 85 | github.com/sagikazarmark/slog-shim v0.1.0 // indirect 86 | github.com/sirupsen/logrus v1.5.0 // indirect 87 | github.com/sourcegraph/conc v0.3.0 // indirect 88 | github.com/spf13/afero v1.10.0 // indirect 89 | github.com/spf13/cast v1.5.1 // indirect 90 | github.com/spf13/pflag v1.0.5 // indirect 91 | github.com/stretchr/testify v1.8.4 // indirect 92 | github.com/subosito/gotenv v1.6.0 // indirect 93 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 94 | github.com/ugorji/go/codec v1.2.11 // indirect 95 | github.com/unidoc/pkcs7 v0.2.0 // indirect 96 | github.com/unidoc/timestamp v0.0.0-20200412005513-91597fd3793a // indirect 97 | github.com/unidoc/unichart v0.1.0 // indirect 98 | github.com/unidoc/unitype v0.2.1 // indirect 99 | go.uber.org/atomic v1.9.0 // indirect 100 | go.uber.org/multierr v1.9.0 // indirect 101 | golang.org/x/arch v0.3.0 // indirect 102 | golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect 103 | golang.org/x/image v0.14.0 // indirect 104 | // golang.org/x/mod v0.12.0 // indirect 105 | golang.org/x/net v0.19.0 // indirect 106 | golang.org/x/sys v0.15.0 // indirect 107 | golang.org/x/text v0.14.0 // indirect 108 | golang.org/x/tools v0.16.1 // indirect 109 | golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect 110 | google.golang.org/protobuf v1.31.0 // indirect 111 | gopkg.in/ini.v1 v1.67.0 // indirect 112 | gopkg.in/yaml.v2 v2.4.0 // indirect 113 | gopkg.in/yaml.v3 v3.0.1 // indirect 114 | ) 115 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: run stop wire 3 | 4 | 5 | run : 6 | docker compose up 7 | stop: 8 | docker compose down 9 | wire : 10 | cd pkg/di && wire -------------------------------------------------------------------------------- /pkg/api/handlers/admin.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "strconv" 7 | 8 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 10 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/response" 11 | "github.com/gin-gonic/gin" 12 | ) 13 | 14 | type AdminHandler struct { 15 | adminUsecase services.AdminUsecase 16 | } 17 | 18 | // constructor function 19 | func NewAdminHandler(adminUsecase services.AdminUsecase) *AdminHandler { 20 | return &AdminHandler{ 21 | adminUsecase: adminUsecase, 22 | } 23 | } 24 | 25 | // @Summary Admin Login 26 | // @Description Login handler for admins 27 | // @Tags Admin 28 | // @Accept json 29 | // @Produce json 30 | // @Param admin body models.AdminLogin true "Admin login details" 31 | // @Success 200 {object} response.Response{} 32 | // @Failure 500 {object} response.Response{} 33 | // @Router /admin/adminlogin [post] 34 | func (ah *AdminHandler) LoginHandler(c *gin.Context) { 35 | // login handler for the admin 36 | var adminDetails models.AdminLogin 37 | 38 | if err := c.BindJSON(&adminDetails); err != nil { 39 | errRes := response.ClientResponse(http.StatusBadRequest, "details not in correct format", nil, err.Error()) 40 | c.JSON(http.StatusBadRequest, errRes) 41 | return 42 | } 43 | admin, err := ah.adminUsecase.LoginHandler(adminDetails) 44 | if err != nil { 45 | errRes := response.ClientResponse(http.StatusBadRequest, "can't authenticate admin", nil, err.Error()) 46 | c.JSON(http.StatusBadRequest, errRes) 47 | return 48 | } 49 | // c.Set("",admin.Token) 50 | 51 | // c.Set("Refresh",admin.RefreshToken) 52 | c.SetCookie("Authorization",admin.Token,3600 *24*30,"/","",false,true) 53 | c.SetCookie("Refresh",admin.RefreshToken,3600 *24*30,"/","",false,true) 54 | 55 | successRes := response.ClientResponse(http.StatusOK, "Admin authenticated successfully", admin, nil) 56 | fmt.Println("from admin handler ",admin) 57 | c.JSON(http.StatusOK, successRes) 58 | } 59 | 60 | // @Summary Block User 61 | // @Description using this handler admins can block an user 62 | // @Tags Admin 63 | // @Accept json 64 | // @Produce json 65 | // @Security Bearer 66 | // @Param id query string true "user-id" 67 | // @Success 200 {object} response.Response{} 68 | // @Failure 500 {object} response.Response{} 69 | // @Router /admin/users/block [post] 70 | func (ah *AdminHandler) BlockUser(c *gin.Context) { 71 | id := c.Query("id") 72 | err := ah.adminUsecase.BlockUser(id) 73 | if err != nil { 74 | errRes := response.ClientResponse(http.StatusBadRequest, "cant block", nil, err.Error()) 75 | c.JSON(http.StatusBadRequest, errRes) 76 | return 77 | } 78 | successRes := response.ClientResponse(http.StatusOK, "blocked the user", nil, nil) 79 | c.JSON(http.StatusOK, successRes) 80 | } 81 | 82 | // @Summary UnBlock an existing user 83 | // @Description UnBlock user 84 | // @Tags Admin 85 | // @Accept json 86 | // @Produce json 87 | // @Security Bearer 88 | // @Param id query string true "user-id" 89 | // @Success 200 {object} response.Response{} 90 | // @Failure 500 {object} response.Response{} 91 | // @Router /admin/users/unblock [POST] 92 | func (ah *AdminHandler) UnblockUser(c *gin.Context) { 93 | id := c.Query("id") 94 | err := ah.adminUsecase.UnblockUser(id) 95 | if err != nil { 96 | errRes := response.ClientResponse(http.StatusBadRequest, "can't unblock user", nil, err.Error()) 97 | c.JSON(http.StatusBadRequest, errRes) 98 | return 99 | } 100 | successRes := response.ClientResponse(http.StatusOK, "unblocked user", nil, nil) 101 | c.JSON(http.StatusOK, successRes) 102 | } 103 | 104 | // @Summary Get Users 105 | // @Description Retrieve users with pagination 106 | // @Tags Admin 107 | // @Accept json 108 | // @Produce json 109 | // @Security Bearer 110 | // @Param limit query string true "limit" 111 | // @Param page query string true "Page number" 112 | // @Success 200 {object} response.Response{} 113 | // @Failure 500 {object} response.Response{} 114 | // @Router /admin/users/getusers [get] 115 | func (ah *AdminHandler) GetUsers(c *gin.Context) { 116 | pageStr := c.Query("page") 117 | page, err := strconv.Atoi(pageStr) 118 | if err != nil { 119 | errorRes := response.ClientResponse(http.StatusBadRequest, "page number not in right format", nil, err.Error()) 120 | c.JSON(http.StatusBadRequest, errorRes) 121 | return 122 | } 123 | limitStr := c.Query("limit") 124 | limit, err := strconv.Atoi(limitStr) 125 | if err != nil { 126 | errorRes := response.ClientResponse(http.StatusBadRequest, "page number not in right format", nil, err.Error()) 127 | c.JSON(http.StatusBadRequest, errorRes) 128 | return 129 | } 130 | users, err := ah.adminUsecase.GetUsers(page, limit) 131 | if err != nil { 132 | errorRes := response.ClientResponse(http.StatusBadRequest, "could not retrieve records", nil, err.Error()) 133 | c.JSON(http.StatusBadRequest, errorRes) 134 | return 135 | } 136 | successRes := response.ClientResponse(http.StatusOK, "Successfully retrieved the users", users, nil) 137 | c.JSON(http.StatusOK, successRes) 138 | } 139 | -------------------------------------------------------------------------------- /pkg/api/handlers/cart.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/response" 10 | "github.com/gin-gonic/gin" 11 | ) 12 | 13 | type CartHandler struct { 14 | cartUsecase services.CartUsecase 15 | } 16 | 17 | // Constructor function 18 | func NewCartHandler(usecase services.CartUsecase) *CartHandler { 19 | return &CartHandler{ 20 | cartUsecase: usecase, 21 | } 22 | } 23 | 24 | // @Summary Add To Cart 25 | // @Description Add products to carts for the purchase 26 | // @Tags User 27 | // @Accept json 28 | // @Produce json 29 | // @Param inventory query string true "inventory ID" 30 | // @Security Bearer 31 | // @Success 200 {object} response.Response{} 32 | // @Failure 500 {object} response.Response{} 33 | // @Router /users/home/add-to-cart [post] 34 | func (ch *CartHandler) AddtoCart(c *gin.Context) { 35 | // userId, err := helper.GetUserId(c) 36 | var cart models.AddToCart 37 | if err := c.BindJSON(&cart); err != nil { 38 | errorRes := response.ClientResponse(http.StatusBadRequest, "fields provided are in wrong format", nil, err.Error()) 39 | c.JSON(http.StatusBadRequest, errorRes) 40 | return 41 | } 42 | 43 | if err := ch.cartUsecase.AddToCart(cart.UserID, cart.InventoryID); err != nil { 44 | errorRes := response.ClientResponse(http.StatusBadRequest, "Could not add the Cart", nil, err.Error()) 45 | c.JSON(http.StatusBadRequest, errorRes) 46 | return 47 | } 48 | 49 | successRes := response.ClientResponse(http.StatusOK, "Successfully added To cart", nil, nil) 50 | c.JSON(http.StatusOK, successRes) 51 | } 52 | 53 | // @Summary Checkout section 54 | // @Description Add products to carts for the purchase 55 | // @Tags User 56 | // @Produce json 57 | // @Security Bearer 58 | // @Param id query string true "id" 59 | // @Success 200 {object} response.Response{} 60 | // @Failure 500 {object} response.Response{} 61 | // @Router /users/check-out [get] 62 | func (ch *CartHandler) CheckOut(c *gin.Context) { 63 | userId, err := strconv.Atoi(c.Query("id")) 64 | if err != nil { 65 | errorRes := response.ClientResponse(http.StatusBadRequest, "Could not get userID", nil, err.Error()) 66 | c.JSON(http.StatusBadRequest, errorRes) 67 | return 68 | } 69 | 70 | products, err := ch.cartUsecase.CheckOut(userId) 71 | if err != nil { 72 | errorRes := response.ClientResponse(http.StatusBadRequest, "could not open checkout", nil, err.Error()) 73 | c.JSON(http.StatusBadRequest, errorRes) 74 | return 75 | } 76 | successRes := response.ClientResponse(http.StatusOK, "Successfully got all records", products, nil) 77 | c.JSON(http.StatusOK, successRes) 78 | } 79 | -------------------------------------------------------------------------------- /pkg/api/handlers/category.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | 6 | // "strconv" 7 | 8 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 10 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/response" 11 | "github.com/gin-gonic/gin" 12 | ) 13 | 14 | type CategoryHandler struct { 15 | CategoryUsecase services.CategoryUsecase 16 | } 17 | 18 | // Constructor function 19 | 20 | func NewCategoryHandler(categoryUsecase services.CategoryUsecase) *CategoryHandler { 21 | return &CategoryHandler{ 22 | CategoryUsecase: categoryUsecase, 23 | } 24 | } 25 | 26 | // @Summary Add Category 27 | // @Description Admin can add new categories for products 28 | // @Tags Admin 29 | // @Accept json 30 | // @Produce json 31 | // @Param category query string true "category" 32 | // @Security Bearer 33 | // @Success 200 {object} response.Response{} 34 | // @Failure 500 {object} response.Response{} 35 | // @Router /admin/category/add [post] 36 | func (catH *CategoryHandler) AddCategory(c *gin.Context) { 37 | cat := c.Query("category") 38 | // var cat domain.Category 39 | 40 | // if err := c.BindJSON(&cat); err != nil { 41 | // fmt.Println("error from cat handler ", err) 42 | // errRes := response.ClientResponse(http.StatusBadRequest, "fields provided are in wrong format", nil, err.Error()) 43 | // c.JSON(http.StatusBadRequest, errRes) 44 | // return 45 | // } 46 | categoryRes, err := catH.CategoryUsecase.AddCategory(cat) 47 | if err != nil { 48 | errRes := response.ClientResponse(http.StatusBadRequest, "Couldn't add category", nil, err.Error()) 49 | c.JSON(http.StatusBadRequest, errRes) 50 | return 51 | } 52 | successRes := response.ClientResponse(http.StatusOK, "Category added successfully", categoryRes, nil) 53 | c.JSON(http.StatusOK, successRes) 54 | 55 | } 56 | 57 | // @Summary Update Category 58 | // @Description Admin can update name of a category into new name 59 | // @Tags Admin 60 | // @Accept json 61 | // @Produce json 62 | // @Param set_new_name body models.SetNewName true "set new name" 63 | // @Security Bearer 64 | // @Success 200 {object} response.Response{} 65 | // @Failure 500 {object} response.Response{} 66 | // @Router /admin/category/update [patch] 67 | func (catH *CategoryHandler) UpdateCategory(c *gin.Context) { 68 | var updateCategory models.SetNewName 69 | 70 | if err := c.BindJSON(&updateCategory); err != nil { 71 | errRes := response.ClientResponse(http.StatusBadRequest, "field provided are in wrong format", nil, err.Error()) 72 | c.JSON(http.StatusBadRequest, errRes) 73 | return 74 | } 75 | 76 | updateRes, err := catH.CategoryUsecase.UpdateCategory(updateCategory.Current, updateCategory.New) 77 | if err != nil { 78 | errRes := response.ClientResponse(http.StatusBadRequest, "update category failed", nil, err.Error()) 79 | c.JSON(http.StatusBadRequest, errRes) 80 | return 81 | } 82 | successRes := response.ClientResponse(http.StatusOK, "category updated successfully", updateRes, nil) 83 | c.JSON(http.StatusOK, successRes) 84 | } 85 | 86 | // @Summary Delete Category 87 | // @Description Admin can delete a category 88 | // @Tags Admin 89 | // @Accept json 90 | // @Produce json 91 | // @Param id query string true "id" 92 | // @Security Bearer 93 | // @Success 200 {object} response.Response{} 94 | // @Failure 500 {object} response.Response{} 95 | // @Router /admin/category/delete [delete] 96 | func (catH *CategoryHandler) DeleteCategory(c *gin.Context) { 97 | // Find category id 98 | categoryId := c.Query("id") 99 | if err := catH.CategoryUsecase.DeleteCategory(categoryId); err != nil { 100 | errRes := response.ClientResponse(http.StatusBadRequest, "fields provided are in wrong format", nil, err.Error()) 101 | c.JSON(http.StatusBadRequest, errRes) 102 | return 103 | } 104 | successRes := response.ClientResponse(http.StatusOK, "category deleted", nil, nil) 105 | c.JSON(http.StatusOK, successRes) 106 | } 107 | 108 | func (catH *CategoryHandler) Categories(c *gin.Context) { 109 | 110 | categories, err := catH.CategoryUsecase.GetCategories() 111 | if err != nil { 112 | errorRes := response.ClientResponse(http.StatusBadRequest, "could not retrieve records", nil, err.Error()) 113 | c.JSON(http.StatusBadRequest, errorRes) 114 | return 115 | } 116 | successRes := response.ClientResponse(http.StatusOK, "successfully retrieved categories", categories, nil) 117 | c.JSON(http.StatusOK, successRes) 118 | } 119 | -------------------------------------------------------------------------------- /pkg/api/handlers/coupon.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/response" 10 | "github.com/gin-gonic/gin" 11 | ) 12 | 13 | type CouponHandler struct { 14 | couponUsecase services.CouponUsecase 15 | } 16 | 17 | // Constructor function 18 | func NewCouponHandler(couponUsecase services.CouponUsecase) *CouponHandler { 19 | return &CouponHandler{ 20 | couponUsecase: couponUsecase, 21 | } 22 | } 23 | 24 | // @Summary Add Coupon 25 | // @Description Admin can add new coupons 26 | // @Tags Admin 27 | // @Accept json 28 | // @Produce json 29 | // @Param coupon body models.Coupon true "coupon" 30 | // @Security Bearer 31 | // @Success 200 {object} response.Response{} 32 | // @Failure 500 {object} response.Response{} 33 | // @Router /admin/coupons/create [post] 34 | func (coupH *CouponHandler) CreateNewCoupon(c *gin.Context) { 35 | var coupon models.Coupon 36 | 37 | if err := c.BindJSON(&coupon); err != nil { 38 | errorRes := response.ClientResponse(http.StatusBadRequest, "fields provided are in wrong format", nil, err.Error()) 39 | c.JSON(http.StatusBadRequest, errorRes) 40 | return 41 | } 42 | if err := coupH.couponUsecase.Addcoupon(coupon); err != nil { 43 | errorRes := response.ClientResponse(http.StatusBadRequest, "Could not add the Coupon", nil, err.Error()) 44 | c.JSON(http.StatusBadRequest, errorRes) 45 | return 46 | } 47 | successRes := response.ClientResponse(http.StatusOK, "Successfully added the coupon", nil, nil) 48 | c.JSON(http.StatusOK, successRes) 49 | } 50 | 51 | // @Summary Make Coupon invalid 52 | // @Description Admin can make the coupons as invalid so that users cannot use that particular coupon 53 | // @Tags Admin 54 | // @Accept json 55 | // @Produce json 56 | // @Param id query string true "id" 57 | // @Security Bearer 58 | // @Success 200 {object} response.Response{} 59 | // @Failure 500 {object} response.Response{} 60 | // @Router /admin/coupons/expire [post] 61 | func (coupH *CouponHandler) MakeCouponInvalid(c *gin.Context) { 62 | idStr := c.Query("id") 63 | id, err := strconv.Atoi(idStr) 64 | if err != nil { 65 | errRes := response.ClientResponse(http.StatusBadRequest, "field provided are in wrong format", nil, err.Error()) 66 | c.JSON(http.StatusBadRequest, errRes) 67 | return 68 | } 69 | if err := coupH.couponUsecase.MakeCouponInvalid(id); err != nil { 70 | errRes := response.ClientResponse(http.StatusBadRequest, "make coupon invalid failed", nil, err.Error()) 71 | c.JSON(http.StatusBadRequest, errRes) 72 | return 73 | } 74 | successRes := response.ClientResponse(http.StatusOK, "successfully made coupon as invalid", nil, nil) 75 | c.JSON(http.StatusOK, successRes) 76 | } 77 | 78 | // @Summary List Coupons 79 | // @Description Admin can view the list of Coupons 80 | // @Tags Admin 81 | // @Accept json 82 | // @Produce json 83 | // @Param page query string true "page" 84 | // @Param limit query string true "limit" 85 | // @Security Bearer 86 | // @Success 200 {object} response.Response{} 87 | // @Failure 500 {object} response.Response{} 88 | // @Router /admin/coupons [get] 89 | func (coupH *CouponHandler) Coupons(c *gin.Context) { 90 | 91 | coupons, err := coupH.couponUsecase.GetCoupons() 92 | if err != nil { 93 | errRes := response.ClientResponse(http.StatusBadRequest, "couldn't get coupons", nil, err.Error()) 94 | c.JSON(http.StatusBadRequest, errRes) 95 | return 96 | } 97 | 98 | successRes := response.ClientResponse(http.StatusOK, "coupons get successfully", coupons, nil) 99 | c.JSON(http.StatusOK, successRes) 100 | 101 | } 102 | -------------------------------------------------------------------------------- /pkg/api/handlers/offer.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/response" 10 | "github.com/gin-gonic/gin" 11 | ) 12 | 13 | type OfferHandler struct { 14 | offerUsecase services.OfferUsecase 15 | } 16 | 17 | // Constructor function 18 | 19 | func NewOfferHandler(offerUsecase services.OfferUsecase) *OfferHandler { 20 | return &OfferHandler{ 21 | offerUsecase: offerUsecase, 22 | } 23 | } 24 | 25 | // @Summary Add Offer 26 | // @Description Admin can add new offers 27 | // @Tags Admin 28 | // @Accept json 29 | // @Produce json 30 | // @Param offer body models.CreateOffer true "Offer" 31 | // @Security Bearer 32 | // @Success 200 {object} response.Response{} 33 | // @Failure 500 {object} response.Response{} 34 | // @Router /admin/offers/create [post] 35 | func (offH *OfferHandler) AddOffer(c *gin.Context) { 36 | var offer models.CreateOffer 37 | 38 | if err := c.BindJSON(&offer); err != nil { 39 | errRes := response.ClientResponse(http.StatusBadRequest, "fields provided are in wrong format", nil, err.Error()) 40 | c.JSON(http.StatusBadRequest, errRes) 41 | return 42 | } 43 | if err := offH.offerUsecase.AddNewOffer(offer); err != nil { 44 | errRes := response.ClientResponse(http.StatusBadRequest, "offer adding failed", nil, err.Error()) 45 | c.JSON(http.StatusBadRequest, errRes) 46 | return 47 | } 48 | successRes := response.ClientResponse(http.StatusOK, "offer added successfully", nil, nil) 49 | c.JSON(http.StatusOK, successRes) 50 | } 51 | 52 | // @Summary Expire Offer 53 | // @Description Admin can add Expire offers 54 | // @Tags Admin 55 | // @Accept json 56 | // @Produce json 57 | // @Param catID query string true "Category ID" 58 | // @Security Bearer 59 | // @Success 200 {object} response.Response{} 60 | // @Failure 500 {object} response.Response{} 61 | // @Router /admin/offers/expire [post] 62 | func (offH *OfferHandler) ExpireValidity(c *gin.Context) { 63 | catIdStr := c.Query("catID") 64 | catId, err := strconv.Atoi(catIdStr) 65 | if err != nil { 66 | errRes := response.ClientResponse(http.StatusBadRequest, "conversion failed", nil, err.Error()) 67 | c.JSON(http.StatusBadRequest, errRes) 68 | return 69 | } 70 | if err := offH.offerUsecase.MakeOfferExpire(catId); err != nil { 71 | errRes := response.ClientResponse(http.StatusBadRequest, "make offer expired failed", nil, err.Error()) 72 | c.JSON(http.StatusBadRequest, errRes) 73 | return 74 | } 75 | successRes := response.ClientResponse(http.StatusOK, "successfully turned the offer invalid", nil, nil) 76 | c.JSON(http.StatusOK, successRes) 77 | } 78 | 79 | // @Summary List Offers 80 | // @Description Admin can view the list of offers 81 | // @Tags Admin 82 | // @Accept json 83 | // @Produce json 84 | // @Param page query string true "page" 85 | // @Param limit query string true "limit" 86 | // @Security Bearer 87 | // @Success 200 {object} response.Response{} 88 | // @Failure 500 {object} response.Response{} 89 | // @Router /admin/offers [get] 90 | func (offH *OfferHandler) Offers(c *gin.Context) { 91 | pageStr := c.Query("page") 92 | page, err := strconv.Atoi(pageStr) 93 | if err != nil { 94 | errorRes := response.ClientResponse(http.StatusBadRequest, "page number not in right format", nil, err.Error()) 95 | c.JSON(http.StatusBadRequest, errorRes) 96 | return 97 | } 98 | limitStr := c.Query("limit") 99 | limit, err := strconv.Atoi(limitStr) 100 | if err != nil { 101 | errorRes := response.ClientResponse(http.StatusBadRequest, "page number not in right format", nil, err.Error()) 102 | c.JSON(http.StatusBadRequest, errorRes) 103 | return 104 | } 105 | offers, err := offH.offerUsecase.GetOffers(page, limit) 106 | if err != nil { 107 | errorRes := response.ClientResponse(http.StatusBadRequest, "couldn't get offers", nil, err.Error()) 108 | c.JSON(http.StatusBadRequest, errorRes) 109 | return 110 | } 111 | successRes := response.ClientResponse(http.StatusOK, "successfully retrieved the offers", offers, nil) 112 | c.JSON(http.StatusOK, successRes) 113 | 114 | } 115 | -------------------------------------------------------------------------------- /pkg/api/handlers/order.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | "strconv" 7 | 8 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 10 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/response" 11 | "github.com/gin-gonic/gin" 12 | ) 13 | 14 | type OrderHandler struct { 15 | orderUsecase services.OrderUsecase 16 | } 17 | 18 | // Constructor function 19 | 20 | func NewOrderHandler(orderUsecase services.OrderUsecase) *OrderHandler { 21 | return &OrderHandler{ 22 | orderUsecase: orderUsecase, 23 | } 24 | } 25 | 26 | // @Summary Get Orders 27 | // @Description user can view the details of the orders 28 | // @Tags User 29 | // @Accept json 30 | // @Produce json 31 | // @Param id query string true "id" 32 | // @Param page query string true "page" 33 | // @Param limit query string true "limit" 34 | // @Security Bearer 35 | // @Success 200 {object} response.Response{} 36 | // @Failure 500 {object} response.Response{} 37 | // @Router /users/profile/orders [get] 38 | func (orH *OrderHandler) GetOrders(c *gin.Context) { 39 | pageStr := c.Query("page") 40 | page, err := strconv.Atoi(pageStr) 41 | if err != nil { 42 | errRes := response.ClientResponse(http.StatusBadRequest, "page number not in right format", nil, err.Error()) 43 | c.JSON(http.StatusBadRequest, errRes) 44 | return 45 | } 46 | 47 | limitStr := c.Query("limit") 48 | limit, err := strconv.Atoi(limitStr) 49 | if err != nil { 50 | errRes := response.ClientResponse(http.StatusBadRequest, "limit number not in right format", nil, err.Error()) 51 | c.JSON(http.StatusBadRequest, errRes) 52 | return 53 | } 54 | id, err := strconv.Atoi(c.Query("id")) 55 | if err != nil { 56 | errRes := response.ClientResponse(http.StatusBadRequest, "geting user id failed", nil, err.Error()) 57 | c.JSON(http.StatusBadRequest, errRes) 58 | return 59 | } 60 | orders, err := orH.orderUsecase.GetOrders(id, page, limit) 61 | if err != nil { 62 | errRes := response.ClientResponse(http.StatusBadRequest, "couldn't retrieve records", nil, err.Error()) 63 | c.JSON(http.StatusBadRequest, errRes) 64 | return 65 | } 66 | 67 | successRes := response.ClientResponse(http.StatusOK, "successfully got orders", orders, nil) 68 | c.JSON(http.StatusOK, successRes) 69 | } 70 | 71 | // @Summary Order Now 72 | // @Description user can order the items that currently in cart 73 | // @Tags User 74 | // @Accept json 75 | // @Produce json 76 | // @Param coupon query string true "coupon" 77 | // @Param order body models.Order true "order" 78 | // @Security Bearer 79 | // @Success 200 {object} response.Response{} 80 | // @Failure 500 {object} response.Response{} 81 | // @Router /users/check-out/order [post] 82 | func (orH *OrderHandler) OrderItemsFromCart(c *gin.Context) { 83 | 84 | var order models.Order 85 | if err := c.BindJSON(&order); err != nil { 86 | errRes := response.ClientResponse(http.StatusBadRequest, "fields provided are in wrong format", nil, err.Error()) 87 | c.JSON(http.StatusBadRequest, errRes) 88 | return 89 | } 90 | if err := orH.orderUsecase.OrderItemsFromCart(order.UserID, order.AddressID, order.PaymentMethodID, order.CouponID); err != nil { 91 | errRes := response.ClientResponse(http.StatusBadRequest, "could not make the order", nil, err.Error()) 92 | c.JSON(http.StatusBadRequest, errRes) 93 | return 94 | } 95 | 96 | successRes := response.ClientResponse(http.StatusOK, "successfully ordered", nil, nil) 97 | c.JSON(http.StatusOK, successRes) 98 | } 99 | 100 | // @Summary Order Cancel 101 | // @Description user can cancel the orders 102 | // @Tags User 103 | // @Accept json 104 | // @Produce json 105 | // @Param orderid query string true "order id" 106 | // @Security Bearer 107 | // @Success 200 {object} response.Response{} 108 | // @Failure 500 {object} response.Response{} 109 | // @Router /users/profile/orders/cancel [post] 110 | func (orH *OrderHandler) CancelOrder(c *gin.Context) { 111 | userId, err := strconv.Atoi(c.Query("id")) 112 | if err != nil { 113 | errRes := response.ClientResponse(http.StatusBadRequest, "couldn't get user id", nil, err.Error()) 114 | c.JSON(http.StatusBadRequest, errRes) 115 | return 116 | } 117 | orderIdStr := c.Query("order_id") 118 | orderId, err := strconv.Atoi(orderIdStr) 119 | if err != nil { 120 | errRes := response.ClientResponse(http.StatusBadRequest, "conversion failed", nil, err.Error()) 121 | c.JSON(http.StatusBadRequest, errRes) 122 | return 123 | } 124 | 125 | if err := orH.orderUsecase.CancelOrder(userId, orderId); err != nil { 126 | errRes := response.ClientResponse(http.StatusBadRequest, "cancel order failed", nil, err.Error()) 127 | c.JSON(http.StatusBadRequest, errRes) 128 | return 129 | } 130 | 131 | successRes := response.ClientResponse(http.StatusOK, "successfully canceled the order", nil, nil) 132 | c.JSON(http.StatusOK, successRes) 133 | } 134 | 135 | // @Summary Update Order Status 136 | // @Description Admin can change the status of the order 137 | // @Tags Admin 138 | // @Accept json 139 | // @Produce json 140 | // @Param id query string true "id" 141 | // @Param status query string true "status" 142 | // @Security Bearer 143 | // @Success 200 {object} response.Response{} 144 | // @Failure 500 {object} response.Response{} 145 | // @Router /admin/orders/edit/status [patch] 146 | func (orH *OrderHandler) EditOrderStatus(c *gin.Context) { 147 | status := c.Query("status") 148 | id, err := strconv.Atoi(c.Query("id")) 149 | if err != nil { 150 | errRes := response.ClientResponse(http.StatusBadRequest, "conversion failed", nil, err.Error()) 151 | c.JSON(http.StatusBadRequest, errRes) 152 | return 153 | } 154 | if err := orH.orderUsecase.EditOrderStatus(status, id); err != nil { 155 | errRes := response.ClientResponse(http.StatusBadRequest, "edit order status failed", nil, err.Error()) 156 | c.JSON(http.StatusBadRequest, errRes) 157 | return 158 | } 159 | 160 | successRes := response.ClientResponse(http.StatusOK, "successfully edited order status", nil, nil) 161 | c.JSON(http.StatusOK, successRes) 162 | } 163 | 164 | // @Summary Update Payment Status 165 | // @Description Admin can change the status of the payment 166 | // @Tags Admin 167 | // @Accept json 168 | // @Produce json 169 | // @Param orderID query string true "order id" 170 | // @Security Bearer 171 | // @Success 200 {object} response.Response{} 172 | // @Failure 500 {object} response.Response{} 173 | // @Router /admin/orders/edit/mark-as-paid [patch] 174 | func (orH *OrderHandler) MarkAsPaid(c *gin.Context) { 175 | orderId, err := strconv.Atoi(c.Query("order_id")) 176 | if err != nil { 177 | errRes := response.ClientResponse(http.StatusBadRequest, "conversion failed", nil, err.Error()) 178 | c.JSON(http.StatusBadRequest, errRes) 179 | return 180 | } 181 | if err := orH.orderUsecase.MarkAsPaid(orderId); err != nil { 182 | errRes := response.ClientResponse(http.StatusBadRequest, "mark as paid failed", nil, err.Error()) 183 | c.JSON(http.StatusBadRequest, errRes) 184 | return 185 | } 186 | 187 | successRes := response.ClientResponse(http.StatusOK, "successfully edited payment status", nil, nil) 188 | c.JSON(http.StatusOK, successRes) 189 | } 190 | 191 | // @Summary Admin Orders 192 | // @Description Admin can view the orders according to status 193 | // @Tags Admin 194 | // @Produce json 195 | // @Param page query string true "page" 196 | // @Param limit query string true "limit" 197 | // @Param status query string true "status" 198 | // @Security Bearer 199 | // @Success 200 {object} response.Response{} 200 | // @Failure 500 {object} response.Response{} 201 | // @Router /admin/orders [get] 202 | func (orH *OrderHandler) AdminOrders(c *gin.Context) { 203 | 204 | orders, err := orH.orderUsecase.AdminOrders() 205 | if err != nil { 206 | errRes := response.ClientResponse(http.StatusBadRequest, "could not retrieve records", nil, err.Error()) 207 | c.JSON(http.StatusBadRequest, errRes) 208 | return 209 | } 210 | 211 | successRes := response.ClientResponse(http.StatusOK, "successfully got all records", orders, nil) 212 | c.JSON(http.StatusOK, successRes) 213 | } 214 | 215 | // @Summary Admin Sales Report 216 | // @Description Admin can view the daily sales Report 217 | // @Tags Admin 218 | // @Produce json 219 | // @Security Bearer 220 | // @Success 200 {object} response.Response{} 221 | // @Failure 500 {object} response.Response{} 222 | // @Router /admin/sales/daily [get] 223 | func (orH *OrderHandler) AdminSalesDailyReport(c *gin.Context) { 224 | salesReport, err := orH.orderUsecase.DailyOrders() 225 | if err != nil { 226 | errRes := response.ClientResponse(http.StatusBadRequest, "could not retrieve records", nil, err.Error()) 227 | c.JSON(http.StatusBadRequest, errRes) 228 | return 229 | } 230 | successRes := response.ClientResponse(http.StatusOK, "successfully got all records", salesReport, nil) 231 | c.JSON(http.StatusOK, successRes) 232 | } 233 | 234 | // @Summary Admin Sales Report 235 | // @Description Admin can view the weekly sales Report 236 | // @Tags Admin 237 | // @Produce json 238 | // @Security Bearer 239 | // @Success 200 {object} response.Response{} 240 | // @Failure 500 {object} response.Response{} 241 | // @Router /admin/sales/weekly [get] 242 | func (orH *OrderHandler) AdminSalesWeeklyReports(c *gin.Context) { 243 | salesReport, err := orH.orderUsecase.WeeklyOrders() 244 | if err != nil { 245 | errRes := response.ClientResponse(http.StatusBadRequest, "could not retrieve records", nil, err.Error()) 246 | c.JSON(http.StatusBadRequest, errRes) 247 | return 248 | } 249 | successRes := response.ClientResponse(http.StatusOK, "successfully got all records", salesReport, nil) 250 | c.JSON(http.StatusOK, successRes) 251 | } 252 | 253 | // @Summary Admin Sales Report 254 | // @Description Admin can view the weekly sales Report 255 | // @Tags Admin 256 | // @Produce json 257 | // @Security Bearer 258 | // @Success 200 {object} response.Response{} 259 | // @Failure 500 {object} response.Response{} 260 | // @Router /admin/sales/monthly [get] 261 | func (orH *OrderHandler) AdminSalesMonthlyReport(c *gin.Context) { 262 | salesReport, err := orH.orderUsecase.MonthlyOrders() 263 | if err != nil { 264 | errRes := response.ClientResponse(http.StatusBadRequest, "could not retrieve records", nil, err.Error()) 265 | c.JSON(http.StatusBadRequest, errRes) 266 | return 267 | } 268 | successRes := response.ClientResponse(http.StatusOK, "successfully got all records", salesReport, nil) 269 | c.JSON(http.StatusOK, successRes) 270 | } 271 | 272 | // @Summary Admin Sales Report 273 | // @Description Admin can view the weekly sales Report 274 | // @Tags Admin 275 | // @Produce json 276 | // @Security Bearer 277 | // @Success 200 {object} response.Response{} 278 | // @Failure 500 {object} response.Response{} 279 | // @Router /admin/sales/annual [get] 280 | func (orH *OrderHandler) AdminSalesAnnualReport(c *gin.Context) { 281 | salesReport, err := orH.orderUsecase.AnnualOrders() 282 | if err != nil { 283 | errRes := response.ClientResponse(http.StatusBadRequest, "could not retrieve records", nil, err.Error()) 284 | c.JSON(http.StatusBadRequest, errRes) 285 | return 286 | } 287 | successRes := response.ClientResponse(http.StatusOK, "successfully got all records", salesReport, nil) 288 | c.JSON(http.StatusOK, successRes) 289 | } 290 | 291 | // @Summary Admin Sales Report 292 | // @Description Admin can view the weekly sales Report 293 | // @Tags Admin 294 | // @Produce json 295 | // @Param customDates body models.CustomDates true "custom dates" 296 | // @Security Bearer 297 | // @Success 200 {object} response.Response{} 298 | // @Failure 500 {object} response.Response{} 299 | // @Router /admin/sales/custom [post] 300 | func (orH *OrderHandler) AdminSaleCustomReport(c *gin.Context) { 301 | var dates models.CustomDates 302 | if err := c.BindJSON(&dates); err != nil { 303 | errRes := response.ClientResponse(http.StatusBadRequest, "fields provided are in wrong format", nil, err.Error()) 304 | c.JSON(http.StatusBadRequest, errRes) 305 | return 306 | } 307 | salesReport, err := orH.orderUsecase.CustomDateOrders(dates) 308 | if err != nil { 309 | errRes := response.ClientResponse(http.StatusBadRequest, "could not retrieve records", nil, err.Error()) 310 | c.JSON(http.StatusBadRequest, errRes) 311 | return 312 | } 313 | 314 | successRes := response.ClientResponse(http.StatusOK, "successfully got all records", salesReport, nil) 315 | c.JSON(http.StatusOK, successRes) 316 | } 317 | 318 | // @Summary Return Order 319 | // @Description user can return the ordered products which is already delivered and then get the amount fot that particular purchase back in their wallet 320 | // @Tags User 321 | // @Accept json 322 | // @Produce json 323 | // @Security Bearer 324 | // @Param id query string true "id" 325 | // @Success 200 {object} response.Response{} 326 | // @Failure 500 {object} response.Response{} 327 | // @Router /users/profile/orders/return [post] 328 | func (orH *OrderHandler) ReturnOrder(c *gin.Context) { 329 | id, err := strconv.Atoi(c.Query("id")) 330 | if err != nil { 331 | errRes := response.ClientResponse(http.StatusBadRequest, "conversion failed", nil, err.Error()) 332 | c.JSON(http.StatusBadRequest, errRes) 333 | return 334 | } 335 | if err := orH.orderUsecase.ReturnOrder(id); err != nil { 336 | errRes := response.ClientResponse(http.StatusBadRequest, "fileds provided are in wrong format", nil, err.Error()) 337 | c.JSON(http.StatusBadRequest, errRes) 338 | return 339 | } 340 | 341 | successRes := response.ClientResponse(http.StatusOK, "return order successfully", nil, nil) 342 | c.JSON(http.StatusOK, successRes) 343 | } 344 | 345 | // @Summary Download Invoice PDF 346 | // @Description Download the invoice PDF file 347 | // @Tags User 348 | // @Security Bearer 349 | // @Produce octet-stream 350 | // @Success 200 {file} application/pdf 351 | // @Router /users/check-out/order/download-invoice [get] 352 | func (orH *OrderHandler) DownloadInvoice(c *gin.Context) { 353 | // Set the appropriate header for the file download 354 | c.Header("Content-Disposition", "attachment; filename=yoursstore_invoice.pdf") 355 | c.Header("Content-Type", "application/pdf") 356 | 357 | // Read the pdf file and write it to the response 358 | pdfData, err := os.ReadFile("yoursstore_invoice.pdf") 359 | if err != nil { 360 | c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to read pdf file"}) 361 | return 362 | } 363 | c.Data(http.StatusOK, "application/pdf", pdfData) 364 | } 365 | -------------------------------------------------------------------------------- /pkg/api/handlers/otp.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | 6 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/response" 9 | "github.com/gin-gonic/gin" 10 | ) 11 | 12 | type OtpHandler struct { 13 | otpUsecase services.OtpUsecase 14 | } 15 | 16 | // Constrctor function 17 | func NewOtpHandler(otpUsecase services.OtpUsecase) *OtpHandler { 18 | return &OtpHandler{ 19 | otpUsecase: otpUsecase, 20 | } 21 | } 22 | 23 | // @Summary Send OTP 24 | // @Description OTP login send otp 25 | // @Tags User 26 | // @Accept json 27 | // @Produce json 28 | // @Param otp body models.OTPData true "otp-data" 29 | // @Success 200 {object} response.Response{} 30 | // @Failure 500 {object} response.Response{} 31 | // @Router /users/otplogin [post] 32 | func (otH *OtpHandler) SendOTP(c *gin.Context) { 33 | var phone models.OTPData 34 | 35 | if err := c.BindJSON(&phone); err != nil { 36 | errRes := response.ClientResponse(http.StatusBadRequest, "fields provided are in wrong format", nil, err.Error()) 37 | c.JSON(http.StatusBadRequest, errRes) 38 | return 39 | } 40 | if err := otH.otpUsecase.SendOTP(phone.PhoneNumber); err != nil { 41 | errRes := response.ClientResponse(http.StatusBadRequest, "Could not sent OTP", nil, err.Error()) 42 | c.JSON(http.StatusBadRequest, errRes) 43 | return 44 | } 45 | successRes := response.ClientResponse(http.StatusOK, "OTP send successfully", nil, nil) 46 | c.JSON(http.StatusOK, successRes) 47 | } 48 | 49 | // @Summary Verify OTP 50 | // @Description OTP login verify otp 51 | // @Tags User 52 | // @Accept json 53 | // @Produce json 54 | // @Param otp body models.VerifyData true "otp-verify" 55 | // @Success 200 {object} response.Response{} 56 | // @Failure 500 {object} response.Response{} 57 | // @Router /users/verifyotp [post] 58 | func (otH *OtpHandler) VerifyOTP(c *gin.Context) { 59 | var code models.VerifyData 60 | if err := c.BindJSON(&code); err != nil { 61 | errRes := response.ClientResponse(http.StatusBadRequest, "fields provided are in wrong format", nil, err.Error()) 62 | c.JSON(http.StatusBadRequest, errRes) 63 | return 64 | } 65 | users, err := otH.otpUsecase.VerifyOTP(code) 66 | if err != nil { 67 | errRes := response.ClientResponse(http.StatusBadRequest, "couldn't verify OTP", nil, err.Error()) 68 | c.JSON(http.StatusBadRequest, errRes) 69 | return 70 | } 71 | successRes := response.ClientResponse(http.StatusOK, "Verifyed OTP", users, nil) 72 | c.SetCookie("Authorization", users.Token, 3600, "", "", true, false) 73 | c.JSON(http.StatusOK, successRes) 74 | } 75 | -------------------------------------------------------------------------------- /pkg/api/handlers/payment.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/response" 9 | "github.com/gin-gonic/gin" 10 | ) 11 | 12 | type PaymentHandler struct { 13 | paymentUsecase services.PaymentUsecase 14 | } 15 | 16 | // Constructor function 17 | 18 | func NewPaymentHandler(payUsecase services.PaymentUsecase) *PaymentHandler { 19 | return &PaymentHandler{ 20 | paymentUsecase: payUsecase, 21 | } 22 | } 23 | 24 | // @Summary Add new payment method 25 | // @Description admin can add a new payment method 26 | // @Tags Admin 27 | // @Produce json 28 | // @Param paymentMethod query string true "Payment Method" 29 | // @Success 200 {object} response.Response{} 30 | // @Failure 500 {object} response.Response{} 31 | // @Router /admin/paymentmethods/add [post] 32 | func (payH *PaymentHandler) AddNewPaymentMethod(c *gin.Context) { 33 | method := c.Query("payment_method") 34 | 35 | if err := payH.paymentUsecase.AddNewPaymentMethod(method); err != nil { 36 | errRes := response.ClientResponse(http.StatusBadRequest, "couldn't add new payment method", nil, err.Error()) 37 | c.JSON(http.StatusBadRequest, errRes) 38 | return 39 | } 40 | successRes := response.ClientResponse(http.StatusOK, "successfully added payment method", nil, nil) 41 | c.JSON(http.StatusOK, successRes) 42 | } 43 | 44 | // @Summary Remove payment method 45 | // @Description admin can remove a payment method 46 | // @Tags Admin 47 | // @Produce json 48 | // @Param paymentMethodID query int true "Payment Method ID" 49 | // @Success 200 {object} response.Response{} 50 | // @Failure 500 {object} response.Response{} 51 | // @Router /admin/paymentmethods/remove [delete] 52 | func (payH *PaymentHandler) RemovePaymentMethod(c *gin.Context) { 53 | methodId, err := strconv.Atoi(c.Query("payment_method_id")) 54 | if err != nil { 55 | errRes := response.ClientResponse(http.StatusBadRequest, "conversion failed", nil, err.Error()) 56 | c.JSON(http.StatusBadRequest, errRes) 57 | return 58 | } 59 | if err := payH.paymentUsecase.RemovePaymentMethod(methodId); err != nil { 60 | errRes := response.ClientResponse(http.StatusBadRequest, "payment method removal failed", nil, err.Error()) 61 | c.JSON(http.StatusBadRequest, errRes) 62 | return 63 | } 64 | 65 | successRes := response.ClientResponse(http.StatusOK, "payment method removed successfully", nil, nil) 66 | c.JSON(http.StatusOK, successRes) 67 | } 68 | 69 | // @Summary Get payment methods 70 | // @Description admin can get all payment methods 71 | // @Tags Admin 72 | // @Produce json 73 | // @Success 200 {object} response.Response{} 74 | // @Failure 500 {object} response.Response{} 75 | // @Router /admin/paymentmethods [get] 76 | func (payH *PaymentHandler) GetPaymentMethods(c *gin.Context) { 77 | paymentMethods, err := payH.paymentUsecase.GetPaymentMethods() 78 | 79 | if err != nil { 80 | errRes := response.ClientResponse(http.StatusBadRequest, "couldn't get payment methods", nil, err.Error()) 81 | c.JSON(http.StatusBadRequest, errRes) 82 | return 83 | } 84 | 85 | successRes := response.ClientResponse(http.StatusOK, "successfully collected payment methods", paymentMethods, nil) 86 | c.JSON(http.StatusOK, successRes) 87 | } 88 | 89 | func (payH *PaymentHandler) MakePaymentRazorPay(c *gin.Context) { 90 | orderId := c.Query("id") 91 | userId, err := strconv.Atoi(c.Query("user_id")) 92 | if err != nil { 93 | errRes := response.ClientResponse(http.StatusBadRequest, "check path paremeter(user id)", nil, err.Error()) 94 | c.JSON(http.StatusBadRequest, errRes) 95 | return 96 | } 97 | 98 | payDetails, err := payH.paymentUsecase.MakePaymentRazorPay(orderId, userId) 99 | if err != nil { 100 | errRes := response.ClientResponse(http.StatusBadRequest, "couldn't generate order details", nil, err.Error()) 101 | c.JSON(http.StatusBadRequest, errRes) 102 | return 103 | } 104 | 105 | c.HTML(http.StatusOK, "razorpay.html", payDetails) 106 | } 107 | 108 | func (payH *PaymentHandler) VerifyPayment(c *gin.Context) { 109 | paymentId := c.Query("payment_id") 110 | razorId := c.Query("razor_id") 111 | orderId := c.Query("order_id") 112 | 113 | if err := payH.paymentUsecase.VerifyPayment(paymentId, razorId, orderId); err != nil { 114 | errRes := response.ClientResponse(http.StatusBadRequest, "couldn't update payment details", nil, err.Error()) 115 | c.JSON(http.StatusBadRequest, errRes) 116 | return 117 | } 118 | 119 | successRes := response.ClientResponse(http.StatusOK, "successfully updated payment details", nil, nil) 120 | c.JSON(http.StatusOK, successRes) 121 | } 122 | -------------------------------------------------------------------------------- /pkg/api/handlers/wishlist.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | "strconv" 6 | 7 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/response" 9 | "github.com/gin-gonic/gin" 10 | ) 11 | 12 | type WishlistHandler struct { 13 | wishlistUsecase services.WishlistUsecase 14 | } 15 | 16 | // Constructor function 17 | func NewWishlistHandler(wishlistUsecase services.WishlistUsecase) *WishlistHandler { 18 | return &WishlistHandler{ 19 | wishlistUsecase: wishlistUsecase, 20 | } 21 | } 22 | 23 | // @Summary Add To Wishlist 24 | // @Description Add products to Wishlsit for the purchase 25 | // @Tags User 26 | // @Accept json 27 | // @Produce json 28 | // @Param id query string true "id" 29 | // @Param inventory query string true "inventory ID" 30 | // @Security Bearer 31 | // @Success 200 {object} response.Response{} 32 | // @Failure 500 {object} response.Response{} 33 | // @Router /users/home/add-to-wishlist [post] 34 | func (wiH *WishlistHandler) AddtoWishlist(c *gin.Context) { 35 | userId, err := strconv.Atoi(c.Query("id")) 36 | if err != nil { 37 | errRes := response.ClientResponse(http.StatusBadRequest, "check path parameter", nil, err.Error()) 38 | c.JSON(http.StatusBadRequest, errRes) 39 | return 40 | } 41 | inventoryId, err := strconv.Atoi(c.Query("inventory")) 42 | if err != nil { 43 | errRes := response.ClientResponse(http.StatusBadRequest, "check parameters properly", nil, err.Error()) 44 | c.JSON(http.StatusBadRequest, errRes) 45 | return 46 | } 47 | if err := wiH.wishlistUsecase.AddToWishlist(userId, inventoryId); err != nil { 48 | errRes := response.ClientResponse(http.StatusBadRequest, "Could not add the wishlsit", nil, err.Error()) 49 | c.JSON(http.StatusBadRequest, errRes) 50 | return 51 | } 52 | 53 | successRes := response.ClientResponse(http.StatusOK, "added to wishlit", nil, nil) 54 | c.JSON(http.StatusOK, successRes) 55 | } 56 | 57 | // @Summary Remove from Wishlist 58 | // @Description user can remove products from their wishlist 59 | // @Tags User 60 | // @Produce json 61 | // @Param id query string true "id" 62 | // @Param inventory query string true "inventory id" 63 | // @Security Bearer 64 | // @Success 200 {object} response.Response{} 65 | // @Failure 500 {object} response.Response{} 66 | // @Router /users/wishlist/remove [delete] 67 | func (wiH *WishlistHandler) RemoveFromWishlist(c *gin.Context) { 68 | id, err := strconv.Atoi(c.Query("id")) 69 | if err != nil { 70 | errRes := response.ClientResponse(http.StatusBadRequest, "check path parameter", nil, err.Error()) 71 | c.JSON(http.StatusBadRequest, errRes) 72 | return 73 | } 74 | wishlistId, err := wiH.wishlistUsecase.GetWishlistID(id) 75 | if err != nil { 76 | errRes := response.ClientResponse(http.StatusBadRequest, "check parameters correctly", nil, err.Error()) 77 | c.JSON(http.StatusBadRequest, errRes) 78 | return 79 | } 80 | inv, err := strconv.Atoi(c.Query("inventory")) 81 | if err != nil { 82 | errRes := response.ClientResponse(http.StatusBadRequest, "check parameters correctly", nil, err.Error()) 83 | c.JSON(http.StatusBadRequest, errRes) 84 | return 85 | } 86 | if err := wiH.wishlistUsecase.RemoveFromWishlist(wishlistId, inv); err != nil { 87 | errRes := response.ClientResponse(http.StatusBadRequest, "remove from wishlist failed", nil, err.Error()) 88 | c.JSON(http.StatusBadRequest, errRes) 89 | return 90 | } 91 | 92 | successRes := response.ClientResponse(http.StatusOK, "removed from wishlist", nil, nil) 93 | c.JSON(http.StatusOK, successRes) 94 | } 95 | 96 | // @Summary Get Wishlist 97 | // @Description user can view their wishlist details 98 | // @Tags User 99 | // @Produce json 100 | // @Param id query string true "id" 101 | // @Security Bearer 102 | // @Success 200 {object} response.Response{} 103 | // @Failure 500 {object} response.Response{} 104 | // @Router /users/wishlist [get] 105 | func (wiH *WishlistHandler) GetWishlist(c *gin.Context) { 106 | id, err := strconv.Atoi(c.Query("id")) 107 | if err != nil { 108 | errRes := response.ClientResponse(http.StatusBadRequest, "check path parameter( user id)", nil, err.Error()) 109 | c.JSON(http.StatusBadRequest, errRes) 110 | return 111 | } 112 | products, err := wiH.wishlistUsecase.GetWishlist(id) 113 | if err != nil { 114 | errRes := response.ClientResponse(http.StatusBadRequest, "couldn't get products in wishlist", nil, err.Error()) 115 | c.JSON(http.StatusBadRequest, errRes) 116 | return 117 | } 118 | 119 | successRes := response.ClientResponse(http.StatusOK, "successfully retrieved products from wishlist", products, nil) 120 | c.JSON(http.StatusOK, successRes) 121 | } 122 | -------------------------------------------------------------------------------- /pkg/api/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/golang-jwt/jwt" 8 | 9 | "github.com/gin-gonic/gin" 10 | ) 11 | 12 | // middleware for admin authentication 13 | 14 | func AdminAuthMiddleware(c *gin.Context) { 15 | token,err:=c.Cookie("Authorization") 16 | fmt.Println("first token: ",token) 17 | if err!=nil{ 18 | c.AbortWithStatus(401) 19 | return 20 | } 21 | 22 | 23 | // fmt.Println("token: ",token) 24 | token = strings.TrimPrefix(token, "Bearer ") 25 | 26 | // fmt.Println("in middleware: ", token) 27 | 28 | jwtToken, err := ValidateToken(token) 29 | fmt.Println("token after validation ",jwtToken) 30 | if err != nil { 31 | c.AbortWithStatus(401) 32 | return 33 | } 34 | if err != nil || !jwtToken.Valid { 35 | c.JSON(401, gin.H{"error": err}) 36 | c.Abort() 37 | return 38 | } 39 | 40 | claims, ok := jwtToken.Claims.(jwt.MapClaims) 41 | if !ok || !jwtToken.Valid { 42 | c.JSON(401, gin.H{"error": err}) 43 | c.Abort() 44 | return 45 | } 46 | 47 | role, ok := claims["role"].(string) 48 | if !ok || role != "admin" { 49 | c.JSON(401, gin.H{"error": err}) 50 | c.Abort() 51 | return 52 | } 53 | fmt.Println("admin auth is fine") 54 | c.Next() 55 | } 56 | 57 | func ValidateToken(token string) (*jwt.Token, error) { 58 | fmt.Println("token validating...") 59 | jwtToken, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) { 60 | fmt.Println("signature: ", t.Signature) 61 | if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { 62 | return nil, fmt.Errorf("unexpected signing method:%v", t.Header["alg"]) 63 | 64 | } 65 | 66 | return []byte("adminsecret"), nil 67 | }) 68 | return jwtToken, err 69 | } 70 | -------------------------------------------------------------------------------- /pkg/api/middleware/userAuth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "strings" 7 | 8 | "github.com/gin-gonic/gin" 9 | "github.com/golang-jwt/jwt" 10 | ) 11 | 12 | func UserAuthMiddleware(c *gin.Context) { 13 | tokenString,err:= c.Cookie("Authorization") 14 | if err!=nil{ 15 | return 16 | } 17 | 18 | if tokenString == "" { 19 | c.JSON(http.StatusUnauthorized, gin.H{"error": "missing authorization token"}) 20 | c.Abort() 21 | return 22 | } 23 | tokenString = strings.TrimPrefix(tokenString, "Bearer ") 24 | 25 | fmt.Println("user token ",tokenString) 26 | 27 | token, err := jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) { 28 | fmt.Println("in user auth parse token...") 29 | return []byte("usersecret"), nil 30 | }) 31 | fmt.Println("after user auth parse ",token) 32 | 33 | if err != nil || !token.Valid { 34 | c.JSON(http.StatusUnauthorized, gin.H{"error": err,}) 35 | c.Abort() 36 | return 37 | } 38 | claims, ok := token.Claims.(jwt.MapClaims) 39 | if !ok || !token.Valid { 40 | c.JSON(http.StatusForbidden, gin.H{"error": err}) 41 | c.Abort() 42 | return 43 | } 44 | 45 | fmt.Println("reached user auth...............") 46 | 47 | role, ok := claims["role"].(string) 48 | if !ok || role != "user" { 49 | c.JSON(http.StatusForbidden, gin.H{"error": "unauthorized access"}) 50 | c.Abort() 51 | return 52 | } 53 | 54 | id, ok := claims["id"].(float64) 55 | 56 | fmt.Println("user id",id) 57 | 58 | if !ok || id == 0 { 59 | c.JSON(http.StatusForbidden, gin.H{"error": err}) 60 | c.Abort() 61 | return 62 | } 63 | // userIdString := fmt.Sprintf("%v", id) 64 | 65 | c.Set("role", role) 66 | c.Set("id", int(id)) 67 | 68 | fmt.Println("user auth is fine") 69 | 70 | c.Next() 71 | } 72 | -------------------------------------------------------------------------------- /pkg/api/server.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | _ "github.com/Anandhu4456/go-Ecommerce/cmd/api/docs" 5 | handlers "github.com/Anandhu4456/go-Ecommerce/pkg/api/handlers" 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/routes" 7 | "github.com/gin-gonic/gin" 8 | swaggerfiles "github.com/swaggo/files" 9 | ginSwagger "github.com/swaggo/gin-swagger" 10 | ) 11 | 12 | // http server for the web application 13 | type ServerHTTP struct { 14 | engine *gin.Engine 15 | } 16 | 17 | func NewServerHttp(categoryHandler *handlers.CategoryHandler, 18 | inventoryHandler *handlers.InventoryHandler, 19 | userHandler *handlers.UserHandler, 20 | otpHandler *handlers.OtpHandler, 21 | adminHandler *handlers.AdminHandler, 22 | cartHandler *handlers.CartHandler, 23 | orderHandler *handlers.OrderHandler, 24 | paymentHandler *handlers.PaymentHandler, 25 | wishlistHandler *handlers.WishlistHandler, 26 | offerHandler *handlers.OfferHandler, 27 | couponHandler *handlers.CouponHandler) *ServerHTTP { 28 | engine := gin.New() 29 | engine.Use(gin.Logger()) 30 | engine.LoadHTMLFiles("pkg/templates/*.html") 31 | engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler)) 32 | 33 | routes.UserRoutes(engine.Group("/users"), userHandler, otpHandler, inventoryHandler, cartHandler, orderHandler, couponHandler, paymentHandler, wishlistHandler) 34 | routes.AdminRoutes(engine.Group("/admin"), adminHandler, categoryHandler, inventoryHandler, orderHandler, paymentHandler, offerHandler, couponHandler) 35 | routes.InventoryRoutes(engine.Group("/products"), inventoryHandler) 36 | 37 | return &ServerHTTP{ 38 | engine: engine, 39 | } 40 | } 41 | 42 | func (sh *ServerHTTP) Start() { 43 | sh.engine.Run(":8082") 44 | } 45 | -------------------------------------------------------------------------------- /pkg/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/joho/godotenv" 7 | "github.com/spf13/viper" 8 | ) 9 | 10 | type Config struct { 11 | DBHost string `mapstructure:"DB_HOST"` 12 | DBName string `mapstructure:"DB_NAME"` 13 | DBUser string `mapstructure:"DB_USER"` 14 | DBPassword string `mapstructure:"DB_PASSWORD"` 15 | DBPort string `mapstructure:"DB_PORT"` 16 | ACCOUNTSID string `mapstructure:"DB_ACCOUNTSID"` 17 | SERVICEID string `mapstructure:"DB_SERVICEID"` 18 | AUTHTOKEN string `mapstructure:"DB_AUTHTOKEN"` 19 | UNIDOCKEY string `mapstructure:"UNIDOC_LICENSE_API_KEY"` 20 | } 21 | 22 | var envs = []string{ 23 | "DB_HOST", "DB_NAME", "DB_USER", "DB_PASSWORD", "DB_PORT", "DB_ACCOUNTSID", "DB_SERVICEID", "DB_AUTHTOKEN", "DB_UNIDOC_LICENSE_API_KEY", 24 | } 25 | 26 | func LoadConfig() (Config, error) { 27 | var config Config 28 | 29 | viper.AddConfigPath("./") 30 | viper.SetConfigFile(".env") 31 | viper.ReadInConfig() 32 | viper.AutomaticEnv() 33 | 34 | for _, env := range envs { 35 | if err := viper.BindEnv(env); err != nil { 36 | return config, err 37 | } 38 | } 39 | err := godotenv.Load() 40 | if err != nil { 41 | log.Fatal("error while loading the env file..") 42 | } 43 | 44 | if err := viper.Unmarshal(&config); err != nil { 45 | return config, err 46 | } 47 | 48 | return config, nil 49 | } 50 | -------------------------------------------------------------------------------- /pkg/db/connection.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/config" 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 8 | "golang.org/x/crypto/bcrypt" 9 | "gorm.io/driver/postgres" 10 | "gorm.io/gorm" 11 | ) 12 | 13 | func ConnectDB(cfg config.Config) (*gorm.DB, error) { 14 | psqlInfo := fmt.Sprintf("host=%s user=%s password=%s port=%s dbname=%s", cfg.DBHost, cfg.DBUser, cfg.DBPassword, cfg.DBPort, cfg.DBName) 15 | 16 | db, dbErr := gorm.Open(postgres.Open(psqlInfo), &gorm.Config{ 17 | SkipDefaultTransaction: true, 18 | }) 19 | 20 | if err:=db.AutoMigrate(&domain.Inventory{});err!=nil{ 21 | return db,err 22 | } 23 | if err:=db.AutoMigrate(&domain.Category{});err!=nil{ 24 | return db,err 25 | } 26 | if err:=db.AutoMigrate(&domain.Admin{});err!=nil{ 27 | return db,err 28 | } 29 | if err:=db.AutoMigrate(&domain.User{});err!=nil{ 30 | return db,err 31 | } 32 | if err:=db.AutoMigrate(&domain.Cart{});err!=nil{ 33 | return db,err 34 | } 35 | if err:=db.AutoMigrate(&domain.Wishlist{});err!=nil{ 36 | return db,err 37 | } 38 | if err:=db.AutoMigrate(&domain.Address{});err!=nil{ 39 | return db,err 40 | } 41 | if err:=db.AutoMigrate(&domain.Order{});err!=nil{ 42 | return db,err 43 | } 44 | if err:=db.AutoMigrate(&domain.OrderItem{});err!=nil{ 45 | return db,err 46 | } 47 | if err:=db.AutoMigrate(&domain.LineItems{});err!=nil{ 48 | return db,err 49 | } 50 | if err:=db.AutoMigrate(&domain.PaymentMethod{});err!=nil{ 51 | return db,err 52 | } 53 | if err:=db.AutoMigrate(&domain.Offer{});err!=nil{ 54 | return db,err 55 | } 56 | if err:=db.AutoMigrate(&domain.Coupon{});err!=nil{ 57 | return db,err 58 | } 59 | if err:=db.AutoMigrate(&domain.Wallet{});err!=nil{ 60 | return db,err 61 | } 62 | 63 | 64 | if err:=CheckAndCreateAdmin(db);err!=nil{ 65 | return db,err 66 | } 67 | return db, dbErr 68 | } 69 | 70 | func CheckAndCreateAdmin(db *gorm.DB)error { 71 | var count int64 72 | db.Model(&domain.Admin{}).Count(&count) 73 | if count == 0 { 74 | password := "adminpass" 75 | hashedPass, err := bcrypt.GenerateFromPassword([]byte(password),10) 76 | if err != nil { 77 | fmt.Println("check and create admin error") 78 | return err 79 | } 80 | admin := domain.Admin{ 81 | ID: 1, 82 | Name: "admin", 83 | UserName: "yoursstore@gmail.com", 84 | Password: string(hashedPass), 85 | } 86 | db.Create(&admin) 87 | } 88 | return nil 89 | } 90 | -------------------------------------------------------------------------------- /pkg/di/wire.go: -------------------------------------------------------------------------------- 1 | //go:build wireinject 2 | // +build wireinject 3 | 4 | package di 5 | 6 | import ( 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/api" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/api/handlers" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/config" 10 | "github.com/Anandhu4456/go-Ecommerce/pkg/db" 11 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository" 12 | "github.com/Anandhu4456/go-Ecommerce/pkg/usecase" 13 | "github.com/google/wire" 14 | ) 15 | 16 | func InitializeAPI(cfg config.Config) (*api.ServerHTTP, error) { 17 | wire.Build(db.ConnectDB, 18 | repository.NewUserRepository, 19 | usecase.NewUserUsecase, 20 | handlers.NewUserHandler, 21 | 22 | repository.NewAdminRepository, 23 | usecase.NewAdminUsecase, 24 | handlers.NewAdminHandler, 25 | 26 | repository.NewCartRepository, 27 | usecase.NewCartUsecase, 28 | handlers.NewCartHandler, 29 | 30 | repository.NewCategoryRepository, 31 | usecase.NewCategoryUsecase, 32 | handlers.NewCategoryHandler, 33 | 34 | repository.NewInventoryRepository, 35 | usecase.NewInventoryUsecase, 36 | handlers.NewInventoryHandler, 37 | 38 | repository.NewOfferRepository, 39 | usecase.NewOfferUsecase, 40 | handlers.NewOfferHandler, 41 | 42 | repository.NewOtpRepository, 43 | usecase.NewOtpUsecase, 44 | handlers.NewOtpHandler, 45 | 46 | repository.NewCouponRepository, 47 | usecase.NewCouponUsecase, 48 | handlers.NewCouponHandler, 49 | 50 | repository.NewPaymentRepository, 51 | usecase.NewPaymentUsecase, 52 | handlers.NewPaymentHandler, 53 | 54 | repository.NewWishlistRepository, 55 | usecase.NewWishlistUsecase, 56 | handlers.NewWishlistHandler, 57 | 58 | repository.NewOrderRepository, 59 | usecase.NewOrderUsecase, 60 | handlers.NewOrderHandler, 61 | 62 | api.NewServerHttp) 63 | return &api.ServerHTTP{}, nil 64 | } 65 | -------------------------------------------------------------------------------- /pkg/di/wire_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by Wire. DO NOT EDIT. 2 | 3 | //go:generate go run github.com/google/wire/cmd/wire 4 | //go:build !wireinject 5 | // +build !wireinject 6 | 7 | package di 8 | 9 | import ( 10 | "github.com/Anandhu4456/go-Ecommerce/pkg/api" 11 | "github.com/Anandhu4456/go-Ecommerce/pkg/api/handlers" 12 | "github.com/Anandhu4456/go-Ecommerce/pkg/config" 13 | "github.com/Anandhu4456/go-Ecommerce/pkg/db" 14 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository" 15 | "github.com/Anandhu4456/go-Ecommerce/pkg/usecase" 16 | ) 17 | 18 | func InitializeAPI(cfg config.Config)(*api.ServerHTTP,error){ 19 | gormDB,err:=db.ConnectDB(cfg) 20 | if err!=nil{ 21 | return nil,err 22 | } 23 | 24 | offerRepository:=repository.NewOfferRepository(gormDB) 25 | offerUsecase:=usecase.NewOfferUsecase(offerRepository) 26 | offerHandler:=handlers.NewOfferHandler(offerUsecase) 27 | 28 | orderRepository:=repository.NewOrderRepository(gormDB) 29 | 30 | userRepository:=repository.NewUserRepository(gormDB) 31 | 32 | userUsecase:=usecase.NewUserUsecase(userRepository,offerRepository,orderRepository) 33 | 34 | couponRepository:=repository.NewCouponRepository(gormDB) 35 | 36 | orderUsecase:=usecase.NewOrderUsecase(orderRepository,userUsecase,couponRepository) 37 | orderHandler:=handlers.NewOrderHandler(orderUsecase) 38 | 39 | userHandler:=handlers.NewUserHandler(userUsecase) 40 | 41 | wishlistRepository:=repository.NewWishlistRepository(gormDB) 42 | wishlistUsecase:=usecase.NewWishlistUsecase(wishlistRepository) 43 | wishlistHandler:=handlers.NewWishlistHandler(wishlistUsecase) 44 | 45 | adminRepository :=repository.NewAdminRepository(gormDB) 46 | adminUsecase:=usecase.NewAdminUsecase(adminRepository) 47 | adminHandler:=handlers.NewAdminHandler(adminUsecase) 48 | 49 | 50 | 51 | 52 | 53 | inventoryRepository:=repository.NewInventoryRepository(gormDB) 54 | inventoryUsecase:=usecase.NewInventoryUsecase(inventoryRepository) 55 | inventoryHandler:=handlers.NewInventoryHandler(inventoryUsecase) 56 | 57 | categoryRepository:=repository.NewCategoryRepository(gormDB) 58 | categoryUsecase:=usecase.NewCategoryUsecase(categoryRepository) 59 | categoryHandler:=handlers.NewCategoryHandler(categoryUsecase) 60 | 61 | paymentRepo:=repository.NewPaymentRepository(gormDB) 62 | paymentUsecase:=usecase.NewPaymentUsecase(paymentRepo,userRepository) 63 | paymentHandler:=handlers.NewPaymentHandler(paymentUsecase) 64 | 65 | cartRepository:=repository.NewCartRepository(gormDB) 66 | cartUsecase:=usecase.NewCartUsecase(cartRepository,inventoryRepository,userUsecase,paymentUsecase) 67 | cartHandler:=handlers.NewCartHandler(cartUsecase) 68 | 69 | 70 | couponUsecase:=usecase.NewCouponUsecase(couponRepository) 71 | couponHandler:=handlers.NewCouponHandler(couponUsecase) 72 | 73 | 74 | otpRepository:=repository.NewOtpRepository(gormDB) 75 | otpUsecase:=usecase.NewOtpUsecase(cfg,otpRepository) 76 | otpHandler:=handlers.NewOtpHandler(otpUsecase) 77 | 78 | serverHTTP:=api.NewServerHttp(categoryHandler,inventoryHandler,userHandler,otpHandler,adminHandler,cartHandler,orderHandler,paymentHandler,wishlistHandler,offerHandler,couponHandler) 79 | 80 | return serverHTTP,nil 81 | } -------------------------------------------------------------------------------- /pkg/domain/admin.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 4 | 5 | type Admin struct { 6 | ID int `json:"id" gorm:"unique;not null"` 7 | Name string `json:"name" gorm:"validate:required"` 8 | UserName string `json:"email" gorm:"validate:required"` 9 | Password string `json:"password" gorm:"validate:required"` 10 | } 11 | type AdminToken struct { 12 | Admin models.AdminDetailsResponse 13 | Token string 14 | RefreshToken string 15 | } 16 | -------------------------------------------------------------------------------- /pkg/domain/cart.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | // cart of a user 4 | type Cart struct { 5 | ID uint `json:"id" gorm:"primarykey"` 6 | UserID uint `json:"user_id" gorm:"not null"` 7 | User User `json:"user" gorm:"foreignkey:UserID"` 8 | } 9 | 10 | // products in the cart of user 11 | type LineItems struct { 12 | ID uint `json:"id" gorm:"primarykey"` 13 | CartID uint `json:"cart_id" gorm:"not null"` 14 | Cart Cart `json:"-" gorm:"foreignkey:CartID"` 15 | InventoryID uint `json:"inventory_id" gorm:"not null"` 16 | Inventory Inventory `json:"-" gorm:"foreignkey:InventoryID"` 17 | Quantity int `json:"quantity" gorm:"default:1"` 18 | } 19 | -------------------------------------------------------------------------------- /pkg/domain/coupon.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import "gorm.io/gorm" 4 | 5 | type Coupon struct { 6 | gorm.Model 7 | Coupon string `json:"coupon" gorm:"unique"` 8 | DiscountRate int `json:"discount_rate" ` 9 | Valid bool `json:"valid" gorm:"default:true"` 10 | } 11 | -------------------------------------------------------------------------------- /pkg/domain/inventory.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | // products in the website 4 | type Inventory struct { 5 | ID uint `json:"id" gorm:"unique;not null"` 6 | CategoryID int `json:"category_id"` 7 | Category Category `json:"-" gorm:"foreignkey:CategoryID;constraint:OnDelete:CASCADE"` 8 | ProductName string `json:"product_name"` 9 | Description string `json:"description"` 10 | Image string `json:"image"` 11 | Stock int `json:"stock"` 12 | Price float64 `json:"price"` 13 | } 14 | 15 | // category of product 16 | type Category struct { 17 | ID int `json:"id" gorm:"unique;not null"` 18 | Category string `json:"category"` 19 | // Image Image `json:"category_image"` 20 | } 21 | 22 | type Image struct { 23 | ID int `json:"id" gorm:"primarykey;not null"` 24 | InventoryID int `json:"inventory_id"` 25 | Inventory Inventory `json:"-" gorm:"foreignkey:InventoryID"` 26 | ImageUrl string `json:"image_url"` 27 | } 28 | -------------------------------------------------------------------------------- /pkg/domain/offer.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | type Offer struct { 4 | ID int `json:"id" gorm:"primarykey;not null"` 5 | CategoryID int `json:"category_id"` 6 | Category Category `json:"-" gorm:"foreignkey:CategoryID;constraint:Ondelete:CASCADE"` 7 | DiscountRate int `json:"discount_rate"` 8 | Valid bool `gorm:"default:true"` 9 | } 10 | -------------------------------------------------------------------------------- /pkg/domain/orders.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "time" 5 | 6 | "gorm.io/gorm" 7 | ) 8 | 9 | // Order of user 10 | type Order struct { 11 | gorm.Model 12 | ID int `json:"id" gorm:"primarykey;autoIncrement"` 13 | UserID int `json:"user_id" gorm:"not null"` 14 | User User `json:"-" gorm:"foreignkey:UserID"` 15 | AddressID int `json:"address_id" gorm:"not null"` 16 | Address Address `json:"-" gorm:"foreignkey:AddressID"` 17 | PaymentMethodID int `json:"paymentmethod_id" gorm:"default:1"` 18 | PaymentMethod PaymentMethod `json:"-" gorm:"foreignkey:PaymentMethodID"` 19 | PaymentID string `json:"payment_id"` 20 | Price float64 `json:"price"` 21 | OrderedAt time.Time `json:"ordered_at"` 22 | OrderStatus string `json:"order_status" gorm:"order_status:4;default:'PENDING';check:order_status IN('PENDING','SHIPPED','DELIVERED','CANCELED','RETURNED')"` 23 | PaymentStatus string `json:"payment_status" gorm:"default:'PENDING'"` 24 | } 25 | 26 | // product details of the order 27 | 28 | type OrderItem struct { 29 | ID int `json:"id" gorm:"primarykey;autoIncrement"` 30 | OrderID int `json:"order_id"` 31 | Order Order `json:"-" gorm:"foreignkey:OrderID"` 32 | InventoryID int `json:"inventory_id"` 33 | Inventory Inventory `json:"-" gorm:"foreignkey:InventoryID"` 34 | Quantity int `json:"quantity"` 35 | TotalPrice float64 `json:"total_price"` 36 | } 37 | 38 | // Order details with order status 39 | 40 | type AdminOrderResponse struct { 41 | Pending []OrderDetails 42 | Shipped []OrderDetails 43 | Delivered []OrderDetails 44 | Returned []OrderDetails 45 | Canceled []OrderDetails 46 | } 47 | 48 | // Details of order 49 | 50 | type OrderDetails struct { 51 | ID int `json:"id" gorm:"column:order_id"` 52 | Username string `json:"username"` 53 | Address string `json:"address"` 54 | PaymentMethod string `json:"paymentmethod"` 55 | Total float64 `json:"total"` 56 | } 57 | 58 | type PaymentMethod struct { 59 | ID int `json:"id" gorm:"primarykey"` 60 | PaymenMethod string `json:"paymentmethod" validate:"required" gorm:"unique"` 61 | } 62 | 63 | type SalesReport struct { 64 | Orders []Order 65 | TotalRevenue float64 66 | TotalOrders int 67 | BestSellers []string 68 | } 69 | 70 | type ProductReport struct { 71 | InventoryID int 72 | Quantity int 73 | } 74 | -------------------------------------------------------------------------------- /pkg/domain/user.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | type User struct { 4 | ID int `json:"id" gorm:"primarykey"` 5 | Name string `json:"name"` 6 | Email string `json:"email" gorm:"unique"` 7 | Username string `json:"username"` 8 | Password string `json:"password"` 9 | Phone string `json:"phone" gorm:"unique"` 10 | Permission bool `json:"permission" gorm:"default:true"` 11 | } 12 | 13 | type Address struct { 14 | Id uint `json:"id" gorm:"unique;not null"` 15 | UserID uint `json:"user_id"` 16 | User User `json:"-" gorm:"foreignkey:UserID"` 17 | Name string `json:"name" validate:"required"` 18 | HouseName string `json:"house_name" validate:"required"` 19 | Street string `json:"street" validate:"required"` 20 | City string `json:"city" validate:"required"` 21 | State string `json:"state" validate:"required"` 22 | Pin string `json:"pin" validate:"required"` 23 | Default bool `json:"default" gorm:"default:false"` 24 | } 25 | -------------------------------------------------------------------------------- /pkg/domain/wallet.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | type Wallet struct { 4 | ID int `json:"id" gorm:"unique;not null"` 5 | UserID int `json:"user_id"` 6 | User User `json:"-" gorm:"foreignkey:UserID"` 7 | Amount float64 `json:"amount" gorm:"default:0"` 8 | } 9 | 10 | // type WalletHistory struct { 11 | // WalletID int `json:"wallet_id"` 12 | // Wallet Wallet `json:"-" gorm:"foreignkey:WalletID"` 13 | // Amount int `json:"amount"` 14 | // Purpose string `json:"purpose"` 15 | // Time time.Time `json:"time"` 16 | // } 17 | -------------------------------------------------------------------------------- /pkg/domain/wishlist.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | // Wishlist of a user 4 | 5 | type Wishlist struct { 6 | ID uint `json:"id" gorm:"primarykey"` 7 | UserID uint `json:"user_id" gorm:"not null"` 8 | User User `json:"-" gorm:"foreignkey:UserID"` 9 | InventoryID uint `json:"inventory_id" gorm:"not null"` 10 | Inventories Inventory `json:"-" gorm:"foreignkey:InventoryID"` 11 | IsDeleted bool `json:"is_deleted" gorm:"default:false"` 12 | } 13 | -------------------------------------------------------------------------------- /pkg/helper/helper.go: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | "mime/multipart" 8 | "time" 9 | 10 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 11 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 12 | "github.com/aws/aws-sdk-go-v2/aws" 13 | "github.com/aws/aws-sdk-go-v2/config" 14 | "github.com/aws/aws-sdk-go-v2/feature/s3/manager" 15 | "github.com/aws/aws-sdk-go-v2/service/s3" 16 | "github.com/golang-jwt/jwt" 17 | "github.com/jinzhu/copier" 18 | "github.com/twilio/twilio-go" 19 | twilioApi "github.com/twilio/twilio-go/rest/verify/v2" 20 | "golang.org/x/crypto/bcrypt" 21 | ) 22 | 23 | 24 | type AuthCustomClaims struct { 25 | Id int `json:"id"` 26 | // Name string `json:"name"` 27 | Email string `json:"email"` 28 | Role string `json:"role"` 29 | jwt.StandardClaims 30 | } 31 | 32 | func GenerateAdminToken(admin models.AdminDetailsResponse) (string, string, error) { 33 | tokenClaimes := &AuthCustomClaims{ 34 | Id: admin.ID, 35 | Email: admin.Email, 36 | // Name: admin.Name, 37 | Role: "admin", 38 | StandardClaims: jwt.StandardClaims{ 39 | ExpiresAt: time.Now().Add(time.Hour * 24 * 30).Unix(), 40 | IssuedAt: time.Now().Unix(), 41 | }, 42 | } 43 | refreshTokenClaims := &AuthCustomClaims{ 44 | Id: admin.ID, 45 | // Name: admin.Name, 46 | Email: admin.Email, 47 | Role: "admin", 48 | StandardClaims: jwt.StandardClaims{ 49 | ExpiresAt: time.Now().Add(time.Hour * 24 * 30).Unix(), 50 | IssuedAt: time.Now().Unix(), 51 | }, 52 | } 53 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, tokenClaimes) 54 | tokenString, err := token.SignedString([]byte("adminsecret")) 55 | 56 | // fmt.Println("in admin helper",tokenString) 57 | if err != nil { 58 | return "", "", err 59 | } 60 | 61 | refreshToken := jwt.NewWithClaims(jwt.SigningMethodHS256, refreshTokenClaims) 62 | refreshTokenString, err := refreshToken.SignedString([]byte("adminrefresh")) 63 | if err != nil { 64 | return "", "", err 65 | } 66 | return tokenString, refreshTokenString, nil 67 | } 68 | 69 | func GenerateUserToken(user models.UserDetailsResponse) (string, error) { 70 | claims := &AuthCustomClaims{ 71 | Id: user.Id, 72 | Email: user.Email, 73 | Role: "user", 74 | StandardClaims: jwt.StandardClaims{ 75 | ExpiresAt: time.Now().Add(time.Hour * 48).Unix(), 76 | IssuedAt: time.Now().Unix(), 77 | }, 78 | } 79 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 80 | tokenString, err := token.SignedString([]byte("usersecret")) 81 | if err != nil { 82 | return "", err 83 | } 84 | return tokenString, nil 85 | } 86 | 87 | func PasswordHashing(password string) (string, error) { 88 | hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), 10) 89 | if err != nil { 90 | return "", errors.New("internal server error") 91 | } 92 | hash := string(hashedPassword) 93 | return hash, nil 94 | } 95 | 96 | // This function will setup the twilio 97 | var client *twilio.RestClient 98 | 99 | func TwilioSetup(username string, password string) { 100 | client = twilio.NewRestClientWithParams(twilio.ClientParams{ 101 | Username: username, 102 | Password: password, 103 | }) 104 | } 105 | 106 | func TwilioSendOTP(phone string, serviceId string) (string, error) { 107 | to := "+91" + phone 108 | params := &twilioApi.CreateVerificationParams{} 109 | params.SetTo(to) 110 | params.SetChannel("sms") 111 | resp, err := client.VerifyV2.CreateVerification(serviceId, params) 112 | 113 | if err != nil { 114 | return "", err 115 | } 116 | return *resp.Sid, nil 117 | } 118 | 119 | func TwilioVerifyOTP(serviceId string, code string, phone string) error { 120 | params := &twilioApi.CreateVerificationCheckParams{} 121 | params.SetTo("+91" + phone) 122 | params.SetCode(code) 123 | 124 | resp, err := client.VerifyV2.CreateVerificationCheck(serviceId, params) 125 | if err != nil { 126 | return err 127 | } 128 | if *resp.Status == "approved" { 129 | return nil 130 | } 131 | return errors.New("otp verification failed") 132 | } 133 | 134 | func FindMostBroughtProduct(products []domain.ProductReport) []int { 135 | productMap := make(map[int]int) 136 | 137 | for _, item := range products { 138 | productMap[item.InventoryID] += item.Quantity 139 | } 140 | maxQty := 0 141 | for _, item := range productMap { 142 | if item > maxQty { 143 | maxQty = item 144 | } 145 | } 146 | var bestSeller []int 147 | for k, item := range productMap { 148 | if item == maxQty { 149 | bestSeller = append(bestSeller, k) 150 | } 151 | } 152 | return bestSeller 153 | } 154 | 155 | func AddImageToS3(file *multipart.FileHeader) (string, error) { 156 | cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion("ap-south-1")) 157 | if err != nil { 158 | fmt.Println("configuration error: ", err) 159 | return "", err 160 | } 161 | client := s3.NewFromConfig(cfg) 162 | uploader := manager.NewUploader(client) 163 | f, openErr := file.Open() 164 | if openErr != nil { 165 | fmt.Println("file open error: ", openErr) 166 | return "", openErr 167 | } 168 | defer f.Close() 169 | 170 | result, uploadErr := uploader.Upload(context.TODO(), &s3.PutObjectInput{ 171 | Bucket: aws.String("samplebucket"), 172 | Key: aws.String(file.Filename), 173 | Body: f, 174 | ACL: "public-read", 175 | }) 176 | if uploadErr != nil { 177 | fmt.Println("upload error : ", uploadErr) 178 | return "", uploadErr 179 | } 180 | return result.Location, nil 181 | } 182 | 183 | func CompareHashAndPassword(a string, b string) error { 184 | err := bcrypt.CompareHashAndPassword([]byte(a), []byte(b)) 185 | if err != nil { 186 | return err 187 | } 188 | return nil 189 | } 190 | 191 | func Copy(a *models.UserDetailsResponse, b *models.UserSignInResponse) (models.UserDetailsResponse, error) { 192 | if err := copier.Copy(a, b); err != nil { 193 | return models.UserDetailsResponse{}, err 194 | } 195 | return *a, nil 196 | } 197 | -------------------------------------------------------------------------------- /pkg/helper/pdf/invoice.go: -------------------------------------------------------------------------------- 1 | package pdf 2 | 3 | type Invoice struct { 4 | Name string 5 | Address string 6 | InvoiceItem []*InvoiceData 7 | } 8 | 9 | func CreateInvoice(name string, address string, invoiceItem []*InvoiceData) *Invoice { 10 | return &Invoice{ 11 | Name: name, 12 | Address: address, 13 | InvoiceItem: invoiceItem, 14 | } 15 | } 16 | 17 | func (i *Invoice) CalculateInvoiceTotalAmount() float64 { 18 | var invoiceTotalAmount int = 0 19 | for _, data := range i.InvoiceItem { 20 | amount := data.CalculateTotalAmount() 21 | invoiceTotalAmount += amount 22 | } 23 | totalAmount := float64(invoiceTotalAmount) / 100 24 | return totalAmount 25 | } 26 | -------------------------------------------------------------------------------- /pkg/helper/pdf/invoiceData.go: -------------------------------------------------------------------------------- 1 | package pdf 2 | 3 | import "errors" 4 | 5 | type InvoiceData struct { 6 | Title string 7 | Quantity int 8 | Price int 9 | TotalAmount int 10 | } 11 | 12 | func (d *InvoiceData) CalculateTotalAmount() int { 13 | totalAmount := d.Quantity * d.Price 14 | return totalAmount 15 | } 16 | 17 | func (d *InvoiceData) ReturnItemTotalAmount() float64 { 18 | totalAmount := d.CalculateTotalAmount() 19 | converted := float64(totalAmount) / 100 20 | return converted 21 | } 22 | 23 | func (d *InvoiceData) ReturnItemPrice() float64 { 24 | returnPrice := float64(d.Price) / 100 25 | return returnPrice 26 | } 27 | 28 | func NewInvoiceData(title string, qty int, price interface{}) (*InvoiceData, error) { 29 | var convertedPrice int 30 | 31 | switch priceValue := price.(type) { 32 | case int: 33 | convertedPrice = priceValue * 100 34 | case float32: 35 | convertedPrice = int(priceValue) * 100 36 | case float64: 37 | convertedPrice = int(priceValue) * 100 38 | default: 39 | return nil, errors.New("type not permitted") 40 | } 41 | return &InvoiceData{ 42 | Title: title, 43 | Quantity: qty, 44 | Price: convertedPrice, 45 | }, nil 46 | } 47 | -------------------------------------------------------------------------------- /pkg/helper/pdf/invoicePdf.go: -------------------------------------------------------------------------------- 1 | package pdf 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/spf13/viper" 8 | "github.com/unidoc/unipdf/v3/common/license" 9 | "github.com/unidoc/unipdf/v3/creator" 10 | ) 11 | 12 | type Client struct { 13 | creator *creator.Creator 14 | } 15 | 16 | type cellStyle struct { 17 | ColSpan int 18 | HAlignment creator.CellHorizontalAlignment 19 | BackgroundColor creator.Color 20 | BorderSide creator.CellBorderSide 21 | BorderStyle creator.CellBorderStyle 22 | BorderWidth float64 23 | BorderColor creator.Color 24 | Indent float64 25 | } 26 | 27 | var cellStyles = map[string]cellStyle{ 28 | "heading-left": { 29 | BackgroundColor: creator.ColorRGBFromHex("#332f3f"), 30 | HAlignment: creator.CellHorizontalAlignmentLeft, 31 | BorderColor: creator.ColorWhite, 32 | BorderSide: creator.CellBorderSideAll, 33 | BorderStyle: creator.CellBorderStyleSingle, 34 | BorderWidth: 6, 35 | }, 36 | "heading-centered": { 37 | BackgroundColor: creator.ColorRGBFromHex("#332f3f"), 38 | HAlignment: creator.CellHorizontalAlignmentCenter, 39 | BorderColor: creator.ColorWhite, 40 | BorderSide: creator.CellBorderSideAll, 41 | BorderStyle: creator.CellBorderStyleSingle, 42 | BorderWidth: 6, 43 | }, 44 | "left-highlighted": { 45 | BackgroundColor: creator.ColorRGBFromHex("#dde4e5"), 46 | HAlignment: creator.CellHorizontalAlignmentLeft, 47 | BorderColor: creator.ColorWhite, 48 | BorderSide: creator.CellBorderSideAll, 49 | BorderStyle: creator.CellBorderStyleSingle, 50 | BorderWidth: 6, 51 | }, 52 | "centered-highlighted": { 53 | BackgroundColor: creator.ColorRGBFromHex("#dde4e5"), 54 | HAlignment: creator.CellHorizontalAlignmentCenter, 55 | BorderColor: creator.ColorWhite, 56 | BorderSide: creator.CellBorderSideAll, 57 | BorderStyle: creator.CellBorderStyleSingle, 58 | BorderWidth: 6, 59 | }, 60 | "left": { 61 | HAlignment: creator.CellHorizontalAlignmentLeft, 62 | }, 63 | "centered": { 64 | HAlignment: creator.CellHorizontalAlignmentCenter, 65 | }, 66 | "gradingsys-head": { 67 | HAlignment: creator.CellHorizontalAlignmentLeft, 68 | }, 69 | "gradingsys-row": { 70 | HAlignment: creator.CellHorizontalAlignmentCenter, 71 | }, 72 | "conduct-head": { 73 | HAlignment: creator.CellHorizontalAlignmentLeft, 74 | }, 75 | "conduct-key": { 76 | HAlignment: creator.CellHorizontalAlignmentLeft, 77 | }, 78 | "conduct-val": { 79 | BackgroundColor: creator.ColorRGBFromHex("#dde4e5"), 80 | HAlignment: creator.CellHorizontalAlignmentCenter, 81 | BorderColor: creator.ColorWhite, 82 | BorderSide: creator.CellBorderSideAll, 83 | BorderStyle: creator.CellBorderStyleSingle, 84 | BorderWidth: 3, 85 | }, 86 | } 87 | 88 | func GenerateInvoicePdf(invoice Invoice) error { 89 | conf := viper.GetString("UNIDOC_LICENSE_API_KEY") 90 | 91 | err := license.SetMeteredKey(conf) 92 | if err != nil { 93 | return err 94 | } 95 | c := creator.New() 96 | c.SetPageMargins(40, 40, 0, 0) 97 | cr := &Client{creator: c} 98 | err = cr.generatePdf(invoice) 99 | if err != nil { 100 | return err 101 | } 102 | return nil 103 | } 104 | 105 | func (c Client) generatePdf(invoice Invoice) error { 106 | rect := c.creator.NewRectangle(0, 0, creator.PageSizeLetter[0], 120) 107 | rect.SetFillColor(creator.ColorRGBFromHex("#dde4e5")) 108 | rect.SetBorderWidth(0) 109 | err := c.creator.Draw(rect) 110 | if err != nil { 111 | return err 112 | } 113 | 114 | headerStyle := c.creator.NewTextStyle() 115 | headerStyle.FontSize = 50 116 | 117 | table := c.creator.NewTable(1) 118 | table.SetMargins(0, 0, 20, 0) 119 | err = drawCell(table, c.newPara("Order Invoice", headerStyle), cellStyles["centered"]) 120 | if err != nil { 121 | return err 122 | } 123 | err = c.creator.Draw(table) 124 | if err != nil { 125 | return err 126 | } 127 | 128 | err = c.writeInvoice(invoice) 129 | if err != nil { 130 | return err 131 | } 132 | 133 | err = c.creator.WriteToFile(strings.ToLower(invoice.Name) + "_invoice.pdf") 134 | if err != nil { 135 | return err 136 | } 137 | return nil 138 | } 139 | func (c *Client) newPara(text string, textStyle creator.TextStyle) *creator.StyledParagraph { 140 | p := c.creator.NewStyledParagraph() 141 | p.Append(text).Style = textStyle 142 | p.SetEnableWrap(false) 143 | return p 144 | } 145 | func drawCell(table *creator.Table, content creator.VectorDrawable, cellStyle cellStyle) error { 146 | var cell *creator.TableCell 147 | if cellStyle.ColSpan > 1 { 148 | cell = table.MultiColCell(cellStyle.ColSpan) 149 | } else { 150 | cell = table.NewCell() 151 | } 152 | err := cell.SetContent(content) 153 | if err != nil { 154 | return err 155 | } 156 | cell.SetHorizontalAlignment(cellStyle.HAlignment) 157 | if cellStyle.BackgroundColor != nil { 158 | cell.SetBackgroundColor(cellStyle.BackgroundColor) 159 | } 160 | cell.SetBorder(cellStyle.BorderSide, cellStyle.BorderStyle, cellStyle.BorderWidth) 161 | if cellStyle.BorderColor != nil { 162 | cell.SetBorderColor(cellStyle.BorderColor) 163 | } 164 | if cellStyle.Indent > 0 { 165 | cell.SetIndent(cellStyle.Indent) 166 | } 167 | return nil 168 | } 169 | func (c *Client) writeInvoice(invoice Invoice) error { 170 | headerStyle := c.creator.NewTextStyle() 171 | // Invoice Header info table. 172 | table := c.creator.NewTable(2) 173 | table.SetMargins(0, 0, 50, 0) 174 | err := drawCell(table, c.newPara("Business: "+invoice.Name, headerStyle), cellStyles["left"]) 175 | if err != nil { 176 | return err 177 | } 178 | err = drawCell(table, c.newPara("Address: "+invoice.Address, headerStyle), cellStyles["left"]) 179 | if err != nil { 180 | return err 181 | } 182 | err = c.creator.Draw(table) 183 | if err != nil { 184 | return err 185 | } 186 | 187 | // Invoice items table. 188 | table = c.creator.NewTable(4) 189 | table.SetMargins(0, 0, 20, 0) 190 | err = table.SetColumnWidths(0.4, 0.2, 0.2, 0.2) 191 | if err != nil { 192 | return err 193 | } 194 | headingStyle := c.creator.NewTextStyle() 195 | headingStyle.FontSize = 20 196 | headingStyle.Color = creator.ColorRGBFromHex("#fdfdfd") 197 | regularStyle := c.creator.NewTextStyle() 198 | 199 | // Draw table header. 200 | err = drawCell(table, c.newPara(" Title", headingStyle), cellStyles["heading-left"]) 201 | if err != nil { 202 | return err 203 | } 204 | err = drawCell(table, c.newPara("Quantity", headingStyle), cellStyles["heading-centered"]) 205 | if err != nil { 206 | return err 207 | } 208 | err = drawCell(table, c.newPara("Price", headingStyle), cellStyles["heading-centered"]) 209 | if err != nil { 210 | return err 211 | } 212 | err = drawCell(table, c.newPara("Total", headingStyle), cellStyles["heading-centered"]) 213 | if err != nil { 214 | return err 215 | } 216 | for _, datum := range invoice.InvoiceItem { 217 | err = drawCell(table, c.newPara(" "+datum.Title, regularStyle), cellStyles["left-highlighted"]) 218 | if err != nil { 219 | return err 220 | } 221 | err = drawCell(table, c.newPara(fmt.Sprintf("%v", datum.Quantity), regularStyle), cellStyles["centered-highlighted"]) 222 | if err != nil { 223 | return err 224 | } 225 | err = drawCell(table, c.newPara(fmt.Sprintf("%v", datum.Price), regularStyle), cellStyles["centered-highlighted"]) 226 | if err != nil { 227 | return err 228 | } 229 | err = drawCell(table, c.newPara(fmt.Sprintf("%v", datum.CalculateTotalAmount()), regularStyle), cellStyles["centered-highlighted"]) 230 | if err != nil { 231 | return err 232 | } 233 | } 234 | err = c.creator.Draw(table) 235 | if err != nil { 236 | return err 237 | } 238 | 239 | boldStyle := c.creator.NewTextStyle() 240 | boldStyle.FontSize = 16 241 | grid := c.creator.NewTable(12) 242 | grid.SetMargins(0, 0, 50, 0) 243 | gradeInfoStyle := c.creator.NewTextStyle() 244 | 245 | table = c.creator.NewTable(2) 246 | err = table.SetColumnWidths(0.6, 0.4) 247 | if err != nil { 248 | return err 249 | } 250 | err = drawCell(table, c.newPara("Total Amount:", gradeInfoStyle), cellStyles["conduct-key"]) 251 | if err != nil { 252 | return err 253 | } 254 | err = drawCell(table, c.newPara(fmt.Sprintf("%v", invoice.CalculateInvoiceTotalAmount()), gradeInfoStyle), cellStyles["conduct-val"]) 255 | if err != nil { 256 | return err 257 | } 258 | err = grid.MultiColCell(5).SetContent(table) 259 | if err != nil { 260 | return err 261 | } 262 | err = c.creator.Draw(grid) 263 | if err != nil { 264 | return err 265 | } 266 | return nil 267 | } 268 | -------------------------------------------------------------------------------- /pkg/repository/admin.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 10 | "gorm.io/gorm" 11 | ) 12 | 13 | type adminRepository struct { 14 | DB *gorm.DB 15 | } 16 | 17 | func NewAdminRepository(DB *gorm.DB)interfaces.AdminRepository{ 18 | return &adminRepository{ 19 | DB:DB, 20 | } 21 | } 22 | 23 | func (ar *adminRepository) LoginHandler(adminDetails models.AdminLogin) (domain.Admin, error) { 24 | var adminCompareDetail domain.Admin 25 | err := ar.DB.Raw("select * from admins where user_name = ?", adminDetails.Email).Scan(&adminCompareDetail).Error 26 | if err != nil { 27 | return domain.Admin{}, err 28 | } 29 | fmt.Println("admincompare details from repo",adminCompareDetail) 30 | return adminCompareDetail, nil 31 | } 32 | 33 | func (ar *adminRepository)GetUserById(id string)(domain.User,error){ 34 | userId,err:=strconv.Atoi(id) 35 | if err!=nil{ 36 | return domain.User{},err 37 | } 38 | query:=fmt.Sprintf("select * from users where id = '%d'",userId) 39 | var userDetails domain.User 40 | err =ar.DB.Raw(query).Scan(&userDetails).Error 41 | if err!=nil{ 42 | return domain.User{},err 43 | } 44 | return userDetails,nil 45 | } 46 | 47 | // This function will both block and unblock user 48 | func (ar *adminRepository)UpdateBlockUserById(user domain.User)error{ 49 | err:=ar.DB.Exec("update users set permission = ? where id = ?",user.Permission,user.ID).Error 50 | if err!=nil{ 51 | return err 52 | } 53 | return nil 54 | } 55 | 56 | func (ar *adminRepository)GetUsers(page,limit int)([]models.UserDetailsAtAdmin,error){ 57 | if page== 0{ 58 | page = 1 59 | } 60 | if limit==0{ 61 | limit =10 62 | } 63 | offset:=(page-1)*limit 64 | var userDetails []models.UserDetailsAtAdmin 65 | err:=ar.DB.Raw("select id,name,email,phone,permission from users limit ? offset ?",limit,offset).Scan(&userDetails).Error 66 | if err!=nil{ 67 | return []models.UserDetailsAtAdmin{},err 68 | } 69 | return userDetails,nil 70 | } -------------------------------------------------------------------------------- /pkg/repository/cart.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | // "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | // "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 7 | "gorm.io/gorm" 8 | ) 9 | 10 | type cartRepository struct{ 11 | DB *gorm.DB 12 | } 13 | 14 | // constructor function 15 | func NewCartRepository (DB *gorm.DB)*cartRepository{ 16 | return &cartRepository{ 17 | DB:DB, 18 | } 19 | } 20 | 21 | func (cr *cartRepository)GetAddresses(id int)([]models.Address,error){ 22 | var addresses []models.Address 23 | err:=cr.DB.Raw("select * from addresses where id = ?",id).Scan(&addresses).Error 24 | if err!=nil{ 25 | return []models.Address{},err 26 | } 27 | return addresses,nil 28 | } 29 | 30 | func (cr *cartRepository)GetCartId(user_id int)(int,error){ 31 | var userId int 32 | err:=cr.DB.Raw("select id from carts where user_id = ?",user_id).Scan(&userId).Error 33 | if err!=nil{ 34 | return 0,err 35 | } 36 | return userId,nil 37 | } 38 | 39 | func (cr *cartRepository)CreateNewCart(user_id int)(int,error){ 40 | var id int 41 | err:=cr.DB.Exec(`INSERT INTO carts (user_id) VALUES (?)`,user_id).Error 42 | if err!=nil{ 43 | return 0,err 44 | } 45 | err = cr.DB.Raw("select id from carts where user_id ",user_id).Scan(&id).Error 46 | if err!=nil{ 47 | return 0,err 48 | } 49 | return id,nil 50 | } 51 | func (cr *cartRepository)AddLineItems(inventory_id ,cart_id int)error{ 52 | err:=cr.DB.Exec(`INSERT INTO line_items (inventory_id,cart_id) VALUES(?,?)`,inventory_id,cart_id).Error 53 | if err!=nil{ 54 | return err 55 | } 56 | return nil 57 | } 58 | 59 | func (cr *cartRepository)CheckIfInvAdded(invId,cartId int)bool{ 60 | var count int=0 61 | err:=cr.DB.Raw("select count(id) from line_items where cart_id=? and inventory_id = ?",cartId,invId).Scan(&count).Error 62 | if err!=nil{ 63 | return false 64 | } 65 | if count <1 { 66 | return false 67 | } 68 | return true 69 | } 70 | 71 | func (cr *cartRepository)AddQuantity(invId,cartId int)error{ 72 | err:=cr.DB.Raw("update line_items set quantity=quantity+1 where cart_id = ? and inventory_id = ? ",cartId,invId).Error 73 | if err!=nil{ 74 | return err 75 | } 76 | return nil 77 | } -------------------------------------------------------------------------------- /pkg/repository/category.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strconv" 7 | 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 10 | "gorm.io/gorm" 11 | ) 12 | 13 | type categoryRepository struct { 14 | DB *gorm.DB 15 | } 16 | 17 | func NewCategoryRepository(db *gorm.DB) interfaces.CategoryRepository { 18 | return &categoryRepository{ 19 | DB: db, 20 | } 21 | } 22 | 23 | func (cat *categoryRepository) AddCategory(category string) (domain.Category, error) { 24 | var b string 25 | err := cat.DB.Raw("INSERT INTO categories (category) VALUES(?)RETURNING category", category).Scan(&b).Error 26 | fmt.Println("cat b from repo",b) 27 | if err != nil { 28 | fmt.Println("error from cat repo ",err) 29 | return domain.Category{}, err 30 | } 31 | var categoryResponse domain.Category 32 | err = cat.DB.Raw(` 33 | SELECT 34 | 35 | cat.id, 36 | cat.category 37 | 38 | FROM 39 | categories cat 40 | WHERE 41 | cat.category = ? 42 | `, b).Scan(&categoryResponse).Error 43 | if err != nil { 44 | return domain.Category{}, err 45 | } 46 | 47 | return categoryResponse, nil 48 | } 49 | 50 | func (cat *categoryRepository) CheckCategory(current string) (bool, error) { 51 | var response int 52 | err := cat.DB.Raw("SELECT COUNT (*) FROM categories WHERE category= ?", current).Scan(&response).Error 53 | if err != nil { 54 | return false, err 55 | } 56 | if response == 0 { 57 | return false, err 58 | } 59 | return true, nil 60 | } 61 | 62 | func (cat *categoryRepository) UpdateCategory(current, new string) (domain.Category, error) { 63 | 64 | // check database connection 65 | 66 | if cat.DB == nil { 67 | return domain.Category{}, errors.New("database connection failed while update category") 68 | } 69 | 70 | // update category 71 | err := cat.DB.Exec("UPDATE categories SET category=? WHERE category=?", new, current).Error 72 | if err != nil { 73 | return domain.Category{}, err 74 | } 75 | // Retrieve updated category 76 | var updatedCat domain.Category 77 | err = cat.DB.First(&updatedCat, "category=?", new).Error 78 | if err != nil { 79 | return domain.Category{}, err 80 | } 81 | return updatedCat, nil 82 | } 83 | 84 | func (cat *categoryRepository) DeleteCategory(categoryId string) error { 85 | id, err := strconv.Atoi(categoryId) 86 | if err != nil { 87 | return errors.New("string to int conversion failed") 88 | } 89 | deleteRes := cat.DB.Exec("DELETE FROM categories WHERE id=?", id) 90 | if deleteRes.RowsAffected < 1 { 91 | return errors.New("no record exists with this id") 92 | } 93 | return nil 94 | } 95 | 96 | func (cat *categoryRepository) GetCategories() ([]domain.Category, error) { 97 | // if page == 0 { 98 | // page = 1 99 | // } 100 | // if limit == 0 { 101 | // limit = 10 102 | // } 103 | // offset:=(page-1)*limit 104 | var categories []domain.Category 105 | err:=cat.DB.Raw("SELECT * FROM categories").Scan(&categories).Error 106 | if err!=nil{ 107 | return []domain.Category{},err 108 | } 109 | return categories,nil 110 | } 111 | -------------------------------------------------------------------------------- /pkg/repository/coupon.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 8 | "gorm.io/gorm" 9 | ) 10 | 11 | type couponRepository struct { 12 | DB *gorm.DB 13 | } 14 | 15 | // constructor function 16 | func NewCouponRepository(DB *gorm.DB) *couponRepository { 17 | return &couponRepository{ 18 | DB: DB, 19 | } 20 | } 21 | 22 | func (couprep *couponRepository) AddCoupon(coupon models.Coupon) error { 23 | err := couprep.DB.Exec("INSERT INTO coupons(coupon,discount_rate,valid)VALUES ($1,$2,$3)",coupon.Coupon, coupon.DiscountRate, coupon.Valid).Error 24 | if err != nil { 25 | return err 26 | } 27 | return nil 28 | } 29 | 30 | func (couprep *couponRepository) MakeCouponInvalid(id int) error { 31 | err := couprep.DB.Exec("UPDATE coupons SET valid=false WHERE id=$1", id).Error 32 | if err != nil { 33 | return err 34 | } 35 | return nil 36 | } 37 | 38 | func (couprep *couponRepository) FindCouponDetails(couponId int) (domain.Coupon, error) { 39 | var coupon domain.Coupon 40 | 41 | err := couprep.DB.Raw("SELECT * FROM coupon WHERE id =? ", couponId).Scan(&coupon).Error 42 | if err != nil { 43 | return domain.Coupon{}, err 44 | } 45 | return coupon, nil 46 | } 47 | 48 | func (couprep *couponRepository) GetCoupons() ([]domain.Coupon, error) { 49 | var coupon []domain.Coupon 50 | err := couprep.DB.Raw("SELECT * FROM coupons").Scan(&coupon).Error 51 | if err != nil { 52 | return []domain.Coupon{}, err 53 | } 54 | return coupon, nil 55 | } 56 | 57 | func (couprep *couponRepository) ValidateCoupon(coupon string) (bool, error) { 58 | count := 0 59 | err := couprep.DB.Raw("SELECT COUNT(id)FROM coupons WHERE name=?", coupon).Scan(&count).Error 60 | if err != nil { 61 | return false, err 62 | } 63 | if count < 1 { 64 | return false, errors.New("not a valid coupon") 65 | } 66 | valid := true 67 | err = couprep.DB.Raw("SELECT valid FROM coupons WHERE name = ?", coupon).Scan(&valid).Error 68 | if err != nil { 69 | return false, err 70 | } 71 | return true, nil 72 | } 73 | -------------------------------------------------------------------------------- /pkg/repository/interfaces/admin.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type AdminRepository interface { 9 | LoginHandler(adminDetails models.AdminLogin) (domain.Admin, error) 10 | GetUserById(id string) (domain.User, error) 11 | UpdateBlockUserById(user domain.User) error 12 | GetUsers(page, limit int) ([]models.UserDetailsAtAdmin, error) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/repository/interfaces/cart.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | // "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type CartRepository interface { 9 | GetAddresses(id int) ([]models.Address, error) 10 | CheckIfInvAdded(invId, cartId int) bool 11 | GetCartId(user_id int) (int, error) 12 | CreateNewCart(user_id int) (int, error) 13 | AddLineItems(invId, cartId int) error 14 | AddQuantity(invId, cartId int) error 15 | } 16 | -------------------------------------------------------------------------------- /pkg/repository/interfaces/category.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 4 | 5 | type CategoryRepository interface{ 6 | AddCategory(category string)(domain.Category,error) 7 | CheckCategory(current string)(bool,error) 8 | UpdateCategory(current,new string)(domain.Category,error) 9 | DeleteCategory(categoryId string)error 10 | GetCategories()([]domain.Category,error) 11 | } -------------------------------------------------------------------------------- /pkg/repository/interfaces/coupon.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type CouponRepository interface{ 9 | AddCoupon(models.Coupon)error 10 | MakeCouponInvalid(id int)error 11 | FindCouponDetails(couponId int)(domain.Coupon,error) 12 | GetCoupons()([]domain.Coupon,error) 13 | ValidateCoupon(coupon string)(bool,error) 14 | } -------------------------------------------------------------------------------- /pkg/repository/interfaces/inventory.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 4 | 5 | type InventoryRespository interface{ 6 | AddInventory(inventory models.Inventory, url string)(models.InventoryResponse,error) 7 | UpdateInventory(pid int, invData models.UpdateInventory)(models.Inventory,error) 8 | DeleteInventory(id string)error 9 | CheckInventory(pid int)(bool,error) 10 | 11 | AddImage(product_id int,image_url string)(models.InventoryResponse,error) 12 | UpdateImage(invId int,url string)(models.Inventory,error) 13 | DeleteImage(product_id int,imageId int)error 14 | GetImagesFromInventoryId(product_id int,)([]models.ImagesInfo,error) 15 | 16 | ListProducts(page,limit int)([]models.InventoryList,error) 17 | ShowIndividualProducts(id string)(models.Inventory,error) 18 | SearchProducts(key string,page,limit int)([]models.InventoryList,error) 19 | GetCategoryProducts(categoryId,page,limit int)([]models.InventoryList,error) 20 | 21 | CheckStock(inventory_id int)(int,error) 22 | CheckPrice(inventory_id int)(float64,error) 23 | } -------------------------------------------------------------------------------- /pkg/repository/interfaces/offer.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type OfferRepository interface { 9 | AddNewOffer(models.CreateOffer) error 10 | MakeOfferExpired(categorytId int) error 11 | FindDiscountPercentage(categorytId int) (int, error) 12 | GetOffers(page, limit int) ([]domain.Offer, error) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/repository/interfaces/order.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | "time" 7 | ) 8 | 9 | type OrderRepository interface{ 10 | GetOrders(id,page,limit int)([]domain.Order,error) 11 | GetProductsQuantity()([]domain.ProductReport,error) 12 | GetOrdersInRange(startDate,endDate time.Time)([]domain.Order,error) 13 | GetProductNameFromId(id int)(string,error) 14 | GetCart(userid int)(models.GetCart,error) 15 | 16 | OrderItems(userid int,addressid int,paymentid int,total float64,coupon string) (int,error) 17 | AddOrderProducts(order_id int, cart []models.GetCart) error 18 | CancelOrder(orderid int) error 19 | EditOrderStatus(status string, id int) error 20 | MarkAsPaid(orderID int) error 21 | AdminOrders(status string) ([]domain.OrderDetails, error) 22 | 23 | CheckOrder(orderID string, userID int) error 24 | GetOrderDetail(orderID string) (domain.Order, error) 25 | FindUserIdFromOrderID(orderID int) (int, error) 26 | FindWalletIdFromUserID(userId int) (int, error) 27 | CreateNewWallet(userID int) (int, error) 28 | CreditToUserWallet(amount float64, walletID int) error 29 | FindAmountFromOrderID(orderID int) (float64, error) 30 | ReturnOrder(id int) error 31 | CheckOrderStatus(orderID int) (string, error) 32 | CheckPaymentStatus(orderID int) (string, error) 33 | } -------------------------------------------------------------------------------- /pkg/repository/interfaces/otp.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 4 | 5 | type OtpRepository interface { 6 | FindUserByMobileNumber(phone string)bool 7 | UserDetailsUsingPhone(phone string)(models.UserDetailsResponse,error) 8 | } -------------------------------------------------------------------------------- /pkg/repository/interfaces/payment.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 5 | ) 6 | 7 | type PaymentRepository interface { 8 | AddNewPaymentMethod(paymentMethod string) error 9 | RemovePaymentMethod(paymentMethodId int) error 10 | GetPaymentMethods() ([]models.PaymentMethod, error) 11 | FindUsername(user_id int) (string, error) 12 | FindPrice(order_id int) (float64, error) 13 | UpdatePaymentDetails(orderId, paymentId, razorId string) error 14 | } 15 | -------------------------------------------------------------------------------- /pkg/repository/interfaces/user.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type UserRepository interface { 9 | CheckUserAvailability(email string) bool 10 | UserBlockStatus(email string) (bool, error) 11 | FindUserByEmail(user models.UserLogin) (models.UserSignInResponse, error) 12 | SignUp(user models.UserDetails) (models.UserDetailsResponse, error) 13 | AddAddress(id int, address models.AddAddress, result bool) error 14 | GetAddresses(id int) ([]domain.Address, error) 15 | CheckIfFirstAddress(id int) bool 16 | GetUserDetails(id int) (models.UserDetailsResponse, error) 17 | FindUserIDByOrderID(orderID int) (int, error) 18 | FindUserByOrderID(orderId string)(domain.User,error) 19 | ChangePassword(id int, password string) error 20 | GetPassword(id int) (string, error) 21 | FindIdFromPhone(phone string) (int, error) 22 | EditName(id int, name string) error 23 | EditEmail(id int, email string) error 24 | EditPhone(id int, phone string) error 25 | EditUsername(id int, username string) error 26 | 27 | RemoveFromCart(id int, inventoryID int) error 28 | ClearCart(cartID int) error 29 | UpdateQuantityAdd(id, inv_id int) error 30 | UpdateQuantityLess(id, inv_id int) error 31 | 32 | GetCartID(id int) (int, error) 33 | GetProductsInCart(cart_id int) ([]int, error) 34 | FindProductNames(inventory_id int) (string, error) 35 | FindCartQuantity(cart_id, inventory_id int) (int, error) 36 | FindPrice(inventory_id int) (float64, error) 37 | FindCategory(inventory_id int) (int, error) 38 | 39 | } 40 | -------------------------------------------------------------------------------- /pkg/repository/interfaces/wishlist.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | 9 | type WishlistRepository interface{ 10 | GetWishlist(id int)([]models.GetWishlist,error) 11 | GetWishlistId(user_id int)(int, error) 12 | CreateNewWishlist(user_id int)(int,error) 13 | AddWishlistItem(wishlistId,inventoryId int)error 14 | GetProductsInWishlist(wishlistId int)([]int,error) 15 | FindProductNames(inventory_id int)(string,error) 16 | FindPrice(inventory_id int)(float64,error) 17 | FindCategory(inventory_id int)(string,error) 18 | RemoveFromWishlist(wishlistId,inventoryId int)error 19 | } -------------------------------------------------------------------------------- /pkg/repository/inventory.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 9 | "gorm.io/gorm" 10 | ) 11 | 12 | type inventoryRespository struct { 13 | DB *gorm.DB 14 | } 15 | 16 | // Constructor function 17 | 18 | func NewInventoryRepository(DB *gorm.DB) interfaces.InventoryRespository { 19 | return &inventoryRespository{ 20 | DB: DB, 21 | } 22 | } 23 | 24 | func (ir *inventoryRespository) AddInventory(inventory models.Inventory, url string) (models.InventoryResponse, error) { 25 | var inventoryResp models.InventoryResponse 26 | 27 | query := `INSERT INTO inventories (category_id,product_name,description,stock,price,image) 28 | VALUES(?,?,?,?,?,?)RETURNING id` 29 | 30 | err := ir.DB.Raw(query, inventory.CategoryID, inventory.ProductName, inventory.Description, inventory.Stock, inventory.Price, inventory.Image, url).Scan(&inventoryResp.ProductID).Error 31 | if err != nil { 32 | return models.InventoryResponse{}, err 33 | } 34 | return models.InventoryResponse{}, nil 35 | } 36 | 37 | func (ir *inventoryRespository) UpdateImage(inventId int, url string) (models.Inventory, error) { 38 | 39 | // check db connecton 40 | if ir.DB == nil { 41 | return models.Inventory{}, errors.New("database connection failed while updating image") 42 | } 43 | 44 | // updating image 45 | err := ir.DB.Exec("UPDATE inventories SET image=? WHERE id= ? ", url, inventId).Error 46 | 47 | if err != nil { 48 | return models.Inventory{}, err 49 | } 50 | // Retrieve the update 51 | var updatedImageInventory models.Inventory 52 | err = ir.DB.Raw("SELECT * FROM inventories WHERE id = ?", inventId).Scan(&updatedImageInventory).Error 53 | if err != nil { 54 | return models.Inventory{}, err 55 | } 56 | return updatedImageInventory, nil 57 | } 58 | 59 | func (ir *inventoryRespository) CheckInventory(pid int) (bool, error) { 60 | var check int 61 | err := ir.DB.Raw("SELECT COUNT(*)FROM inventories WHERE id = ?", pid).Scan(&check).Error 62 | if err != nil { 63 | return false, err 64 | } 65 | if check == 0 { 66 | return false, err 67 | } 68 | return true, nil 69 | } 70 | 71 | func (ir *inventoryRespository) UpdateInventory(pid int, invData models.UpdateInventory) (models.Inventory, error) { 72 | if ir.DB == nil { 73 | return models.Inventory{}, errors.New("database connection failed while update inventory") 74 | } 75 | 76 | if invData.CategoryID != 0 { 77 | if err := ir.DB.Exec("UPDATE inventories SET categorie_id WHERE id=?", invData.CategoryID, pid).Error; err != nil { 78 | return models.Inventory{}, err 79 | } 80 | } 81 | 82 | if invData.ProductName != "" && invData.ProductName != "string" { 83 | if err := ir.DB.Exec("UPDATE inventories SET product_name=? WHERE id= ?", invData.ProductName, pid).Error; err != nil { 84 | return models.Inventory{}, err 85 | } 86 | } 87 | 88 | if invData.Description != "" && invData.Description != "string" { 89 | if err := ir.DB.Exec("UPDATE inventories SET description=? WHERE id=?", invData.Description, pid).Error; err != nil { 90 | return models.Inventory{}, err 91 | } 92 | } 93 | 94 | if invData.Stock != 0 { 95 | if err := ir.DB.Exec("UPDATE inventories SET stock= ? WHERE id=?", invData.Stock, pid).Error; err != nil { 96 | return models.Inventory{}, err 97 | } 98 | } 99 | 100 | if invData.Price != 0 { 101 | if err := ir.DB.Exec("UPDATE inventories SET price=? WHERE id=?", invData.Price, pid).Error; err != nil { 102 | return models.Inventory{}, err 103 | } 104 | } 105 | 106 | // retrieve the updates 107 | var updatedInventory models.Inventory 108 | err := ir.DB.Raw("SELECT * FROM inventories WHERE Id = ?", pid).Scan(&updatedInventory).Error 109 | if err != nil { 110 | return models.Inventory{}, err 111 | } 112 | return updatedInventory, nil 113 | } 114 | 115 | func (ir *inventoryRespository) DeleteInventory(inventoryId string) error { 116 | id, err := strconv.Atoi(inventoryId) 117 | if err != nil { 118 | return errors.New("string to int conversion failed") 119 | } 120 | result := ir.DB.Exec("DELETE FROM inventories WHERE id = ? ", id) 121 | 122 | if result.RowsAffected < 1 { 123 | return errors.New("no records exists with this id") 124 | } 125 | return nil 126 | } 127 | 128 | func (ir *inventoryRespository) ShowIndividualProducts(id string) (models.Inventory, error) { 129 | pid, err := strconv.Atoi(id) 130 | if err != nil { 131 | return models.Inventory{}, errors.New("string to int conversion failed") 132 | } 133 | var product models.Inventory 134 | 135 | err = ir.DB.Raw(` 136 | SELECT * FROM inventories 137 | WHERE Inventories.id = ? 138 | `, pid).Scan(&product).Error 139 | if err != nil { 140 | return models.Inventory{}, errors.New("error occured while showing individual product") 141 | } 142 | return product, err 143 | } 144 | 145 | func (ir *inventoryRespository) ListProducts(page, limit int) ([]models.InventoryList, error) { 146 | if page == 0 { 147 | page = 1 148 | } 149 | if limit == 0 { 150 | limit = 10 151 | } 152 | offset := (page - 1) * limit 153 | var productDetails []models.InventoryList 154 | 155 | err := ir.DB.Raw("SELECT inventories.id,inventories.product_name,inventories.description,inventories.stock,inventories.price,inventories.image,categories.category AS category FROM inventories JOIN categories ON inventories.category_id = categories.id LIMIT ? OFFSET ?", limit, offset).Scan(&productDetails).Error 156 | if err != nil { 157 | return []models.InventoryList{}, err 158 | } 159 | return productDetails, nil 160 | } 161 | func (ir *inventoryRespository) CheckStock(inventory_id int) (int, error) { 162 | var stock int 163 | err := ir.DB.Raw("SELECT stock FROM inventories WHERE id = ? ", inventory_id).Scan(&stock).Error 164 | if err != nil { 165 | return 0, err 166 | } 167 | return stock, nil 168 | } 169 | 170 | func (ir *inventoryRespository) CheckPrice(inventory_id int) (float64, error) { 171 | var price float64 172 | err := ir.DB.Raw("SELECT price FROM inventories WHERE id = ?", inventory_id).Scan(&price).Error 173 | if err != nil { 174 | return 0, err 175 | } 176 | return price, err 177 | } 178 | 179 | func (ir *inventoryRespository) SearchProducts(key string, page, limit int) ([]models.InventoryList, error) { 180 | if page == 0 { 181 | page = 1 182 | } 183 | if limit == 0 { 184 | limit = 10 185 | } 186 | offset := (page - 1) * limit 187 | 188 | var productSearchResult []models.InventoryList 189 | 190 | query := ` 191 | 192 | SELECT 193 | inventories.id, 194 | inventories.product_name, 195 | inventories.description, 196 | inventories.stock, 197 | inventories.price, 198 | inventories.image, 199 | categories.category AS category 200 | FROM 201 | inventories 202 | JOIN 203 | categories 204 | ON 205 | inventories.category_id = categories.id 206 | WHERE 207 | product_name ILIKE '%' || ? || '%' 208 | OR description ILIKE '%' || ? || '%' 209 | LIMIT ? OFFSET ? 210 | ` 211 | err := ir.DB.Raw(query, key, limit, offset).Scan(&productSearchResult).Error 212 | if err != nil { 213 | return []models.InventoryList{}, err 214 | } 215 | return productSearchResult, nil 216 | } 217 | 218 | func (ir *inventoryRespository) GetCategoryProducts(categoryId, page, limit int) ([]models.InventoryList, error) { 219 | if page == 0 { 220 | page = 1 221 | } 222 | if limit == 0 { 223 | limit = 10 224 | } 225 | offset := (page - 1) * limit 226 | var categoryProd []models.InventoryList 227 | 228 | query := ` 229 | 230 | SELECT 231 | inventories.id, 232 | inventories.product_name, 233 | inventories.description, 234 | inventories.image, 235 | inventories.stock, 236 | inventories.price 237 | categories.categorie AS category 238 | FROM 239 | inventories 240 | JOIN 241 | categories 242 | ON 243 | inventories.category_id = categories.id 244 | WHERE 245 | inventories.category_id = ? 246 | LIMIT ? OFFSET ? 247 | ` 248 | 249 | err := ir.DB.Raw(query, categoryId, limit, offset).Scan(&categoryProd).Error 250 | if err != nil { 251 | return []models.InventoryList{}, err 252 | } 253 | return categoryProd, nil 254 | } 255 | 256 | func (ir *inventoryRespository) AddImage(product_id int, image_url string) (models.InventoryResponse, error) { 257 | var addImageResponse models.InventoryResponse 258 | 259 | query := ` 260 | 261 | INSERT INTO 262 | images (inventory_id,image_url) 263 | VALUES (?,?) 264 | RETURNING 265 | inventory_id 266 | ` 267 | err := ir.DB.Raw(query, product_id, image_url).Scan(&addImageResponse).Error 268 | if err != nil { 269 | return models.InventoryResponse{}, errors.New("adding image failed") 270 | } 271 | return addImageResponse, nil 272 | } 273 | 274 | func (ir *inventoryRespository) DeleteImage(product_id int, imageId int) error { 275 | result := ir.DB.Exec("DELETE FROM images WHERE id= ?", imageId) 276 | 277 | if result.RowsAffected < 1 { 278 | return errors.New("no image exists with this id") 279 | } 280 | return nil 281 | } 282 | 283 | func (ir *inventoryRespository) GetImagesFromInventoryId(product_id int) ([]models.ImagesInfo, error) { 284 | var imagesFromInvId []models.ImagesInfo 285 | err := ir.DB.Raw("SELECT id,image_url FROM images WHERE inventory_id = ?", product_id).Scan(&imagesFromInvId).Error 286 | if err != nil { 287 | return []models.ImagesInfo{}, err 288 | } 289 | return imagesFromInvId, nil 290 | } 291 | -------------------------------------------------------------------------------- /pkg/repository/offer.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 7 | "gorm.io/gorm" 8 | ) 9 | 10 | type offerRepository struct { 11 | DB *gorm.DB 12 | } 13 | 14 | // constructor function 15 | 16 | func NewOfferRepository(DB *gorm.DB) interfaces.OfferRepository { 17 | return &offerRepository{ 18 | DB: DB, 19 | } 20 | } 21 | 22 | func (or *offerRepository) AddNewOffer(offer models.CreateOffer) error { 23 | err := or.DB.Exec("INSERT INTO offers(category_id,discount_rate) VALUES (?,?)", offer.CategoryID, offer.Discount).Error 24 | if err != nil { 25 | return err 26 | } 27 | return nil 28 | } 29 | 30 | func (or *offerRepository) MakeOfferExpired(categoryId int) error { 31 | err := or.DB.Exec("UPDATE offers SET valid=false WHERE id=$1", categoryId).Error 32 | if err != nil { 33 | return err 34 | } 35 | return nil 36 | } 37 | 38 | func (or *offerRepository) FindDiscountPercentage(categoryId int) (int, error) { 39 | var percentage int 40 | 41 | err := or.DB.Raw("SELECT discount_rate FROM offers WHERE category_id=$1 and valid=true", categoryId).Scan(&percentage).Error 42 | if err != nil { 43 | return 0, err 44 | } 45 | return percentage, nil 46 | } 47 | 48 | func (or *offerRepository) GetOffers(page, limit int) ([]domain.Offer, error) { 49 | if page == 0 { 50 | page = 1 51 | } 52 | if limit == 0 { 53 | limit = 10 54 | } 55 | offset := (page - 1) * limit 56 | 57 | var getOffers []domain.Offer 58 | 59 | if err := or.DB.Raw("SELECT id,category_id,discount_rate,valid FROM offers limit ? offset ?", limit, offset).Scan(&getOffers).Error; err != nil { 60 | return []domain.Offer{}, err 61 | } 62 | return getOffers, nil 63 | } 64 | -------------------------------------------------------------------------------- /pkg/repository/order.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 9 | "gorm.io/gorm" 10 | ) 11 | 12 | type orderRepository struct { 13 | DB *gorm.DB 14 | } 15 | 16 | // constructor function 17 | func NewOrderRepository(DB *gorm.DB) *orderRepository { 18 | return &orderRepository{ 19 | DB: DB, 20 | } 21 | } 22 | 23 | func (orr *orderRepository) GetOrders(id, page, limit int) ([]domain.Order, error) { 24 | if page == 0 { 25 | page = 1 26 | } 27 | if limit == 0 { 28 | limit = 10 29 | } 30 | offset := (page - 1) * limit 31 | 32 | var getOrders []domain.Order 33 | 34 | err := orr.DB.Raw("SELECT * FROM orders WHERE id= ? limit ? offset ?", id, limit, offset).Scan(&getOrders).Error 35 | if err != nil { 36 | return []domain.Order{}, err 37 | } 38 | return getOrders, nil 39 | } 40 | 41 | func (orr *orderRepository) GetOrdersInRange(startDate, endDate time.Time) ([]domain.Order, error) { 42 | var getOrdersInTimeRange []domain.Order 43 | 44 | // to fetch orders with in a time range 45 | err := orr.DB.Raw("SELECT * FROM orders WHERE ordered_at BETWEEN ? AND ?", startDate, endDate).Scan(&getOrdersInTimeRange).Error 46 | if err != nil { 47 | return []domain.Order{}, err 48 | } 49 | return getOrdersInTimeRange, nil 50 | } 51 | 52 | func (orr *orderRepository) GetProductsQuantity() ([]domain.ProductReport, error) { 53 | 54 | var getProductQuantity []domain.ProductReport 55 | 56 | err := orr.DB.Raw("SELECT inventory_id,quantity FROM order_items").Scan(&getProductQuantity).Error 57 | if err != nil { 58 | return []domain.ProductReport{}, err 59 | } 60 | return getProductQuantity, nil 61 | } 62 | 63 | func (orr *orderRepository) CreditToUserWallet(amount float64, walletId int) error { 64 | 65 | if err := orr.DB.Exec("update wallets set amount=$1 where id=$2", amount, walletId).Error; err != nil { 66 | return err 67 | } 68 | 69 | return nil 70 | 71 | } 72 | 73 | func (orr *orderRepository) GetCart(userid int) (models.GetCart, error) { 74 | 75 | var cart models.GetCart 76 | err := orr.DB.Raw("SELECT inventories.product_name,cart_products.quantity,cart_products.total_price AS total FROM cart_products JOIN inventories ON cart_products.inventory_id=inventores.id WHERE user_id=?", userid).Scan(&cart).Error 77 | if err != nil { 78 | return models.GetCart{}, err 79 | } 80 | return cart, nil 81 | } 82 | 83 | func (orr *orderRepository) GetProductNameFromId(id int) (string, error) { 84 | 85 | var productName string 86 | 87 | err := orr.DB.Raw("SELECT product_name FROM inventories WHERE id = ?", id).Scan(&productName).Error 88 | if err != nil { 89 | return "", err 90 | } 91 | return productName, nil 92 | } 93 | 94 | func (orr *orderRepository) OrderItems(userid int, addressid int, paymentid int, total float64, coupon string) (int, error) { 95 | 96 | var id int 97 | 98 | query := ` 99 | 100 | INSERT INTO orders 101 | (user_id,address_id,price,payment_method_id,total,coupon_used) 102 | VALUES 103 | (?,?,?,?,?) 104 | RETURNING id 105 | ` 106 | err := orr.DB.Raw(query, userid, addressid, paymentid, total, coupon).Scan(&id).Error 107 | if err != nil { 108 | return 0, err 109 | } 110 | return id, nil 111 | } 112 | 113 | func (orr *orderRepository) CreateNewWallet(userID int) (int, error) { 114 | 115 | var walletID int 116 | err := orr.DB.Exec("Insert into wallets(user_id,amount) values($1,$2)", userID, 0).Error 117 | if err != nil { 118 | return 0, err 119 | } 120 | 121 | if err := orr.DB.Raw("select id from wallets where user_id=$1", userID).Scan(&walletID).Error; err != nil { 122 | return 0, err 123 | } 124 | 125 | return walletID, nil 126 | } 127 | 128 | func (orr *orderRepository) AddOrderProducts(order_id int, cart []models.GetCart) error { 129 | query := ` 130 | 131 | INSERT INTO 132 | order_items 133 | (order_id,inventory_id,quantity,total_price) 134 | VALUES 135 | (?,?,?,?) 136 | 137 | ` 138 | for _, cartVals := range cart { 139 | var invId int 140 | err := orr.DB.Raw("SELECT id FROM inventories WHERE product_name=?", cartVals.ProductName).Scan(&invId).Error 141 | if err != nil { 142 | return err 143 | } 144 | if err := orr.DB.Raw(query, order_id, invId, cartVals.Quantity, cartVals.Total).Error; err != nil { 145 | return err 146 | } 147 | 148 | } 149 | return nil 150 | } 151 | 152 | func (orr *orderRepository) FindWalletIdFromUserID(userId int) (int, error) { 153 | 154 | var count int 155 | err := orr.DB.Raw("select count(*) from wallets where user_id = ?", userId).Scan(&count).Error 156 | if err != nil { 157 | return 0, err 158 | } 159 | 160 | var walletID int 161 | if count > 0 { 162 | err := orr.DB.Raw("select id from wallets where user_id = ?", userId).Scan(&walletID).Error 163 | if err != nil { 164 | return 0, err 165 | } 166 | } 167 | 168 | return walletID, nil 169 | 170 | } 171 | 172 | func (orr *orderRepository) CancelOrder(orderid int) error { 173 | err := orr.DB.Exec("UPDATE orders SET order_status='CANCELED' WHERE id=?", orderid).Error 174 | if err != nil { 175 | return err 176 | } 177 | return nil 178 | } 179 | 180 | func (orr *orderRepository) EditOrderStatus(status string, id int) error { 181 | err := orr.DB.Exec("UPDATE orders SET order_status=? WHERE id=?", status, id).Error 182 | if err != nil { 183 | return err 184 | } 185 | return nil 186 | } 187 | 188 | func (orr *orderRepository) MarkAsPaid(orderID int) error { 189 | if err := orr.DB.Exec("UPDATE orders SET payment_status='PAID' WHERE id=?", orderID).Error; err != nil { 190 | return err 191 | } 192 | return nil 193 | } 194 | 195 | func (orr *orderRepository) AdminOrders(status string) ([]domain.OrderDetails, error) { 196 | 197 | var orderDetails []domain.OrderDetails 198 | query := ` 199 | SELECT orders.id AS id, users.name AS username, CONCAT('House Name:',addresses.house_name, ',', 'Street:', addresses.street, ',', 'City:', addresses.city, ',', 'State', addresses.state, ',', 'Phone:', addresses.phone) AS address, payment_methods.payment_name AS payment_method, orders.final_price As total FROM orders JOIN users ON users.id = orders.user_id JOIN payment_methods ON payment_methods.id = orders.payment_method_id JOIN addresses ON orders.address_id = addresses.id WHERE order_status = $1 200 | ` 201 | err := orr.DB.Raw(query, status).Scan(&orderDetails).Error 202 | if err != nil { 203 | return []domain.OrderDetails{}, err 204 | } 205 | return orderDetails, nil 206 | } 207 | 208 | func (orr *orderRepository) CheckOrder(orderID string, userID int) error { 209 | 210 | var count int 211 | err := orr.DB.Raw("SELECT COUNT (*)FROM orders WHERE order_id=?", orderID).Scan(&count).Error 212 | if err != nil { 213 | return err 214 | } 215 | if count < 0 { 216 | return errors.New("no such order exist") 217 | } 218 | 219 | var checkUser int 220 | chUser := orr.DB.Raw("SELECT user_id FROM orders WHERE order_id=?", orderID).Scan(&checkUser).Error 221 | if err != nil { 222 | return chUser 223 | } 224 | if userID != checkUser { 225 | return errors.New("no order did by this user") 226 | } 227 | return nil 228 | } 229 | 230 | func (orr *orderRepository) GetOrderDetail(orderID string) (domain.Order, error) { 231 | var orderDetails domain.Order 232 | 233 | err := orr.DB.Raw("SELECT * FROM orders WHERE order_id=?", orderID).Scan(&orderDetails).Error 234 | if err != nil { 235 | return domain.Order{}, err 236 | } 237 | return orderDetails, nil 238 | } 239 | 240 | func (orr *orderRepository) FindAmountFromOrderID(orderID int) (float64, error) { 241 | var amount float64 242 | 243 | err := orr.DB.Raw("SELECT price FROM orders WHERE order_id=?", orderID).Scan(&amount).Error 244 | if err != nil { 245 | return 0, err 246 | } 247 | return amount, nil 248 | } 249 | 250 | func (orr *orderRepository) FindUserIdFromOrderID(orderID int) (int, error) { 251 | var userId int 252 | 253 | err := orr.DB.Raw("SELECT user_id FROM orders WHERE order_id=?", orderID).Scan(&userId).Error 254 | if err != nil { 255 | return 0, err 256 | } 257 | return userId, nil 258 | } 259 | 260 | func (orr *orderRepository) ReturnOrder(id int) error { 261 | err := orr.DB.Exec("UPDATE orders SET order_status='RETURNED' WHERE id=?", id).Error 262 | if err != nil { 263 | return err 264 | } 265 | return nil 266 | } 267 | 268 | func (orr *orderRepository) CheckOrderStatus(orderID int) (string, error) { 269 | var orderStatus string 270 | 271 | err := orr.DB.Raw("SELECT order_status FROM orders WHERE order_id=?", orderID).Scan(&orderStatus).Error 272 | if err != nil { 273 | return "", err 274 | } 275 | return orderStatus, nil 276 | } 277 | 278 | func (orr *orderRepository) CheckPaymentStatus(orderID int) (string, error) { 279 | var paymentStatus string 280 | err := orr.DB.Raw("SELECT payment_status FROM orders WHERE order_id=?", orderID).Scan(&paymentStatus).Error 281 | if err != nil { 282 | return "", err 283 | } 284 | return paymentStatus, nil 285 | } 286 | -------------------------------------------------------------------------------- /pkg/repository/otp.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | "gorm.io/gorm" 7 | ) 8 | 9 | type otpRepository struct { 10 | DB *gorm.DB 11 | } 12 | 13 | // constructor function 14 | 15 | func NewOtpRepository(DB *gorm.DB) interfaces.OtpRepository { 16 | return &otpRepository{ 17 | DB: DB, 18 | } 19 | } 20 | 21 | func (otr *otpRepository) FindUserByMobileNumber(phone string) bool { 22 | var count int 23 | 24 | err := otr.DB.Raw("SELECT COUNT(*) FROM users WHERE phone=?", phone).Scan(&count).Error 25 | if err != nil { 26 | return false 27 | } 28 | return count > 0 29 | } 30 | 31 | func (otr *otpRepository) UserDetailsUsingPhone(phone string) (models.UserDetailsResponse, error) { 32 | var userDetails models.UserDetailsResponse 33 | 34 | err := otr.DB.Raw("SELECT * FROM users WHERE phone=?", phone).Scan(&userDetails).Error 35 | if err != nil { 36 | return models.UserDetailsResponse{}, err 37 | } 38 | return userDetails, nil 39 | } 40 | -------------------------------------------------------------------------------- /pkg/repository/payment.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | "gorm.io/gorm" 7 | ) 8 | 9 | type paymentRepository struct { 10 | DB *gorm.DB 11 | } 12 | 13 | // constructor function 14 | 15 | func NewPaymentRepository(DB *gorm.DB) interfaces.PaymentRepository { 16 | return &paymentRepository{ 17 | DB: DB, 18 | } 19 | } 20 | 21 | func (pr *paymentRepository) AddNewPaymentMethod(paymentMethod string) error { 22 | query := `INSERT INTO payment_methods(payment_method)VALUES(?)` 23 | 24 | if err := pr.DB.Exec(query, paymentMethod).Error; err != nil { 25 | return err 26 | } 27 | return nil 28 | } 29 | 30 | func (pr *paymentRepository) RemovePaymentMethod(paymentMethodId int) error { 31 | query := `DELETE FROM payment_methods WHERE id=?` 32 | 33 | if err := pr.DB.Exec(query, paymentMethodId).Error; err != nil { 34 | return err 35 | } 36 | return nil 37 | } 38 | 39 | func (pr *paymentRepository) GetPaymentMethods() ([]models.PaymentMethod, error) { 40 | var paymentMethods []models.PaymentMethod 41 | err := pr.DB.Raw("SELECT * FROM payment_methods").Scan(&paymentMethods).Error 42 | if err != nil { 43 | return []models.PaymentMethod{}, err 44 | } 45 | return paymentMethods, nil 46 | } 47 | 48 | func (pr *paymentRepository) FindUsername(user_id int) (string, error) { 49 | var userName string 50 | err := pr.DB.Raw("SELECT name FROM users WHERE id=?", user_id).Scan(&userName).Error 51 | if err != nil { 52 | return "", err 53 | } 54 | return userName, nil 55 | } 56 | 57 | func (pr *paymentRepository) FindPrice(order_id int) (float64, error) { 58 | var price float64 59 | 60 | err := pr.DB.Raw("SELECT price FROM orders WHERE id=?", order_id).Scan(&price).Error 61 | if err != nil { 62 | return 0, err 63 | } 64 | return price, nil 65 | } 66 | 67 | func (pr *paymentRepository) UpdatePaymentDetails(orderId, paymentId, razorId string) error { 68 | status := "PAID" 69 | query := `UPDATE orders SET payment_status=$1,payment_id=$3 WHERE id=$2` 70 | if err := pr.DB.Exec(query, status, orderId, paymentId).Error; err != nil { 71 | return err 72 | } 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /pkg/repository/user.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 10 | "gorm.io/gorm" 11 | ) 12 | 13 | type userRepository struct { 14 | DB *gorm.DB 15 | } 16 | 17 | // constructor funciton 18 | 19 | func NewUserRepository(DB *gorm.DB) interfaces.UserRepository { 20 | return &userRepository{ 21 | DB: DB, 22 | } 23 | } 24 | 25 | func (ur *userRepository) CheckUserAvailability(email string) bool { 26 | var userCount int 27 | 28 | err := ur.DB.Raw("SELECT COUNT(*) FROM users WHERE email=?", email).Scan(&userCount).Error 29 | if err != nil { 30 | return false 31 | } 32 | // if count greater than 0, user already exist 33 | return userCount > 0 34 | } 35 | 36 | func (ur *userRepository) UserBlockStatus(email string) (bool, error) { 37 | var permission bool 38 | err := ur.DB.Raw("SELECT permission FROM users WHERE email=?", email).Scan(&permission).Error 39 | if err != nil { 40 | return false, err 41 | } 42 | return permission, nil 43 | } 44 | 45 | func (ur *userRepository) FindUserByEmail(user models.UserLogin) (models.UserSignInResponse, error) { 46 | var userResponse models.UserSignInResponse 47 | err := ur.DB.Raw("SELECT * FROM users WHERE email=? AND permission=true", user.Email).Scan(&userResponse).Error 48 | if err != nil { 49 | return models.UserSignInResponse{}, errors.New("no user found") 50 | } 51 | return userResponse, nil 52 | } 53 | 54 | func (ur *userRepository) FindUserIDByOrderID(orderID int) (int, error) { 55 | var userId int 56 | err := ur.DB.Raw("SELECT user_id FROM orders WHERE order_id=?", orderID).Scan(&userId).Error 57 | if err != nil { 58 | return 0, errors.New("user id not found") 59 | } 60 | return userId, nil 61 | } 62 | 63 | func (ur *userRepository) SignUp(user models.UserDetails) (models.UserDetailsResponse, error) { 64 | var userResponse models.UserDetailsResponse 65 | err := ur.DB.Raw("INSERT INTO users(name,email,username,phone,password)VALUES(?,?,?,?,?)RETURNING id,name,email,phone", user.Name, user.Email, user.Username, user.Phone,user.Password).Scan(&userResponse).Error 66 | if err != nil { 67 | return models.UserDetailsResponse{}, err 68 | } 69 | return userResponse, nil 70 | } 71 | 72 | func (ur *userRepository) AddAddress(id int, address models.AddAddress, result bool) error { 73 | query := ` 74 | 75 | INSERT INTO addresses(user_id,name,house_name,street,city,state,pin,"default") 76 | VALUES($1,$2,$3,$4,$5,$6,$7,$8) 77 | 78 | ` 79 | fmt.Println("user id from add address repo",id) 80 | err := ur.DB.Exec(query, id, address.Name, address.HouseName, address.Street, address.City, address.State, address.Pin, result).Error 81 | if err != nil { 82 | return errors.New("adding address failed") 83 | } 84 | return nil 85 | } 86 | 87 | func (ur *userRepository) CheckIfFirstAddress(id int) bool { 88 | var addressCount int 89 | err := ur.DB.Raw("SELECT COUNT(*)FROM addresses WHERE user_id=?", id).Scan(&addressCount).Error 90 | if err != nil { 91 | return false 92 | } 93 | // if addresscount >0 there is already a address 94 | return addressCount > 0 95 | } 96 | 97 | func (ur *userRepository) GetAddresses(id int) ([]domain.Address, error) { 98 | var getAddress []domain.Address 99 | err := ur.DB.Raw("SELECT * FROM addresses WHERE user_id=?", id).Scan(&getAddress).Error 100 | if err != nil { 101 | return []domain.Address{}, errors.New("failed to getting address") 102 | } 103 | return getAddress, nil 104 | } 105 | 106 | func (ur *userRepository) GetUserDetails(id int) (models.UserDetailsResponse, error) { 107 | var userDetails models.UserDetailsResponse 108 | 109 | err := ur.DB.Raw("SELECT * FROM users WHERE id=?", id).Scan(&userDetails).Error 110 | if err != nil { 111 | return models.UserDetailsResponse{}, errors.New("error while getting user details") 112 | } 113 | return userDetails, nil 114 | } 115 | 116 | func (ur *userRepository) ChangePassword(id int, password string) error { 117 | err := ur.DB.Exec("UPDATE users SET password=? WHERE id=?", password, id).Error 118 | if err != nil { 119 | return errors.New("password changing failed") 120 | } 121 | return nil 122 | } 123 | 124 | func (ur *userRepository) GetPassword(id int) (string, error) { 125 | var password string 126 | err := ur.DB.Raw("SELECT password FROM users WHERE id=?", id).Scan(&password).Error 127 | if err != nil { 128 | return "", errors.New("password getting failed") 129 | } 130 | return password, nil 131 | } 132 | 133 | func (ur *userRepository) FindIdFromPhone(phone string) (int, error) { 134 | var userid int 135 | err := ur.DB.Raw("SELECT id FROM users WHERE phone=?", phone).Scan(&userid).Error 136 | if err != nil { 137 | return 0, err 138 | } 139 | return userid, nil 140 | } 141 | 142 | func (ur *userRepository) EditName(id int, name string) error { 143 | err := ur.DB.Exec("UPDATE users SET name=? WHERE id=?", name, id).Error 144 | if err != nil { 145 | return errors.New("error while editing name") 146 | } 147 | return nil 148 | } 149 | 150 | func (ur *userRepository) EditEmail(id int, email string) error { 151 | if err := ur.DB.Exec("UPDATE users SET email=? WHERE id=?", email, id).Error; err != nil { 152 | return errors.New("error while changing email") 153 | } 154 | return nil 155 | } 156 | 157 | func (ur *userRepository) EditPhone(id int, phone string) error { 158 | if err := ur.DB.Exec("UPDATE users SET phone=?,WHERE id=?", phone, id).Error; err != nil { 159 | return errors.New("error while changing phone number") 160 | } 161 | return nil 162 | } 163 | 164 | func (ur *userRepository) EditUsername(id int, username string) error { 165 | if err := ur.DB.Exec("UPDATE users SET username=? WHERE id=?", username, id).Error; err != nil { 166 | return errors.New("error while changing username") 167 | } 168 | return nil 169 | } 170 | 171 | func (ur *userRepository) RemoveFromCart(id int, inventoryID int) error { 172 | if err := ur.DB.Exec("DELETE FROM line_items WHERE id=? AND inventory_id=?", id, inventoryID).Error; err != nil { 173 | return errors.New("item not removed") 174 | } 175 | return nil 176 | } 177 | 178 | func (ur *userRepository) ClearCart(cartID int) error { 179 | if err := ur.DB.Exec("DELETE FROM line_items WHERE cart_id=?", cartID).Error; err != nil { 180 | return errors.New("cart not cleared") 181 | } 182 | return nil 183 | } 184 | 185 | func (ur *userRepository) UpdateQuantityAdd(id, inv_id int) error { 186 | query := ` 187 | UPDATE line_items SET quantity=quantity+1 188 | WHERE cart_id=? AND inventory_id=? 189 | ` 190 | if err := ur.DB.Exec(query, id, inv_id).Error; err != nil { 191 | return errors.New("failed to add quantity") 192 | } 193 | return nil 194 | } 195 | 196 | func (ur *userRepository) UpdateQuantityLess(id, inv_id int) error { 197 | query := 198 | ` 199 | UPDATE line_items SET quantity=quantity-1 200 | WHERE cart_id=? AND inventory_id=? 201 | ` 202 | if err := ur.DB.Exec(query, id, inv_id).Error; err != nil { 203 | return errors.New("failed to decrease quantity") 204 | } 205 | return nil 206 | } 207 | 208 | func (ur *userRepository) FindUserByOrderID(orderId string) (domain.User, error) { 209 | var userDetails domain.User 210 | err := ur.DB.Raw("SELECT users.name,users.email,users.phone FROM users JOIN orders ON orders.user_id=users.id WHERE order_id=?", orderId).Scan(&userDetails).Error 211 | if err != nil { 212 | return domain.User{}, errors.New("user not found with order id") 213 | } 214 | return userDetails, nil 215 | } 216 | 217 | func (ur *userRepository) GetCartID(id int) (int, error) { 218 | var cartid int 219 | if err := ur.DB.Raw("SELECT id FROM cart_id WHERE user_id=?", id).Scan(&cartid).Error; err != nil { 220 | return 0, errors.New("cart id not found") 221 | } 222 | return cartid, nil 223 | } 224 | 225 | func (ur *userRepository) GetProductsInCart(cart_id int) ([]int, error) { 226 | var cartProducts []int 227 | 228 | err := ur.DB.Raw("SELECT inventory_id FROM line_items WHERE cart_id=?", cart_id).Scan(&cartProducts).Error 229 | if err != nil { 230 | return []int{}, err 231 | } 232 | return cartProducts, nil 233 | } 234 | 235 | func (ur *userRepository) FindProductNames(inventory_id int) (string, error) { 236 | var productName string 237 | if err := ur.DB.Raw("SELECT product_name FROM inventories WHERE id=?", inventory_id).Scan(&productName).Error; err != nil { 238 | return "", errors.New("product name not found") 239 | } 240 | return productName, nil 241 | } 242 | 243 | func (ur *userRepository) FindCartQuantity(cart_id, inventory_id int) (int, error) { 244 | var quantity int 245 | if err := ur.DB.Raw("SELECT quantity FROM line_items WHERE cart_id=? AND inventory_id=?", cart_id, inventory_id).Scan(&quantity).Error; err != nil { 246 | return 0, errors.New("quantity not found") 247 | } 248 | return quantity, nil 249 | } 250 | 251 | func (ur *userRepository) FindPrice(inventory_id int) (float64, error) { 252 | var price float64 253 | if err := ur.DB.Raw("SELECT price FROM inventories WHERE id=?", inventory_id).Scan(&price).Error; err != nil { 254 | return 0, errors.New("price not found") 255 | } 256 | return price, nil 257 | } 258 | 259 | func (ur *userRepository) FindCategory(inventory_id int) (int, error) { 260 | var categoryId int 261 | if err := ur.DB.Raw("SELECT category_id FROM inventories WHERE id=?", inventory_id).Scan(&categoryId).Error; err != nil { 262 | return 0, errors.New("category id not found") 263 | } 264 | return categoryId, nil 265 | } 266 | -------------------------------------------------------------------------------- /pkg/repository/wishlist.go: -------------------------------------------------------------------------------- 1 | package repository 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 8 | "gorm.io/gorm" 9 | ) 10 | 11 | type wishlistReposotory struct { 12 | DB *gorm.DB 13 | } 14 | 15 | // constructor function 16 | 17 | func NewWishlistRepository(DB *gorm.DB) interfaces.WishlistRepository { 18 | return &wishlistReposotory{ 19 | DB: DB, 20 | } 21 | } 22 | 23 | func (wlr *wishlistReposotory) GetWishlistId(user_id int) (int, error) { 24 | var wishlistId int 25 | if err := wlr.DB.Raw("SELECT id FROM wishlist WHERE user_id=?", user_id).Scan(&wishlistId).Error; err != nil { 26 | return 0, errors.New("wishlist id not found") 27 | } 28 | return wishlistId, nil 29 | } 30 | 31 | func (wlr *wishlistReposotory) GetWishlist(id int) ([]models.GetWishlist, error) { 32 | var getWishlist []models.GetWishlist 33 | 34 | query := ` 35 | SELECT wishlist.user_id,categories.category,inventories.product_name,inventories.price 36 | FROM wishlist 37 | JOIN wishlist_items.wishlist_id=wishlist.idgetWishlist 38 | JOIN invenotries ON wishlist_items.inventory_id=inventories.id 39 | JOIN categories ON inventories.category_id=categories.id 40 | WHERE wishlist.user_id 41 | 42 | ` 43 | if err := wlr.DB.Raw(query, id).Scan(&getWishlist).Error; err != nil { 44 | return []models.GetWishlist{}, err 45 | } 46 | return getWishlist, nil 47 | } 48 | 49 | func (wlr *wishlistReposotory) GetProductsInWishlist(wishlistId int) ([]int, error) { 50 | var productsInWishlist []int 51 | 52 | if err := wlr.DB.Raw("SELECT inventory_id FROM wishlist_items WHERE wishlist_id", wishlistId).Scan(&productsInWishlist).Error; err != nil { 53 | return []int{}, err 54 | } 55 | return productsInWishlist, nil 56 | } 57 | 58 | func (wlr *wishlistReposotory) FindProductNames(inventory_id int) (string, error) { 59 | var productName string 60 | 61 | if err := wlr.DB.Raw("SELECT product_name FROM inventories WHERE inventory_id=?", inventory_id).Scan(&productName).Error; err != nil { 62 | return "", errors.New("product name not found") 63 | } 64 | return productName, nil 65 | } 66 | 67 | func (wlr *wishlistReposotory) FindPrice(inventory_id int) (float64, error) { 68 | var price float64 69 | if err := wlr.DB.Raw("SELECT price FROM inventories WHERE inventory_id=?", inventory_id).Scan(&price).Error; err != nil { 70 | return 0, errors.New("price not found") 71 | } 72 | return price, nil 73 | } 74 | 75 | func (wlr *wishlistReposotory) FindCategory(inventory_id int) (string, error) { 76 | var category string 77 | 78 | query := ` 79 | 80 | SELECT categories.category FROM invenotries 81 | JOIN categories ON inventories.category_id=category.id 82 | WHERE inventory_id=? 83 | 84 | ` 85 | if err := wlr.DB.Raw(query, inventory_id).Scan(&category).Error; err != nil { 86 | return "", errors.New("category not found") 87 | } 88 | return category, nil 89 | } 90 | 91 | func (wlr *wishlistReposotory) RemoveFromWishlist(wishlistId, inventoryId int) error { 92 | if err := wlr.DB.Exec("DELETE FROM wishlist_item WHERE wishlist_id=? AND inventory_id=?", wishlistId, inventoryId).Error; err != nil { 93 | return errors.New("remove from wishlist failed") 94 | } 95 | return nil 96 | } 97 | 98 | func (wlr *wishlistReposotory) AddWishlistItem(wishlistId, inventoryId int) error { 99 | if err := wlr.DB.Exec("INSERT INTO wishlist_item(wishlist_id,inventory_id)VALUES(?,?)", wishlistId, inventoryId).Error; err != nil { 100 | return err 101 | } 102 | return nil 103 | } 104 | 105 | func (wlr *wishlistReposotory) CreateNewWishlist(user_id int) (int, error) { 106 | var wishlistId int 107 | 108 | if err := wlr.DB.Exec("INSERT INTO wishlist(user_id)VALUES(?)", user_id).Error; err != nil { 109 | return 0, errors.New("wishlist creation failed") 110 | } 111 | if err := wlr.DB.Raw("SELECT id FROM wishlist WHERE user_id", user_id).Scan(&wishlistId).Error; err != nil { 112 | return 0, errors.New("wishlist id not found") 113 | } 114 | return wishlistId, nil 115 | } 116 | -------------------------------------------------------------------------------- /pkg/routes/admin.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/api/handlers" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/api/middleware" 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func AdminRoutes(engine *gin.RouterGroup, 10 | adminHandler *handlers.AdminHandler, 11 | // userHandler *handlers.UserHandler, 12 | categoryHandler *handlers.CategoryHandler, 13 | inventoryHandler *handlers.InventoryHandler, 14 | orderHandler *handlers.OrderHandler, 15 | paymentHandler *handlers.PaymentHandler, 16 | offerHandler *handlers.OfferHandler, 17 | couponHandler *handlers.CouponHandler) { 18 | engine.POST("/adminlogin", adminHandler.LoginHandler) 19 | { 20 | engine.Use(middleware.AdminAuthMiddleware) 21 | 22 | userManagement := engine.Group("/users") 23 | { 24 | userManagement.POST("/block", adminHandler.BlockUser) 25 | userManagement.POST("/unblock", adminHandler.UnblockUser) 26 | userManagement.GET("/getusers", adminHandler.GetUsers) 27 | } 28 | 29 | categoryManagement := engine.Group("/category") 30 | { 31 | categoryManagement.GET("/categories", categoryHandler.Categories) 32 | categoryManagement.POST("/add", categoryHandler.AddCategory) 33 | categoryManagement.PATCH("/update", categoryHandler.UpdateCategory) 34 | categoryManagement.DELETE("/delete", categoryHandler.DeleteCategory) 35 | } 36 | 37 | inventoryManagement := engine.Group("/inventories") 38 | { 39 | // inventoryManagement.GET("", inventoryHandler.ListProdutcs) 40 | // inventoryManagement.GET("/details", inventoryHandler.ShowIndividualProducts) 41 | inventoryManagement.POST("/add", inventoryHandler.AddInventory) 42 | inventoryManagement.POST("/add-image", inventoryHandler.AddImage) 43 | inventoryManagement.PATCH("/update", inventoryHandler.UpdateInventory) 44 | inventoryManagement.PATCH("/update-image", inventoryHandler.UpdateImage) 45 | inventoryManagement.DELETE("/delete-image", inventoryHandler.DeleteImage) 46 | inventoryManagement.DELETE("/delete", inventoryHandler.DeleteInventory) 47 | } 48 | 49 | orderManagement := engine.Group("/orders") 50 | { 51 | orderManagement.GET("", orderHandler.AdminOrders) 52 | orderManagement.PATCH("/edit/status", orderHandler.EditOrderStatus) 53 | orderManagement.PATCH("/edit/mark-as-paid", orderHandler.MarkAsPaid) 54 | } 55 | 56 | paymentManangement := engine.Group("/paymentmethods") 57 | { 58 | paymentManangement.GET("/", paymentHandler.GetPaymentMethods) 59 | paymentManangement.POST("/add", paymentHandler.AddNewPaymentMethod) 60 | paymentManangement.DELETE("/delete", paymentHandler.RemovePaymentMethod) 61 | } 62 | 63 | offerManagement := engine.Group("/offers") 64 | { 65 | offerManagement.GET("", offerHandler.Offers) 66 | offerManagement.POST("/create", offerHandler.AddOffer) 67 | offerManagement.POST("/expire", offerHandler.ExpireValidity) 68 | } 69 | 70 | couponManagement := engine.Group("/coupons") 71 | { 72 | couponManagement.GET("", couponHandler.Coupons) 73 | couponManagement.POST("/create", couponHandler.CreateNewCoupon) 74 | couponManagement.POST("/expire", couponHandler.MakeCouponInvalid) 75 | } 76 | salesManagement := engine.Group("/sales") 77 | { 78 | salesManagement.GET("/daily", orderHandler.AdminSalesDailyReport) 79 | salesManagement.GET("/weekly", orderHandler.AdminSalesWeeklyReports) 80 | salesManagement.GET("/monthly", orderHandler.AdminSalesMonthlyReport) 81 | salesManagement.GET("/annual", orderHandler.AdminSalesAnnualReport) 82 | salesManagement.POST("/custom", orderHandler.AdminSaleCustomReport) 83 | } 84 | productsManagement := engine.Group("/products") 85 | { 86 | productsManagement.GET("", inventoryHandler.AdminListProdutcs) 87 | productsManagement.GET("/details", inventoryHandler.ShowIndividualProducts) 88 | productsManagement.GET("/search", inventoryHandler.SearchProducts) 89 | productsManagement.GET("/category", inventoryHandler.GetCategoryProducts) 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /pkg/routes/inventory.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/api/handlers" 5 | "github.com/gin-gonic/gin" 6 | ) 7 | 8 | // this function is for use this routes for all users without login 9 | 10 | func InventoryRoutes(engine *gin.RouterGroup, inventoryHandler *handlers.InventoryHandler) { 11 | engine.GET("", inventoryHandler.ListProdutcs) 12 | engine.GET("/details", inventoryHandler.ShowIndividualProducts) 13 | engine.GET("/search", inventoryHandler.SearchProducts) 14 | engine.GET("/category", inventoryHandler.GetCategoryProducts) 15 | } 16 | -------------------------------------------------------------------------------- /pkg/routes/user.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/api/handlers" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/api/middleware" 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func UserRoutes(engine *gin.RouterGroup, 10 | userHandler *handlers.UserHandler, 11 | otpHandler *handlers.OtpHandler, 12 | inventoryHandler *handlers.InventoryHandler, 13 | cartHandler *handlers.CartHandler, 14 | orderHandler *handlers.OrderHandler, 15 | couponHandler *handlers.CouponHandler, 16 | paymentHandler *handlers.PaymentHandler, 17 | wishlistHandler *handlers.WishlistHandler) { 18 | 19 | engine.POST("/signup", userHandler.SignUp) 20 | engine.POST("/login", userHandler.Login) 21 | engine.POST("/otplogin", otpHandler.SendOTP) 22 | engine.POST("/otpverify", otpHandler.VerifyOTP) 23 | 24 | // Auth middleware 25 | engine.Use(middleware.UserAuthMiddleware) 26 | { 27 | payment := engine.Group("/payment") 28 | { 29 | payment.GET("/razorpay", paymentHandler.MakePaymentRazorPay) 30 | payment.GET("/verify-status", paymentHandler.VerifyPayment) 31 | } 32 | 33 | home := engine.Group("/home") 34 | { 35 | home.POST("/add-to-cart", cartHandler.AddtoCart) 36 | home.POST("/add-to-wishlist", wishlistHandler.AddtoWishlist) 37 | } 38 | 39 | profile := engine.Group("/profile") 40 | { 41 | profile.GET("/details", userHandler.GetUserDetails) 42 | profile.GET("/address", userHandler.GetAddresses) 43 | profile.POST("/address/add", userHandler.AddAddress) 44 | profile.PATCH("/edit", userHandler.EditUser) 45 | 46 | security := profile.Group("/security") 47 | { 48 | security.PATCH("/change-password", userHandler.ChangePassword) 49 | } 50 | // wallet := profile.Group("/wallet") 51 | // { 52 | // wallet.GET("", userHandler.GetWallet) 53 | // } 54 | orders := profile.Group("/orders") 55 | { 56 | orders.GET("", orderHandler.GetOrders) 57 | orders.POST("/cancel-order", orderHandler.CancelOrder) 58 | orders.POST("return-order", orderHandler.ReturnOrder) 59 | } 60 | } 61 | 62 | cart := engine.Group("/cart") 63 | { 64 | cart.GET("", userHandler.GetCart) 65 | cart.PATCH("/update-quantity-plus", userHandler.UpdateQuantityAdd) 66 | cart.PATCH("/update-quantity-minus", userHandler.UpdateQuantityLess) 67 | cart.DELETE("/remove", userHandler.RemoveFromCart) 68 | } 69 | wishlist := engine.Group("/wishlist") 70 | { 71 | wishlist.GET("", wishlistHandler.GetWishlist) 72 | wishlist.DELETE("/remove", wishlistHandler.RemoveFromWishlist) 73 | } 74 | checkout := engine.Group("/checkout") 75 | { 76 | checkout.GET("", cartHandler.CheckOut) 77 | checkout.GET("/download-invoice", orderHandler.DownloadInvoice) 78 | checkout.POST("/order", orderHandler.OrderItemsFromCart) 79 | } 80 | engine.GET("/coupons", couponHandler.Coupons) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /pkg/templates/razorpay.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Payment Gateway 7 | 13 | 14 | 20 | 21 |
24 |
25 |
Payment Details
26 |
27 |
{{.Username}}
28 |

{{.OrderID}}

29 |

Total : {{.FinalPrice}}

30 | 33 |
34 | 35 |
36 |
37 | 38 | 39 | 40 | 108 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /pkg/usecase/admin.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/helper" 8 | interfaces "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 9 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 10 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 11 | "golang.org/x/crypto/bcrypt" 12 | // "golang.org/x/crypto/bcrypt" 13 | ) 14 | 15 | type adminUsecase struct { 16 | adminRepository interfaces.AdminRepository 17 | } 18 | 19 | // constructor function 20 | func NewAdminUsecase(adRepo interfaces.AdminRepository) services.AdminUsecase { 21 | return &adminUsecase{ 22 | adminRepository: adRepo, 23 | } 24 | } 25 | 26 | func (au *adminUsecase) LoginHandler(adminDetails models.AdminLogin) (domain.AdminToken, error) { 27 | // Getting details of the admin based on the email provided 28 | 29 | adminCompareDetails, _ := au.adminRepository.LoginHandler(adminDetails) 30 | 31 | if adminCompareDetails.UserName != adminDetails.Email { 32 | 33 | return domain.AdminToken{}, errors.New("admin not exist") 34 | 35 | } 36 | // Compare password from database that provided by admin 37 | err := bcrypt.CompareHashAndPassword([]byte(adminCompareDetails.Password), []byte(adminDetails.Password)) 38 | 39 | if err != nil { 40 | return domain.AdminToken{}, err 41 | } 42 | 43 | var adminDetailsResponse models.AdminDetailsResponse 44 | 45 | // err = copier.Copy(&adminDetailsResponse, &adminCompareDetails) 46 | // if err != nil { 47 | // return domain.AdminToken{}, err 48 | // } 49 | 50 | adminDetailsResponse.ID = adminCompareDetails.ID 51 | adminDetailsResponse.Name = adminCompareDetails.Name 52 | adminDetailsResponse.Email = adminCompareDetails.UserName 53 | 54 | // fmt.Println("admindetails response id", adminDetailsResponse.ID) 55 | // fmt.Println("admin details response name", adminDetailsResponse.Name) 56 | // fmt.Println("admin details response email", adminDetailsResponse.Email) 57 | 58 | // fmt.Println("reached here--------------") 59 | 60 | token, refresh, err := helper.GenerateAdminToken(adminDetailsResponse) 61 | if err != nil { 62 | return domain.AdminToken{}, err 63 | } 64 | return domain.AdminToken{ 65 | Admin: adminDetailsResponse, 66 | Token: token, 67 | RefreshToken: refresh, 68 | }, nil 69 | } 70 | 71 | func (au *adminUsecase) BlockUser(id string) error { 72 | user, err := au.adminRepository.GetUserById(id) 73 | if err != nil { 74 | return errors.New("user not found") 75 | } 76 | if !user.Permission { 77 | return errors.New("already blocked") 78 | } else { 79 | user.Permission = false 80 | } 81 | err = au.adminRepository.UpdateBlockUserById(user) 82 | if err != nil { 83 | return err 84 | } 85 | return nil 86 | } 87 | 88 | func (au *adminUsecase) UnblockUser(id string) error { 89 | user, err := au.adminRepository.GetUserById(id) 90 | if err != nil { 91 | return errors.New("user not found") 92 | } 93 | if !user.Permission { 94 | // means that user is blocked(false)..then, 95 | user.Permission = true 96 | } 97 | err = au.adminRepository.UpdateBlockUserById(user) 98 | if err != nil { 99 | return errors.New("error in unblock user") 100 | } 101 | return nil 102 | } 103 | 104 | func (au *adminUsecase) GetUsers(page, limit int) ([]models.UserDetailsAtAdmin, error) { 105 | users, err := au.adminRepository.GetUsers(page, limit) 106 | if err != nil { 107 | return []models.UserDetailsAtAdmin{}, errors.New("getting users failed") 108 | } 109 | return users, nil 110 | 111 | } 112 | -------------------------------------------------------------------------------- /pkg/usecase/cart.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | 6 | // "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 7 | interfaces "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 8 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 10 | ) 11 | 12 | type CartUsecase struct { 13 | cartRepo interfaces.CartRepository 14 | invRepo interfaces.InventoryRespository 15 | userUsecase services.UserUsecase 16 | paymentUsecase services.PaymentUsecase 17 | } 18 | 19 | // Constructor funciton 20 | 21 | func NewCartUsecase(cartRepo interfaces.CartRepository, invRepo interfaces.InventoryRespository, userUsecase services.UserUsecase, paymentUsecase services.PaymentUsecase) *CartUsecase { 22 | return &CartUsecase{ 23 | cartRepo: cartRepo, 24 | invRepo: invRepo, 25 | userUsecase: userUsecase, 26 | paymentUsecase: paymentUsecase, 27 | } 28 | } 29 | 30 | func (cu *CartUsecase) AddToCart(user_id, inventory_id int) error { 31 | 32 | // check the product has quantity available 33 | stock, err := cu.invRepo.CheckStock(inventory_id) 34 | if err != nil { 35 | return errors.New("no stock") 36 | } 37 | if stock <= 0 { 38 | return errors.New("out of stock") 39 | } 40 | // Find user cart id 41 | cartId, err := cu.cartRepo.GetCartId(user_id) 42 | if err != nil { 43 | return errors.New("cart id not found") 44 | } 45 | // If user has no cart,create a cart 46 | if cartId == 0 { 47 | cartId, err = cu.cartRepo.CreateNewCart(user_id) 48 | if err != nil { 49 | return errors.New("cart creation failed") 50 | } 51 | } 52 | // Check if already added 53 | 54 | if cu.cartRepo.CheckIfInvAdded(inventory_id, cartId) { 55 | err := cu.cartRepo.AddQuantity(inventory_id, cartId) 56 | if err != nil { 57 | return err 58 | } 59 | return nil 60 | } 61 | // add product in line item 62 | err = cu.cartRepo.AddLineItems(inventory_id, cartId) 63 | if err != nil { 64 | return errors.New("product adding failed") 65 | } 66 | return nil 67 | } 68 | 69 | func (cu *CartUsecase) CheckOut(id int) (models.CheckOut, error) { 70 | 71 | // Getting address 72 | address, err := cu.cartRepo.GetAddresses(id) 73 | if err != nil { 74 | return models.CheckOut{}, errors.New("address not found") 75 | } 76 | products, err := cu.userUsecase.GetCart(id) 77 | if err != nil { 78 | return models.CheckOut{}, err 79 | } 80 | paymentMethod, err := cu.paymentUsecase.GetPaymentMethods() 81 | if err != nil { 82 | return models.CheckOut{}, err 83 | } 84 | var price, discount float64 85 | 86 | for _, v := range products.Values { 87 | discount += v.DiscountPrice 88 | price += v.Total 89 | } 90 | 91 | var checkOut models.CheckOut 92 | checkOut.CartId = products.Id 93 | checkOut.Addresses = address 94 | checkOut.Products = products.Values 95 | checkOut.PaymentMethods = paymentMethod 96 | checkOut.TotalPrice = price 97 | checkOut.DiscountPrice = discount 98 | 99 | return checkOut, nil 100 | } 101 | -------------------------------------------------------------------------------- /pkg/usecase/category.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 9 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 10 | ) 11 | 12 | type categoryUsecase struct { 13 | repo interfaces.CategoryRepository 14 | } 15 | 16 | // constructor function 17 | 18 | func NewCategoryUsecase(repo interfaces.CategoryRepository) services.CategoryUsecase { 19 | return &categoryUsecase{ 20 | repo: repo, 21 | } 22 | } 23 | 24 | func (catU *categoryUsecase) AddCategory(category string) (domain.Category, error) { 25 | productResponse, err := catU.repo.AddCategory(category) 26 | if err != nil { 27 | fmt.Println("error from cat usecase ",err) 28 | return domain.Category{}, err 29 | } 30 | return productResponse, nil 31 | } 32 | 33 | func (catU *categoryUsecase) UpdateCategory(currrent, new string) (domain.Category, error) { 34 | result, err := catU.repo.CheckCategory(currrent) 35 | if err != nil { 36 | return domain.Category{}, err 37 | } 38 | if !result { 39 | return domain.Category{}, errors.New("no category as you mentioned") 40 | } 41 | newCat, err := catU.UpdateCategory(currrent, new) 42 | if err != nil { 43 | return domain.Category{}, err 44 | } 45 | return newCat, nil 46 | } 47 | 48 | func (catU *categoryUsecase) DeleteCategory(categoryId string) error { 49 | err := catU.repo.DeleteCategory(categoryId) 50 | if err != nil { 51 | return err 52 | } 53 | return nil 54 | } 55 | 56 | func (catU *categoryUsecase) GetCategories() ([]domain.Category, error) { 57 | categories, err := catU.repo.GetCategories() 58 | if err != nil { 59 | return []domain.Category{}, errors.New("categories not found") 60 | } 61 | return categories, nil 62 | } 63 | -------------------------------------------------------------------------------- /pkg/usecase/coupon.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 7 | interfaces "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 8 | services"github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 10 | ) 11 | 12 | type couponUsecase struct { 13 | couponRepo interfaces.CouponRepository 14 | } 15 | 16 | // constructor function 17 | 18 | func NewCouponUsecase(couponRepo interfaces.CouponRepository) services.CouponUsecase { 19 | return &couponUsecase{ 20 | couponRepo: couponRepo, 21 | } 22 | } 23 | 24 | func (coupU *couponUsecase) Addcoupon(coupon models.Coupon) error { 25 | if err := coupU.couponRepo.AddCoupon(coupon); err != nil { 26 | return errors.New("coupon adding failed") 27 | } 28 | return nil 29 | } 30 | 31 | func (coupU *couponUsecase) MakeCouponInvalid(id int) error { 32 | if err := coupU.couponRepo.MakeCouponInvalid(id); err != nil { 33 | return err 34 | } 35 | return nil 36 | } 37 | 38 | func (coupU *couponUsecase) GetCoupons() ([]domain.Coupon, error) { 39 | coupons, err := coupU.couponRepo.GetCoupons() 40 | if err != nil { 41 | return []domain.Coupon{}, err 42 | } 43 | return coupons, nil 44 | } 45 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/admin.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type AdminUsecase interface { 9 | LoginHandler(adminDetails models.AdminLogin) (domain.AdminToken, error) 10 | BlockUser(id string) error 11 | UnblockUser(id string) error 12 | GetUsers(page, limit int) ([]models.UserDetailsAtAdmin, error) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/cart.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 4 | 5 | type CartUsecase interface { 6 | AddToCart(user_id, inventory_id int) error 7 | CheckOut(id int) (models.CheckOut, error) 8 | } 9 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/category.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | ) 6 | 7 | type CategoryUsecase interface { 8 | AddCategory(category string) (domain.Category, error) 9 | UpdateCategory(currrent, new string) (domain.Category, error) 10 | DeleteCategory(categoryId string) error 11 | GetCategories() ([]domain.Category, error) 12 | } 13 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/coupon.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type CouponUsecase interface { 9 | Addcoupon(coupon models.Coupon) error 10 | MakeCouponInvalid(id int) error 11 | GetCoupons() ([]domain.Coupon, error) 12 | } 13 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/inventory.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "mime/multipart" 5 | 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 7 | ) 8 | 9 | type InventoryUsecase interface { 10 | AddInventory(inventory models.Inventory, image *multipart.FileHeader) (models.InventoryResponse, error) 11 | UpdateInventory(invID int, invData models.UpdateInventory) (models.Inventory, error) 12 | UpdateImage(invID int, image *multipart.FileHeader) (models.Inventory, error) 13 | DeleteInventory(id string) error 14 | 15 | ShowIndividualProducts(id string) (models.InventoryDetails, error) 16 | ListProducts(page int, limit int) ([]models.InventoryList, error) 17 | SearchProducts(key string, page, limit int) ([]models.InventoryList, error) 18 | GetCategoryProducts(catID int, page, limit int) ([]models.InventoryList, error) 19 | AddImage(product_id int, image *multipart.FileHeader) (models.InventoryResponse, error) 20 | DeleteImage(product_id, image_id int) error 21 | } 22 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/offer.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type OfferUsecase interface { 9 | AddNewOffer(model models.CreateOffer) error 10 | MakeOfferExpire(catID int) error 11 | GetOffers(page, limit int) ([]domain.Offer, error) 12 | } 13 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/order.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type OrderUsecase interface { 9 | GetOrders(id, page, limit int) ([]domain.Order, error) 10 | OrderItemsFromCart(userid int, addressid int, paymentid int, couponid int) error 11 | CancelOrder(id, orderid int) error 12 | EditOrderStatus(status string, id int) error 13 | MarkAsPaid(orderID int) error 14 | AdminOrders() (domain.AdminOrderResponse, error) 15 | DailyOrders() (domain.SalesReport, error) 16 | WeeklyOrders() (domain.SalesReport, error) 17 | MonthlyOrders() (domain.SalesReport, error) 18 | AnnualOrders() (domain.SalesReport, error) 19 | CustomDateOrders(dates models.CustomDates) (domain.SalesReport, error) 20 | ReturnOrder(id int) error 21 | } 22 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/otp.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 4 | 5 | type OtpUsecase interface { 6 | VerifyOTP(code models.VerifyData) (models.UserToken, error) 7 | SendOTP(phone string) error 8 | } 9 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/payment.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | // "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type PaymentUsecase interface { 9 | AddNewPaymentMethod(paymentMethod string) error 10 | RemovePaymentMethod(paymentMethodID int) error 11 | GetPaymentMethods() ([]models.PaymentMethod, error) 12 | MakePaymentRazorPay(orderID string, userID int) (models.OrderPaymentDetails, error) 13 | VerifyPayment(paymentID string, razorID string, orderID string) error 14 | } 15 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/user.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import ( 4 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 5 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 6 | ) 7 | 8 | type UserUsecase interface { 9 | Login(user models.UserLogin) (models.UserToken, error) 10 | SignUp(user models.UserDetails) (models.UserToken, error) 11 | AddAddress(id int, address models.AddAddress) error 12 | GetAddresses(id int) ([]domain.Address, error) 13 | GetUserDetails(id int) (models.UserDetailsResponse, error) 14 | 15 | ChangePassword(id int, old string, password string, repassword string) error 16 | EditUser(id int, userData models.EditUser) error 17 | 18 | GetCartID(userID int) (int, error) 19 | GetCart(id int) (models.GetCartResponse, error) 20 | RemoveFromCart(id int, inventoryID int) error 21 | ClearCart(cartID int) error 22 | UpdateQuantityAdd(id, inv_id int) error 23 | UpdateQuantityLess(id, inv_id int) error 24 | 25 | // GetWallet(id, page, limit int) (models.Wallet, error) 26 | } 27 | -------------------------------------------------------------------------------- /pkg/usecase/interfaces/wishlist.go: -------------------------------------------------------------------------------- 1 | package interfaces 2 | 3 | import "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 4 | 5 | type WishlistUsecase interface { 6 | AddToWishlist(user_id, inventory_id int) error 7 | GetWishlistID(userID int) (int, error) 8 | GetWishlist(id int) ([]models.GetWishlist, error) 9 | RemoveFromWishlist(id int, inventoryID int) error 10 | } 11 | -------------------------------------------------------------------------------- /pkg/usecase/inventory.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | "mime/multipart" 6 | "strconv" 7 | 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/helper" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 10 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 11 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 12 | ) 13 | 14 | type inventoryUsecase struct { 15 | invRepo interfaces.InventoryRespository 16 | } 17 | 18 | // constructor function 19 | func NewInventoryUsecase(invRepo interfaces.InventoryRespository) services.InventoryUsecase { 20 | return &inventoryUsecase{ 21 | invRepo: invRepo, 22 | } 23 | } 24 | 25 | func (invU *inventoryUsecase) AddInventory(inventory models.Inventory, image *multipart.FileHeader) (models.InventoryResponse, error) { 26 | url, err := helper.AddImageToS3(image) 27 | if err != nil { 28 | return models.InventoryResponse{}, err 29 | } 30 | inventory.Image = url 31 | 32 | // Send the url and save in db 33 | inventoryResponse, err := invU.invRepo.AddInventory(inventory, url) 34 | if err != nil { 35 | return models.InventoryResponse{}, err 36 | } 37 | return inventoryResponse, nil 38 | } 39 | 40 | func (invU *inventoryUsecase) UpdateImage(invID int, image *multipart.FileHeader) (models.Inventory, error) { 41 | url, err := helper.AddImageToS3(image) 42 | if err != nil { 43 | return models.Inventory{}, err 44 | } 45 | 46 | inventoryResponse, err := invU.invRepo.UpdateImage(invID, url) 47 | if err != nil { 48 | return models.Inventory{}, err 49 | } 50 | return inventoryResponse, nil 51 | } 52 | 53 | func (invU *inventoryUsecase) UpdateInventory(invID int, invData models.UpdateInventory) (models.Inventory, error) { 54 | result, err := invU.invRepo.CheckInventory(invID) 55 | if err != nil { 56 | return models.Inventory{}, err 57 | } 58 | if !result { 59 | return models.Inventory{}, errors.New("there is no inventory as you mentioned") 60 | } 61 | newinventory, err := invU.invRepo.UpdateInventory(invID, invData) 62 | if err != nil { 63 | return models.Inventory{}, err 64 | } 65 | return newinventory, nil 66 | } 67 | 68 | func (invU *inventoryUsecase) DeleteInventory(id string) error { 69 | if err := invU.invRepo.DeleteInventory(id); err != nil { 70 | return err 71 | } 72 | return nil 73 | } 74 | 75 | func (invU *inventoryUsecase) ShowIndividualProducts(id string) (models.InventoryDetails, error) { 76 | product, err := invU.invRepo.ShowIndividualProducts(id) 77 | if err != nil { 78 | return models.InventoryDetails{}, err 79 | } 80 | productId, err := strconv.Atoi(id) 81 | if err != nil { 82 | return models.InventoryDetails{}, err 83 | } 84 | var AdditionalImage []models.ImagesInfo 85 | AdditionalImage, err = invU.invRepo.GetImagesFromInventoryId(productId) 86 | if err != nil { 87 | return models.InventoryDetails{}, err 88 | } 89 | InvDetails := models.InventoryDetails{Inventory: product, AdditionalImages: AdditionalImage} 90 | return InvDetails, nil 91 | } 92 | 93 | func (invU *inventoryUsecase) ListProducts(page int, limit int) ([]models.InventoryList, error) { 94 | productDetails, err := invU.invRepo.ListProducts(page, limit) 95 | 96 | if err != nil { 97 | return []models.InventoryList{}, err 98 | } 99 | return productDetails, nil 100 | } 101 | 102 | func (invU *inventoryUsecase) SearchProducts(key string, page, limit int) ([]models.InventoryList, error) { 103 | productsDetails, err := invU.invRepo.SearchProducts(key, page, limit) 104 | if err != nil { 105 | return []models.InventoryList{}, err 106 | } 107 | return productsDetails, nil 108 | } 109 | 110 | func (invU *inventoryUsecase) GetCategoryProducts(catID int, page, limit int) ([]models.InventoryList, error) { 111 | productsDetails, err := invU.invRepo.GetCategoryProducts(catID, page, limit) 112 | if err != nil { 113 | return []models.InventoryList{}, err 114 | } 115 | return productsDetails, nil 116 | } 117 | 118 | func (invU *inventoryUsecase) AddImage(product_id int, image *multipart.FileHeader) (models.InventoryResponse, error) { 119 | // adding the image to Aws s3 bucket 120 | imageUrl, err := helper.AddImageToS3(image) 121 | if err!=nil{ 122 | return models.InventoryResponse{},err 123 | } 124 | 125 | inventoryResponse, err := invU.invRepo.AddImage(product_id, imageUrl) 126 | if err != nil { 127 | return models.InventoryResponse{}, err 128 | } 129 | return inventoryResponse, nil 130 | } 131 | 132 | func (invU *inventoryUsecase) DeleteImage(product_id, image_id int) error { 133 | if err := invU.invRepo.DeleteImage(product_id, image_id); err != nil { 134 | return errors.New("image not deleted") 135 | } 136 | return nil 137 | } 138 | -------------------------------------------------------------------------------- /pkg/usecase/offer.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 7 | interfaces "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 8 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 10 | ) 11 | 12 | type offerUsecase struct { 13 | offerRepo interfaces.OfferRepository 14 | } 15 | 16 | // constructor function 17 | 18 | func NewOfferUsecase(offerRepo interfaces.OfferRepository) services.OfferUsecase { 19 | return &offerUsecase{ 20 | offerRepo: offerRepo, 21 | } 22 | } 23 | 24 | func (offU *offerUsecase) AddNewOffer(model models.CreateOffer) error { 25 | if err := offU.offerRepo.AddNewOffer(model); err != nil { 26 | return errors.New("adding offer failed") 27 | } 28 | return nil 29 | } 30 | 31 | func (offU *offerUsecase) MakeOfferExpire(catID int) error { 32 | if err := offU.offerRepo.MakeOfferExpired(catID); err != nil { 33 | return err 34 | } 35 | return nil 36 | } 37 | 38 | func (offU *offerUsecase) GetOffers(page, limit int) ([]domain.Offer, error) { 39 | offers, err := offU.offerRepo.GetOffers(page, limit) 40 | if err != nil { 41 | return []domain.Offer{}, err 42 | } 43 | return offers, nil 44 | } 45 | -------------------------------------------------------------------------------- /pkg/usecase/order.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/helper" 10 | interfaces "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 11 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 12 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 13 | ) 14 | 15 | type orderUsecase struct { 16 | orderRepo interfaces.OrderRepository 17 | userUsecase services.UserUsecase 18 | // walletRepo interfaces.WalletRepository 19 | couponRepo interfaces.CouponRepository 20 | } 21 | 22 | func NewOrderUsecase(orderRepo interfaces.OrderRepository, userUsecase services.UserUsecase /*walletRepo interfaces.WalletRepository*/, couponRepo interfaces.CouponRepository) services.OrderUsecase { 23 | return &orderUsecase{ 24 | orderRepo: orderRepo, 25 | userUsecase: userUsecase, 26 | // walletRepo: walletRepo, 27 | couponRepo: couponRepo, 28 | } 29 | } 30 | 31 | func (orU *orderUsecase) GetOrders(id, page, limit int) ([]domain.Order, error) { 32 | orders, err := orU.orderRepo.GetOrders(id, page, limit) 33 | if err != nil { 34 | return []domain.Order{}, err 35 | } 36 | return orders, nil 37 | } 38 | 39 | func (orU *orderUsecase) OrderItemsFromCart(userid int, addressid int, paymentid int, couponid int) error { 40 | cart, err := orU.userUsecase.GetCart(userid) 41 | if err != nil { 42 | return err 43 | } 44 | 45 | var total float64 46 | for _, v := range cart.Values { 47 | total = total + v.DiscountPrice 48 | } 49 | // Find discount if any 50 | coupon, err := orU.couponRepo.FindCouponDetails(couponid) 51 | if err != nil { 52 | return err 53 | } 54 | totalDiscount := (total * float64(coupon.DiscountRate)) / 100 55 | total = total - totalDiscount 56 | 57 | order_id, err := orU.orderRepo.OrderItems(userid, addressid, paymentid, total, coupon.Coupon) 58 | if err != nil { 59 | return err 60 | } 61 | if err := orU.orderRepo.AddOrderProducts(order_id, cart.Values); err != nil { 62 | return err 63 | } 64 | for _, v := range cart.Values { 65 | if err := orU.userUsecase.RemoveFromCart(cart.Id, v.Id); err != nil { 66 | return err 67 | } 68 | } 69 | return nil 70 | 71 | } 72 | 73 | func (orU *orderUsecase) EditOrderStatus(status string, id int) error { 74 | if err := orU.orderRepo.EditOrderStatus(status, id); err != nil { 75 | return err 76 | } 77 | return nil 78 | } 79 | 80 | func (orU *orderUsecase) MarkAsPaid(orderID int) error { 81 | if err := orU.orderRepo.MarkAsPaid(orderID); err != nil { 82 | return err 83 | } 84 | return nil 85 | } 86 | 87 | func (orU *orderUsecase) AdminOrders() (domain.AdminOrderResponse, error) { 88 | var response domain.AdminOrderResponse 89 | 90 | pending, err := orU.orderRepo.AdminOrders("PENDING") 91 | if err != nil { 92 | return domain.AdminOrderResponse{}, err 93 | } 94 | shipped, err := orU.orderRepo.AdminOrders("SHIPPED") 95 | if err != nil { 96 | return domain.AdminOrderResponse{}, err 97 | } 98 | delivered, err := orU.orderRepo.AdminOrders("DELIVERED") 99 | if err != nil { 100 | return domain.AdminOrderResponse{}, err 101 | } 102 | returned, err := orU.orderRepo.AdminOrders("RETURNED") 103 | if err != nil { 104 | return domain.AdminOrderResponse{}, err 105 | } 106 | canceled, err := orU.orderRepo.AdminOrders("CANCELED") 107 | if err != nil { 108 | return domain.AdminOrderResponse{}, err 109 | } 110 | 111 | response.Pending = pending 112 | response.Shipped = shipped 113 | response.Delivered = delivered 114 | response.Returned = returned 115 | response.Canceled = canceled 116 | 117 | return response, nil 118 | 119 | } 120 | 121 | func (orU *orderUsecase) DailyOrders() (domain.SalesReport, error) { 122 | var SalesReport domain.SalesReport 123 | endDate := time.Now() 124 | startDate := time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 0, 0, 0, 0, time.UTC) 125 | SalesReport.Orders, _ = orU.orderRepo.GetOrdersInRange(startDate, endDate) 126 | SalesReport.TotalOrders = len(SalesReport.Orders) 127 | total := 0.0 128 | 129 | for _, items := range SalesReport.Orders { 130 | total += items.Price 131 | } 132 | SalesReport.TotalRevenue = total 133 | 134 | products, err := orU.orderRepo.GetProductsQuantity() 135 | if err != nil { 136 | return domain.SalesReport{}, err 137 | } 138 | bestSellerIds := helper.FindMostBroughtProduct(products) 139 | 140 | var bestSellers []string 141 | 142 | for _, items := range bestSellerIds { 143 | 144 | product, err := orU.orderRepo.GetProductNameFromId(items) 145 | if err != nil { 146 | return domain.SalesReport{}, err 147 | } 148 | bestSellers = append(bestSellers, product) 149 | } 150 | SalesReport.BestSellers = bestSellers 151 | 152 | return SalesReport, nil 153 | } 154 | 155 | func (orU *orderUsecase) WeeklyOrders() (domain.SalesReport, error) { 156 | var SalesReport domain.SalesReport 157 | endDate := time.Now() 158 | startDate := endDate.Add(-time.Duration(endDate.Weekday()) * 24 * time.Hour) 159 | SalesReport.Orders, _ = orU.orderRepo.GetOrdersInRange(startDate, endDate) 160 | SalesReport.TotalOrders = len(SalesReport.Orders) 161 | total := 0.0 162 | 163 | for _, items := range SalesReport.Orders { 164 | total += items.Price 165 | } 166 | SalesReport.TotalRevenue = total 167 | 168 | products, err := orU.orderRepo.GetProductsQuantity() 169 | if err != nil { 170 | return domain.SalesReport{}, err 171 | } 172 | bestSellerIds := helper.FindMostBroughtProduct(products) 173 | 174 | var bestSellers []string 175 | 176 | for _, items := range bestSellerIds { 177 | 178 | product, err := orU.orderRepo.GetProductNameFromId(items) 179 | if err != nil { 180 | return domain.SalesReport{}, err 181 | } 182 | bestSellers = append(bestSellers, product) 183 | } 184 | SalesReport.BestSellers = bestSellers 185 | 186 | return SalesReport, nil 187 | } 188 | 189 | func (orU *orderUsecase) MonthlyOrders() (domain.SalesReport, error) { 190 | var SalesReport domain.SalesReport 191 | endDate := time.Now() 192 | startDate := time.Date(endDate.Year(), endDate.Month(), 1, 0, 0, 0, 0, time.UTC) 193 | SalesReport.Orders, _ = orU.orderRepo.GetOrdersInRange(startDate, endDate) 194 | SalesReport.TotalOrders = len(SalesReport.Orders) 195 | total := 0.0 196 | 197 | for _, items := range SalesReport.Orders { 198 | total += items.Price 199 | } 200 | SalesReport.TotalRevenue = total 201 | 202 | products, err := orU.orderRepo.GetProductsQuantity() 203 | if err != nil { 204 | return domain.SalesReport{}, err 205 | } 206 | bestSellerIds := helper.FindMostBroughtProduct(products) 207 | 208 | var bestSellers []string 209 | 210 | for _, items := range bestSellerIds { 211 | 212 | product, err := orU.orderRepo.GetProductNameFromId(items) 213 | if err != nil { 214 | return domain.SalesReport{}, err 215 | } 216 | bestSellers = append(bestSellers, product) 217 | } 218 | SalesReport.BestSellers = bestSellers 219 | 220 | return SalesReport, nil 221 | } 222 | func (orU *orderUsecase) AnnualOrders() (domain.SalesReport, error) { 223 | var SalesReport domain.SalesReport 224 | endDate := time.Now() 225 | startDate := time.Date(endDate.Year(), 1, 1, 0, 0, 0, 0, time.UTC) 226 | SalesReport.Orders, _ = orU.orderRepo.GetOrdersInRange(startDate, endDate) 227 | SalesReport.TotalOrders = len(SalesReport.Orders) 228 | total := 0.0 229 | 230 | for _, items := range SalesReport.Orders { 231 | total += items.Price 232 | } 233 | SalesReport.TotalRevenue = total 234 | 235 | products, err := orU.orderRepo.GetProductsQuantity() 236 | if err != nil { 237 | return domain.SalesReport{}, err 238 | } 239 | bestSellerIds := helper.FindMostBroughtProduct(products) 240 | 241 | var bestSellers []string 242 | 243 | for _, items := range bestSellerIds { 244 | 245 | product, err := orU.orderRepo.GetProductNameFromId(items) 246 | if err != nil { 247 | return domain.SalesReport{}, err 248 | } 249 | bestSellers = append(bestSellers, product) 250 | } 251 | SalesReport.BestSellers = bestSellers 252 | 253 | return SalesReport, nil 254 | } 255 | 256 | func (orU *orderUsecase) CustomDateOrders(dates models.CustomDates) (domain.SalesReport, error) { 257 | var SalesReport domain.SalesReport 258 | endDate := dates.EndDate 259 | startDate := dates.StartingDate 260 | SalesReport.Orders, _ = orU.orderRepo.GetOrdersInRange(startDate, endDate) 261 | SalesReport.TotalOrders = len(SalesReport.Orders) 262 | total := 0.0 263 | 264 | for _, items := range SalesReport.Orders { 265 | total += items.Price 266 | } 267 | SalesReport.TotalRevenue = total 268 | 269 | products, err := orU.orderRepo.GetProductsQuantity() 270 | if err != nil { 271 | return domain.SalesReport{}, err 272 | } 273 | bestSellerIds := helper.FindMostBroughtProduct(products) 274 | 275 | var bestSellers []string 276 | 277 | for _, items := range bestSellerIds { 278 | 279 | product, err := orU.orderRepo.GetProductNameFromId(items) 280 | if err != nil { 281 | return domain.SalesReport{}, err 282 | } 283 | bestSellers = append(bestSellers, product) 284 | } 285 | SalesReport.BestSellers = bestSellers 286 | 287 | return SalesReport, nil 288 | } 289 | 290 | func (orU *orderUsecase) ReturnOrder(id int) error { 291 | 292 | status, err := orU.orderRepo.CheckOrderStatus(id) 293 | if err != nil { 294 | return err 295 | } 296 | if status == "RETURNED" { 297 | return errors.New("item already returned") 298 | } 299 | 300 | if status != "DELIVERED" { 301 | return errors.New("user is trying to return an item which is still not delivered") 302 | } 303 | 304 | // make order is return order 305 | if err := orU.orderRepo.ReturnOrder(id); err != nil { 306 | return err 307 | } 308 | // find amount to return to user 309 | 310 | amount, err := orU.orderRepo.FindAmountFromOrderID(id) 311 | fmt.Println(amount) 312 | if err != nil { 313 | return err 314 | } 315 | // find the user 316 | 317 | userId, err := orU.orderRepo.FindUserIdFromOrderID(id) 318 | fmt.Println(userId) 319 | if err != nil { 320 | return err 321 | } 322 | // find if the user having a wallet 323 | walletId, err := orU.orderRepo.FindWalletIdFromUserID(userId) 324 | fmt.Println(walletId) 325 | if err != nil { 326 | return err 327 | } 328 | // if no wallet,create new wallet for user 329 | 330 | if walletId == 0 { 331 | walletId, err = orU.orderRepo.CreateNewWallet(userId) 332 | if err != nil { 333 | return err 334 | } 335 | } 336 | // credit the amount into user wallet 337 | if err := orU.orderRepo.CreditToUserWallet(amount, walletId); err != nil { 338 | return err 339 | } 340 | return nil 341 | } 342 | 343 | func (orU *orderUsecase) CancelOrder(id, orderid int) error { 344 | 345 | status, err := orU.orderRepo.CheckOrderStatus(orderid) 346 | if err != nil { 347 | return err 348 | } 349 | if status == "CANCELLED" { 350 | return errors.New("item already cancelled") 351 | } 352 | if status == "DELIVERED" { 353 | return errors.New("item delivered") 354 | } 355 | 356 | if status == "PENDING" || status == "SHIPPED" { 357 | if err := orU.orderRepo.CancelOrder(orderid); err != nil { 358 | return err 359 | } 360 | } 361 | // check if already payed 362 | 363 | paymentStatus, err := orU.orderRepo.CheckPaymentStatus(orderid) 364 | if err != nil { 365 | return err 366 | } 367 | if paymentStatus != "PAID" { 368 | return nil 369 | } 370 | 371 | // find amount 372 | amount, err := orU.orderRepo.FindAmountFromOrderID(id) 373 | fmt.Println(amount) 374 | if err != nil { 375 | return err 376 | } 377 | 378 | return nil 379 | } 380 | -------------------------------------------------------------------------------- /pkg/usecase/otp.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/Anandhu4456/go-Ecommerce/pkg/config" 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/helper" 8 | interfaces "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 9 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 10 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 11 | "github.com/jinzhu/copier" 12 | ) 13 | 14 | type otpUsecase struct { 15 | cfg config.Config 16 | otpRepo interfaces.OtpRepository 17 | } 18 | 19 | // constructor function 20 | func NewOtpUsecase(cfg config.Config, otpRepo interfaces.OtpRepository) services.OtpUsecase { 21 | return &otpUsecase{ 22 | cfg: cfg, 23 | otpRepo: otpRepo, 24 | } 25 | } 26 | 27 | func (otU *otpUsecase) SendOTP(phone string) error { 28 | ok := otU.otpRepo.FindUserByMobileNumber(phone) 29 | if !ok { 30 | return errors.New("phone number not found") 31 | } 32 | helper.TwilioSetup(otU.cfg.ACCOUNTSID, otU.cfg.AUTHTOKEN) 33 | _, err := helper.TwilioSendOTP(phone, otU.cfg.SERVICEID) 34 | if err != nil { 35 | return errors.New("error occured while generating OTP") 36 | } 37 | return nil 38 | } 39 | 40 | func (otU *otpUsecase) VerifyOTP(code models.VerifyData) (models.UserToken, error) { 41 | helper.TwilioSetup(otU.cfg.ACCOUNTSID, otU.cfg.AUTHTOKEN) 42 | if err := helper.TwilioVerifyOTP(otU.cfg.SERVICEID, code.Code, code.PhoneNumber); err != nil { 43 | return models.UserToken{}, errors.New("error while verifying OTP") 44 | } 45 | // getting user details to generate user token after verify OTP 46 | userDetails, err := otU.otpRepo.UserDetailsUsingPhone(code.PhoneNumber) 47 | if err != nil { 48 | return models.UserToken{}, err 49 | } 50 | tokenString, err := helper.GenerateUserToken(userDetails) 51 | if err != nil { 52 | return models.UserToken{}, err 53 | } 54 | 55 | var userResponse models.UserDetailsResponse 56 | err = copier.Copy(&userResponse,&userDetails) 57 | if err!=nil{ 58 | return models.UserToken{},err 59 | } 60 | return models.UserToken{ 61 | User: userResponse, 62 | Token: tokenString, 63 | }, nil 64 | } 65 | -------------------------------------------------------------------------------- /pkg/usecase/payment.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strconv" 7 | 8 | interfaces "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 9 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 10 | "github.com/razorpay/razorpay-go" 11 | ) 12 | 13 | type paymentUsecase struct { 14 | paymentRepo interfaces.PaymentRepository 15 | userRepo interfaces.UserRepository 16 | } 17 | 18 | // Constructor function 19 | func NewPaymentUsecase(paymentRepo interfaces.PaymentRepository, userRepo interfaces.UserRepository) *paymentUsecase { 20 | return &paymentUsecase{ 21 | paymentRepo: paymentRepo, 22 | userRepo: userRepo, 23 | } 24 | } 25 | 26 | func (payU *paymentUsecase) AddNewPaymentMethod(paymentMethod string) error { 27 | if paymentMethod == "" { 28 | return errors.New("enter payment method") 29 | } 30 | if err := payU.paymentRepo.AddNewPaymentMethod(paymentMethod); err != nil { 31 | return err 32 | } 33 | return nil 34 | } 35 | 36 | func (payU *paymentUsecase) RemovePaymentMethod(paymentMethodID int) error { 37 | if paymentMethodID == 0 { 38 | return errors.New("enter method id") 39 | } 40 | if err := payU.paymentRepo.RemovePaymentMethod(paymentMethodID); err != nil { 41 | return err 42 | } 43 | return nil 44 | } 45 | 46 | func (payU *paymentUsecase) GetPaymentMethods() ([]models.PaymentMethod, error) { 47 | paymentMethods, err := payU.paymentRepo.GetPaymentMethods() 48 | if err != nil { 49 | return []models.PaymentMethod{}, err 50 | } 51 | return paymentMethods, nil 52 | } 53 | 54 | func (payU *paymentUsecase) MakePaymentRazorPay(orderID string, userID int) (models.OrderPaymentDetails, error) { 55 | var orderDetails models.OrderPaymentDetails 56 | 57 | // Get order id 58 | orderId, err := strconv.Atoi(orderID) 59 | if err != nil { 60 | return models.OrderPaymentDetails{}, err 61 | } 62 | orderDetails.OrderID = orderId 63 | orderDetails.UserID = userID 64 | 65 | // Get username 66 | username, err := payU.paymentRepo.FindUsername(userID) 67 | if err != nil { 68 | return models.OrderPaymentDetails{}, err 69 | } 70 | orderDetails.Username = username 71 | 72 | // Get total 73 | total, err := payU.paymentRepo.FindPrice(orderId) 74 | if err != nil { 75 | return models.OrderPaymentDetails{}, err 76 | } 77 | orderDetails.FinalPrice = total 78 | 79 | // need to add key and secret 80 | client := razorpay.NewClient("key", "secret") 81 | 82 | data := map[string]interface{}{ 83 | "amount": int(orderDetails.FinalPrice) * 100, 84 | "currency": "INR", 85 | "receipt": "some receipt id", 86 | } 87 | 88 | fmt.Println("razorpay::91", orderDetails, data) 89 | 90 | body, err := client.Order.Create(data, nil) 91 | if err != nil { 92 | fmt.Println(err) 93 | return models.OrderPaymentDetails{}, err 94 | } 95 | razorpayOrderId := body["id"].(int) 96 | orderDetails.RazorID = razorpayOrderId 97 | 98 | fmt.Println("razorpay::100", orderDetails) 99 | 100 | return orderDetails, nil 101 | } 102 | 103 | func (payU *paymentUsecase) VerifyPayment(paymentID string, razorID string, orderID string) error { 104 | 105 | if err := payU.paymentRepo.UpdatePaymentDetails(orderID, paymentID, razorID); err != nil { 106 | return err 107 | } 108 | 109 | // Clear cart 110 | // orderIdInt, err := strconv.Atoi(orderID) 111 | // if err != nil { 112 | // return err 113 | // } 114 | 115 | // userId, err := payU.userRepo.FindUserIDByOrderID(orderIdInt) 116 | // if err != nil { 117 | // return err 118 | // } 119 | // cartId, err := payU.userRepo.GetCartID(userId) 120 | // if err != nil { 121 | // return err 122 | // } 123 | // if err := payU.userRepo.ClearCart(cartId); err != nil { 124 | // return err 125 | // } 126 | return nil 127 | } 128 | -------------------------------------------------------------------------------- /pkg/usecase/user.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/Anandhu4456/go-Ecommerce/pkg/domain" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/helper" 9 | interfaces "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 10 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 11 | "golang.org/x/crypto/bcrypt" 12 | ) 13 | 14 | type userUsecase struct { 15 | userRepo interfaces.UserRepository 16 | offerRepo interfaces.OfferRepository 17 | orderRepo interfaces.OrderRepository 18 | } 19 | 20 | func NewUserUsecase(userRepo interfaces.UserRepository, offerRepo interfaces.OfferRepository, orderRepo interfaces.OrderRepository) *userUsecase { 21 | return &userUsecase{ 22 | userRepo: userRepo, 23 | offerRepo: offerRepo, 24 | orderRepo: orderRepo, 25 | } 26 | } 27 | 28 | func (usrU *userUsecase) Login(user models.UserLogin) (models.UserToken, error) { 29 | // check the user already exist or not 30 | 31 | ok := usrU.userRepo.CheckUserAvailability(user.Email) 32 | if !ok { 33 | return models.UserToken{}, errors.New("user not exist") 34 | } 35 | // check admin blocked this user or not 36 | permission, err := usrU.userRepo.UserBlockStatus(user.Email) 37 | if err != nil { 38 | return models.UserToken{}, err 39 | } 40 | if !permission { 41 | return models.UserToken{}, errors.New("user is blocked by admin") 42 | } 43 | // Get the user details in order to check password 44 | user_details, err := usrU.userRepo.FindUserByEmail(user) 45 | if err != nil { 46 | return models.UserToken{}, err 47 | } 48 | // check the password 49 | err = bcrypt.CompareHashAndPassword([]byte(user_details.Password), []byte(user.Password)) 50 | if err != nil { 51 | return models.UserToken{}, errors.New("password incorrect") 52 | } 53 | 54 | var userResponse models.UserDetailsResponse 55 | userResponse.Id = int(user_details.Id) 56 | userResponse.Name = user_details.Name 57 | userResponse.Email = user_details.Email 58 | userResponse.Phone = user_details.Phone 59 | 60 | // generate token 61 | tokenString, err := helper.GenerateUserToken(userResponse) 62 | if err != nil { 63 | return models.UserToken{}, errors.New("could't create token for user") 64 | } 65 | return models.UserToken{ 66 | User: userResponse, 67 | Token: tokenString, 68 | }, nil 69 | } 70 | 71 | func (usrU *userUsecase) SignUp(user models.UserDetails) (models.UserToken, error) { 72 | // check the user exist or not,if exist show the error(its a signup function) 73 | 74 | userExist := usrU.userRepo.CheckUserAvailability(user.Email) 75 | if userExist { 76 | return models.UserToken{}, errors.New("user already exist please sign in") 77 | } 78 | if user.Password != user.ConfirmPassword { 79 | return models.UserToken{}, errors.New("password does't match") 80 | } 81 | // hash the password 82 | hashedPass, err := helper.PasswordHashing(user.Password) 83 | if err != nil { 84 | return models.UserToken{}, err 85 | } 86 | user.Password = hashedPass 87 | // insert the user into database 88 | userData, err := usrU.userRepo.SignUp(user) 89 | if err != nil { 90 | return models.UserToken{}, err 91 | } 92 | // create jwt token for user 93 | tokenString, err := helper.GenerateUserToken(userData) 94 | if err != nil { 95 | return models.UserToken{}, errors.New("couldn't create token for user due to some internal error") 96 | } 97 | // create new wallet for user 98 | if _, err := usrU.orderRepo.CreateNewWallet(userData.Id); err != nil { 99 | return models.UserToken{}, errors.New("error creating new wallet for user") 100 | } 101 | return models.UserToken{ 102 | User: userData, 103 | Token: tokenString, 104 | }, nil 105 | 106 | } 107 | 108 | func (usrU *userUsecase) AddAddress(id int, address models.AddAddress) error { 109 | fmt.Println("user id from add address usecase ",id) 110 | rslt := usrU.userRepo.CheckIfFirstAddress(id) 111 | var checkAddress bool 112 | 113 | if !rslt { 114 | checkAddress = true 115 | } else { 116 | checkAddress = false 117 | } 118 | if err := usrU.userRepo.AddAddress(id, address, checkAddress); err != nil { 119 | return err 120 | } 121 | return nil 122 | } 123 | 124 | func (usrU *userUsecase) GetAddresses(id int) ([]domain.Address, error) { 125 | addresses, err := usrU.userRepo.GetAddresses(id) 126 | if err != nil { 127 | return []domain.Address{}, err 128 | } 129 | return addresses, nil 130 | } 131 | 132 | func (usrU *userUsecase) GetUserDetails(id int) (models.UserDetailsResponse, error) { 133 | userDetails, err := usrU.userRepo.GetUserDetails(id) 134 | if err != nil { 135 | return models.UserDetailsResponse{}, err 136 | } 137 | return userDetails, nil 138 | } 139 | 140 | func (usrU *userUsecase) ChangePassword(id int, old string, password string, repassword string) error { 141 | userPass, err := usrU.userRepo.GetPassword(id) 142 | if err != nil { 143 | return errors.New("couldn't get user password") 144 | } 145 | if err := bcrypt.CompareHashAndPassword([]byte(userPass), []byte(old)); err != nil { 146 | return errors.New("password incorrect") 147 | } 148 | if password != repassword { 149 | return errors.New("password doesn't match") 150 | } 151 | newPass, err := bcrypt.GenerateFromPassword([]byte(password), 10) 152 | if err != nil { 153 | return err 154 | } 155 | return usrU.userRepo.ChangePassword(id, string(newPass)) 156 | } 157 | 158 | func (usrU *userUsecase) GetCartID(userID int) (int, error) { 159 | cartId, err := usrU.userRepo.GetCartID(userID) 160 | if err != nil { 161 | return 0, errors.New("couldn't get cart id") 162 | } 163 | return cartId, nil 164 | } 165 | 166 | func (usrU *userUsecase) EditUser(id int, userData models.EditUser) error { 167 | 168 | if userData.Name != "" && userData.Name != "string" { 169 | err := usrU.userRepo.EditName(id, userData.Name) 170 | if err != nil { 171 | return err 172 | } 173 | } 174 | if userData.Email != "" && userData.Email != "string" { 175 | err := usrU.userRepo.EditEmail(id, userData.Email) 176 | if err != nil { 177 | return err 178 | } 179 | } 180 | if userData.Phone != "" && userData.Phone != "string" { 181 | err := usrU.userRepo.EditPhone(id, userData.Phone) 182 | if err != nil { 183 | return err 184 | } 185 | } 186 | if userData.Username != "" && userData.Username != "string" { 187 | err := usrU.userRepo.EditUsername(id, userData.Username) 188 | if err != nil { 189 | return err 190 | } 191 | } 192 | return nil 193 | } 194 | func (usrU *userUsecase) GetCart(id int) (models.GetCartResponse, error) { 195 | // Find cart id 196 | cartId, err := usrU.GetCartID(id) 197 | if err != nil { 198 | return models.GetCartResponse{}, errors.New("couldn't find cart id") 199 | } 200 | // Find products inside cart 201 | products, err := usrU.userRepo.GetProductsInCart(cartId) 202 | if err != nil { 203 | return models.GetCartResponse{}, errors.New("couldn't find products in cart") 204 | } 205 | // Find products name 206 | 207 | var productsName []string 208 | 209 | for i := range products { 210 | prdName, err := usrU.userRepo.FindProductNames(products[i]) 211 | 212 | if err != nil { 213 | return models.GetCartResponse{}, err 214 | } 215 | productsName = append(productsName, prdName) 216 | } 217 | // Find quantity 218 | var productQuantity []int 219 | 220 | for q := range products { 221 | prdQ, err := usrU.userRepo.FindCartQuantity(cartId, products[q]) 222 | if err != nil { 223 | return models.GetCartResponse{}, err 224 | } 225 | productQuantity = append(productQuantity, prdQ) 226 | } 227 | // Find price of the product 228 | var productPrice []float64 229 | 230 | for p := range products { 231 | prdP, err := usrU.userRepo.FindPrice(products[p]) 232 | if err != nil { 233 | return models.GetCartResponse{}, err 234 | } 235 | productPrice = append(productPrice, prdP) 236 | } 237 | // Find Category 238 | var productCategory []int 239 | 240 | for c := range products { 241 | prdC, err := usrU.userRepo.FindCategory(products[c]) 242 | if err != nil { 243 | return models.GetCartResponse{}, err 244 | } 245 | productCategory = append(productCategory, prdC) 246 | } 247 | 248 | var getCart []models.GetCart 249 | 250 | for i := range products { 251 | var get models.GetCart 252 | get.ProductName = productsName[i] 253 | get.CategoryId = productCategory[i] 254 | get.Quantity = productQuantity[i] 255 | get.Total = productPrice[i] 256 | 257 | getCart = append(getCart, get) 258 | } 259 | // Find offers 260 | var offers []int 261 | 262 | for i := range productCategory { 263 | c, err := usrU.offerRepo.FindDiscountPercentage(productCategory[i]) 264 | if err != nil { 265 | return models.GetCartResponse{}, err 266 | } 267 | offers = append(offers, c) 268 | } 269 | // Find Discount price 270 | for i := range getCart { 271 | getCart[i].DiscountPrice = (getCart[i].Total) - (getCart[i].Total * float64(offers[i]) / 100) 272 | } 273 | var response models.GetCartResponse 274 | response.Id = cartId 275 | response.Values = getCart 276 | 277 | return response, nil 278 | 279 | } 280 | 281 | func (usrU *userUsecase) RemoveFromCart(id int, inventoryID int) error { 282 | err := usrU.userRepo.RemoveFromCart(id, inventoryID) 283 | if err != nil { 284 | return err 285 | } 286 | return nil 287 | } 288 | 289 | func (usrU *userUsecase) ClearCart(cartID int) error { 290 | err := usrU.userRepo.ClearCart(cartID) 291 | if err != nil { 292 | return err 293 | } 294 | return nil 295 | } 296 | 297 | func (usrU *userUsecase) UpdateQuantityAdd(id, inv_id int) error { 298 | if err := usrU.userRepo.UpdateQuantityAdd(id, inv_id); err != nil { 299 | return err 300 | } 301 | return nil 302 | } 303 | 304 | func (usrU *userUsecase) UpdateQuantityLess(id, inv_id int) error { 305 | if err := usrU.userRepo.UpdateQuantityLess(id, inv_id); err != nil { 306 | return err 307 | } 308 | return nil 309 | } 310 | 311 | // func (usrU *userUsecase) GetWallet(id, page, limit int) (models.Wallet, error) { 312 | // // Get wallet id 313 | // walletId, err := usrU.walletRepo.FindWalletIdFromUserId(id) 314 | // if err != nil { 315 | // return models.Wallet{}, errors.New("couldn't find wallet id from user id") 316 | // } 317 | // // Get wallet balance 318 | // balance, err := usrU.walletRepo.GetBalance(walletId) 319 | // if err != nil { 320 | // return models.Wallet{}, errors.New("couldn't find wallet balance") 321 | // } 322 | // // Get wallet history(history with amount,purpose,time,walletId) 323 | // history, err := usrU.walletRepo.GetHistory(walletId, page, limit) 324 | // if err != nil { 325 | // return models.Wallet{}, errors.New("couldn't find wallet history") 326 | // } 327 | // var wallet models.Wallet 328 | // wallet.Balance = balance 329 | // wallet.History = history 330 | 331 | // return wallet, nil 332 | // } 333 | -------------------------------------------------------------------------------- /pkg/usecase/wishlist.go: -------------------------------------------------------------------------------- 1 | package usecase 2 | 3 | import ( 4 | "errors" 5 | 6 | interfaces "github.com/Anandhu4456/go-Ecommerce/pkg/repository/interfaces" 7 | services "github.com/Anandhu4456/go-Ecommerce/pkg/usecase/interfaces" 8 | "github.com/Anandhu4456/go-Ecommerce/pkg/utils/models" 9 | ) 10 | 11 | type wishlistUsecase struct { 12 | wishRepo interfaces.WishlistRepository 13 | } 14 | 15 | // Constructor function 16 | func NewWishlistUsecase(wishRepo interfaces.WishlistRepository) services.WishlistUsecase { 17 | return &wishlistUsecase{ 18 | wishRepo: wishRepo, 19 | } 20 | } 21 | 22 | func (wlU *wishlistUsecase) GetWishlistID(userID int) (int, error) { 23 | wishlistId, err := wlU.wishRepo.GetWishlistId(userID) 24 | if err != nil { 25 | return 0, err 26 | } 27 | return wishlistId, nil 28 | } 29 | 30 | func (wlU *wishlistUsecase) GetWishlist(id int) ([]models.GetWishlist, error) { 31 | // Find wishlist id 32 | wishlistId, err := wlU.wishRepo.GetWishlistId(id) 33 | if err != nil { 34 | return []models.GetWishlist{}, errors.New("couldn't find wishlist id from user id") 35 | } 36 | // Find products inside wishlist 37 | products, err := wlU.wishRepo.GetProductsInWishlist(wishlistId) 38 | if err != nil { 39 | return []models.GetWishlist{}, errors.New("couldn't find products inside wishlist") 40 | } 41 | // Find product name 42 | var productName []string 43 | 44 | for i := range products { 45 | prdName, err := wlU.wishRepo.FindProductNames(products[i]) 46 | if err != nil { 47 | return []models.GetWishlist{}, err 48 | } 49 | productName = append(productName, prdName) 50 | } 51 | // Find price 52 | var productPrice []float64 53 | 54 | for i := range products { 55 | p, err := wlU.wishRepo.FindPrice(products[i]) 56 | if err != nil { 57 | return []models.GetWishlist{}, err 58 | } 59 | productPrice = append(productPrice, p) 60 | } 61 | // Find category 62 | var category []string 63 | 64 | for i := range products { 65 | c, err := wlU.wishRepo.FindCategory(products[i]) 66 | if err != nil { 67 | return []models.GetWishlist{}, errors.New("couldn't find category") 68 | } 69 | category = append(category, c) 70 | } 71 | 72 | var getWishlist []models.GetWishlist 73 | 74 | for i := range products { 75 | var get models.GetWishlist 76 | get.ProductName = productName[i] 77 | get.Price = productPrice[i] 78 | get.Category = category[i] 79 | 80 | getWishlist = append(getWishlist, get) 81 | } 82 | return getWishlist, nil 83 | } 84 | 85 | func (wlU *wishlistUsecase) RemoveFromWishlist(id int, inventoryID int) error { 86 | err := wlU.wishRepo.RemoveFromWishlist(id, inventoryID) 87 | if err != nil { 88 | return err 89 | } 90 | return nil 91 | } 92 | 93 | func (wlU *wishlistUsecase) AddToWishlist(user_id, inventory_id int) error { 94 | // Find user wishlist id 95 | wishlistId, err := wlU.wishRepo.GetWishlistId(user_id) 96 | if err != nil { 97 | return errors.New("couldn't find wishlist id") 98 | } 99 | // If user has no cart,create new cart 100 | if wishlistId == 0 { 101 | wishlistId, err := wlU.wishRepo.CreateNewWishlist(user_id) 102 | if err != nil { 103 | return err 104 | } 105 | // Add products to line items 106 | if err := wlU.wishRepo.AddWishlistItem(wishlistId, inventory_id); err != nil { 107 | return errors.New("add to wishlist failed") 108 | } 109 | 110 | } 111 | return nil 112 | } 113 | -------------------------------------------------------------------------------- /pkg/utils/models/admin.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | 6 | ) 7 | 8 | type AdminLogin struct { 9 | Email string `json:"email,omitempty" validate:"required"` 10 | Password string `json:"password" validate:"min=6,max=12"` 11 | } 12 | 13 | type AdminDetailsResponse struct { 14 | ID int `json:"id"` 15 | Name string `json:"name"` 16 | Email string `json:"email"` 17 | 18 | 19 | } 20 | 21 | type UserDetailsAtAdmin struct { 22 | ID int `json:"id"` 23 | Name string `json:"name"` 24 | Email string `json:"email"` 25 | Phone string `json:"phone"` 26 | Permission bool `json:"permission"` 27 | } 28 | 29 | type CustomDates struct { 30 | StartingDate time.Time `json:"starting_date"` 31 | EndDate time.Time `json:"end_date"` 32 | } 33 | type Coupon struct { 34 | Coupon string `json:"coupon" gorm:"unique"` 35 | DiscountRate int `json:"discount_rate"` 36 | Valid bool `json:"valid" gorm:"default:true"` 37 | } -------------------------------------------------------------------------------- /pkg/utils/models/category.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SetNewName struct { 4 | Current string `json:"current"` 5 | New string `json:"new"` 6 | } 7 | -------------------------------------------------------------------------------- /pkg/utils/models/inventory.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type InventoryResponse struct { 4 | ProductID int 5 | } 6 | 7 | type Inventory struct { 8 | ID uint `json:"id"` 9 | CategoryID int `json:"category_id"` 10 | Image string `json:"image"` 11 | ProductName string `json:"product_name"` 12 | Description string `json:"description"` 13 | Stock int `json:"stock"` 14 | Price float64 `json:"price"` 15 | } 16 | 17 | type AddToCart struct { 18 | UserID int `json:"user_id"` 19 | InventoryID int `json:"inventory_id"` 20 | } 21 | 22 | type UpdateInventory struct { 23 | CategoryID int `json:"category_id"` 24 | ProductName string `json:"product_name"` 25 | Description string `json:"description"` 26 | Stock int `json:"stock"` 27 | Price float64 `json:"price"` 28 | } 29 | 30 | type InventoryList struct { 31 | ID uint `json:"id"` 32 | CategoryID int `json:"category_id"` 33 | Image string `json:"image"` 34 | ProductName string `json:"product_name"` 35 | Description string `json:"description"` 36 | Stock int `json:"stock"` 37 | Price float64 `json:"price"` 38 | } 39 | 40 | type ImagesInfo struct { 41 | ID int `json:"id"` 42 | ImageUrl string `json:"image_url"` 43 | } 44 | 45 | type InventoryDetails struct { 46 | Inventory Inventory 47 | AdditionalImages []ImagesInfo 48 | } 49 | -------------------------------------------------------------------------------- /pkg/utils/models/offer.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type CreateOffer struct { 4 | CategoryID int 5 | Discount int 6 | } -------------------------------------------------------------------------------- /pkg/utils/models/order.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type OrderPaymentDetails struct { 4 | UserID int `json:"user_id"` 5 | Username string `json:"username"` 6 | RazorID int `json:"razor_id"` 7 | OrderID int `json:"order_id"` 8 | FinalPrice float64 `json:"final_price"` 9 | } 10 | 11 | type Order struct { 12 | UserID int `json:"user_id"` 13 | AddressID int `json:"address_id"` 14 | PaymentMethodID int `json:"payment_id"` 15 | CouponID int `json:"coupon_id"` 16 | } 17 | 18 | type InvoiceData struct { 19 | Title string 20 | Quantity int 21 | Price int 22 | TotalAmount int 23 | } 24 | 25 | type Invoice struct { 26 | Name string 27 | Address string 28 | InvoiceItems []*InvoiceData 29 | } 30 | -------------------------------------------------------------------------------- /pkg/utils/models/otp.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type VerifyData struct { 4 | PhoneNumber string `json:"phone,omitempty" validate:"required"` 5 | Code string `json:"code,omitempty" validate:"required"` 6 | } 7 | 8 | type OTPData struct { 9 | PhoneNumber string `json:"phone,omitempty" validate:"required"` 10 | } 11 | type PaymentMethod struct { 12 | ID uint `json:"id"` 13 | Payment_Name string `json:"payment_name"` 14 | } -------------------------------------------------------------------------------- /pkg/utils/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type UserLogin struct { 4 | Email string `json:"email"` 5 | Password string `json:"password"` 6 | } 7 | 8 | // User Signup 9 | type UserDetails struct { 10 | Name string `json:"name"` 11 | Email string `json:"email" validate:"required"` 12 | Username string `json:"username"` 13 | Phone string `json:"phone"` 14 | Password string `json:"password"` 15 | ConfirmPassword string `json:"confirm_password"` 16 | } 17 | 18 | type UserToken struct { 19 | User UserDetailsResponse 20 | Token string 21 | } 22 | 23 | // user details shown after loggin 24 | type UserDetailsResponse struct { 25 | Id int `json:"id"` 26 | Name string `json:"name"` 27 | Email string `json:"email" validate:"email"` 28 | Phone string `json:"phone"` 29 | } 30 | 31 | type UserSignInResponse struct{ 32 | Id uint `json:"id"` 33 | UserID uint `json:"user_id"` 34 | Name string `json:"name"` 35 | Email string `json:"email" validate:"email"` 36 | Phone string `json:"phone"` 37 | Password string `json:"password"` 38 | } 39 | 40 | 41 | type Address struct { 42 | Id uint `json:"id" gorm:"unique;not null"` 43 | UserID uint `json:"user_id"` 44 | Name string `json:"name" validate:"required"` 45 | HouseName string `json:"house_name" validate:"required"` 46 | Street string `json:"street" validate:"required"` 47 | City string `json:"city" validate:"required"` 48 | State string `json:"state" validate:"required"` 49 | Pin string `json:"pin" validate:"required"` 50 | } 51 | 52 | type AddAddress struct { 53 | Name string `json:"name" validate:"required"` 54 | HouseName string `json:"house_name" validate:"required"` 55 | Street string `json:"street" validate:"required"` 56 | City string `json:"city" validate:"required"` 57 | State string `json:"state" validate:"required"` 58 | Pin string `json:"pin" validate:"required"` 59 | } 60 | 61 | type ChangePassword struct { 62 | OldPassword string `json:"old_password"` 63 | NewPassword string `json:"new_password"` 64 | RePassword string `json:"re_password"` 65 | } 66 | 67 | type GetCart struct { 68 | Id int `json:"product_id"` 69 | ProductName string `json:"product_name"` 70 | CategoryId int `json:"category_id"` 71 | Quantity int `json:"quantity"` 72 | Total float64 `json:"total"` 73 | DiscountPrice float64 `json:"discount_price"` 74 | } 75 | 76 | type GetCartResponse struct { 77 | Id int 78 | Values []GetCart 79 | } 80 | 81 | type CheckOut struct { 82 | CartId int 83 | Addresses []Address 84 | Products []GetCart 85 | PaymentMethods []PaymentMethod 86 | TotalPrice float64 87 | DiscountPrice float64 88 | } 89 | type EditUser struct { 90 | Name string `json:"name"` 91 | Username string `json:"username"` 92 | Email string `json:"email"` 93 | Phone string `json:"phone"` 94 | } 95 | 96 | type UserKey string 97 | 98 | func (k UserKey) String() string { 99 | return string(k) 100 | } 101 | -------------------------------------------------------------------------------- /pkg/utils/models/wishlis.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type GetWishlist struct { 4 | ProductName string `json:"product_name"` 5 | Category string `json:"category"` 6 | Price float64 `json:"price"` 7 | } 8 | -------------------------------------------------------------------------------- /pkg/utils/response/response.go: -------------------------------------------------------------------------------- 1 | package response 2 | 3 | type Response struct { 4 | StatusCode int `json:"statuscode"` 5 | Message string `json:"message"` 6 | Data interface{} `json:"data"` 7 | Error interface{} `json:"error"` 8 | } 9 | 10 | func ClientResponse(statusCode int, message string, data interface{}, err interface{}) Response { 11 | return Response{ 12 | StatusCode: statusCode, 13 | Message: message, 14 | Data: data, 15 | Error: err, 16 | } 17 | } 18 | --------------------------------------------------------------------------------