├── .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 |{{.OrderID}}
29 |Total : {{.FinalPrice}}
30 | 33 |