fix and refact: architecture updated and refactored
This commit is contained in:
parent
aa786d646b
commit
822caa8121
22
.env.example
22
.env.example
|
@ -1,13 +1,19 @@
|
|||
# SERVER SETTINGS
|
||||
SERVER_HOST=localhost
|
||||
SERVER_PORT= # isi listen port anda (bebas)
|
||||
SERVER_HOST=
|
||||
SERVER_PORT=
|
||||
|
||||
# DATABASE SETTINGS
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5432 # port default postgres
|
||||
DB_NAME= # nama_database di postgres
|
||||
DB_USER= # username yang digunakan di postgres
|
||||
DB_PASSWORD= # password yang digunakan di postgres
|
||||
DB_HOST=
|
||||
DB_PORT=
|
||||
DB_NAME=
|
||||
DB_USER=
|
||||
DB_PASSWORD=
|
||||
|
||||
# api keyauth
|
||||
# REDIS SETTINGS
|
||||
REDIS_HOST=
|
||||
REDIS_PORT=
|
||||
REDIS_PASSWORD=
|
||||
REDIS_DB=
|
||||
|
||||
# Keyauth
|
||||
API_KEY=
|
||||
|
|
|
@ -23,3 +23,5 @@ go.work.sum
|
|||
|
||||
# env file
|
||||
.env
|
||||
.env.prod
|
||||
.env.dev
|
|
@ -0,0 +1,17 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/middleware"
|
||||
"github.com/pahmiudahgede/senggoldong/presentation"
|
||||
)
|
||||
|
||||
func main() {
|
||||
config.SetupConfig()
|
||||
|
||||
app := fiber.New()
|
||||
app.Use(middleware.APIKeyMiddleware)
|
||||
presentation.AuthRouter(app)
|
||||
config.StartServer(app)
|
||||
}
|
|
@ -3,54 +3,36 @@ package config
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/model"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var DB *gorm.DB
|
||||
|
||||
func InitDatabase() {
|
||||
|
||||
InitConfig()
|
||||
func ConnectDatabase() {
|
||||
|
||||
dsn := fmt.Sprintf(
|
||||
"host=%s port=%s user=%s dbname=%s password=%s sslmode=disable",
|
||||
DBHost, DBPort, DBUser, DBName, DBPassword,
|
||||
"host=%s user=%s password=%s dbname=%s port=%s sslmode=disable",
|
||||
os.Getenv("DB_HOST"),
|
||||
os.Getenv("DB_USER"),
|
||||
os.Getenv("DB_PASSWORD"),
|
||||
os.Getenv("DB_NAME"),
|
||||
os.Getenv("DB_PORT"),
|
||||
)
|
||||
|
||||
var err error
|
||||
|
||||
DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
log.Fatalf("Error: Gagal terhubung ke database: %v", err)
|
||||
log.Fatalf("Error connecting to database: %v", err)
|
||||
}
|
||||
log.Println("Database connected successfully!")
|
||||
|
||||
err = DB.AutoMigrate(
|
||||
&domain.Point{},
|
||||
&domain.User{},
|
||||
&domain.UserRole{},
|
||||
&domain.UserPin{},
|
||||
&domain.MenuAccess{},
|
||||
&domain.PlatformHandle{},
|
||||
&domain.Address{},
|
||||
&domain.Article{},
|
||||
&domain.TrashCategory{},
|
||||
&domain.TrashDetail{},
|
||||
&domain.Banner{},
|
||||
&domain.CoverageArea{},
|
||||
&domain.CoverageDistric{},
|
||||
&domain.CoverageSubdistrict{},
|
||||
&domain.RequestPickup{},
|
||||
&domain.RequestItem{},
|
||||
&domain.Product{},
|
||||
&domain.ProductImage{},
|
||||
&domain.Store{},
|
||||
)
|
||||
err = DB.AutoMigrate(&model.User{})
|
||||
if err != nil {
|
||||
log.Fatalf("Error: Gagal melakukan migrasi schema: %v", err)
|
||||
log.Fatalf("Error performing auto-migration: %v", err)
|
||||
}
|
||||
|
||||
log.Println("Koneksi ke database berhasil dan migrasi schema juga berhasil")
|
||||
log.Println("Database migrated successfully!")
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
DBHost string
|
||||
DBPort string
|
||||
DBName string
|
||||
DBUser string
|
||||
DBPassword string
|
||||
|
||||
RedisHost string
|
||||
RedisPort string
|
||||
RedisPassword string
|
||||
RedisDB int
|
||||
|
||||
ServerHost string
|
||||
ServerPort string
|
||||
APIKey string
|
||||
)
|
||||
|
||||
func InitConfig() {
|
||||
|
||||
ServerHost = os.Getenv("SERVER_HOST")
|
||||
ServerPort = os.Getenv("SERVER_PORT")
|
||||
DBHost = os.Getenv("DB_HOST")
|
||||
DBPort = os.Getenv("DB_PORT")
|
||||
DBName = os.Getenv("DB_NAME")
|
||||
DBUser = os.Getenv("DB_USER")
|
||||
DBPassword = os.Getenv("DB_PASSWORD")
|
||||
APIKey = os.Getenv("API_KEY")
|
||||
|
||||
RedisHost = os.Getenv("REDIS_HOST")
|
||||
RedisPort = os.Getenv("REDIS_PORT")
|
||||
RedisPassword = os.Getenv("REDIS_PASSWORD")
|
||||
RedisDB = 0
|
||||
|
||||
if ServerHost == "" || ServerPort == "" || DBHost == "" || DBPort == "" || DBName == "" || DBUser == "" || DBPassword == "" || APIKey == "" {
|
||||
log.Fatal("Error: Beberapa environment variables tidak ditemukan.")
|
||||
}
|
||||
}
|
|
@ -4,58 +4,24 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
"os"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
)
|
||||
|
||||
var RedisClient *redis.Client
|
||||
var Ctx = context.Background()
|
||||
|
||||
func Context() context.Context {
|
||||
return context.Background()
|
||||
}
|
||||
|
||||
func InitRedis() {
|
||||
|
||||
InitConfig()
|
||||
|
||||
func ConnectRedis() {
|
||||
RedisClient = redis.NewClient(&redis.Options{
|
||||
Addr: fmt.Sprintf("%s:%s", RedisHost, RedisPort),
|
||||
Password: RedisPassword,
|
||||
DB: RedisDB,
|
||||
Addr: fmt.Sprintf("%s:%s", os.Getenv("REDIS_HOST"), os.Getenv("REDIS_PORT")),
|
||||
Password: os.Getenv("REDIS_PASSWORD"),
|
||||
DB: 0,
|
||||
})
|
||||
|
||||
_, err := RedisClient.Ping(context.Background()).Result()
|
||||
_, err := RedisClient.Ping(Ctx).Result()
|
||||
if err != nil {
|
||||
log.Fatalf("Error: Gagal terhubung ke Redis: %v", err)
|
||||
log.Fatalf("Error connecting to Redis: %v", err)
|
||||
}
|
||||
|
||||
log.Println("Koneksi ke Redis berhasil.")
|
||||
}
|
||||
|
||||
func GetFromCache(key string) (string, error) {
|
||||
val, err := RedisClient.Get(Context(), key).Result()
|
||||
if err == redis.Nil {
|
||||
|
||||
return "", nil
|
||||
} else if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func SetToCache(key string, value string, ttl time.Duration) error {
|
||||
err := RedisClient.Set(Context(), key, value, ttl).Err()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteFromCache(key string) error {
|
||||
err := RedisClient.Del(Context(), key).Err()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
log.Println("Redis connected successfully!")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func StartServer(app *fiber.App) {
|
||||
host := os.Getenv("SERVER_HOST")
|
||||
port := os.Getenv("SERVER_PORT")
|
||||
|
||||
address := fmt.Sprintf("%s:%s", host, port)
|
||||
|
||||
log.Printf("Server is running on http://%s", address)
|
||||
if err := app.Listen(address); err != nil {
|
||||
log.Fatalf("Error starting server: %v", err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func SetupConfig() {
|
||||
err := godotenv.Load(".env.dev")
|
||||
if err != nil {
|
||||
log.Fatalf("Error loading .env file: %v", err)
|
||||
}
|
||||
|
||||
ConnectDatabase()
|
||||
ConnectRedis()
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package domain
|
||||
|
||||
type Province struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
ListRegency []Regency `json:"list_regency,omitempty"`
|
||||
}
|
||||
|
||||
type Regency struct {
|
||||
ID string `json:"id"`
|
||||
ProvinceID string `json:"province_id"`
|
||||
Name string `json:"name"`
|
||||
Province *Province `json:"province,omitempty"`
|
||||
ListDistrict []District `json:"list_district,omitempty"`
|
||||
}
|
||||
|
||||
type District struct {
|
||||
ID string `json:"id"`
|
||||
RegencyID string `json:"regency_id"`
|
||||
Name string `json:"name"`
|
||||
Regency *Regency `json:"regency,omitempty"`
|
||||
ListVillage []Village `json:"list_village,omitempty"`
|
||||
}
|
||||
|
||||
type Village struct {
|
||||
ID string `json:"id"`
|
||||
DistrictID string `json:"district_id"`
|
||||
Name string `json:"name"`
|
||||
District *District `json:"district,omitempty"`
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type Address struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
|
||||
UserID string `gorm:"not null" json:"userId"`
|
||||
User User `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"user"`
|
||||
Province string `gorm:"not null" json:"province"`
|
||||
District string `gorm:"not null" json:"district"`
|
||||
Subdistrict string `gorm:"not null" json:"subdistrict"`
|
||||
PostalCode int `gorm:"not null" json:"postalCode"`
|
||||
Village string `gorm:"not null" json:"village"`
|
||||
Detail string `gorm:"not null" json:"detail"`
|
||||
Geography string `gorm:"not null" json:"geography"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type Article struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
|
||||
Title string `gorm:"not null" json:"title"`
|
||||
CoverImage string `gorm:"not null" json:"coverImage"`
|
||||
Author string `gorm:"not null" json:"author"`
|
||||
Heading string `gorm:"not null" json:"heading"`
|
||||
Content string `gorm:"not null" json:"content"`
|
||||
PublishedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type Banner struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
BannerName string `gorm:"not null" json:"bannername"`
|
||||
BannerImage string `gorm:"not null" json:"bannerimage"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type CoverageArea struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
Province string `gorm:"not null" json:"province"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
CoverageDistrics []CoverageDistric `gorm:"foreignKey:CoverageAreaID" json:"coverage_districs"`
|
||||
}
|
||||
|
||||
type CoverageDistric struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
CoverageAreaID string `gorm:"not null;constraint:OnDelete:CASCADE;OnUpdate:CASCADE;" json:"coverage_area_id"`
|
||||
District string `gorm:"not null" json:"district"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
CoverageSubdistricts []CoverageSubdistrict `gorm:"foreignKey:CoverageDistrictId" json:"subdistricts"`
|
||||
}
|
||||
|
||||
type CoverageSubdistrict struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
CoverageAreaID string `gorm:"not null" json:"coverage_area_id"`
|
||||
CoverageDistrictId string `gorm:"not null;constraint:OnDelete:CASCADE;OnUpdate:CASCADE;" json:"coverage_district_id"`
|
||||
Subdistrict string `gorm:"not null" json:"subdistrict"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type Point struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
CoinName string `gorm:"not null" json:"coin_name"`
|
||||
ValuePerUnit float64 `gorm:"not null" json:"value_perunit"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type MenuAccess struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
|
||||
RoleID string `gorm:"not null" json:"roleId"`
|
||||
Role UserRole `gorm:"foreignKey:RoleID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"role"`
|
||||
MenuName string `gorm:"not null" json:"menuName"`
|
||||
Path string `gorm:"not null" json:"path"`
|
||||
IconURL string `gorm:"not null" json:"iconUrl"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package domain
|
||||
|
||||
type PlatformHandle struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
|
||||
Platform string `gorm:"not null" json:"platform"`
|
||||
Description string `gorm:"not null" json:"description"`
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type Product struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
UserID string `gorm:"type:uuid;not null" json:"user_id"`
|
||||
StoreID string `gorm:"type:uuid;not null" json:"store_id"`
|
||||
Store Store `gorm:"foreignKey:StoreID" json:"store"`
|
||||
ProductTitle string `gorm:"not null" json:"product_title"`
|
||||
ProductImages []ProductImage `gorm:"foreignKey:ProductID;constraint:OnDelete:CASCADE;" json:"product_images"`
|
||||
TrashDetailID string `gorm:"type:uuid;not null" json:"trash_detail_id"`
|
||||
TrashDetail TrashDetail `gorm:"foreignKey:TrashDetailID" json:"trash_detail"`
|
||||
SalePrice int64 `gorm:"not null" json:"sale_price"`
|
||||
Quantity int `gorm:"not null" json:"quantity"`
|
||||
ProductDescribe string `gorm:"type:text" json:"product_describe"`
|
||||
Sold int `gorm:"default:0" json:"sold"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
}
|
||||
|
||||
type ProductImage struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
ProductID string `gorm:"type:uuid;not null" json:"product_id"`
|
||||
ImageURL string `gorm:"not null" json:"image_url"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
|
||||
type RequestPickup struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
UserID string `gorm:"type:uuid;not null" json:"userId"`
|
||||
Request []RequestItem `gorm:"foreignKey:RequestPickupID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"request"`
|
||||
RequestTime string `gorm:"type:text;not null" json:"requestTime"`
|
||||
UserAddressID string `gorm:"type:uuid;not null" json:"userAddressId"`
|
||||
UserAddress Address `gorm:"foreignKey:UserAddressID" json:"userAddress"`
|
||||
StatusRequest string `gorm:"type:text;not null" json:"statusRequest"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
||||
|
||||
type RequestItem struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
RequestPickupID string `gorm:"type:uuid;not null;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"requestPickupId"`
|
||||
TrashCategoryID string `gorm:"type:uuid;not null" json:"trashCategoryId"`
|
||||
TrashCategory TrashCategory `gorm:"foreignKey:TrashCategoryID" json:"trashCategory"`
|
||||
EstimatedAmount string `gorm:"type:text;not null" json:"estimatedAmount"`
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package domain
|
||||
|
||||
type UserRole struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
|
||||
RoleName string `gorm:"unique;not null" json:"roleName"`
|
||||
// Users []User `gorm:"foreignKey:RoleID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"users"`
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type Store struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
UserID string `gorm:"type:uuid;not null" json:"user_id"`
|
||||
User User `gorm:"foreignKey:UserID" json:"user"`
|
||||
StoreName string `gorm:"not null;unique" json:"store_name"`
|
||||
StoreLogo string `json:"store_logo"`
|
||||
StoreBanner string `json:"store_banner"`
|
||||
StoreDesc string `gorm:"type:text" json:"store_desc"`
|
||||
Follower int `gorm:"default:0" json:"follower"`
|
||||
StoreRating float64 `gorm:"default:0" json:"store_rating"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
}
|
||||
|
||||
// type StoreFinance struct {
|
||||
// ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
// StoreID string `gorm:"type:uuid;not null" json:"store_id"`
|
||||
// TotalRevenue int64 `gorm:"default:0" json:"total_revenue"`
|
||||
// TotalExpenses int64 `gorm:"default:0" json:"total_expenses"`
|
||||
// NetProfit int64 `gorm:"default:0" json:"net_profit"`
|
||||
// OrdersCount int `gorm:"default:0" json:"orders_count"`
|
||||
// CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
// UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
// }
|
||||
|
||||
// type Order struct {
|
||||
// ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
// StoreID string `gorm:"type:uuid;not null" json:"store_id"`
|
||||
// UserID string `gorm:"type:uuid;not null" json:"user_id"`
|
||||
// TotalPrice int64 `gorm:"not null" json:"total_price"`
|
||||
// OrderStatus string `gorm:"not null" json:"order_status"`
|
||||
// ShippingStatus string `gorm:"not null" json:"shipping_status"`
|
||||
// PaymentStatus string `gorm:"not null" json:"payment_status"`
|
||||
// CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
// UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
// }
|
||||
|
||||
// type OrderDetail struct {
|
||||
// ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
// OrderID string `gorm:"type:uuid;not null" json:"order_id"`
|
||||
// ProductID string `gorm:"type:uuid;not null" json:"product_id"`
|
||||
// Quantity int `gorm:"not null" json:"quantity"`
|
||||
// UnitPrice int64 `gorm:"not null" json:"unit_price"`
|
||||
// TotalPrice int64 `gorm:"not null" json:"total_price"`
|
||||
// CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
// UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
// }
|
||||
|
||||
// type Shipping struct {
|
||||
// ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
// OrderID string `gorm:"type:uuid;not null" json:"order_id"`
|
||||
// ShippingDate time.Time `gorm:"default:current_timestamp" json:"shipping_date"`
|
||||
// ShippingCost int64 `gorm:"not null" json:"shipping_cost"`
|
||||
// TrackingNo string `gorm:"not null" json:"tracking_no"`
|
||||
// ShippingStatus string `gorm:"not null" json:"shipping_status"`
|
||||
// CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
// UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
// }
|
||||
|
||||
// type Cancellation struct {
|
||||
// ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
// OrderID string `gorm:"type:uuid;not null" json:"order_id"`
|
||||
// Reason string `gorm:"type:text" json:"reason"`
|
||||
// CancelledAt time.Time `gorm:"default:current_timestamp" json:"cancelled_at"`
|
||||
// CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
// UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
// }
|
||||
|
||||
// type Return struct {
|
||||
// ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
// OrderID string `gorm:"type:uuid;not null" json:"order_id"`
|
||||
// Reason string `gorm:"type:text" json:"reason"`
|
||||
// ReturnedAt time.Time `gorm:"default:current_timestamp" json:"returned_at"`
|
||||
// CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"`
|
||||
// UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"`
|
||||
// }
|
|
@ -1,20 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type TrashCategory struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
Name string `gorm:"not null" json:"name"`
|
||||
Details []TrashDetail `gorm:"foreignKey:CategoryID" json:"details"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
||||
|
||||
type TrashDetail struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||
CategoryID string `gorm:"type:uuid;not null" json:"category_id"`
|
||||
Description string `gorm:"not null" json:"description"`
|
||||
Price int `gorm:"not null" json:"price"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
type UserPin struct {
|
||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
|
||||
UserID string `gorm:"not null" json:"userId"`
|
||||
Pin string `gorm:"not null" json:"pin"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
package dto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
type AddressInput struct {
|
||||
Province string `json:"province" validate:"required"`
|
||||
District string `json:"district" validate:"required"`
|
||||
Subdistrict string `json:"subdistrict" validate:"required"`
|
||||
PostalCode int `json:"postalCode" validate:"required,numeric"`
|
||||
Village string `json:"village" validate:"required"`
|
||||
Detail string `json:"detail" validate:"required"`
|
||||
Geography string `json:"geography" validate:"required"`
|
||||
}
|
||||
|
||||
type AddressResponse struct {
|
||||
ID string `json:"id"`
|
||||
Province string `json:"province"`
|
||||
District string `json:"district"`
|
||||
Subdistrict string `json:"subdistrict"`
|
||||
PostalCode int `json:"postalCode"`
|
||||
Village string `json:"village"`
|
||||
Detail string `json:"detail"`
|
||||
Geography string `json:"geography"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (c *AddressInput) ValidatePost() error {
|
||||
err := validate.Struct(c)
|
||||
if err != nil {
|
||||
|
||||
for _, e := range err.(validator.ValidationErrors) {
|
||||
|
||||
switch e.Field() {
|
||||
case "Province":
|
||||
return fmt.Errorf("provinsi harus diisisi")
|
||||
case "District":
|
||||
return fmt.Errorf("kabupaten harus diisi")
|
||||
case "Subdistrict":
|
||||
return fmt.Errorf("kecamatan harus diisi")
|
||||
case "PostalCode":
|
||||
return fmt.Errorf("postal code harus diisi dan berupa angka")
|
||||
case "Village":
|
||||
return fmt.Errorf("desa harus diisi")
|
||||
case "Detail":
|
||||
return fmt.Errorf("detail wajib diisi")
|
||||
case "Geography":
|
||||
return fmt.Errorf("lokasi kordinat harus diisi")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *AddressInput) ValidateUpdate() error {
|
||||
err := validate.Struct(c)
|
||||
if err != nil {
|
||||
|
||||
for _, e := range err.(validator.ValidationErrors) {
|
||||
|
||||
switch e.Field() {
|
||||
case "Province":
|
||||
return fmt.Errorf("provinsi harus diisisi")
|
||||
case "District":
|
||||
return fmt.Errorf("kabupaten harus diisi")
|
||||
case "Subdistrict":
|
||||
return fmt.Errorf("kecamatan harus diisi")
|
||||
case "PostalCode":
|
||||
return fmt.Errorf("postal code harus diisi dan berupa angka")
|
||||
case "Village":
|
||||
return fmt.Errorf("desa harus diisi")
|
||||
case "Detail":
|
||||
return fmt.Errorf("detail wajib diisi")
|
||||
case "Geography":
|
||||
return fmt.Errorf("lokasi kordinat harus diisi")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package dto
|
||||
|
||||
type ArticleResponse struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
CoverImage string `json:"coverImage"`
|
||||
Author string `json:"author"`
|
||||
Heading string `json:"heading"`
|
||||
Content string `json:"content"`
|
||||
PublishedAt string `json:"publishedAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type ArticleCreateRequest struct {
|
||||
Title string `json:"title" validate:"required"`
|
||||
CoverImage string `json:"coverImage" validate:"required"`
|
||||
Author string `json:"author" validate:"required"`
|
||||
Heading string `json:"heading" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
}
|
||||
|
||||
type ArticleUpdateRequest struct {
|
||||
Title string `json:"title" validate:"required"`
|
||||
CoverImage string `json:"coverImage" validate:"required"`
|
||||
Author string `json:"author" validate:"required"`
|
||||
Heading string `json:"heading" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
}
|
||||
|
||||
func (p *ArticleCreateRequest) Validate() error {
|
||||
validate := GetValidator()
|
||||
return validate.Struct(p)
|
||||
}
|
||||
|
||||
func (p *ArticleUpdateRequest) Validate() error {
|
||||
validate := GetValidator()
|
||||
return validate.Struct(p)
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package dto
|
||||
|
||||
type LoginDTO struct {
|
||||
Identifier string `json:"identifier" validate:"required"`
|
||||
Password string `json:"password" validate:"required,min=6"`
|
||||
}
|
||||
|
||||
type UserResponseWithToken struct {
|
||||
UserID string `json:"user_id"`
|
||||
Token string `json:"token"`
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package dto
|
||||
|
||||
type BannerResponse struct {
|
||||
ID string `json:"id"`
|
||||
BannerName string `json:"bannername"`
|
||||
BannerImage string `json:"bannerimage"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type BannerCreateRequest struct {
|
||||
BannerName string `json:"bannername" validate:"required"`
|
||||
BannerImage string `json:"bannerimage" validate:"required"`
|
||||
}
|
||||
|
||||
type BannerUpdateRequest struct {
|
||||
BannerName *string `json:"bannername,omitempty"`
|
||||
BannerImage *string `json:"bannerimage,omitempty"`
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
package dto
|
||||
|
||||
type CoverageAreaResponse struct {
|
||||
ID string `json:"id"`
|
||||
Province string `json:"province"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type CoverageAreaWithDistrictsResponse struct {
|
||||
ID string `json:"id"`
|
||||
Province string `json:"province"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
CoverageArea []CoverageAreaResponse `json:"coverage_area"`
|
||||
}
|
||||
|
||||
type CoverageAreaDetailWithLocation struct {
|
||||
ID string `json:"id"`
|
||||
Province string `json:"province"`
|
||||
District string `json:"district"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
Subdistrict []SubdistrictResponse `json:"subdistrict"`
|
||||
}
|
||||
|
||||
type SubdistrictResponse struct {
|
||||
ID string `json:"id"`
|
||||
Subdistrict string `json:"subdistrict"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func NewCoverageAreaResponse(id, province, createdAt, updatedAt string) CoverageAreaResponse {
|
||||
return CoverageAreaResponse{
|
||||
ID: id,
|
||||
Province: province,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCoverageAreaWithDistrictsResponse(id, province, createdAt, updatedAt string, coverageArea []CoverageAreaResponse) CoverageAreaWithDistrictsResponse {
|
||||
return CoverageAreaWithDistrictsResponse{
|
||||
ID: id,
|
||||
Province: province,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
CoverageArea: coverageArea,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCoverageAreaDetailWithLocation(id, province, district, createdAt, updatedAt string, subdistricts []SubdistrictResponse) CoverageAreaDetailWithLocation {
|
||||
return CoverageAreaDetailWithLocation{
|
||||
ID: id,
|
||||
Province: province,
|
||||
District: district,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
Subdistrict: subdistricts,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSubdistrictResponse(id, subdistrict, createdAt, updatedAt string) SubdistrictResponse {
|
||||
return SubdistrictResponse{
|
||||
ID: id,
|
||||
Subdistrict: subdistrict,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
type CoverageAreaCreateRequest struct {
|
||||
Province string `json:"province" validate:"required"`
|
||||
}
|
||||
|
||||
func NewCoverageAreaCreateRequest(province string) CoverageAreaCreateRequest {
|
||||
return CoverageAreaCreateRequest{
|
||||
Province: province,
|
||||
}
|
||||
}
|
||||
|
||||
type CoverageDistrictCreateRequest struct {
|
||||
CoverageAreaID string `json:"coverage_area_id" validate:"required"`
|
||||
District string `json:"district" validate:"required"`
|
||||
}
|
||||
|
||||
func NewCoverageDistrictCreateRequest(coverageAreaID, district string) CoverageDistrictCreateRequest {
|
||||
return CoverageDistrictCreateRequest{
|
||||
CoverageAreaID: coverageAreaID,
|
||||
District: district,
|
||||
}
|
||||
}
|
||||
|
||||
type CoverageSubdistrictCreateRequest struct {
|
||||
CoverageAreaID string `json:"coverage_area_id" validate:"required"`
|
||||
CoverageDistrictId string `json:"coverage_district_id" validate:"required"`
|
||||
Subdistrict string `json:"subdistrict" validate:"required"`
|
||||
}
|
||||
|
||||
func NewCoverageSubdistrictCreateRequest(coverageAreaID, coverageDistrictId, subdistrict string) CoverageSubdistrictCreateRequest {
|
||||
return CoverageSubdistrictCreateRequest{
|
||||
CoverageAreaID: coverageAreaID,
|
||||
CoverageDistrictId: coverageDistrictId,
|
||||
Subdistrict: subdistrict,
|
||||
}
|
||||
}
|
||||
|
||||
type CoverageAreaUpdateRequest struct {
|
||||
Province string `json:"province" validate:"required"`
|
||||
}
|
||||
|
||||
type CoverageDistrictUpdateRequest struct {
|
||||
District string `json:"district" validate:"required"`
|
||||
}
|
||||
|
||||
type CoverageSubdistrictUpdateRequest struct {
|
||||
Subdistrict string `json:"subdistrict" validate:"required"`
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package dto
|
||||
|
||||
type PointResponse struct {
|
||||
ID string `json:"id"`
|
||||
CoinName string `json:"coin_name"`
|
||||
ValuePerUnit float64 `json:"value_perunit"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type PointCreateRequest struct {
|
||||
CoinName string `json:"coin_name" validate:"required"`
|
||||
ValuePerUnit float64 `json:"value_perunit" validate:"required,gt=0"`
|
||||
}
|
||||
|
||||
type PointUpdateRequest struct {
|
||||
CoinName string `json:"coin_name" validate:"required"`
|
||||
ValuePerUnit float64 `json:"value_perunit" validate:"required,gt=0"`
|
||||
}
|
||||
|
||||
func (p *PointCreateRequest) Validate() error {
|
||||
validate := GetValidator()
|
||||
return validate.Struct(p)
|
||||
}
|
||||
|
||||
func (p *PointUpdateRequest) Validate() error {
|
||||
validate := GetValidator()
|
||||
return validate.Struct(p)
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
package dto
|
||||
|
||||
import "errors"
|
||||
|
||||
type ProductResponseWithSoldDTO struct {
|
||||
ID string `json:"id"`
|
||||
StoreID string `json:"store_id"`
|
||||
ProductTitle string `json:"product_title"`
|
||||
ProductImages []ProductImageDTO `json:"product_images"`
|
||||
TrashDetail TrashDetailResponseDTO `json:"trash_detail"`
|
||||
SalePrice int64 `json:"sale_price"`
|
||||
Quantity int `json:"quantity"`
|
||||
ProductDescribe string `json:"product_describe"`
|
||||
Sold int `json:"sold"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
type ProductResponseWithoutSoldDTO struct {
|
||||
ID string `json:"id"`
|
||||
StoreID string `json:"store_id"`
|
||||
ProductTitle string `json:"product_title"`
|
||||
ProductImages []ProductImageDTO `json:"product_images"`
|
||||
TrashDetail TrashDetailResponseDTO `json:"trash_detail"`
|
||||
SalePrice int64 `json:"sale_price"`
|
||||
Quantity int `json:"quantity"`
|
||||
ProductDescribe string `json:"product_describe"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
type ProductResponseDTO struct {
|
||||
ID string `json:"id"`
|
||||
StoreID string `json:"store_id"`
|
||||
ProductTitle string `json:"product_title"`
|
||||
ProductImages []ProductImageDTO `json:"product_images"`
|
||||
TrashDetail TrashDetailResponseDTO `json:"trash_detail"`
|
||||
SalePrice int64 `json:"sale_price"`
|
||||
Quantity int `json:"quantity"`
|
||||
ProductDescribe string `json:"product_describe"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
type ProductImageDTO struct {
|
||||
ImageURL string `json:"image_url"`
|
||||
}
|
||||
|
||||
type TrashDetailResponseDTO struct {
|
||||
ID string `json:"id"`
|
||||
Description string `json:"description"`
|
||||
Price int `json:"price"`
|
||||
}
|
||||
|
||||
type CreateProductRequestDTO struct {
|
||||
StoreID string `json:"storeid" validate:"required,uuid"`
|
||||
ProductTitle string `json:"product_title" validate:"required,min=3,max=255"`
|
||||
ProductImages []string `json:"product_images" validate:"required,min=1,dive,url"`
|
||||
TrashDetailID string `json:"trash_detail_id" validate:"required,uuid"`
|
||||
SalePrice int64 `json:"sale_price" validate:"required,gt=0"`
|
||||
Quantity int `json:"quantity" validate:"required,gt=0"`
|
||||
ProductDescribe string `json:"product_describe,omitempty"`
|
||||
}
|
||||
|
||||
type CreateProductResponseDTO struct {
|
||||
ID string `json:"id"`
|
||||
StoreID string `json:"store_id"`
|
||||
ProductTitle string `json:"product_title"`
|
||||
ProductImages []string `json:"product_images"`
|
||||
TrashDetail TrashDetailResponseDTO `json:"trash_detail"`
|
||||
SalePrice int64 `json:"sale_price"`
|
||||
Quantity int `json:"quantity"`
|
||||
ProductDescribe string `json:"product_describe,omitempty"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
type UpdateProductRequestDTO struct {
|
||||
ProductTitle string `json:"product_title" validate:"required,min=3,max=255"`
|
||||
ProductImages []string `json:"product_images" validate:"required,min=1,dive,url"`
|
||||
TrashDetailID string `json:"trash_detail_id" validate:"required,uuid"`
|
||||
SalePrice int64 `json:"sale_price" validate:"required,gt=0"`
|
||||
Quantity int `json:"quantity" validate:"required,gt=0"`
|
||||
ProductDescribe string `json:"product_describe,omitempty"`
|
||||
}
|
||||
|
||||
func ValidateSalePrice(marketPrice, salePrice int64) error {
|
||||
|
||||
if salePrice > marketPrice*2 {
|
||||
return errors.New("sale price cannot be more than twice the market price")
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package dto
|
||||
|
||||
type RequestPickupRequest struct {
|
||||
RequestItems []RequestItemDTO `json:"request_items"`
|
||||
RequestTime string `json:"requestTime"`
|
||||
UserAddressID string `json:"userAddressId"`
|
||||
}
|
||||
|
||||
type RequestPickupResponse struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"userId"`
|
||||
Request []RequestItemDTO `json:"request"`
|
||||
RequestTime string `json:"requestTimePickup"`
|
||||
UserAddress UserAddressDTO `json:"userAddress"`
|
||||
StatusRequest string `json:"status"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type RequestItemDTO struct {
|
||||
TrashCategory string `json:"trashCategory"`
|
||||
EstimatedAmount string `json:"estimatedAmount"`
|
||||
}
|
||||
|
||||
type UserAddressDTO struct {
|
||||
Province string `json:"province"`
|
||||
District string `json:"district"`
|
||||
Subdistrict string `json:"subdistrict"`
|
||||
PostalCode int `json:"postalCode"`
|
||||
Village string `json:"village"`
|
||||
Detail string `json:"detail"`
|
||||
Geography string `json:"geography"`
|
||||
}
|
||||
|
||||
func NewRequestPickupResponse(id, userID, requestTime, statusRequest string, request []RequestItemDTO, userAddress UserAddressDTO, createdAt, updatedAt string) RequestPickupResponse {
|
||||
return RequestPickupResponse{
|
||||
ID: id,
|
||||
UserID: userID,
|
||||
Request: request,
|
||||
RequestTime: requestTime,
|
||||
UserAddress: userAddress,
|
||||
StatusRequest: statusRequest,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
}
|
14
dto/store.go
14
dto/store.go
|
@ -1,14 +0,0 @@
|
|||
package dto
|
||||
|
||||
type StoreResponseDTO struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"`
|
||||
StoreName string `json:"store_name"`
|
||||
StoreLogo string `json:"store_logo"`
|
||||
StoreBanner string `json:"store_banner"`
|
||||
StoreDesc string `json:"store_desc"`
|
||||
Follower int `json:"follower"`
|
||||
StoreRating float64 `json:"store_rating"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
package dto
|
||||
|
||||
import "github.com/go-playground/validator/v10"
|
||||
|
||||
type TrashCategoryDTO struct {
|
||||
Name string `json:"name" validate:"required,min=3,max=100"`
|
||||
}
|
||||
|
||||
func (t *TrashCategoryDTO) Validate() error {
|
||||
validate := validator.New()
|
||||
return validate.Struct(t)
|
||||
}
|
||||
|
||||
type TrashDetailDTO struct {
|
||||
CategoryID string `json:"category_id" validate:"required,uuid4"`
|
||||
Description string `json:"description" validate:"required,min=3,max=255"`
|
||||
Price int `json:"price" validate:"required,min=0"`
|
||||
}
|
||||
|
||||
func (t *TrashDetailDTO) Validate() error {
|
||||
validate := validator.New()
|
||||
return validate.Struct(t)
|
||||
}
|
||||
|
||||
type TrashCategoryResponse struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func NewTrashCategoryResponse(id, name, createdAt, updatedAt string) TrashCategoryResponse {
|
||||
return TrashCategoryResponse{
|
||||
ID: id,
|
||||
Name: name,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
type TrashDetailResponse struct {
|
||||
ID string `json:"id"`
|
||||
Description string `json:"description"`
|
||||
Price int `json:"price"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func NewTrashDetailResponse(id, description string, price int, createdAt, updatedAt string) TrashDetailResponse {
|
||||
return TrashDetailResponse{
|
||||
ID: id,
|
||||
Description: description,
|
||||
Price: price,
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
type UpdateTrashCategoryDTO struct {
|
||||
Name string `json:"name" validate:"required,min=3,max=100"`
|
||||
}
|
||||
|
||||
func (t *UpdateTrashCategoryDTO) Validate() error {
|
||||
validate := validator.New()
|
||||
return validate.Struct(t)
|
||||
}
|
||||
|
||||
type UpdateTrashDetailDTO struct {
|
||||
Description string `json:"description" validate:"required,min=3,max=255"`
|
||||
Price int `json:"price" validate:"required,min=0"`
|
||||
}
|
||||
|
||||
func (t *UpdateTrashDetailDTO) Validate() error {
|
||||
validate := validator.New()
|
||||
return validate.Struct(t)
|
||||
}
|
152
dto/user.go
152
dto/user.go
|
@ -1,152 +0,0 @@
|
|||
package dto
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type UserResponseDTO struct {
|
||||
ID string `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
RoleId string `json:"roleId"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func ValidateEmail(email string) error {
|
||||
if email == "" {
|
||||
return errors.New("email harus diisi")
|
||||
}
|
||||
|
||||
emailRegex := `^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$`
|
||||
re := regexp.MustCompile(emailRegex)
|
||||
if !re.MatchString(email) {
|
||||
return errors.New("format email belum sesuai")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidatePhone(phone string) error {
|
||||
if phone == "" {
|
||||
return errors.New("nomor telepon harus diisi")
|
||||
}
|
||||
|
||||
phoneRegex := `^\+?[0-9]{10,15}$`
|
||||
re := regexp.MustCompile(phoneRegex)
|
||||
if !re.MatchString(phone) {
|
||||
return errors.New("nomor telepon tidak valid")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidatePassword(password string) error {
|
||||
if password == "" {
|
||||
return errors.New("password harus diisi")
|
||||
}
|
||||
|
||||
if len(password) < 8 {
|
||||
return errors.New("password minimal 8 karakter")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RegisterUserInput struct {
|
||||
Username string `json:"username"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
Password string `json:"password"`
|
||||
ConfirmPassword string `json:"confirm_password"`
|
||||
RoleId string `json:"roleId"`
|
||||
}
|
||||
|
||||
func (input *RegisterUserInput) Validate() error {
|
||||
|
||||
if input.Username == "" {
|
||||
return errors.New("username harus diisi")
|
||||
}
|
||||
|
||||
if input.Name == "" {
|
||||
return errors.New("nama harus diisi")
|
||||
}
|
||||
|
||||
if err := ValidateEmail(input.Email); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ValidatePhone(input.Phone); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ValidatePassword(input.Password); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if input.Password != input.ConfirmPassword {
|
||||
return errors.New("password dan confirm password tidak cocok")
|
||||
}
|
||||
|
||||
if input.RoleId == "" {
|
||||
return errors.New("roleId harus diisi")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdatePasswordInput struct {
|
||||
OldPassword string `json:"old_password"`
|
||||
NewPassword string `json:"new_password"`
|
||||
}
|
||||
|
||||
func (input *UpdatePasswordInput) Validate() error {
|
||||
|
||||
if input.OldPassword == "" {
|
||||
return errors.New("old password must be provided")
|
||||
}
|
||||
|
||||
if input.NewPassword == "" {
|
||||
return errors.New("new password must be provided")
|
||||
}
|
||||
|
||||
if len(input.NewPassword) < 8 {
|
||||
return errors.New("new password must be at least 8 characters long")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateUserInput struct {
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
Name string `json:"name"`
|
||||
Phone string `json:"phone"`
|
||||
}
|
||||
|
||||
func (input *UpdateUserInput) Validate() error {
|
||||
|
||||
if input.Email != "" {
|
||||
if err := ValidateEmail(input.Email); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if input.Username == "" {
|
||||
return errors.New("username harus diisi")
|
||||
}
|
||||
|
||||
if input.Name == "" {
|
||||
return errors.New("name harus diisi")
|
||||
}
|
||||
|
||||
if input.Phone != "" {
|
||||
if err := ValidatePhone(input.Phone); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package dto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
type PinResponse struct {
|
||||
CreatedAt string `json:"createdAt"`
|
||||
}
|
||||
type PinInput struct {
|
||||
Pin string `json:"pin" validate:"required,len=6,numeric"`
|
||||
}
|
||||
|
||||
func (p *PinInput) ValidateCreate() error {
|
||||
err := validate.Struct(p)
|
||||
if err != nil {
|
||||
for _, e := range err.(validator.ValidationErrors) {
|
||||
switch e.Field() {
|
||||
case "Pin":
|
||||
return fmt.Errorf("PIN harus terdiri dari 6 digit angka")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PinUpdateInput struct {
|
||||
OldPin string `json:"old_pin" validate:"required,len=6,numeric"`
|
||||
NewPin string `json:"new_pin" validate:"required,len=6,numeric"`
|
||||
}
|
||||
|
||||
func (p *PinUpdateInput) ValidateUpdate() error {
|
||||
err := validate.Struct(p)
|
||||
if err != nil {
|
||||
for _, e := range err.(validator.ValidationErrors) {
|
||||
switch e.Field() {
|
||||
case "OldPin":
|
||||
return fmt.Errorf("PIN lama harus terdiri dari 6 digit angka")
|
||||
case "NewPin":
|
||||
return fmt.Errorf("PIN baru harus terdiri dari 6 digit angka")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package dto
|
||||
|
||||
import "github.com/go-playground/validator/v10"
|
||||
|
||||
var validate = validator.New()
|
||||
|
||||
func GetValidator() *validator.Validate {
|
||||
return validate
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/controllers"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/middleware"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func AppRouter(app *fiber.App) {
|
||||
// # init
|
||||
pointRepo := repositories.NewPointRepository()
|
||||
pointService := services.NewPointService(pointRepo)
|
||||
pointController := controllers.NewPointController(pointService)
|
||||
|
||||
bannerRepo := repositories.NewBannerRepository()
|
||||
bannerService := services.NewBannerService(bannerRepo)
|
||||
bannerController := controllers.NewBannerController(bannerService)
|
||||
|
||||
articleRepo := repositories.NewArticleRepository()
|
||||
articleService := services.NewArticleService(articleRepo)
|
||||
articleController := controllers.NewArticleController(articleService)
|
||||
|
||||
// # api group domain endpoint #
|
||||
api := app.Group("/apirijikid")
|
||||
|
||||
// # API Secure #
|
||||
api.Use(middleware.APIKeyMiddleware)
|
||||
api.Use(middleware.RateLimitMiddleware)
|
||||
|
||||
// # user initial coint #
|
||||
api.Get("/user/initial-coint", pointController.GetAllPoints)
|
||||
api.Get("/user/initial-coint/:id", pointController.GetPointByID)
|
||||
api.Post("/user/initial-coint", middleware.RoleRequired(utils.RoleAdministrator), pointController.CreatePoint)
|
||||
api.Put("/user/initial-coint/:id", middleware.RoleRequired(utils.RoleAdministrator), pointController.UpdatePoint)
|
||||
api.Delete("/user/initial-coint/:id", middleware.RoleRequired(utils.RoleAdministrator), pointController.DeletePoint)
|
||||
|
||||
//# coverage area #
|
||||
api.Get("/coverage-areas", controllers.GetCoverageAreas)
|
||||
api.Get("/coverage-areas-district/:id", controllers.GetCoverageAreaByIDProvince)
|
||||
api.Get("/coverage-areas-subdistrict/:id", controllers.GetCoverageAreaByIDDistrict)
|
||||
api.Post("/coverage-areas", middleware.RoleRequired(utils.RoleAdministrator), controllers.CreateCoverageArea)
|
||||
api.Post("/coverage-areas-district", middleware.RoleRequired(utils.RoleAdministrator), controllers.CreateCoverageDistrict)
|
||||
api.Post("/coverage-areas-subdistrict", middleware.RoleRequired(utils.RoleAdministrator), controllers.CreateCoverageSubdistrict)
|
||||
api.Put("/coverage-areas/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.UpdateCoverageArea)
|
||||
api.Put("/coverage-areas-district/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.UpdateCoverageDistrict)
|
||||
api.Put("/coverage-areas-subdistrict/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.UpdateCoverageSubdistrict)
|
||||
api.Delete("/coverage-areas/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.DeleteCoverageArea)
|
||||
api.Delete("/coverage-areas-district/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.DeleteCoverageDistrict)
|
||||
api.Delete("/coverage-areas-subdistrict/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.DeleteCoverageSubdistrict)
|
||||
|
||||
// # role #
|
||||
api.Get("/roles", middleware.RoleRequired(utils.RoleAdministrator), controllers.GetAllUserRoles)
|
||||
api.Get("/role/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.GetUserRoleByID)
|
||||
|
||||
// # authentication #
|
||||
api.Post("/register", controllers.Register)
|
||||
api.Post("/login", controllers.Login)
|
||||
api.Post("/logout", controllers.Logout)
|
||||
|
||||
// # userinfo #
|
||||
api.Get("/user", middleware.AuthMiddleware, controllers.GetUserInfo)
|
||||
api.Post("/user/update-password", middleware.AuthMiddleware, controllers.UpdatePassword)
|
||||
api.Put("/user/update-user", middleware.AuthMiddleware, controllers.UpdateUser)
|
||||
|
||||
// # view all user (admin)
|
||||
api.Get("/user/listallusers", middleware.RoleRequired(utils.RoleAdministrator), controllers.GetListUsers)
|
||||
api.Get("/user/listalluser/:roleid", middleware.RoleRequired(utils.RoleAdministrator), controllers.GetUsersByRole)
|
||||
api.Get("/user/listuser/:userid", middleware.RoleRequired(utils.RoleAdministrator), controllers.GetUserByUserID)
|
||||
|
||||
// # user set pin #
|
||||
api.Get("/user/verif-pin", middleware.AuthMiddleware, controllers.GetPin)
|
||||
api.Get("/user/cek-pin-status", middleware.AuthMiddleware, controllers.GetPinStatus)
|
||||
api.Post("/user/set-pin", middleware.AuthMiddleware, controllers.CreatePin)
|
||||
api.Put("/user/update-pin", middleware.AuthMiddleware, controllers.UpdatePin)
|
||||
api.Put("/user/update-pin", middleware.AuthMiddleware, controllers.UpdatePin)
|
||||
|
||||
// # address routing #
|
||||
api.Get("/addresses", middleware.AuthMiddleware, controllers.GetListAddress)
|
||||
api.Get("/address/:id", middleware.AuthMiddleware, controllers.GetAddressByID)
|
||||
api.Post("/address/create-address", middleware.AuthMiddleware, controllers.CreateAddress)
|
||||
api.Put("/address/update-address/:id", middleware.AuthMiddleware, controllers.UpdateAddress)
|
||||
api.Delete("/address/delete-address/:id", middleware.AuthMiddleware, controllers.DeleteAddress)
|
||||
|
||||
// # article #
|
||||
api.Get("/articles", articleController.GetAllArticles)
|
||||
api.Get("/article/:id", articleController.GetArticleByID)
|
||||
api.Post("/article/create-article", middleware.RoleRequired(utils.RoleAdministrator), articleController.CreateArticle)
|
||||
api.Put("/article/update-article/:id", middleware.RoleRequired(utils.RoleAdministrator), articleController.UpdateArticle)
|
||||
api.Delete("/article/delete-article/:id", middleware.RoleRequired(utils.RoleAdministrator), articleController.DeleteArticle)
|
||||
|
||||
// # trash type #
|
||||
api.Get("/trash-categorys", controllers.GetTrashCategories)
|
||||
api.Get("/trash-category/:id", controllers.GetTrashCategoryDetail)
|
||||
api.Post("/trash-category/create-trash-category", middleware.RoleRequired(utils.RoleAdministrator), controllers.CreateTrashCategory)
|
||||
api.Post("/trash-category/create-trash-categorydetail", middleware.RoleRequired(utils.RoleAdministrator), controllers.CreateTrashDetail)
|
||||
api.Put("/trash-category/update-trash-category/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.UpdateTrashCategory)
|
||||
api.Put("/trash-category/update-trash-detail/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.UpdateTrashDetail)
|
||||
api.Delete("/trash-category/delete-trash-category/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.DeleteTrashCategory)
|
||||
api.Delete("/trash-category/delete-trash-detail/:id", middleware.RoleRequired(utils.RoleAdministrator), controllers.DeleteTrashDetail)
|
||||
|
||||
// # banner #
|
||||
api.Get("/banners", bannerController.GetAllBanners)
|
||||
api.Get("/banner/:id", bannerController.GetBannerByID)
|
||||
api.Post("/banner/create-banner", middleware.RoleRequired(utils.RoleAdministrator), bannerController.CreateBanner)
|
||||
api.Put("/banner/update-banner/:id", middleware.RoleRequired(utils.RoleAdministrator), bannerController.UpdateBanner)
|
||||
api.Delete("/banner/delete-banner/:id", middleware.RoleRequired(utils.RoleAdministrator), bannerController.DeleteBanner)
|
||||
|
||||
// # wilayah di indonesia #
|
||||
api.Get("/wilayah-indonesia/provinces", controllers.GetProvinces)
|
||||
api.Get("/wilayah-indonesia/regencies", controllers.GetRegencies)
|
||||
api.Get("/wilayah-indonesia/subdistricts", controllers.GetDistricts)
|
||||
api.Get("/wilayah-indonesia/villages", controllers.GetVillages)
|
||||
api.Get("/wilayah-indonesia/provinces/:id", controllers.GetProvinceByID)
|
||||
api.Get("/wilayah-indonesia/regencies/:id", controllers.GetRegencyByID)
|
||||
api.Get("/wilayah-indonesia/subdistricts/:id", controllers.GetDistrictByID)
|
||||
api.Get("/wilayah-indonesia/villages/:id", controllers.GetVillageByID)
|
||||
|
||||
// # request pickup by user (masyarakat) #
|
||||
api.Get("/requestpickup", middleware.RoleRequired(utils.RoleMasyarakat, utils.RolePengepul), controllers.GetRequestPickupsByUser)
|
||||
api.Post("/addrequestpickup", middleware.RoleRequired(utils.RoleMasyarakat), controllers.CreateRequestPickup)
|
||||
api.Delete("/deleterequestpickup/:id", middleware.RoleRequired(utils.RoleMasyarakat), controllers.DeleteRequestPickup)
|
||||
|
||||
// # product post by pengepul
|
||||
api.Get("/post/products", middleware.RoleRequired(utils.RolePengepul), controllers.GetAllProducts)
|
||||
api.Get("/post/product/:productid", middleware.RoleRequired(utils.RolePengepul), controllers.GetProductByID)
|
||||
api.Get("/view/product/:storeid", middleware.RoleRequired(utils.RolePengepul), controllers.GetProductsByStore)
|
||||
api.Post("/post/addproduct", middleware.RoleRequired(utils.RolePengepul), controllers.CreateProduct)
|
||||
api.Put("/post/product/:productid", middleware.RoleRequired(utils.RolePengepul), controllers.UpdateProduct)
|
||||
api.Delete("/delete/product/:productid", middleware.RoleRequired(utils.RolePengepul), controllers.DeleteProduct)
|
||||
|
||||
// # marketplace
|
||||
api.Get("/store/marketplace", middleware.RoleRequired(utils.RolePengepul), controllers.GetStoresByUserID)
|
||||
api.Get("/store/marketplace/:storeid", middleware.RoleRequired(utils.RolePengepul), controllers.GetStoreByID)
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetProvinces(c *fiber.Ctx) error {
|
||||
provinces, err := services.GetProvinces()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to retrieve provinces",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Provinces retrieved successfully",
|
||||
provinces,
|
||||
))
|
||||
}
|
||||
|
||||
func GetRegencies(c *fiber.Ctx) error {
|
||||
regencies, err := services.GetRegencies()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to retrieve regencies",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Regencies retrieved successfully",
|
||||
regencies,
|
||||
))
|
||||
}
|
||||
|
||||
func GetDistricts(c *fiber.Ctx) error {
|
||||
districts, err := services.GetDistricts()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to retrieve districts",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Districts retrieved successfully",
|
||||
districts,
|
||||
))
|
||||
}
|
||||
|
||||
func GetVillages(c *fiber.Ctx) error {
|
||||
villages, err := services.GetVillages()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to retrieve villages",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Villages retrieved successfully",
|
||||
villages,
|
||||
))
|
||||
}
|
||||
|
||||
func GetProvinceByID(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
province, err := services.GetProvinceByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to retrieve province",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Province by id retrieved successfully",
|
||||
province,
|
||||
))
|
||||
}
|
||||
|
||||
func GetRegencyByID(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
regency, err := services.GetRegencyByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to retrieve regency",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Regency by id retrieved successfully",
|
||||
regency,
|
||||
))
|
||||
}
|
||||
|
||||
func GetDistrictByID(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
district, err := services.GetDistrictByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to retrieve district",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"District by id retrieved successfully",
|
||||
district,
|
||||
))
|
||||
}
|
||||
|
||||
func GetVillageByID(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
village, err := services.GetVillageByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to retrieve village",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Village by id retrieved successfully",
|
||||
village,
|
||||
))
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func CreateAddress(c *fiber.Ctx) error {
|
||||
var input dto.AddressInput
|
||||
if err := c.BodyParser(&input); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Mohon masukkan alamat dengan benar",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := input.ValidatePost(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userID := c.Locals("userID").(string)
|
||||
address, err := services.CreateAddress(userID, input)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to create address",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
createdAtFormatted := utils.FormatDateToIndonesianFormat(address.CreatedAt)
|
||||
updatedAtFormatted := utils.FormatDateToIndonesianFormat(address.UpdatedAt)
|
||||
|
||||
addressResponse := dto.AddressResponse{
|
||||
ID: address.ID,
|
||||
Province: address.Province,
|
||||
District: address.District,
|
||||
Subdistrict: address.Subdistrict,
|
||||
PostalCode: address.PostalCode,
|
||||
Village: address.Village,
|
||||
Detail: address.Detail,
|
||||
Geography: address.Geography,
|
||||
CreatedAt: createdAtFormatted,
|
||||
UpdatedAt: updatedAtFormatted,
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Address created successfully",
|
||||
addressResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func GetListAddress(c *fiber.Ctx) error {
|
||||
userID := c.Locals("userID").(string)
|
||||
addresses, err := services.GetAllAddressesByUserID(userID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Addresses not found",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var addressResponses []dto.AddressResponse
|
||||
for _, address := range addresses {
|
||||
|
||||
createdAtFormatted := utils.FormatDateToIndonesianFormat(address.CreatedAt)
|
||||
updatedAtFormatted := utils.FormatDateToIndonesianFormat(address.UpdatedAt)
|
||||
|
||||
addressResponse := dto.AddressResponse{
|
||||
ID: address.ID,
|
||||
Province: address.Province,
|
||||
District: address.District,
|
||||
Subdistrict: address.Subdistrict,
|
||||
PostalCode: address.PostalCode,
|
||||
Village: address.Village,
|
||||
Detail: address.Detail,
|
||||
Geography: address.Geography,
|
||||
CreatedAt: createdAtFormatted,
|
||||
UpdatedAt: updatedAtFormatted,
|
||||
}
|
||||
addressResponses = append(addressResponses, addressResponse)
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Addresses fetched successfully",
|
||||
addressResponses,
|
||||
))
|
||||
}
|
||||
|
||||
func GetAddressByID(c *fiber.Ctx) error {
|
||||
addressID := c.Params("id")
|
||||
|
||||
address, err := services.GetAddressByID(addressID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Address not found",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
createdAtFormatted := utils.FormatDateToIndonesianFormat(address.CreatedAt)
|
||||
updatedAtFormatted := utils.FormatDateToIndonesianFormat(address.UpdatedAt)
|
||||
|
||||
addressResponse := dto.AddressResponse{
|
||||
ID: address.ID,
|
||||
Province: address.Province,
|
||||
District: address.District,
|
||||
Subdistrict: address.Subdistrict,
|
||||
PostalCode: address.PostalCode,
|
||||
Village: address.Village,
|
||||
Detail: address.Detail,
|
||||
Geography: address.Geography,
|
||||
CreatedAt: createdAtFormatted,
|
||||
UpdatedAt: updatedAtFormatted,
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Address fetched successfully",
|
||||
addressResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func UpdateAddress(c *fiber.Ctx) error {
|
||||
addressID := c.Params("id")
|
||||
|
||||
var input dto.AddressInput
|
||||
|
||||
if err := c.BodyParser(&input); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input data",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := input.ValidateUpdate(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
address, err := services.UpdateAddress(addressID, input)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to update address",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
createdAtFormatted := utils.FormatDateToIndonesianFormat(address.CreatedAt)
|
||||
updatedAtFormatted := utils.FormatDateToIndonesianFormat(address.UpdatedAt)
|
||||
|
||||
addressResponse := dto.AddressResponse{
|
||||
ID: address.ID,
|
||||
Province: address.Province,
|
||||
District: address.District,
|
||||
Subdistrict: address.Subdistrict,
|
||||
PostalCode: address.PostalCode,
|
||||
Village: address.Village,
|
||||
Detail: address.Detail,
|
||||
Geography: address.Geography,
|
||||
CreatedAt: createdAtFormatted,
|
||||
UpdatedAt: updatedAtFormatted,
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Address updated successfully",
|
||||
addressResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func DeleteAddress(c *fiber.Ctx) error {
|
||||
addressID := c.Params("id")
|
||||
|
||||
err := services.DeleteAddress(addressID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to delete address",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Address deleted successfully",
|
||||
nil,
|
||||
))
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
type ArticleController struct {
|
||||
service *services.ArticleService
|
||||
}
|
||||
|
||||
func NewArticleController(service *services.ArticleService) *ArticleController {
|
||||
return &ArticleController{service: service}
|
||||
}
|
||||
|
||||
func (ac *ArticleController) GetAllArticles(c *fiber.Ctx) error {
|
||||
articles, err := ac.service.GetAllArticles()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.ErrorResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch articles",
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Articles fetched successfully",
|
||||
articles,
|
||||
))
|
||||
}
|
||||
|
||||
func (ac *ArticleController) GetArticleByID(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
article, err := ac.service.GetArticleByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.ErrorResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Article not found",
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Article fetched successfully",
|
||||
article,
|
||||
))
|
||||
}
|
||||
|
||||
func (ac *ArticleController) CreateArticle(c *fiber.Ctx) error {
|
||||
var request dto.ArticleCreateRequest
|
||||
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.ErrorResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request body",
|
||||
))
|
||||
}
|
||||
|
||||
article, err := ac.service.CreateArticle(&request)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.ErrorResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||
fiber.StatusCreated,
|
||||
"Article created successfully",
|
||||
article,
|
||||
))
|
||||
}
|
||||
|
||||
func (ac *ArticleController) UpdateArticle(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
var request dto.ArticleUpdateRequest
|
||||
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.ErrorResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request body",
|
||||
))
|
||||
}
|
||||
|
||||
article, err := ac.service.UpdateArticle(id, &request)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.ErrorResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Point updated successfully",
|
||||
article,
|
||||
))
|
||||
}
|
||||
|
||||
func (ac *ArticleController) DeleteArticle(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
err := ac.service.DeleteArticle(id)
|
||||
if err != nil {
|
||||
if err.Error() == "article not found" {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.ErrorResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Article not found",
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.ErrorResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
err.Error(),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Article deleted successfully",
|
||||
nil,
|
||||
))
|
||||
}
|
|
@ -1,294 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func Register(c *fiber.Ctx) error {
|
||||
var userInput dto.RegisterUserInput
|
||||
|
||||
if err := c.BodyParser(&userInput); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input data",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := userInput.Validate(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
err := services.RegisterUser(userInput.Username, userInput.Name, userInput.Email, userInput.Phone, userInput.Password, userInput.ConfirmPassword, userInput.RoleId)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusConflict).JSON(utils.FormatResponse(
|
||||
fiber.StatusConflict,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
user, err := repositories.GetUserByEmailUsernameOrPhone(userInput.Email, userInput.RoleId)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch user after registration",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userResponse := dto.UserResponseDTO{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Name: user.Name,
|
||||
Email: user.Email,
|
||||
Phone: user.Phone,
|
||||
RoleId: user.RoleID,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(user.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(user.UpdatedAt),
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"User registered successfully",
|
||||
userResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func Login(c *fiber.Ctx) error {
|
||||
var credentials struct {
|
||||
Identifier string `json:"identifier"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
if err := c.BodyParser(&credentials); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input data",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
token, err := services.LoginUser(credentials.Identifier, credentials.Password)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
err = config.RedisClient.Set(ctx, "auth_token:"+token, credentials.Identifier, time.Hour*24).Err()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to store session",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
user, err := repositories.GetUserByEmailUsernameOrPhone(credentials.Identifier, "")
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Login successful",
|
||||
map[string]interface{}{
|
||||
"token": token,
|
||||
"role": user.RoleID,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
func GetUserInfo(c *fiber.Ctx) error {
|
||||
userID := c.Locals("userID").(string)
|
||||
|
||||
user, err := services.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"user tidak ditemukan",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userResponse := dto.UserResponseDTO{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Name: user.Name,
|
||||
Phone: user.Phone,
|
||||
Email: user.Email,
|
||||
RoleId: user.RoleID,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(user.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(user.UpdatedAt),
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Data user berhasil ditampilkan",
|
||||
userResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func UpdateUser(c *fiber.Ctx) error {
|
||||
var userInput dto.UpdateUserInput
|
||||
|
||||
if err := c.BodyParser(&userInput); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input data",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := userInput.Validate(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userID, ok := c.Locals("userID").(string)
|
||||
if !ok || userID == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Unauthorized access",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
err := services.UpdateUser(userID, userInput.Email, userInput.Username, userInput.Name, userInput.Phone)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusConflict).JSON(utils.FormatResponse(
|
||||
fiber.StatusConflict,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
user, err := repositories.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch user after update",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userResponse := dto.UserResponseDTO{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Name: user.Name,
|
||||
Email: user.Email,
|
||||
Phone: user.Phone,
|
||||
RoleId: user.RoleID,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(user.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(user.UpdatedAt),
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"User updated successfully",
|
||||
userResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func UpdatePassword(c *fiber.Ctx) error {
|
||||
var passwordInput dto.UpdatePasswordInput
|
||||
|
||||
if err := c.BodyParser(&passwordInput); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input data",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := passwordInput.Validate(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userID := c.Locals("userID").(string)
|
||||
|
||||
err := services.UpdatePassword(userID, passwordInput.OldPassword, passwordInput.NewPassword)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
user, err := repositories.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch user after password update",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
updatedAtFormatted := utils.FormatDateToIndonesianFormat(user.UpdatedAt)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Password updated successfully",
|
||||
map[string]string{
|
||||
"updatedAt": updatedAtFormatted,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
func Logout(c *fiber.Ctx) error {
|
||||
tokenString := c.Get("Authorization")
|
||||
tokenString = strings.TrimPrefix(tokenString, "Bearer ")
|
||||
|
||||
if tokenString == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Token is required",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
err := config.RedisClient.Del(ctx, "auth_token:"+tokenString).Err()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to delete session",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Logout successful",
|
||||
nil,
|
||||
))
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
type BannerController struct {
|
||||
service *services.BannerService
|
||||
}
|
||||
|
||||
func NewBannerController(service *services.BannerService) *BannerController {
|
||||
return &BannerController{service: service}
|
||||
}
|
||||
|
||||
func (bc *BannerController) GetAllBanners(c *fiber.Ctx) error {
|
||||
banners, err := bc.service.GetAllBanners()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.ErrorResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch banners",
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Banners fetched successfully",
|
||||
banners,
|
||||
))
|
||||
}
|
||||
|
||||
func (bc *BannerController) GetBannerByID(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
banner, err := bc.service.GetBannerByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.ErrorResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Banner not found",
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Banner fetched successfully",
|
||||
banner,
|
||||
))
|
||||
}
|
||||
|
||||
func (bc *BannerController) CreateBanner(c *fiber.Ctx) error {
|
||||
var request dto.BannerCreateRequest
|
||||
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.ErrorResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request body",
|
||||
))
|
||||
}
|
||||
|
||||
banner, err := bc.service.CreateBanner(&request)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.ErrorResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
err.Error(),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||
fiber.StatusCreated,
|
||||
"Banner created successfully",
|
||||
banner,
|
||||
))
|
||||
}
|
||||
|
||||
func (bc *BannerController) UpdateBanner(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
var request dto.BannerUpdateRequest
|
||||
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.ErrorResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request body",
|
||||
))
|
||||
}
|
||||
|
||||
banner, err := bc.service.UpdateBanner(id, &request)
|
||||
if err != nil {
|
||||
if err.Error() == "banner not found" {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.ErrorResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Banner not found",
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.ErrorResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
err.Error(),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Banner updated successfully",
|
||||
banner,
|
||||
))
|
||||
}
|
||||
|
||||
func (bc *BannerController) DeleteBanner(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
err := bc.service.DeleteBanner(id)
|
||||
if err != nil {
|
||||
if err.Error() == "banner not found" {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.ErrorResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Banner not found",
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.ErrorResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
err.Error(),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Banner deleted successfully",
|
||||
nil,
|
||||
))
|
||||
}
|
|
@ -1,409 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetCoverageAreas(c *fiber.Ctx) error {
|
||||
coverageAreas, err := services.GetCoverageAreas()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch coverage areas",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var coverageAreaResponses []dto.CoverageAreaResponse
|
||||
for _, area := range coverageAreas {
|
||||
coverageAreaResponses = append(coverageAreaResponses, dto.NewCoverageAreaResponse(
|
||||
area.ID,
|
||||
area.Province,
|
||||
utils.FormatDateToIndonesianFormat(area.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(area.UpdatedAt),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage areas has been fetched",
|
||||
coverageAreaResponses,
|
||||
))
|
||||
}
|
||||
|
||||
func GetCoverageAreaByIDProvince(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
coverageArea, err := services.GetCoverageAreaByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch coverage area details by province",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var coverageAreaResponse dto.CoverageAreaWithDistrictsResponse
|
||||
coverageAreaResponse.ID = coverageArea.ID
|
||||
coverageAreaResponse.Province = coverageArea.Province
|
||||
coverageAreaResponse.CreatedAt = utils.FormatDateToIndonesianFormat(coverageArea.CreatedAt)
|
||||
coverageAreaResponse.UpdatedAt = utils.FormatDateToIndonesianFormat(coverageArea.UpdatedAt)
|
||||
|
||||
districts, err := services.GetCoverageDistricsByCoverageAreaID(coverageArea.ID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch coverage districts",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var coverageAreas []dto.CoverageAreaResponse
|
||||
for _, district := range districts {
|
||||
coverageAreas = append(coverageAreas, dto.NewCoverageAreaResponse(
|
||||
district.ID,
|
||||
district.District,
|
||||
utils.FormatDateToIndonesianFormat(district.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(district.UpdatedAt),
|
||||
))
|
||||
}
|
||||
|
||||
coverageAreaResponse.CoverageArea = coverageAreas
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage areas detail by province has been fetched",
|
||||
coverageAreaResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func GetCoverageAreaByIDDistrict(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
coverageDetail, err := services.GetCoverageAreaByDistrictID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch coverage area details by district",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageArea, err := services.GetCoverageAreaByID(coverageDetail.CoverageAreaID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch coverage area details by province",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
subdistricts, err := services.GetSubdistrictsByCoverageDistrictID(coverageDetail.ID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch subdistricts",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var subdistrictResponses []dto.SubdistrictResponse
|
||||
for _, loc := range subdistricts {
|
||||
subdistrictResponses = append(subdistrictResponses, dto.NewSubdistrictResponse(
|
||||
loc.ID,
|
||||
loc.Subdistrict,
|
||||
utils.FormatDateToIndonesianFormat(loc.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(loc.UpdatedAt),
|
||||
))
|
||||
}
|
||||
|
||||
coverageAreaResponse := dto.NewCoverageAreaDetailWithLocation(
|
||||
coverageDetail.ID,
|
||||
coverageArea.Province,
|
||||
coverageDetail.District,
|
||||
utils.FormatDateToIndonesianFormat(coverageDetail.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(coverageDetail.UpdatedAt),
|
||||
subdistrictResponses,
|
||||
)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage areas detail by district has been fetched",
|
||||
coverageAreaResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func CreateCoverageArea(c *fiber.Ctx) error {
|
||||
var request dto.CoverageAreaCreateRequest
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request payload",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageArea, err := services.CreateCoverageArea(request.Province)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to create coverage area",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageAreaResponse := dto.NewCoverageAreaResponse(
|
||||
coverageArea.ID,
|
||||
coverageArea.Province,
|
||||
utils.FormatDateToIndonesianFormat(coverageArea.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(coverageArea.UpdatedAt),
|
||||
)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage area has been created",
|
||||
coverageAreaResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func CreateCoverageDistrict(c *fiber.Ctx) error {
|
||||
var request dto.CoverageDistrictCreateRequest
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request payload",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageDistrict, err := services.CreateCoverageDistrict(request.CoverageAreaID, request.District)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to create coverage district",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageDistrictResponse := dto.NewCoverageAreaResponse(
|
||||
coverageDistrict.ID,
|
||||
coverageDistrict.District,
|
||||
utils.FormatDateToIndonesianFormat(coverageDistrict.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(coverageDistrict.UpdatedAt),
|
||||
)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage district has been created",
|
||||
coverageDistrictResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func CreateCoverageSubdistrict(c *fiber.Ctx) error {
|
||||
|
||||
var request dto.CoverageSubdistrictCreateRequest
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request payload",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageSubdistrict, err := services.CreateCoverageSubdistrict(
|
||||
request.CoverageAreaID,
|
||||
request.CoverageDistrictId,
|
||||
request.Subdistrict,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to create coverage subdistrict",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageSubdistrictResponse := dto.NewCoverageAreaResponse(
|
||||
coverageSubdistrict.ID,
|
||||
coverageSubdistrict.Subdistrict,
|
||||
utils.FormatDateToIndonesianFormat(coverageSubdistrict.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(coverageSubdistrict.UpdatedAt),
|
||||
)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage subdistrict has been created",
|
||||
coverageSubdistrictResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func UpdateCoverageArea(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
var request dto.CoverageAreaUpdateRequest
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request payload",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageArea, err := services.UpdateCoverageArea(id, domain.CoverageArea{
|
||||
Province: request.Province,
|
||||
})
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to update coverage area",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageAreaResponse := dto.NewCoverageAreaResponse(
|
||||
coverageArea.ID,
|
||||
coverageArea.Province,
|
||||
utils.FormatDateToIndonesianFormat(coverageArea.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(coverageArea.UpdatedAt),
|
||||
)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage area has been updated",
|
||||
coverageAreaResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func UpdateCoverageDistrict(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
var request dto.CoverageDistrictUpdateRequest
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request payload",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageDistrict, err := services.UpdateCoverageDistrict(id, domain.CoverageDistric{
|
||||
District: request.District,
|
||||
})
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to update coverage district",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageDistrictResponse := dto.NewCoverageAreaResponse(
|
||||
coverageDistrict.ID,
|
||||
coverageDistrict.District,
|
||||
utils.FormatDateToIndonesianFormat(coverageDistrict.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(coverageDistrict.UpdatedAt),
|
||||
)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage district has been updated",
|
||||
coverageDistrictResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func UpdateCoverageSubdistrict(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
var request dto.CoverageSubdistrictUpdateRequest
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request payload",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageSubdistrict, err := services.UpdateCoverageSubdistrict(id, domain.CoverageSubdistrict{
|
||||
Subdistrict: request.Subdistrict,
|
||||
})
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to update coverage subdistrict",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
coverageSubdistrictResponse := dto.NewSubdistrictResponse(
|
||||
coverageSubdistrict.ID,
|
||||
coverageSubdistrict.Subdistrict,
|
||||
utils.FormatDateToIndonesianFormat(coverageSubdistrict.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(coverageSubdistrict.UpdatedAt),
|
||||
)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage subdistrict has been updated",
|
||||
coverageSubdistrictResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func DeleteCoverageArea(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
if err := services.DeleteCoverageArea(id); err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to delete coverage area",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage area has been deleted",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
func DeleteCoverageDistrict(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
if err := services.DeleteCoverageDistrict(id); err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to delete coverage district",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage district has been deleted",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
func DeleteCoverageSubdistrict(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
if err := services.DeleteCoverageSubdistrict(id); err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to delete coverage subdistrict",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Coverage subdistrict has been deleted",
|
||||
nil,
|
||||
))
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
type PointController struct {
|
||||
service *services.PointService
|
||||
}
|
||||
|
||||
func NewPointController(service *services.PointService) *PointController {
|
||||
return &PointController{service: service}
|
||||
}
|
||||
|
||||
func (pc *PointController) GetAllPoints(c *fiber.Ctx) error {
|
||||
points, err := pc.service.GetAllPoints()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.ErrorResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch points",
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Points fetched successfully",
|
||||
points,
|
||||
))
|
||||
}
|
||||
|
||||
func (pc *PointController) GetPointByID(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
point, err := pc.service.GetPointByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.ErrorResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Point not found",
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Point fetched successfully",
|
||||
point,
|
||||
))
|
||||
}
|
||||
|
||||
func (pc *PointController) CreatePoint(c *fiber.Ctx) error {
|
||||
var request dto.PointCreateRequest
|
||||
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.ErrorResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request body",
|
||||
))
|
||||
}
|
||||
|
||||
point, err := pc.service.CreatePoint(&request)
|
||||
if err != nil {
|
||||
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.ErrorResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||
fiber.StatusCreated,
|
||||
"Point created successfully",
|
||||
point,
|
||||
))
|
||||
}
|
||||
|
||||
func (pc *PointController) UpdatePoint(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
var request dto.PointUpdateRequest
|
||||
|
||||
if err := c.BodyParser(&request); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.ErrorResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request body",
|
||||
))
|
||||
}
|
||||
|
||||
point, err := pc.service.UpdatePoint(id, &request)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.ErrorResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Point updated successfully",
|
||||
point,
|
||||
))
|
||||
}
|
||||
|
||||
func (pc *PointController) DeletePoint(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
err := pc.service.DeletePoint(id)
|
||||
if err != nil {
|
||||
if err.Error() == "point not found" {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.ErrorResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Point not found",
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.ErrorResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
err.Error(),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Point deleted successfully",
|
||||
nil,
|
||||
))
|
||||
}
|
|
@ -1,262 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetAllProducts(c *fiber.Ctx) error {
|
||||
userID, ok := c.Locals("userID").(string)
|
||||
if !ok || userID == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Unauthorized: user ID is missing",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
storeID := c.Query("storeID", "")
|
||||
|
||||
limit := c.QueryInt("limit", 10)
|
||||
page := c.QueryInt("page", 1)
|
||||
|
||||
if limit <= 0 || page <= 0 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid pagination parameters",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var products []dto.ProductResponseWithSoldDTO
|
||||
var err error
|
||||
|
||||
if storeID != "" {
|
||||
|
||||
products, err = services.GetProductsByStoreID(storeID, limit, page)
|
||||
} else {
|
||||
|
||||
products, err = services.GetProductsByUserID(userID, limit, page)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch products",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Products fetched successfully",
|
||||
products,
|
||||
))
|
||||
}
|
||||
|
||||
func GetProductByID(c *fiber.Ctx) error {
|
||||
storeID, ok := c.Locals("userID").(string)
|
||||
if !ok || storeID == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Unauthorized: store ID is missing",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
productID := c.Params("productid")
|
||||
if productID == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Product ID is required",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
product, err := services.GetProductByIDAndStoreID(productID, storeID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Product not found",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Product fetched successfully",
|
||||
product,
|
||||
))
|
||||
}
|
||||
|
||||
func GetProductsByStore(c *fiber.Ctx) error {
|
||||
storeID := c.Params("storeid")
|
||||
if storeID == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Store ID is required",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
limit := c.QueryInt("limit", 10)
|
||||
page := c.QueryInt("page", 1)
|
||||
|
||||
if limit <= 0 || page <= 0 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid pagination parameters",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
products, err := services.GetProductsByStoreID(storeID, limit, page)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Store not found",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Products fetched successfully",
|
||||
products,
|
||||
))
|
||||
}
|
||||
|
||||
func CreateProduct(c *fiber.Ctx) error {
|
||||
var input dto.CreateProductRequestDTO
|
||||
|
||||
if err := c.BodyParser(&input); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request payload",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userID, ok := c.Locals("userID").(string)
|
||||
if !ok || userID == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Unauthorized: user ID is missing",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if input.StoreID == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Store ID is required in the body",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
product, err := services.CreateProduct(input, userID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnprocessableEntity).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnprocessableEntity,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||
fiber.StatusCreated,
|
||||
"Product created successfully",
|
||||
product,
|
||||
))
|
||||
}
|
||||
|
||||
func UpdateProduct(c *fiber.Ctx) error {
|
||||
productID := c.Params("productid")
|
||||
|
||||
userID, ok := c.Locals("userID").(string)
|
||||
if !ok || userID == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Unauthorized: user ID is missing",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if productID == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Product ID is required",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var input dto.UpdateProductRequestDTO
|
||||
if err := c.BodyParser(&input); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request payload",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := dto.GetValidator().Struct(input); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid product data",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
updatedProduct, err := services.UpdateProduct(productID, input)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnprocessableEntity).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnprocessableEntity,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Product updated successfully",
|
||||
updatedProduct,
|
||||
))
|
||||
}
|
||||
|
||||
func DeleteProduct(c *fiber.Ctx) error {
|
||||
productID := c.Params("productid")
|
||||
|
||||
userID, ok := c.Locals("userID").(string)
|
||||
if !ok || userID == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Unauthorized: user ID is missing",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if productID == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Product ID is required",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
err := services.DeleteProduct(productID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Product not found or unable to delete",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Product deleted successfully",
|
||||
nil,
|
||||
))
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetRequestPickupsByUser(c *fiber.Ctx) error {
|
||||
userID, ok := c.Locals("userID").(string)
|
||||
if !ok || userID == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"User not authenticated",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
service := services.NewRequestPickupService(repositories.NewRequestPickupRepository())
|
||||
|
||||
requestPickups, err := service.GetRequestPickupsByUser(userID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch request pickups",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var requestPickupResponses []dto.RequestPickupResponse
|
||||
for _, requestPickup := range requestPickups {
|
||||
userAddress := dto.UserAddressDTO{
|
||||
Province: requestPickup.UserAddress.Province,
|
||||
District: requestPickup.UserAddress.District,
|
||||
Subdistrict: requestPickup.UserAddress.Subdistrict,
|
||||
PostalCode: requestPickup.UserAddress.PostalCode,
|
||||
Village: requestPickup.UserAddress.Village,
|
||||
Detail: requestPickup.UserAddress.Detail,
|
||||
Geography: requestPickup.UserAddress.Geography,
|
||||
}
|
||||
|
||||
var requestItems []dto.RequestItemDTO
|
||||
for _, item := range requestPickup.Request {
|
||||
requestItems = append(requestItems, dto.RequestItemDTO{
|
||||
TrashCategory: item.TrashCategory.Name,
|
||||
EstimatedAmount: item.EstimatedAmount,
|
||||
})
|
||||
}
|
||||
|
||||
requestPickupResponses = append(requestPickupResponses, dto.NewRequestPickupResponse(
|
||||
requestPickup.ID,
|
||||
requestPickup.UserID,
|
||||
requestPickup.RequestTime,
|
||||
requestPickup.StatusRequest,
|
||||
requestItems,
|
||||
userAddress,
|
||||
utils.FormatDateToIndonesianFormat(requestPickup.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(requestPickup.UpdatedAt),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Request pickup by user has been fetched",
|
||||
requestPickupResponses,
|
||||
))
|
||||
}
|
||||
|
||||
func CreateRequestPickup(c *fiber.Ctx) error {
|
||||
var req dto.RequestPickupRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid request body",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userID, ok := c.Locals("userID").(string)
|
||||
if !ok || userID == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"User not authenticated",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if req.UserAddressID == "" || len(req.RequestItems) == 0 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Missing required fields",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var requestItems []domain.RequestItem
|
||||
for _, item := range req.RequestItems {
|
||||
requestItems = append(requestItems, domain.RequestItem{
|
||||
TrashCategoryID: item.TrashCategory,
|
||||
EstimatedAmount: item.EstimatedAmount,
|
||||
})
|
||||
}
|
||||
|
||||
requestPickup := &domain.RequestPickup{
|
||||
UserID: userID,
|
||||
Request: requestItems,
|
||||
RequestTime: req.RequestTime,
|
||||
UserAddressID: req.UserAddressID,
|
||||
StatusRequest: "Pending",
|
||||
}
|
||||
|
||||
service := services.NewRequestPickupService(repositories.NewRequestPickupRepository())
|
||||
|
||||
if err := service.CreateRequestPickup(requestPickup); err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to create request pickup",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
detail, err := service.GetRequestPickupByID(requestPickup.ID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch created request pickup",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var requestItemsDTO []dto.RequestItemDTO
|
||||
for _, item := range detail.Request {
|
||||
requestItemsDTO = append(requestItemsDTO, dto.RequestItemDTO{
|
||||
TrashCategory: item.TrashCategory.Name,
|
||||
EstimatedAmount: item.EstimatedAmount,
|
||||
})
|
||||
}
|
||||
|
||||
userAddressDTO := dto.UserAddressDTO{
|
||||
Province: detail.UserAddress.Province,
|
||||
District: detail.UserAddress.District,
|
||||
Subdistrict: detail.UserAddress.Subdistrict,
|
||||
PostalCode: detail.UserAddress.PostalCode,
|
||||
Village: detail.UserAddress.Village,
|
||||
Detail: detail.UserAddress.Detail,
|
||||
Geography: detail.UserAddress.Geography,
|
||||
}
|
||||
|
||||
response := dto.NewRequestPickupResponse(
|
||||
detail.ID,
|
||||
detail.UserID,
|
||||
detail.RequestTime,
|
||||
detail.StatusRequest,
|
||||
requestItemsDTO,
|
||||
userAddressDTO,
|
||||
utils.FormatDateToIndonesianFormat(detail.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(detail.UpdatedAt),
|
||||
)
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||
fiber.StatusCreated,
|
||||
"Request pickup created successfully",
|
||||
response,
|
||||
))
|
||||
}
|
||||
|
||||
func DeleteRequestPickup(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
if id == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Missing required ID",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
service := services.NewRequestPickupService(repositories.NewRequestPickupRepository())
|
||||
if err := service.DeleteRequestPickupByID(id); err != nil {
|
||||
if err.Error() == fmt.Sprintf("request pickup with id %s not found", id) {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Request pickup not found",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to delete request pickup",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Request pickup deleted successfully",
|
||||
nil,
|
||||
))
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetUserRoleByID(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
role, err := services.GetUserRoleByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"UserRole tidak ditemukan",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"UserRole ditemukan",
|
||||
role,
|
||||
))
|
||||
}
|
||||
|
||||
func GetAllUserRoles(c *fiber.Ctx) error {
|
||||
roles, err := services.GetAllUserRoles()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Gagal mengambil data UserRole",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Daftar UserRole",
|
||||
roles,
|
||||
))
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetStoreByID(c *fiber.Ctx) error {
|
||||
storeID := c.Params("storeid")
|
||||
if storeID == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Store ID is required",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
store, err := services.GetStoreByID(storeID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Store not found",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Store fetched successfully",
|
||||
store,
|
||||
))
|
||||
}
|
||||
|
||||
func GetStoresByUserID(c *fiber.Ctx) error {
|
||||
userID, ok := c.Locals("userID").(string)
|
||||
if !ok || userID == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Unauthorized: user ID is missing",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
limit := c.QueryInt("limit", 0)
|
||||
page := c.QueryInt("page", 1)
|
||||
|
||||
if limit < 0 || page <= 0 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid pagination parameters",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
stores, err := services.GetStoresByUserID(userID, limit, page)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch stores",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Stores fetched successfully",
|
||||
stores,
|
||||
))
|
||||
}
|
|
@ -1,293 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetTrashCategories(c *fiber.Ctx) error {
|
||||
trashCategories, err := services.GetTrashCategories()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch trash categories",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
var response []dto.TrashCategoryResponse
|
||||
for _, category := range trashCategories {
|
||||
|
||||
response = append(response, dto.NewTrashCategoryResponse(
|
||||
category.ID,
|
||||
category.Name,
|
||||
utils.FormatDateToIndonesianFormat(category.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(category.UpdatedAt),
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Trash categories fetched successfully",
|
||||
response,
|
||||
))
|
||||
}
|
||||
|
||||
func GetTrashCategoryDetail(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
trashCategoryDetail, err := services.GetTrashCategoryDetail(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch trash category detail",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
detailResponse := dto.NewTrashCategoryResponse(
|
||||
trashCategoryDetail.ID,
|
||||
trashCategoryDetail.Name,
|
||||
utils.FormatDateToIndonesianFormat(trashCategoryDetail.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(trashCategoryDetail.UpdatedAt),
|
||||
)
|
||||
|
||||
var detailResponseList []dto.TrashDetailResponse
|
||||
if trashCategoryDetail.Details != nil {
|
||||
for _, detail := range trashCategoryDetail.Details {
|
||||
detailResponseList = append(detailResponseList, dto.NewTrashDetailResponse(
|
||||
detail.ID,
|
||||
detail.Description,
|
||||
detail.Price,
|
||||
utils.FormatDateToIndonesianFormat(detail.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(detail.UpdatedAt),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Trash category detail fetched successfully",
|
||||
struct {
|
||||
Category dto.TrashCategoryResponse `json:"category"`
|
||||
Details []dto.TrashDetailResponse `json:"details,omitempty"`
|
||||
}{
|
||||
Category: detailResponse,
|
||||
Details: detailResponseList,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
func CreateTrashCategory(c *fiber.Ctx) error {
|
||||
var categoryInput dto.TrashCategoryDTO
|
||||
|
||||
if err := c.BodyParser(&categoryInput); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input data",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := categoryInput.Validate(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Validation failed: "+err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
newCategory, err := services.CreateTrashCategory(categoryInput.Name)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to create trash category",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
categoryResponse := map[string]interface{}{
|
||||
"id": newCategory.ID,
|
||||
"name": newCategory.Name,
|
||||
"createdAt": newCategory.CreatedAt,
|
||||
"updatedAt": newCategory.UpdatedAt,
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||
fiber.StatusCreated,
|
||||
"Trash category created successfully",
|
||||
categoryResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func CreateTrashDetail(c *fiber.Ctx) error {
|
||||
var detailInput dto.TrashDetailDTO
|
||||
|
||||
if err := c.BodyParser(&detailInput); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input data",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := detailInput.Validate(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Validation failed: "+err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
newDetail, err := services.CreateTrashDetail(detailInput.CategoryID, detailInput.Description, detailInput.Price)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to create trash detail",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
detailResponse := map[string]interface{}{
|
||||
"id": newDetail.ID,
|
||||
"description": newDetail.Description,
|
||||
"price": newDetail.Price,
|
||||
"createdAt": newDetail.CreatedAt,
|
||||
"updatedAt": newDetail.UpdatedAt,
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||
fiber.StatusCreated,
|
||||
"Trash detail created successfully",
|
||||
detailResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func UpdateTrashCategory(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
var categoryInput dto.UpdateTrashCategoryDTO
|
||||
if err := c.BodyParser(&categoryInput); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input data",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := categoryInput.Validate(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Validation failed: "+err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
updatedCategory, err := services.UpdateTrashCategory(id, categoryInput.Name)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to update trash category",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
response := dto.NewTrashCategoryResponse(
|
||||
updatedCategory.ID,
|
||||
updatedCategory.Name,
|
||||
utils.FormatDateToIndonesianFormat(updatedCategory.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(updatedCategory.UpdatedAt),
|
||||
)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Trash category updated successfully",
|
||||
response,
|
||||
))
|
||||
}
|
||||
|
||||
func UpdateTrashDetail(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
var detailInput dto.UpdateTrashDetailDTO
|
||||
if err := c.BodyParser(&detailInput); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Invalid input data",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := detailInput.Validate(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Validation failed: "+err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
updatedDetail, err := services.UpdateTrashDetail(id, detailInput.Description, detailInput.Price)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to update trash detail",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
response := dto.NewTrashDetailResponse(
|
||||
updatedDetail.ID,
|
||||
updatedDetail.Description,
|
||||
updatedDetail.Price,
|
||||
utils.FormatDateToIndonesianFormat(updatedDetail.CreatedAt),
|
||||
utils.FormatDateToIndonesianFormat(updatedDetail.UpdatedAt),
|
||||
)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Trash detail updated successfully",
|
||||
response,
|
||||
))
|
||||
}
|
||||
|
||||
func DeleteTrashCategory(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
err := services.DeleteTrashCategory(id)
|
||||
if err != nil {
|
||||
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to delete trash category",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Trash category deleted successfully",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
func DeleteTrashDetail(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
err := services.DeleteTrashDetail(id)
|
||||
if err != nil {
|
||||
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to delete trash detail",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Trash detail deleted successfully",
|
||||
nil,
|
||||
))
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetListUsers(c *fiber.Ctx) error {
|
||||
users, err := services.GetUsers()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch users",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Users fetched successfully",
|
||||
users,
|
||||
))
|
||||
}
|
||||
|
||||
func GetUsersByRole(c *fiber.Ctx) error {
|
||||
roleID := c.Params("roleID")
|
||||
|
||||
users, err := services.GetUsersByRole(roleID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch users by role",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if len(users) == 0 {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"No users found for the specified role",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"Users fetched successfully",
|
||||
users,
|
||||
))
|
||||
}
|
||||
|
||||
func GetUserByUserID(c *fiber.Ctx) error {
|
||||
userID := c.Params("userID")
|
||||
|
||||
user, err := services.GetUserByUserID(userID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"User not found",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"User fetched successfully",
|
||||
struct {
|
||||
User dto.UserResponseDTO `json:"user"`
|
||||
}{
|
||||
User: user,
|
||||
},
|
||||
))
|
||||
}
|
|
@ -1,240 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func CreatePin(c *fiber.Ctx) error {
|
||||
var input dto.PinInput
|
||||
if err := c.BodyParser(&input); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Data input tidak valid",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := input.ValidateCreate(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userID := c.Locals("userID").(string)
|
||||
|
||||
redisPin, err := config.RedisClient.Get(c.Context(), "pin:"+userID).Result()
|
||||
if err != nil && err != redis.Nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to check PIN from Redis",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if redisPin != "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"PIN sudah ada, tidak perlu dibuat lagi",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
pin, err := services.CreatePin(userID, input)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to create PIN",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
err = config.RedisClient.Set(c.Context(), "pin:"+userID, pin.Pin, time.Minute*30).Err()
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to save PIN to Redis",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
formattedCreatedAt := utils.FormatDateToIndonesianFormat(pin.CreatedAt)
|
||||
|
||||
pinResponse := dto.PinResponse{
|
||||
CreatedAt: formattedCreatedAt,
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"PIN created successfully",
|
||||
pinResponse,
|
||||
))
|
||||
}
|
||||
|
||||
func GetPinStatus(c *fiber.Ctx) error {
|
||||
userID := c.Locals("userID").(string)
|
||||
|
||||
_, err := config.RedisClient.Get(c.Context(), "pin:"+userID).Result()
|
||||
if err == redis.Nil {
|
||||
|
||||
pin, err := services.GetPinByUserID(userID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Anda belum membuat PIN",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
formattedCreatedAt := utils.FormatDateToIndonesianFormat(pin.CreatedAt)
|
||||
formattedUpdatedAt := utils.FormatDateToIndonesianFormat(pin.UpdatedAt)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"PIN sudah dibuat",
|
||||
map[string]interface{}{
|
||||
"createdAt": formattedCreatedAt,
|
||||
"updatedAt": formattedUpdatedAt,
|
||||
},
|
||||
))
|
||||
} else if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch PIN from Redis",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"PIN sudah dibuat",
|
||||
map[string]interface{}{
|
||||
"createdAt": "PIN ditemukan di Redis",
|
||||
"updatedAt": "PIN ditemukan di Redis",
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
func GetPin(c *fiber.Ctx) error {
|
||||
var input dto.PinInput
|
||||
if err := c.BodyParser(&input); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Data input tidak valid",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userID := c.Locals("userID").(string)
|
||||
|
||||
redisPin, err := config.RedisClient.Get(c.Context(), "pin:"+userID).Result()
|
||||
if err == redis.Nil {
|
||||
|
||||
pin, err := services.GetPinByUserID(userID)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||
fiber.StatusNotFound,
|
||||
"Sepertinya anda belum membuat pin",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
isPinValid := services.CheckPin(pin.Pin, input.Pin)
|
||||
if isPinValid {
|
||||
|
||||
config.RedisClient.Set(c.Context(), "pin:"+userID, pin.Pin, time.Minute*30)
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"PIN benar",
|
||||
true,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"PIN salah",
|
||||
false,
|
||||
))
|
||||
} else if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to fetch PIN from Redis",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
isPinValid := services.CheckPin(redisPin, input.Pin)
|
||||
if isPinValid {
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"PIN benar",
|
||||
true,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"PIN salah",
|
||||
false,
|
||||
))
|
||||
}
|
||||
|
||||
func UpdatePin(c *fiber.Ctx) error {
|
||||
var input dto.PinUpdateInput
|
||||
if err := c.BodyParser(&input); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
"Data input tidak valid",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
if err := input.ValidateUpdate(); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||
fiber.StatusBadRequest,
|
||||
err.Error(),
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userID := c.Locals("userID").(string)
|
||||
|
||||
updatedPin, err := services.UpdatePin(userID, input.OldPin, input.NewPin)
|
||||
if err != nil {
|
||||
if err.Error() == "PIN lama salah" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"PIN lama salah",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||
fiber.StatusInternalServerError,
|
||||
"Failed to update PIN",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
config.RedisClient.Del(c.Context(), "pin:"+userID)
|
||||
config.RedisClient.Set(c.Context(), "pin:"+userID, updatedPin.Pin, time.Minute*30)
|
||||
|
||||
formattedUpdatedAt := utils.FormatDateToIndonesianFormat(updatedPin.UpdatedAt)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||
fiber.StatusOK,
|
||||
"PIN updated successfully",
|
||||
map[string]interface{}{
|
||||
"id": updatedPin.ID,
|
||||
"updatedAt": formattedUpdatedAt,
|
||||
},
|
||||
))
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type UserHandler struct {
|
||||
UserService services.UserService
|
||||
}
|
||||
|
||||
func NewUserHandler(userService services.UserService) *UserHandler {
|
||||
return &UserHandler{UserService: userService}
|
||||
}
|
||||
|
||||
func (h *UserHandler) Login(c *fiber.Ctx) error {
|
||||
var loginDTO dto.LoginDTO
|
||||
if err := c.BodyParser(&loginDTO); err != nil {
|
||||
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
|
||||
}
|
||||
|
||||
user, err := h.UserService.Login(loginDTO)
|
||||
if err != nil {
|
||||
if err.Error() == "user not found" {
|
||||
|
||||
return utils.ErrorResponse(c, "User not found")
|
||||
}
|
||||
if err == bcrypt.ErrMismatchedHashAndPassword {
|
||||
|
||||
return utils.ErrorResponse(c, "Invalid password")
|
||||
}
|
||||
|
||||
return utils.InternalServerErrorResponse(c, "Error logging in")
|
||||
}
|
||||
|
||||
return utils.LogResponse(c, user, "Login successful")
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func APIKeyMiddleware(c *fiber.Ctx) error {
|
||||
apiKey := c.Get("x-api-key")
|
||||
expectedAPIKey := os.Getenv("API_KEY")
|
||||
|
||||
if apiKey != expectedAPIKey {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Invalid API Key",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
func RateLimitMiddleware(c *fiber.Ctx) error {
|
||||
apiKey := c.Get("x-api-key")
|
||||
if apiKey == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"API Key is missing",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
rateLimitKey := fmt.Sprintf("rate_limit:%s", apiKey)
|
||||
|
||||
count, _ := config.RedisClient.Incr(ctx, rateLimitKey).Result()
|
||||
if count > 100 {
|
||||
return c.Status(fiber.StatusTooManyRequests).JSON(utils.FormatResponse(
|
||||
fiber.StatusTooManyRequests,
|
||||
"Rate limit exceeded",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
config.RedisClient.Expire(ctx, rateLimitKey, time.Minute)
|
||||
|
||||
return c.Next()
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func containsRole(roles []string, role string) bool {
|
||||
for _, r := range roles {
|
||||
if r == role {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func RoleRequired(roles ...string) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
tokenString := strings.TrimPrefix(c.Get("Authorization"), "Bearer ")
|
||||
if tokenString == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Token is required",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
cachedToken, err := config.RedisClient.Get(ctx, "auth_token:"+tokenString).Result()
|
||||
if err != nil || cachedToken == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Invalid or expired token",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, errors.New("unexpected signing method")
|
||||
}
|
||||
return []byte(os.Getenv("API_KEY")), nil
|
||||
})
|
||||
if err != nil || !token.Valid {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Invalid or expired token",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
claims, ok := token.Claims.(jwt.MapClaims)
|
||||
if !ok {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Invalid token claims",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userID, ok := claims["sub"].(string)
|
||||
if !ok || userID == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Missing or invalid user ID in token",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
role, ok := claims["role"].(string)
|
||||
if !ok || role == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Missing or invalid role in token",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
c.Locals("userID", userID)
|
||||
c.Locals("role", role)
|
||||
|
||||
if !containsRole(roles, role) {
|
||||
return c.Status(fiber.StatusForbidden).JSON(utils.FormatResponse(
|
||||
fiber.StatusForbidden,
|
||||
"You do not have permission to access this resource",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
return c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func AuthMiddleware(c *fiber.Ctx) error {
|
||||
tokenString := strings.TrimPrefix(c.Get("Authorization"), "Bearer ")
|
||||
if tokenString == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Missing or invalid token",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
cachedToken, err := config.RedisClient.Get(ctx, "auth_token:"+tokenString).Result()
|
||||
if err != nil || cachedToken == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Invalid or expired token",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(os.Getenv("API_KEY")), nil
|
||||
})
|
||||
if err != nil || !token.Valid {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Invalid or expired token",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
claims, ok := token.Claims.(jwt.MapClaims)
|
||||
if !ok {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||
fiber.StatusUnauthorized,
|
||||
"Invalid token claims",
|
||||
nil,
|
||||
))
|
||||
}
|
||||
|
||||
userID := claims["sub"].(string)
|
||||
c.Locals("userID", userID)
|
||||
|
||||
config.RedisClient.Expire(ctx, "auth_token:"+tokenString, time.Hour*24)
|
||||
|
||||
return c.Next()
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetProvinces() ([]domain.Province, error) {
|
||||
records, err := utils.ReadCSV("public/document/provinces.csv")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var provinces []domain.Province
|
||||
for _, record := range records {
|
||||
province := domain.Province{
|
||||
ID: record[0],
|
||||
Name: record[1],
|
||||
}
|
||||
provinces = append(provinces, province)
|
||||
}
|
||||
|
||||
return provinces, nil
|
||||
}
|
||||
|
||||
func GetRegencies() ([]domain.Regency, error) {
|
||||
records, err := utils.ReadCSV("public/document/regencies.csv")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var regencies []domain.Regency
|
||||
for _, record := range records {
|
||||
regency := domain.Regency{
|
||||
ID: record[0],
|
||||
ProvinceID: record[1],
|
||||
Name: record[2],
|
||||
}
|
||||
regencies = append(regencies, regency)
|
||||
}
|
||||
|
||||
return regencies, nil
|
||||
}
|
||||
|
||||
func GetDistricts() ([]domain.District, error) {
|
||||
records, err := utils.ReadCSV("public/document/districts.csv")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var districts []domain.District
|
||||
for _, record := range records {
|
||||
district := domain.District{
|
||||
ID: record[0],
|
||||
RegencyID: record[1],
|
||||
Name: record[2],
|
||||
}
|
||||
districts = append(districts, district)
|
||||
}
|
||||
|
||||
return districts, nil
|
||||
}
|
||||
|
||||
func GetVillages() ([]domain.Village, error) {
|
||||
records, err := utils.ReadCSV("public/document/villages.csv")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var villages []domain.Village
|
||||
for _, record := range records {
|
||||
village := domain.Village{
|
||||
ID: record[0],
|
||||
DistrictID: record[1],
|
||||
Name: record[2],
|
||||
}
|
||||
villages = append(villages, village)
|
||||
}
|
||||
|
||||
return villages, nil
|
||||
}
|
||||
|
||||
func GetProvinceByID(id string) (domain.Province, error) {
|
||||
provinces, err := GetProvinces()
|
||||
if err != nil {
|
||||
return domain.Province{}, err
|
||||
}
|
||||
|
||||
for _, province := range provinces {
|
||||
if province.ID == id {
|
||||
|
||||
regencies, err := GetRegenciesByProvinceID(id)
|
||||
if err != nil {
|
||||
return domain.Province{}, err
|
||||
}
|
||||
|
||||
province.ListRegency = regencies
|
||||
return province, nil
|
||||
}
|
||||
}
|
||||
return domain.Province{}, errors.New("province not found")
|
||||
}
|
||||
|
||||
func GetRegencyByID(id string) (domain.Regency, error) {
|
||||
regencies, err := GetRegencies()
|
||||
if err != nil {
|
||||
return domain.Regency{}, err
|
||||
}
|
||||
|
||||
for _, regency := range regencies {
|
||||
if regency.ID == id {
|
||||
|
||||
districts, err := GetDistrictsByRegencyID(id)
|
||||
if err != nil {
|
||||
return domain.Regency{}, err
|
||||
}
|
||||
|
||||
regency.ListDistrict = districts
|
||||
return regency, nil
|
||||
}
|
||||
}
|
||||
return domain.Regency{}, errors.New("regency not found")
|
||||
}
|
||||
|
||||
func GetDistrictByID(id string) (domain.District, error) {
|
||||
districts, err := GetDistricts()
|
||||
if err != nil {
|
||||
return domain.District{}, err
|
||||
}
|
||||
|
||||
for _, district := range districts {
|
||||
if district.ID == id {
|
||||
|
||||
villages, err := GetVillagesByDistrictID(id)
|
||||
if err != nil {
|
||||
return domain.District{}, err
|
||||
}
|
||||
|
||||
district.ListVillage = villages
|
||||
return district, nil
|
||||
}
|
||||
}
|
||||
return domain.District{}, errors.New("district not found")
|
||||
}
|
||||
|
||||
func GetVillageByID(id string) (domain.Village, error) {
|
||||
villages, err := GetVillages()
|
||||
if err != nil {
|
||||
return domain.Village{}, err
|
||||
}
|
||||
|
||||
for _, village := range villages {
|
||||
if village.ID == id {
|
||||
return village, nil
|
||||
}
|
||||
}
|
||||
return domain.Village{}, errors.New("village not found")
|
||||
}
|
||||
|
||||
func GetRegenciesByProvinceID(provinceID string) ([]domain.Regency, error) {
|
||||
regencies, err := GetRegencies()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []domain.Regency
|
||||
for _, regency := range regencies {
|
||||
if regency.ProvinceID == provinceID {
|
||||
result = append(result, regency)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func GetDistrictsByRegencyID(regencyID string) ([]domain.District, error) {
|
||||
districts, err := GetDistricts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []domain.District
|
||||
for _, district := range districts {
|
||||
if district.RegencyID == regencyID {
|
||||
result = append(result, district)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func GetVillagesByDistrictID(districtID string) ([]domain.Village, error) {
|
||||
villages, err := GetVillages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []domain.Village
|
||||
for _, village := range villages {
|
||||
if village.DistrictID == districtID {
|
||||
result = append(result, village)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
)
|
||||
|
||||
func CreateAddress(address *domain.Address) error {
|
||||
result := config.DB.Create(address)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("address:user:%s", address.UserID)
|
||||
config.RedisClient.Del(context.Background(), cacheKey)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAddressesByUserID(userID string) ([]domain.Address, error) {
|
||||
ctx := context.Background()
|
||||
cacheKey := fmt.Sprintf("address:user:%s", userID)
|
||||
|
||||
cachedAddresses, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil {
|
||||
var addresses []domain.Address
|
||||
if json.Unmarshal([]byte(cachedAddresses), &addresses) == nil {
|
||||
return addresses, nil
|
||||
}
|
||||
}
|
||||
|
||||
var addresses []domain.Address
|
||||
err = config.DB.Where("user_id = ?", userID).Find(&addresses).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addressesJSON, _ := json.Marshal(addresses)
|
||||
config.RedisClient.Set(ctx, cacheKey, addressesJSON, time.Hour).Err()
|
||||
|
||||
return addresses, nil
|
||||
}
|
||||
|
||||
func GetAddressByID(addressID string) (domain.Address, error) {
|
||||
var address domain.Address
|
||||
if err := config.DB.Where("id = ?", addressID).First(&address).Error; err != nil {
|
||||
return address, errors.New("address not found")
|
||||
}
|
||||
return address, nil
|
||||
}
|
||||
|
||||
func UpdateAddress(address domain.Address) (domain.Address, error) {
|
||||
if err := config.DB.Save(&address).Error; err != nil {
|
||||
return address, err
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("address:user:%s", address.UserID)
|
||||
config.RedisClient.Del(context.Background(), cacheKey)
|
||||
|
||||
return address, nil
|
||||
}
|
||||
|
||||
func DeleteAddress(addressID string) error {
|
||||
var address domain.Address
|
||||
if err := config.DB.Where("id = ?", addressID).First(&address).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := config.DB.Delete(&address).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("address:user:%s", address.UserID)
|
||||
config.RedisClient.Del(context.Background(), cacheKey)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
)
|
||||
|
||||
type ArticleRepository struct{}
|
||||
|
||||
func NewArticleRepository() *ArticleRepository {
|
||||
return &ArticleRepository{}
|
||||
}
|
||||
|
||||
func (r *ArticleRepository) GetAll() ([]domain.Article, error) {
|
||||
var articles []domain.Article
|
||||
err := config.DB.Find(&articles).Error
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to fetch articles from database")
|
||||
}
|
||||
return articles, nil
|
||||
}
|
||||
|
||||
func (r *ArticleRepository) GetByID(id string) (*domain.Article, error) {
|
||||
var article domain.Article
|
||||
err := config.DB.First(&article, "id = ?", id).Error
|
||||
if err != nil {
|
||||
return nil, errors.New("article not found")
|
||||
}
|
||||
return &article, nil
|
||||
}
|
||||
|
||||
func (r *ArticleRepository) Create(article *domain.Article) error {
|
||||
return config.DB.Create(article).Error
|
||||
}
|
||||
|
||||
func (r *ArticleRepository) Update(article *domain.Article) error {
|
||||
return config.DB.Save(article).Error
|
||||
}
|
||||
|
||||
func (r *ArticleRepository) Delete(article *domain.Article) error {
|
||||
return config.DB.Delete(article).Error
|
||||
}
|
|
@ -1,176 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
)
|
||||
|
||||
func IsEmailExist(email, roleId string) bool {
|
||||
ctx := context.Background()
|
||||
cacheKey := fmt.Sprintf("email:%s", email)
|
||||
cachedRole, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil && cachedRole == roleId {
|
||||
return true
|
||||
}
|
||||
|
||||
var user domain.User
|
||||
if err := config.DB.Where("email = ?", email).First(&user).Error; err == nil {
|
||||
if user.RoleID == roleId {
|
||||
if err := config.RedisClient.Set(ctx, cacheKey, roleId, 24*time.Hour).Err(); err != nil {
|
||||
log.Printf("Redis Set error: %v", err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsUsernameExist(username, roleId string) bool {
|
||||
ctx := context.Background()
|
||||
cacheKey := fmt.Sprintf("username:%s", username)
|
||||
cachedRole, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil && cachedRole == roleId {
|
||||
return true
|
||||
}
|
||||
|
||||
var user domain.User
|
||||
if err := config.DB.Where("username = ?", username).First(&user).Error; err == nil {
|
||||
if user.RoleID == roleId {
|
||||
if err := config.RedisClient.Set(ctx, cacheKey, roleId, 24*time.Hour).Err(); err != nil {
|
||||
log.Printf("Redis Set error: %v", err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsPhoneExist(phone, roleId string) bool {
|
||||
ctx := context.Background()
|
||||
cacheKey := fmt.Sprintf("phone:%s", phone)
|
||||
cachedRole, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil && cachedRole == roleId {
|
||||
return true
|
||||
}
|
||||
|
||||
var user domain.User
|
||||
if err := config.DB.Where("phone = ?", phone).First(&user).Error; err == nil {
|
||||
if user.RoleID == roleId {
|
||||
if err := config.RedisClient.Set(ctx, cacheKey, roleId, 24*time.Hour).Err(); err != nil {
|
||||
log.Printf("Redis Set error: %v", err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func CreateUser(username, name, email, phone, password, roleId string) error {
|
||||
user := domain.User{
|
||||
Username: username,
|
||||
Name: name,
|
||||
Email: email,
|
||||
Phone: phone,
|
||||
Password: password,
|
||||
RoleID: roleId,
|
||||
}
|
||||
|
||||
result := config.DB.Create(&user)
|
||||
if result.Error != nil {
|
||||
return errors.New("failed to create user")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetUserByEmailUsernameOrPhone(identifier, roleId string) (domain.User, error) {
|
||||
ctx := context.Background()
|
||||
cacheKey := fmt.Sprintf("user:%s", identifier)
|
||||
var user domain.User
|
||||
|
||||
cachedUser, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil {
|
||||
if err := json.Unmarshal([]byte(cachedUser), &user); err == nil {
|
||||
if roleId == "" || user.RoleID == roleId {
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = config.DB.Where("email = ? OR username = ? OR phone = ?", identifier, identifier, identifier).First(&user).Error
|
||||
if err != nil {
|
||||
return user, errors.New("user not found")
|
||||
}
|
||||
|
||||
if roleId != "" && user.RoleID != roleId {
|
||||
return user, errors.New("identifier found but role does not match")
|
||||
}
|
||||
|
||||
userJSON, _ := json.Marshal(user)
|
||||
if err := config.RedisClient.Set(ctx, cacheKey, userJSON, 1*time.Hour).Err(); err != nil {
|
||||
log.Printf("Redis Set error: %v", err)
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func GetUserByID(userID string) (domain.User, error) {
|
||||
ctx := context.Background()
|
||||
cacheKey := fmt.Sprintf("user:%s", userID)
|
||||
var user domain.User
|
||||
|
||||
cachedUser, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil {
|
||||
if err := json.Unmarshal([]byte(cachedUser), &user); err == nil {
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := config.DB.Preload("Role").Where("id = ?", userID).First(&user).Error; err != nil {
|
||||
return user, errors.New("user not found")
|
||||
}
|
||||
|
||||
userJSON, _ := json.Marshal(user)
|
||||
if err := config.RedisClient.Set(ctx, cacheKey, userJSON, 1*time.Hour).Err(); err != nil {
|
||||
log.Printf("Redis Set error: %v", err)
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func UpdateUser(user *domain.User) error {
|
||||
if err := config.DB.Save(user).Error; err != nil {
|
||||
return errors.New("failed to update user")
|
||||
}
|
||||
cacheKey := fmt.Sprintf("user:%s", user.ID)
|
||||
if err := config.RedisClient.Del(context.Background(), cacheKey).Err(); err != nil {
|
||||
log.Printf("Redis Del error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateUserPassword(userID, newPassword string) error {
|
||||
var user domain.User
|
||||
|
||||
if err := config.DB.Where("id = ?", userID).First(&user).Error; err != nil {
|
||||
return errors.New("user not found")
|
||||
}
|
||||
|
||||
user.Password = newPassword
|
||||
|
||||
if err := config.DB.Save(&user).Error; err != nil {
|
||||
return errors.New("failed to update password")
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("user:%s", userID)
|
||||
if err := config.RedisClient.Del(context.Background(), cacheKey).Err(); err != nil {
|
||||
log.Printf("Redis Del error: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type UserRepository interface {
|
||||
FindByEmailOrUsernameOrPhone(identifier string) (*model.User, error)
|
||||
}
|
||||
|
||||
type userRepository struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func NewUserRepository(db *gorm.DB) UserRepository {
|
||||
return &userRepository{DB: db}
|
||||
}
|
||||
|
||||
func (r *userRepository) FindByEmailOrUsernameOrPhone(identifier string) (*model.User, error) {
|
||||
var user model.User
|
||||
err := r.DB.Where("email = ? OR username = ? OR phone = ?", identifier, identifier, identifier).First(&user).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
)
|
||||
|
||||
type BannerRepository struct{}
|
||||
|
||||
func NewBannerRepository() *BannerRepository {
|
||||
return &BannerRepository{}
|
||||
}
|
||||
|
||||
func (r *BannerRepository) GetAll() ([]domain.Banner, error) {
|
||||
var banners []domain.Banner
|
||||
err := config.DB.Find(&banners).Error
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to fetch banners from database")
|
||||
}
|
||||
return banners, nil
|
||||
}
|
||||
|
||||
func (r *BannerRepository) GetByID(id string) (*domain.Banner, error) {
|
||||
var banner domain.Banner
|
||||
err := config.DB.First(&banner, "id = ?", id).Error
|
||||
if err != nil {
|
||||
return nil, errors.New("banner not found")
|
||||
}
|
||||
return &banner, nil
|
||||
}
|
||||
|
||||
func (r *BannerRepository) Create(banner *domain.Banner) error {
|
||||
return config.DB.Create(banner).Error
|
||||
}
|
||||
|
||||
func (r *BannerRepository) Update(banner *domain.Banner) error {
|
||||
return config.DB.Save(banner).Error
|
||||
}
|
||||
|
||||
func (r *BannerRepository) Delete(banner *domain.Banner) error {
|
||||
return config.DB.Delete(banner).Error
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
)
|
||||
|
||||
func GetCoverageAreas() ([]domain.CoverageArea, error) {
|
||||
var coverageAreas []domain.CoverageArea
|
||||
if err := config.DB.Find(&coverageAreas).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return coverageAreas, nil
|
||||
}
|
||||
|
||||
func GetCoverageAreaByID(id string) (domain.CoverageArea, error) {
|
||||
var coverageArea domain.CoverageArea
|
||||
if err := config.DB.Where("id = ?", id).First(&coverageArea).Error; err != nil {
|
||||
return coverageArea, err
|
||||
}
|
||||
return coverageArea, nil
|
||||
}
|
||||
|
||||
func GetCoverageAreaByDistrictID(id string) (domain.CoverageDistric, error) {
|
||||
var coverageDistric domain.CoverageDistric
|
||||
if err := config.DB.Where("id = ?", id).First(&coverageDistric).Error; err != nil {
|
||||
return coverageDistric, err
|
||||
}
|
||||
return coverageDistric, nil
|
||||
}
|
||||
|
||||
func GetCoverageDistricsByCoverageAreaID(areaID string) ([]domain.CoverageDistric, error) {
|
||||
var districts []domain.CoverageDistric
|
||||
if err := config.DB.Where("coverage_area_id = ?", areaID).Find(&districts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return districts, nil
|
||||
}
|
||||
|
||||
func GetSubdistrictsByCoverageDistrictID(districtID string) ([]domain.CoverageSubdistrict, error) {
|
||||
var subdistricts []domain.CoverageSubdistrict
|
||||
if err := config.DB.Where("coverage_district_id = ?", districtID).Find(&subdistricts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return subdistricts, nil
|
||||
}
|
||||
|
||||
func CreateCoverageArea(coverageArea *domain.CoverageArea) error {
|
||||
if err := config.DB.Create(&coverageArea).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateCoverageDistrict(coverageDistrict *domain.CoverageDistric) error {
|
||||
if err := config.DB.Create(&coverageDistrict).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateCoverageSubdistrict(coverageSubdistrict *domain.CoverageSubdistrict) error {
|
||||
if err := config.DB.Create(&coverageSubdistrict).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateCoverageArea(id string, coverageArea domain.CoverageArea) (domain.CoverageArea, error) {
|
||||
var existingCoverageArea domain.CoverageArea
|
||||
if err := config.DB.Where("id = ?", id).First(&existingCoverageArea).Error; err != nil {
|
||||
return existingCoverageArea, err
|
||||
}
|
||||
|
||||
existingCoverageArea.Province = coverageArea.Province
|
||||
if err := config.DB.Save(&existingCoverageArea).Error; err != nil {
|
||||
return existingCoverageArea, err
|
||||
}
|
||||
|
||||
return existingCoverageArea, nil
|
||||
}
|
||||
|
||||
func UpdateCoverageDistrict(id string, coverageDistrict domain.CoverageDistric) (domain.CoverageDistric, error) {
|
||||
var existingCoverageDistrict domain.CoverageDistric
|
||||
if err := config.DB.Where("id = ?", id).First(&existingCoverageDistrict).Error; err != nil {
|
||||
return existingCoverageDistrict, err
|
||||
}
|
||||
|
||||
existingCoverageDistrict.District = coverageDistrict.District
|
||||
if err := config.DB.Save(&existingCoverageDistrict).Error; err != nil {
|
||||
return existingCoverageDistrict, err
|
||||
}
|
||||
|
||||
return existingCoverageDistrict, nil
|
||||
}
|
||||
|
||||
func UpdateCoverageSubdistrict(id string, coverageSubdistrict domain.CoverageSubdistrict) (domain.CoverageSubdistrict, error) {
|
||||
var existingCoverageSubdistrict domain.CoverageSubdistrict
|
||||
if err := config.DB.Where("id = ?", id).First(&existingCoverageSubdistrict).Error; err != nil {
|
||||
return existingCoverageSubdistrict, err
|
||||
}
|
||||
|
||||
existingCoverageSubdistrict.Subdistrict = coverageSubdistrict.Subdistrict
|
||||
if err := config.DB.Save(&existingCoverageSubdistrict).Error; err != nil {
|
||||
return existingCoverageSubdistrict, err
|
||||
}
|
||||
|
||||
return existingCoverageSubdistrict, nil
|
||||
}
|
||||
|
||||
func DeleteCoverageArea(id string) error {
|
||||
var coverageArea domain.CoverageArea
|
||||
if err := config.DB.Where("id = ?", id).First(&coverageArea).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := config.DB.Delete(&coverageArea).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteCoverageDistrict(id string) error {
|
||||
var coverageDistrict domain.CoverageDistric
|
||||
if err := config.DB.Where("id = ?", id).First(&coverageDistrict).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := config.DB.Delete(&coverageDistrict).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteCoverageSubdistrict(id string) error {
|
||||
var coverageSubdistrict domain.CoverageSubdistrict
|
||||
if err := config.DB.Where("id = ?", id).First(&coverageSubdistrict).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := config.DB.Delete(&coverageSubdistrict).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
)
|
||||
|
||||
type PointRepository struct{}
|
||||
|
||||
func NewPointRepository() *PointRepository {
|
||||
return &PointRepository{}
|
||||
}
|
||||
|
||||
func (r *PointRepository) GetAll() ([]domain.Point, error) {
|
||||
var points []domain.Point
|
||||
err := config.DB.Find(&points).Error
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to fetch points from database")
|
||||
}
|
||||
return points, nil
|
||||
}
|
||||
|
||||
func (r *PointRepository) GetByID(id string) (*domain.Point, error) {
|
||||
var point domain.Point
|
||||
err := config.DB.First(&point, "id = ?", id).Error
|
||||
if err != nil {
|
||||
return nil, errors.New("point not found")
|
||||
}
|
||||
return &point, nil
|
||||
}
|
||||
|
||||
func (r *PointRepository) Create(point *domain.Point) error {
|
||||
return config.DB.Create(point).Error
|
||||
}
|
||||
|
||||
func (r *PointRepository) Update(point *domain.Point) error {
|
||||
return config.DB.Save(point).Error
|
||||
}
|
||||
|
||||
func (r *PointRepository) Delete(point *domain.Point) error {
|
||||
return config.DB.Delete(point).Error
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func GetProductsByStoreID(storeID string, limit, offset int) ([]domain.Product, error) {
|
||||
var products []domain.Product
|
||||
query := config.DB.Preload("ProductImages").Preload("TrashDetail").Where("store_id = ?", storeID)
|
||||
|
||||
if limit > 0 {
|
||||
query = query.Limit(limit).Offset(offset)
|
||||
}
|
||||
|
||||
err := query.Find(&products).Error
|
||||
return products, err
|
||||
}
|
||||
|
||||
func GetProductsByUserID(userID string, limit, offset int) ([]domain.Product, error) {
|
||||
var products []domain.Product
|
||||
query := config.DB.Preload("ProductImages").Preload("TrashDetail").Where("user_id = ?", userID)
|
||||
|
||||
if limit > 0 {
|
||||
query = query.Limit(limit).Offset(offset)
|
||||
}
|
||||
|
||||
err := query.Find(&products).Error
|
||||
return products, err
|
||||
}
|
||||
|
||||
func GetProductByIDAndStoreID(productID, storeID string) (domain.Product, error) {
|
||||
var product domain.Product
|
||||
err := config.DB.Preload("ProductImages").Preload("TrashDetail").
|
||||
Where("id = ? AND store_id = ?", productID, storeID).
|
||||
First(&product).Error
|
||||
|
||||
return product, err
|
||||
}
|
||||
|
||||
func GetProductByID(productID string) (domain.Product, error) {
|
||||
var product domain.Product
|
||||
err := config.DB.Preload("ProductImages").Preload("TrashDetail").
|
||||
Where("id = ?", productID).First(&product).Error
|
||||
return product, err
|
||||
}
|
||||
|
||||
func IsValidStoreID(storeID string) bool {
|
||||
var count int64
|
||||
err := config.DB.Model(&domain.Store{}).Where("id = ?", storeID).Count(&count).Error
|
||||
if err != nil || count == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func CreateProduct(product *domain.Product, images []domain.ProductImage) error {
|
||||
|
||||
return config.DB.Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
if err := tx.Create(product).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(images) > 0 {
|
||||
for i := range images {
|
||||
images[i].ProductID = product.ID
|
||||
}
|
||||
|
||||
if err := tx.Create(&images).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateProduct(product *domain.Product, images []domain.ProductImage) error {
|
||||
return config.DB.Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
if err := tx.Save(product).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(images) > 0 {
|
||||
for i := range images {
|
||||
images[i].ProductID = product.ID
|
||||
}
|
||||
|
||||
if err := tx.Where("product_id = ?", product.ID).Delete(&domain.ProductImage{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Create(&images).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteProduct(productID string) error {
|
||||
|
||||
return config.DB.Where("id = ?", productID).Delete(&domain.Product{}).Error
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
)
|
||||
|
||||
type RequestPickupRepository interface {
|
||||
Create(request *domain.RequestPickup) error
|
||||
GetByID(id string) (*domain.RequestPickup, error)
|
||||
GetByUserID(userID string) ([]domain.RequestPickup, error)
|
||||
DeleteByID(id string) error
|
||||
ExistsByID(id string) (bool, error)
|
||||
}
|
||||
|
||||
type requestPickupRepository struct{}
|
||||
|
||||
func NewRequestPickupRepository() RequestPickupRepository {
|
||||
return &requestPickupRepository{}
|
||||
}
|
||||
|
||||
func (r *requestPickupRepository) Create(request *domain.RequestPickup) error {
|
||||
return config.DB.Create(request).Error
|
||||
}
|
||||
|
||||
func (r *requestPickupRepository) GetByID(id string) (*domain.RequestPickup, error) {
|
||||
var requestPickup domain.RequestPickup
|
||||
if err := config.DB.Preload("Request").
|
||||
Preload("Request.TrashCategory").
|
||||
Preload("UserAddress").
|
||||
Where("id = ?", id).
|
||||
First(&requestPickup).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &requestPickup, nil
|
||||
}
|
||||
|
||||
func (r *requestPickupRepository) GetByUserID(userID string) ([]domain.RequestPickup, error) {
|
||||
var requestPickups []domain.RequestPickup
|
||||
err := config.DB.Preload("Request").
|
||||
Preload("Request.TrashCategory").
|
||||
Preload("UserAddress").
|
||||
Where("user_id = ?", userID).
|
||||
Find(&requestPickups).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return requestPickups, nil
|
||||
}
|
||||
|
||||
func (r *requestPickupRepository) ExistsByID(id string) (bool, error) {
|
||||
var count int64
|
||||
if err := config.DB.Model(&domain.RequestPickup{}).Where("id = ?", id).Count(&count).Error; err != nil {
|
||||
return false, err
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
|
||||
func (r *requestPickupRepository) DeleteByID(id string) error {
|
||||
return config.DB.Where("id = ?", id).Delete(&domain.RequestPickup{}).Error
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
)
|
||||
|
||||
func GetUserRoleByID(id string) (domain.UserRole, error) {
|
||||
var role domain.UserRole
|
||||
|
||||
ctx := config.Context()
|
||||
cachedRole, err := config.RedisClient.Get(ctx, "userRole:"+id).Result()
|
||||
|
||||
if err == nil {
|
||||
|
||||
err := json.Unmarshal([]byte(cachedRole), &role)
|
||||
if err != nil {
|
||||
return role, errors.New("gagal mendekode data cache Redis")
|
||||
}
|
||||
return role, nil
|
||||
}
|
||||
|
||||
err = config.DB.Where("id = ?", id).First(&role).Error
|
||||
if err != nil {
|
||||
return role, errors.New("userRole tidak ditemukan")
|
||||
}
|
||||
|
||||
roleJSON, err := json.Marshal(role)
|
||||
if err != nil {
|
||||
return role, errors.New("gagal mendekode data untuk Redis")
|
||||
}
|
||||
|
||||
err = config.RedisClient.Set(ctx, "userRole:"+id, roleJSON, time.Hour*24).Err()
|
||||
if err != nil {
|
||||
return role, errors.New("gagal menyimpan data di Redis")
|
||||
}
|
||||
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func GetAllUserRoles() ([]domain.UserRole, error) {
|
||||
var roles []domain.UserRole
|
||||
|
||||
ctx := config.Context()
|
||||
cachedRoles, err := config.RedisClient.Get(ctx, "allUserRoles").Result()
|
||||
|
||||
if err == nil {
|
||||
|
||||
err := json.Unmarshal([]byte(cachedRoles), &roles)
|
||||
if err != nil {
|
||||
return roles, errors.New("gagal mendekode data cache Redis")
|
||||
}
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
err = config.DB.Find(&roles).Error
|
||||
if err != nil {
|
||||
return nil, errors.New("gagal mengambil data UserRole")
|
||||
}
|
||||
|
||||
rolesJSON, err := json.Marshal(roles)
|
||||
if err != nil {
|
||||
return roles, errors.New("gagal mendekode data untuk Redis")
|
||||
}
|
||||
|
||||
err = config.RedisClient.Set(ctx, "allUserRoles", rolesJSON, time.Hour*24).Err()
|
||||
if err != nil {
|
||||
return roles, errors.New("gagal menyimpan data di Redis")
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
)
|
||||
|
||||
func GetStoreByID(storeID string) (domain.Store, error) {
|
||||
var store domain.Store
|
||||
err := config.DB.Where("id = ?", storeID).First(&store).Error
|
||||
return store, err
|
||||
}
|
||||
|
||||
func GetStoresByUserID(userID string, limit, offset int) ([]domain.Store, error) {
|
||||
var stores []domain.Store
|
||||
query := config.DB.Where("user_id = ?", userID)
|
||||
|
||||
if limit > 0 {
|
||||
query = query.Limit(limit).Offset(offset)
|
||||
}
|
||||
|
||||
err := query.Find(&stores).Error
|
||||
return stores, err
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
)
|
||||
|
||||
func GetTrashCategories() ([]domain.TrashCategory, error) {
|
||||
var categories []domain.TrashCategory
|
||||
if err := config.DB.Find(&categories).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return categories, nil
|
||||
}
|
||||
|
||||
func GetTrashCategoryDetail(id string) (domain.TrashCategory, error) {
|
||||
var category domain.TrashCategory
|
||||
if err := config.DB.Preload("Details").Where("id = ?", id).First(&category).Error; err != nil {
|
||||
return category, err
|
||||
}
|
||||
return category, nil
|
||||
}
|
||||
|
||||
func GetTrashDetailByID(id string) (domain.TrashDetail, error) {
|
||||
var detail domain.TrashDetail
|
||||
|
||||
if err := config.DB.Where("id = ?", id).First(&detail).Error; err != nil {
|
||||
return detail, err
|
||||
}
|
||||
return detail, nil
|
||||
}
|
||||
|
||||
func CreateTrashCategory(category *domain.TrashCategory) error {
|
||||
if err := config.DB.Create(category).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateTrashDetail(detail *domain.TrashDetail) error {
|
||||
if err := config.DB.Create(detail).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateTrashCategory(category *domain.TrashCategory) error {
|
||||
if err := config.DB.Save(category).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdateTrashDetail(detail *domain.TrashDetail) error {
|
||||
if err := config.DB.Save(detail).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteTrashCategory(id string) error {
|
||||
|
||||
if err := config.DB.Where("category_id = ?", id).Delete(&domain.TrashDetail{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := config.DB.Where("id = ?", id).Delete(&domain.TrashCategory{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteTrashDetail(id string) error {
|
||||
|
||||
if err := config.DB.Where("id = ?", id).Delete(&domain.TrashDetail{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
)
|
||||
|
||||
func GetUsers() ([]domain.User, error) {
|
||||
var users []domain.User
|
||||
|
||||
if err := config.DB.Find(&users).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func GetUsersByRole(roleID string) ([]domain.User, error) {
|
||||
var users []domain.User
|
||||
|
||||
if err := config.DB.Where("role_id = ?", roleID).Find(&users).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func GetUserByUserrId(userID string) (domain.User, error) {
|
||||
var user domain.User
|
||||
|
||||
if err := config.DB.Where("id = ?", userID).First(&user).Error; err != nil {
|
||||
return domain.User{}, err
|
||||
}
|
||||
return user, nil
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func CreatePin(pin *domain.UserPin) error {
|
||||
result := config.DB.Create(pin)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetPinByUserID(userID string) (domain.UserPin, error) {
|
||||
|
||||
ctx := context.Background()
|
||||
redisClient := config.RedisClient
|
||||
|
||||
redisKey := fmt.Sprintf("user_pin:%s", userID)
|
||||
|
||||
pin, err := redisClient.Get(ctx, redisKey).Result()
|
||||
if err == nil {
|
||||
|
||||
return domain.UserPin{
|
||||
UserID: userID,
|
||||
Pin: pin,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var dbPin domain.UserPin
|
||||
err = config.DB.Where("user_id = ?", userID).First(&dbPin).Error
|
||||
if err != nil {
|
||||
return dbPin, errors.New("PIN tidak ditemukan")
|
||||
}
|
||||
|
||||
redisClient.Set(ctx, redisKey, dbPin.Pin, 5*time.Minute)
|
||||
|
||||
return dbPin, nil
|
||||
}
|
||||
|
||||
func UpdatePin(userID string, newPin string) (domain.UserPin, error) {
|
||||
var pin domain.UserPin
|
||||
|
||||
err := config.DB.Where("user_id = ?", userID).First(&pin).Error
|
||||
if err != nil {
|
||||
return pin, errors.New("PIN tidak ditemukan")
|
||||
}
|
||||
|
||||
hashedPin, err := bcrypt.GenerateFromPassword([]byte(newPin), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return pin, err
|
||||
}
|
||||
|
||||
pin.Pin = string(hashedPin)
|
||||
|
||||
if err := config.DB.Save(&pin).Error; err != nil {
|
||||
return pin, err
|
||||
}
|
||||
|
||||
redisClient := config.RedisClient
|
||||
redisClient.Del(context.Background(), fmt.Sprintf("user_pin:%s", userID))
|
||||
|
||||
return pin, nil
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
)
|
||||
|
||||
func GetProvinces() ([]domain.Province, error) {
|
||||
provinces, err := repositories.GetProvinces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return provinces, nil
|
||||
}
|
||||
|
||||
func GetRegencies() ([]domain.Regency, error) {
|
||||
regencies, err := repositories.GetRegencies()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return regencies, nil
|
||||
}
|
||||
|
||||
func GetDistricts() ([]domain.District, error) {
|
||||
districts, err := repositories.GetDistricts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return districts, nil
|
||||
}
|
||||
|
||||
func GetVillages() ([]domain.Village, error) {
|
||||
villages, err := repositories.GetVillages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return villages, nil
|
||||
}
|
||||
|
||||
func GetProvinceByID(id string) (domain.Province, error) {
|
||||
province, err := repositories.GetProvinceByID(id)
|
||||
if err != nil {
|
||||
return domain.Province{}, err
|
||||
}
|
||||
return province, nil
|
||||
}
|
||||
|
||||
func GetRegencyByID(id string) (domain.Regency, error) {
|
||||
regency, err := repositories.GetRegencyByID(id)
|
||||
if err != nil {
|
||||
return domain.Regency{}, err
|
||||
}
|
||||
return regency, nil
|
||||
}
|
||||
|
||||
func GetDistrictByID(id string) (domain.District, error) {
|
||||
district, err := repositories.GetDistrictByID(id)
|
||||
if err != nil {
|
||||
return domain.District{}, err
|
||||
}
|
||||
return district, nil
|
||||
}
|
||||
|
||||
func GetVillageByID(id string) (domain.Village, error) {
|
||||
village, err := repositories.GetVillageByID(id)
|
||||
if err != nil {
|
||||
return domain.Village{}, err
|
||||
}
|
||||
return village, nil
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
)
|
||||
|
||||
func CreateAddress(userID string, input dto.AddressInput) (domain.Address, error) {
|
||||
address := domain.Address{
|
||||
UserID: userID,
|
||||
Province: input.Province,
|
||||
District: input.District,
|
||||
Subdistrict: input.Subdistrict,
|
||||
PostalCode: input.PostalCode,
|
||||
Village: input.Village,
|
||||
Detail: input.Detail,
|
||||
Geography: input.Geography,
|
||||
}
|
||||
|
||||
err := repositories.CreateAddress(&address)
|
||||
if err != nil {
|
||||
return domain.Address{}, err
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("address:user:%s", userID)
|
||||
config.RedisClient.Del(context.Background(), cacheKey)
|
||||
|
||||
return address, nil
|
||||
}
|
||||
|
||||
func GetAllAddressesByUserID(userID string) ([]domain.Address, error) {
|
||||
ctx := context.Background()
|
||||
cacheKey := fmt.Sprintf("address:user:%s", userID)
|
||||
|
||||
cachedAddresses, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil {
|
||||
var addresses []domain.Address
|
||||
if json.Unmarshal([]byte(cachedAddresses), &addresses) == nil {
|
||||
return addresses, nil
|
||||
}
|
||||
}
|
||||
|
||||
addresses, err := repositories.GetAddressesByUserID(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addressesJSON, _ := json.Marshal(addresses)
|
||||
config.RedisClient.Set(ctx, cacheKey, addressesJSON, time.Hour).Err()
|
||||
|
||||
return addresses, nil
|
||||
}
|
||||
|
||||
func GetAddressByID(addressID string) (domain.Address, error) {
|
||||
address, err := repositories.GetAddressByID(addressID)
|
||||
if err != nil {
|
||||
return address, errors.New("address not found")
|
||||
}
|
||||
return address, nil
|
||||
}
|
||||
|
||||
func UpdateAddress(addressID string, input dto.AddressInput) (domain.Address, error) {
|
||||
address, err := repositories.GetAddressByID(addressID)
|
||||
if err != nil {
|
||||
return address, errors.New("address not found")
|
||||
}
|
||||
|
||||
address.Province = input.Province
|
||||
address.District = input.District
|
||||
address.Subdistrict = input.Subdistrict
|
||||
address.PostalCode = input.PostalCode
|
||||
address.Village = input.Village
|
||||
address.Detail = input.Detail
|
||||
address.Geography = input.Geography
|
||||
|
||||
updatedAddress, err := repositories.UpdateAddress(address)
|
||||
if err != nil {
|
||||
return updatedAddress, errors.New("failed to update address")
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("address:user:%s", address.UserID)
|
||||
config.RedisClient.Del(context.Background(), cacheKey)
|
||||
|
||||
return updatedAddress, nil
|
||||
}
|
||||
|
||||
func DeleteAddress(addressID string) error {
|
||||
address, err := repositories.GetAddressByID(addressID)
|
||||
if err != nil {
|
||||
return errors.New("address not found")
|
||||
}
|
||||
|
||||
err = repositories.DeleteAddress(addressID)
|
||||
if err != nil {
|
||||
return errors.New("failed to delete address")
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("address:user:%s", address.UserID)
|
||||
config.RedisClient.Del(context.Background(), cacheKey)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
type ArticleService struct {
|
||||
repo *repositories.ArticleRepository
|
||||
}
|
||||
|
||||
func NewArticleService(repo *repositories.ArticleRepository) *ArticleService {
|
||||
return &ArticleService{repo: repo}
|
||||
}
|
||||
|
||||
func (s *ArticleService) GetAllArticles() ([]dto.ArticleResponse, error) {
|
||||
ctx := config.Context()
|
||||
cacheKey := "articles:all"
|
||||
|
||||
cachedData, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil && cachedData != "" {
|
||||
var cachedArticles []dto.ArticleResponse
|
||||
if err := json.Unmarshal([]byte(cachedData), &cachedArticles); err == nil {
|
||||
return cachedArticles, nil
|
||||
}
|
||||
}
|
||||
|
||||
articles, err := s.repo.GetAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []dto.ArticleResponse
|
||||
for _, article := range articles {
|
||||
result = append(result, dto.ArticleResponse{
|
||||
ID: article.ID,
|
||||
Title: article.Title,
|
||||
CoverImage: article.CoverImage,
|
||||
Author: article.Author,
|
||||
Heading: article.Heading,
|
||||
Content: article.Content,
|
||||
PublishedAt: utils.FormatDateToIndonesianFormat(article.PublishedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(article.UpdatedAt),
|
||||
})
|
||||
}
|
||||
|
||||
cacheData, _ := json.Marshal(result)
|
||||
config.RedisClient.Set(ctx, cacheKey, cacheData, time.Minute*5)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *ArticleService) GetArticleByID(id string) (*dto.ArticleResponse, error) {
|
||||
ctx := config.Context()
|
||||
cacheKey := "articles:" + id
|
||||
|
||||
cachedData, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil && cachedData != "" {
|
||||
var cachedArticle dto.ArticleResponse
|
||||
if err := json.Unmarshal([]byte(cachedData), &cachedArticle); err == nil {
|
||||
return &cachedArticle, nil
|
||||
}
|
||||
}
|
||||
|
||||
article, err := s.repo.GetByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &dto.ArticleResponse{
|
||||
ID: article.ID,
|
||||
Title: article.Title,
|
||||
CoverImage: article.CoverImage,
|
||||
Author: article.Author,
|
||||
Heading: article.Heading,
|
||||
Content: article.Content,
|
||||
PublishedAt: utils.FormatDateToIndonesianFormat(article.PublishedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(article.UpdatedAt),
|
||||
}
|
||||
|
||||
cacheData, _ := json.Marshal(result)
|
||||
config.RedisClient.Set(ctx, cacheKey, cacheData, time.Minute*5)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *ArticleService) CreateArticle(request *dto.ArticleCreateRequest) (*dto.ArticleResponse, error) {
|
||||
|
||||
if err := request.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newArticle := &domain.Article{
|
||||
Title: request.Title,
|
||||
CoverImage: request.CoverImage,
|
||||
Author: request.Author,
|
||||
Heading: request.Heading,
|
||||
Content: request.Content,
|
||||
}
|
||||
|
||||
err := s.repo.Create(newArticle)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to create article")
|
||||
}
|
||||
|
||||
ctx := config.Context()
|
||||
config.RedisClient.Del(ctx, "articles:all")
|
||||
|
||||
response := &dto.ArticleResponse{
|
||||
ID: newArticle.ID,
|
||||
Title: newArticle.Title,
|
||||
CoverImage: newArticle.CoverImage,
|
||||
Author: newArticle.Author,
|
||||
Heading: newArticle.Heading,
|
||||
Content: newArticle.Content,
|
||||
PublishedAt: utils.FormatDateToIndonesianFormat(newArticle.PublishedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(newArticle.UpdatedAt),
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *ArticleService) UpdateArticle(id string, request *dto.ArticleUpdateRequest) (*dto.ArticleResponse, error) {
|
||||
|
||||
// if err := dto.GetValidator().Struct(request); err != nil {
|
||||
// return nil, errors.New("invalid input data")
|
||||
// }
|
||||
|
||||
if err := request.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
article, err := s.repo.GetByID(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("article not found")
|
||||
}
|
||||
|
||||
article.Title = request.Title
|
||||
article.CoverImage = request.CoverImage
|
||||
article.Author = request.Author
|
||||
article.Heading = request.Heading
|
||||
article.Content = request.Content
|
||||
article.UpdatedAt = time.Now()
|
||||
|
||||
err = s.repo.Update(article)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to update article")
|
||||
}
|
||||
|
||||
ctx := config.Context()
|
||||
config.RedisClient.Del(ctx, "articles:all")
|
||||
config.RedisClient.Del(ctx, "articles:"+id)
|
||||
|
||||
response := &dto.ArticleResponse{
|
||||
ID: article.ID,
|
||||
Title: article.Title,
|
||||
CoverImage: article.CoverImage,
|
||||
Author: article.Author,
|
||||
Heading: article.Heading,
|
||||
Content: article.Content,
|
||||
PublishedAt: utils.FormatDateToIndonesianFormat(article.PublishedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(article.UpdatedAt),
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *ArticleService) DeleteArticle(id string) error {
|
||||
|
||||
article, err := s.repo.GetByID(id)
|
||||
if err != nil {
|
||||
return errors.New("article not found")
|
||||
}
|
||||
|
||||
err = s.repo.Delete(article)
|
||||
if err != nil {
|
||||
return errors.New("failed to delete article")
|
||||
}
|
||||
|
||||
ctx := config.Context()
|
||||
config.RedisClient.Del(ctx, "articles:all")
|
||||
config.RedisClient.Del(ctx, "articles:"+id)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func RegisterUser(username, name, email, phone, password, confirmPassword, roleId string) error {
|
||||
if password != confirmPassword {
|
||||
return errors.New("password dan confirm password tidak cocok")
|
||||
}
|
||||
|
||||
if repositories.IsEmailExist(email, roleId) {
|
||||
return errors.New("email is already registered with the same role")
|
||||
}
|
||||
|
||||
if repositories.IsUsernameExist(username, roleId) {
|
||||
return errors.New("username is already registered with the same role")
|
||||
}
|
||||
|
||||
if repositories.IsPhoneExist(phone, roleId) {
|
||||
return errors.New("phone number is already registered with the same role")
|
||||
}
|
||||
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return errors.New("failed to hash password")
|
||||
}
|
||||
|
||||
err = repositories.CreateUser(username, name, email, phone, string(hashedPassword), roleId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoginUser(identifier, password string) (string, error) {
|
||||
if identifier == "" || password == "" {
|
||||
return "", errors.New("email/username/phone and password must be provided")
|
||||
}
|
||||
|
||||
const roleId = ""
|
||||
user, err := repositories.GetUserByEmailUsernameOrPhone(identifier, roleId)
|
||||
if err != nil {
|
||||
return "", errors.New("invalid email/username/phone or password")
|
||||
}
|
||||
|
||||
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
|
||||
if err != nil {
|
||||
return "", errors.New("invalid email/username/phone or password")
|
||||
}
|
||||
|
||||
token := generateJWT(user.ID, user.RoleID)
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func generateJWT(userID, role string) string {
|
||||
claims := jwt.MapClaims{
|
||||
"sub": userID,
|
||||
"role": role,
|
||||
"exp": time.Now().Add(time.Hour * 24 * 7).Unix(),
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
t, err := token.SignedString([]byte(os.Getenv("API_KEY")))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func GetUserByID(userID string) (domain.User, error) {
|
||||
user, err := repositories.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return user, errors.New("user not found")
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func UpdateUser(userID, email, username, name, phone string) error {
|
||||
user, err := repositories.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return errors.New("user not found")
|
||||
}
|
||||
|
||||
if email != "" && email != user.Email {
|
||||
if repositories.IsEmailExist(email, user.RoleID) {
|
||||
return errors.New("email is already registered with the same role")
|
||||
}
|
||||
user.Email = email
|
||||
}
|
||||
|
||||
if username != "" && username != user.Username {
|
||||
if repositories.IsUsernameExist(username, user.RoleID) {
|
||||
return errors.New("username is already registered with the same role")
|
||||
}
|
||||
user.Username = username
|
||||
}
|
||||
|
||||
if phone != "" && phone != user.Phone {
|
||||
if repositories.IsPhoneExist(phone, user.RoleID) {
|
||||
return errors.New("phone number is already registered with the same role")
|
||||
}
|
||||
user.Phone = phone
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
user.Name = name
|
||||
}
|
||||
|
||||
err = repositories.UpdateUser(&user)
|
||||
if err != nil {
|
||||
return errors.New("failed to update user")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdatePassword(userID, oldPassword, newPassword string) error {
|
||||
user, err := repositories.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return errors.New("user not found")
|
||||
}
|
||||
|
||||
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(oldPassword))
|
||||
if err != nil {
|
||||
return errors.New("old password is incorrect")
|
||||
}
|
||||
|
||||
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(newPassword))
|
||||
if err == nil {
|
||||
return errors.New("new password cannot be the same as the old password")
|
||||
}
|
||||
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return errors.New("failed to hash new password")
|
||||
}
|
||||
|
||||
err = repositories.UpdateUserPassword(userID, string(hashedPassword))
|
||||
if err != nil {
|
||||
return errors.New("failed to update password")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/model"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type UserService interface {
|
||||
Login(credentials dto.LoginDTO) (*dto.UserResponseWithToken, error)
|
||||
}
|
||||
|
||||
type userService struct {
|
||||
UserRepo repositories.UserRepository
|
||||
SecretKey string
|
||||
}
|
||||
|
||||
func NewUserService(userRepo repositories.UserRepository, secretKey string) UserService {
|
||||
return &userService{UserRepo: userRepo, SecretKey: secretKey}
|
||||
}
|
||||
|
||||
func (s *userService) Login(credentials dto.LoginDTO) (*dto.UserResponseWithToken, error) {
|
||||
|
||||
user, err := s.UserRepo.FindByEmailOrUsernameOrPhone(credentials.Identifier)
|
||||
if err != nil {
|
||||
|
||||
return nil, fmt.Errorf("user not found")
|
||||
}
|
||||
|
||||
if !CheckPasswordHash(credentials.Password, user.Password) {
|
||||
return nil, bcrypt.ErrMismatchedHashAndPassword
|
||||
}
|
||||
|
||||
token, err := s.generateJWT(user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = utils.SetData(credentials.Identifier, token, time.Hour*24)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &dto.UserResponseWithToken{
|
||||
UserID: user.ID,
|
||||
Token: token,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *userService) generateJWT(user *model.User) (string, error) {
|
||||
claims := jwt.MapClaims{
|
||||
"sub": user.ID,
|
||||
"iat": time.Now().Unix(),
|
||||
"exp": time.Now().Add(time.Hour * 24).Unix(),
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
|
||||
tokenString, err := token.SignedString([]byte(s.SecretKey))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
}
|
||||
|
||||
func CheckPasswordHash(password, hashedPassword string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
|
||||
return err == nil
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
type BannerService struct {
|
||||
repo *repositories.BannerRepository
|
||||
}
|
||||
|
||||
func NewBannerService(repo *repositories.BannerRepository) *BannerService {
|
||||
return &BannerService{repo: repo}
|
||||
}
|
||||
|
||||
func (s *BannerService) GetAllBanners() ([]dto.BannerResponse, error) {
|
||||
ctx := config.Context()
|
||||
cacheKey := "banners:all"
|
||||
|
||||
cachedData, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil && cachedData != "" {
|
||||
var cachedBanners []dto.BannerResponse
|
||||
if err := json.Unmarshal([]byte(cachedData), &cachedBanners); err == nil {
|
||||
return cachedBanners, nil
|
||||
}
|
||||
}
|
||||
|
||||
banners, err := s.repo.GetAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []dto.BannerResponse
|
||||
for _, banner := range banners {
|
||||
result = append(result, dto.BannerResponse{
|
||||
ID: banner.ID,
|
||||
BannerName: banner.BannerName,
|
||||
BannerImage: banner.BannerImage,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(banner.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(banner.UpdatedAt),
|
||||
})
|
||||
}
|
||||
|
||||
cacheData, _ := json.Marshal(result)
|
||||
config.RedisClient.Set(ctx, cacheKey, cacheData, time.Minute*5)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *BannerService) GetBannerByID(id string) (*dto.BannerResponse, error) {
|
||||
ctx := config.Context()
|
||||
cacheKey := "banners:" + id
|
||||
|
||||
cachedData, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil && cachedData != "" {
|
||||
var cachedBanner dto.BannerResponse
|
||||
if err := json.Unmarshal([]byte(cachedData), &cachedBanner); err == nil {
|
||||
return &cachedBanner, nil
|
||||
}
|
||||
}
|
||||
|
||||
banner, err := s.repo.GetByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &dto.BannerResponse{
|
||||
ID: banner.ID,
|
||||
BannerName: banner.BannerName,
|
||||
BannerImage: banner.BannerImage,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(banner.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(banner.UpdatedAt),
|
||||
}
|
||||
|
||||
cacheData, _ := json.Marshal(result)
|
||||
config.RedisClient.Set(ctx, cacheKey, cacheData, time.Minute*5)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *BannerService) CreateBanner(request *dto.BannerCreateRequest) (*dto.BannerResponse, error) {
|
||||
|
||||
if request.BannerName == "" || request.BannerImage == "" {
|
||||
return nil, errors.New("invalid input data")
|
||||
}
|
||||
|
||||
newBanner := &domain.Banner{
|
||||
BannerName: request.BannerName,
|
||||
BannerImage: request.BannerImage,
|
||||
}
|
||||
|
||||
err := s.repo.Create(newBanner)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to create banner")
|
||||
}
|
||||
|
||||
ctx := config.Context()
|
||||
config.RedisClient.Del(ctx, "banners:all")
|
||||
|
||||
response := &dto.BannerResponse{
|
||||
ID: newBanner.ID,
|
||||
BannerName: newBanner.BannerName,
|
||||
BannerImage: newBanner.BannerImage,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(newBanner.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(newBanner.UpdatedAt),
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *BannerService) UpdateBanner(id string, request *dto.BannerUpdateRequest) (*dto.BannerResponse, error) {
|
||||
|
||||
banner, err := s.repo.GetByID(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("banner not found")
|
||||
}
|
||||
|
||||
if request.BannerName != nil && *request.BannerName != "" {
|
||||
banner.BannerName = *request.BannerName
|
||||
}
|
||||
if request.BannerImage != nil && *request.BannerImage != "" {
|
||||
banner.BannerImage = *request.BannerImage
|
||||
}
|
||||
banner.UpdatedAt = time.Now()
|
||||
|
||||
err = s.repo.Update(banner)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to update banner")
|
||||
}
|
||||
|
||||
ctx := config.Context()
|
||||
config.RedisClient.Del(ctx, "banners:all")
|
||||
config.RedisClient.Del(ctx, "banners:"+id)
|
||||
|
||||
response := &dto.BannerResponse{
|
||||
ID: banner.ID,
|
||||
BannerName: banner.BannerName,
|
||||
BannerImage: banner.BannerImage,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(banner.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(banner.UpdatedAt),
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *BannerService) DeleteBanner(id string) error {
|
||||
|
||||
banner, err := s.repo.GetByID(id)
|
||||
if err != nil {
|
||||
return errors.New("banner not found")
|
||||
}
|
||||
|
||||
err = s.repo.Delete(banner)
|
||||
if err != nil {
|
||||
return errors.New("failed to delete banner")
|
||||
}
|
||||
|
||||
ctx := config.Context()
|
||||
config.RedisClient.Del(ctx, "banners:all")
|
||||
config.RedisClient.Del(ctx, "banners:"+id)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
)
|
||||
|
||||
func GetCoverageAreas() ([]domain.CoverageArea, error) {
|
||||
return repositories.GetCoverageAreas()
|
||||
}
|
||||
|
||||
func GetCoverageAreaByID(id string) (domain.CoverageArea, error) {
|
||||
return repositories.GetCoverageAreaByID(id)
|
||||
}
|
||||
|
||||
func GetCoverageAreaByDistrictID(id string) (domain.CoverageDistric, error) {
|
||||
return repositories.GetCoverageAreaByDistrictID(id)
|
||||
}
|
||||
|
||||
func GetCoverageDistricsByCoverageAreaID(areaID string) ([]domain.CoverageDistric, error) {
|
||||
return repositories.GetCoverageDistricsByCoverageAreaID(areaID)
|
||||
}
|
||||
|
||||
func GetSubdistrictsByCoverageDistrictID(districtID string) ([]domain.CoverageSubdistrict, error) {
|
||||
return repositories.GetSubdistrictsByCoverageDistrictID(districtID)
|
||||
}
|
||||
|
||||
func CreateCoverageArea(province string) (*domain.CoverageArea, error) {
|
||||
coverageArea := &domain.CoverageArea{
|
||||
Province: province,
|
||||
}
|
||||
|
||||
if err := repositories.CreateCoverageArea(coverageArea); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return coverageArea, nil
|
||||
}
|
||||
|
||||
func CreateCoverageDistrict(coverageAreaID, district string) (*domain.CoverageDistric, error) {
|
||||
coverageDistrict := &domain.CoverageDistric{
|
||||
CoverageAreaID: coverageAreaID,
|
||||
District: district,
|
||||
}
|
||||
|
||||
if err := repositories.CreateCoverageDistrict(coverageDistrict); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return coverageDistrict, nil
|
||||
}
|
||||
|
||||
func CreateCoverageSubdistrict(coverageAreaID, coverageDistrictId, subdistrict string) (*domain.CoverageSubdistrict, error) {
|
||||
coverageSubdistrict := &domain.CoverageSubdistrict{
|
||||
CoverageAreaID: coverageAreaID,
|
||||
CoverageDistrictId: coverageDistrictId,
|
||||
Subdistrict: subdistrict,
|
||||
}
|
||||
|
||||
if err := repositories.CreateCoverageSubdistrict(coverageSubdistrict); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return coverageSubdistrict, nil
|
||||
}
|
||||
|
||||
func UpdateCoverageArea(id string, request domain.CoverageArea) (domain.CoverageArea, error) {
|
||||
return repositories.UpdateCoverageArea(id, request)
|
||||
}
|
||||
|
||||
func UpdateCoverageDistrict(id string, request domain.CoverageDistric) (domain.CoverageDistric, error) {
|
||||
return repositories.UpdateCoverageDistrict(id, request)
|
||||
}
|
||||
|
||||
func UpdateCoverageSubdistrict(id string, request domain.CoverageSubdistrict) (domain.CoverageSubdistrict, error) {
|
||||
return repositories.UpdateCoverageSubdistrict(id, request)
|
||||
}
|
||||
|
||||
func DeleteCoverageArea(id string) error {
|
||||
return repositories.DeleteCoverageArea(id)
|
||||
}
|
||||
|
||||
func DeleteCoverageDistrict(id string) error {
|
||||
return repositories.DeleteCoverageDistrict(id)
|
||||
}
|
||||
|
||||
func DeleteCoverageSubdistrict(id string) error {
|
||||
return repositories.DeleteCoverageSubdistrict(id)
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
type PointService struct {
|
||||
repo *repositories.PointRepository
|
||||
}
|
||||
|
||||
func NewPointService(repo *repositories.PointRepository) *PointService {
|
||||
return &PointService{repo: repo}
|
||||
}
|
||||
|
||||
func (s *PointService) GetAllPoints() ([]dto.PointResponse, error) {
|
||||
ctx := config.Context()
|
||||
|
||||
cacheKey := "points:all"
|
||||
cachedData, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil && cachedData != "" {
|
||||
var cachedPoints []dto.PointResponse
|
||||
if err := json.Unmarshal([]byte(cachedData), &cachedPoints); err == nil {
|
||||
return cachedPoints, nil
|
||||
}
|
||||
}
|
||||
|
||||
points, err := s.repo.GetAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []dto.PointResponse
|
||||
for _, point := range points {
|
||||
result = append(result, dto.PointResponse{
|
||||
ID: point.ID,
|
||||
CoinName: point.CoinName,
|
||||
ValuePerUnit: point.ValuePerUnit,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(point.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(point.UpdatedAt),
|
||||
})
|
||||
}
|
||||
|
||||
cacheData, _ := json.Marshal(result)
|
||||
config.RedisClient.Set(ctx, cacheKey, cacheData, time.Minute*5)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *PointService) GetPointByID(id string) (*dto.PointResponse, error) {
|
||||
ctx := config.Context()
|
||||
|
||||
cacheKey := "points:" + id
|
||||
cachedData, err := config.RedisClient.Get(ctx, cacheKey).Result()
|
||||
if err == nil && cachedData != "" {
|
||||
var cachedPoint dto.PointResponse
|
||||
if err := json.Unmarshal([]byte(cachedData), &cachedPoint); err == nil {
|
||||
return &cachedPoint, nil
|
||||
}
|
||||
}
|
||||
|
||||
point, err := s.repo.GetByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &dto.PointResponse{
|
||||
ID: point.ID,
|
||||
CoinName: point.CoinName,
|
||||
ValuePerUnit: point.ValuePerUnit,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(point.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(point.UpdatedAt),
|
||||
}
|
||||
|
||||
cacheData, _ := json.Marshal(result)
|
||||
config.RedisClient.Set(ctx, cacheKey, cacheData, time.Minute*5)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *PointService) CreatePoint(request *dto.PointCreateRequest) (*dto.PointResponse, error) {
|
||||
|
||||
if err := request.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newPoint := &domain.Point{
|
||||
CoinName: request.CoinName,
|
||||
ValuePerUnit: request.ValuePerUnit,
|
||||
}
|
||||
|
||||
err := s.repo.Create(newPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx := config.Context()
|
||||
config.RedisClient.Del(ctx, "points:all")
|
||||
|
||||
response := &dto.PointResponse{
|
||||
ID: newPoint.ID,
|
||||
CoinName: newPoint.CoinName,
|
||||
ValuePerUnit: newPoint.ValuePerUnit,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(newPoint.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(newPoint.UpdatedAt),
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *PointService) UpdatePoint(id string, request *dto.PointUpdateRequest) (*dto.PointResponse, error) {
|
||||
|
||||
if err := request.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
point, err := s.repo.GetByID(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("point not found")
|
||||
}
|
||||
|
||||
point.CoinName = request.CoinName
|
||||
point.ValuePerUnit = request.ValuePerUnit
|
||||
point.UpdatedAt = time.Now()
|
||||
|
||||
err = s.repo.Update(point)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to update point")
|
||||
}
|
||||
|
||||
ctx := config.Context()
|
||||
config.RedisClient.Del(ctx, "points:all")
|
||||
config.RedisClient.Del(ctx, "points:"+id)
|
||||
|
||||
response := &dto.PointResponse{
|
||||
ID: point.ID,
|
||||
CoinName: point.CoinName,
|
||||
ValuePerUnit: point.ValuePerUnit,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(point.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(point.UpdatedAt),
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *PointService) DeletePoint(id string) error {
|
||||
|
||||
point, err := s.repo.GetByID(id)
|
||||
if err != nil {
|
||||
return errors.New("point not found")
|
||||
}
|
||||
|
||||
err = s.repo.Delete(point)
|
||||
if err != nil {
|
||||
return errors.New("failed to delete point")
|
||||
}
|
||||
|
||||
ctx := config.Context()
|
||||
config.RedisClient.Del(ctx, "points:all")
|
||||
config.RedisClient.Del(ctx, "points:"+id)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,208 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetProductsByStoreID(storeID string, limit, page int) ([]dto.ProductResponseWithSoldDTO, error) {
|
||||
|
||||
offset := (page - 1) * limit
|
||||
|
||||
products, err := repositories.GetProductsByStoreID(storeID, limit, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mapProductsToDTO(products), nil
|
||||
}
|
||||
|
||||
func GetProductsByUserID(userID string, limit, page int) ([]dto.ProductResponseWithSoldDTO, error) {
|
||||
offset := (page - 1) * limit
|
||||
products, err := repositories.GetProductsByUserID(userID, limit, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mapProductsToDTO(products), nil
|
||||
}
|
||||
|
||||
func mapProductsToDTO(products []domain.Product) []dto.ProductResponseWithSoldDTO {
|
||||
var productResponses []dto.ProductResponseWithSoldDTO
|
||||
for _, product := range products {
|
||||
var images []dto.ProductImageDTO
|
||||
for _, img := range product.ProductImages {
|
||||
images = append(images, dto.ProductImageDTO{ImageURL: img.ImageURL})
|
||||
}
|
||||
|
||||
productResponses = append(productResponses, dto.ProductResponseWithSoldDTO{
|
||||
ID: product.ID,
|
||||
StoreID: product.StoreID,
|
||||
ProductTitle: product.ProductTitle,
|
||||
ProductImages: images,
|
||||
TrashDetail: dto.TrashDetailResponseDTO{
|
||||
ID: product.TrashDetail.ID,
|
||||
Description: product.TrashDetail.Description,
|
||||
Price: product.TrashDetail.Price,
|
||||
},
|
||||
SalePrice: product.SalePrice,
|
||||
Quantity: product.Quantity,
|
||||
ProductDescribe: product.ProductDescribe,
|
||||
Sold: product.Sold,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(product.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(product.UpdatedAt),
|
||||
})
|
||||
}
|
||||
return productResponses
|
||||
}
|
||||
|
||||
func GetProductByIDAndStoreID(productID, storeID string) (dto.ProductResponseWithSoldDTO, error) {
|
||||
product, err := repositories.GetProductByIDAndStoreID(productID, storeID)
|
||||
if err != nil {
|
||||
return dto.ProductResponseWithSoldDTO{}, err
|
||||
}
|
||||
|
||||
var images []dto.ProductImageDTO
|
||||
for _, img := range product.ProductImages {
|
||||
images = append(images, dto.ProductImageDTO{ImageURL: img.ImageURL})
|
||||
}
|
||||
|
||||
return dto.ProductResponseWithSoldDTO{
|
||||
ID: product.ID,
|
||||
StoreID: product.StoreID,
|
||||
ProductTitle: product.ProductTitle,
|
||||
ProductImages: images,
|
||||
TrashDetail: dto.TrashDetailResponseDTO{
|
||||
ID: product.TrashDetail.ID,
|
||||
Description: product.TrashDetail.Description,
|
||||
Price: product.TrashDetail.Price,
|
||||
},
|
||||
SalePrice: product.SalePrice,
|
||||
Quantity: product.Quantity,
|
||||
ProductDescribe: product.ProductDescribe,
|
||||
Sold: product.Sold,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(product.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(product.UpdatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func CreateProduct(input dto.CreateProductRequestDTO, userID string) (dto.CreateProductResponseDTO, error) {
|
||||
if err := dto.GetValidator().Struct(input); err != nil {
|
||||
return dto.CreateProductResponseDTO{}, err
|
||||
}
|
||||
|
||||
trashDetail, err := repositories.GetTrashDetailByID(input.TrashDetailID)
|
||||
if err != nil {
|
||||
return dto.CreateProductResponseDTO{}, err
|
||||
}
|
||||
|
||||
marketPrice := int64(trashDetail.Price)
|
||||
|
||||
if err := dto.ValidateSalePrice(marketPrice, input.SalePrice); err != nil {
|
||||
return dto.CreateProductResponseDTO{}, err
|
||||
}
|
||||
|
||||
product := &domain.Product{
|
||||
UserID: userID,
|
||||
StoreID: input.StoreID,
|
||||
ProductTitle: input.ProductTitle,
|
||||
TrashDetailID: input.TrashDetailID,
|
||||
SalePrice: input.SalePrice,
|
||||
Quantity: input.Quantity,
|
||||
ProductDescribe: input.ProductDescribe,
|
||||
}
|
||||
|
||||
var images []domain.ProductImage
|
||||
for _, imageURL := range input.ProductImages {
|
||||
images = append(images, domain.ProductImage{ImageURL: imageURL})
|
||||
}
|
||||
|
||||
if err := repositories.CreateProduct(product, images); err != nil {
|
||||
return dto.CreateProductResponseDTO{}, err
|
||||
}
|
||||
|
||||
trashDetail, err = repositories.GetTrashDetailByID(product.TrashDetailID)
|
||||
if err != nil {
|
||||
return dto.CreateProductResponseDTO{}, err
|
||||
}
|
||||
|
||||
return dto.CreateProductResponseDTO{
|
||||
ID: product.ID,
|
||||
StoreID: product.StoreID,
|
||||
ProductTitle: product.ProductTitle,
|
||||
ProductImages: input.ProductImages,
|
||||
TrashDetail: dto.TrashDetailResponseDTO{
|
||||
ID: trashDetail.ID,
|
||||
Description: trashDetail.Description,
|
||||
Price: trashDetail.Price,
|
||||
},
|
||||
SalePrice: product.SalePrice,
|
||||
Quantity: product.Quantity,
|
||||
ProductDescribe: product.ProductDescribe,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(product.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(product.UpdatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func UpdateProduct(productID string, input dto.UpdateProductRequestDTO) (dto.CreateProductResponseDTO, error) {
|
||||
|
||||
product, err := repositories.GetProductByID(productID)
|
||||
if err != nil {
|
||||
return dto.CreateProductResponseDTO{}, errors.New("product not found")
|
||||
}
|
||||
|
||||
product.ProductTitle = input.ProductTitle
|
||||
product.TrashDetailID = input.TrashDetailID
|
||||
product.SalePrice = input.SalePrice
|
||||
product.Quantity = input.Quantity
|
||||
product.ProductDescribe = input.ProductDescribe
|
||||
|
||||
var images []domain.ProductImage
|
||||
for _, imageURL := range input.ProductImages {
|
||||
images = append(images, domain.ProductImage{ImageURL: imageURL})
|
||||
}
|
||||
|
||||
if err := repositories.UpdateProduct(&product, images); err != nil {
|
||||
return dto.CreateProductResponseDTO{}, err
|
||||
}
|
||||
|
||||
trashDetail, err := repositories.GetTrashDetailByID(product.TrashDetailID)
|
||||
if err != nil {
|
||||
return dto.CreateProductResponseDTO{}, err
|
||||
}
|
||||
|
||||
return dto.CreateProductResponseDTO{
|
||||
ID: product.ID,
|
||||
StoreID: product.StoreID,
|
||||
ProductTitle: product.ProductTitle,
|
||||
ProductImages: input.ProductImages,
|
||||
TrashDetail: dto.TrashDetailResponseDTO{
|
||||
ID: trashDetail.ID,
|
||||
Description: trashDetail.Description,
|
||||
Price: trashDetail.Price,
|
||||
},
|
||||
SalePrice: product.SalePrice,
|
||||
Quantity: product.Quantity,
|
||||
ProductDescribe: product.ProductDescribe,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(product.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(product.UpdatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func DeleteProduct(productID string) error {
|
||||
|
||||
_, err := repositories.GetProductByID(productID)
|
||||
if err != nil {
|
||||
return errors.New("product not found")
|
||||
}
|
||||
|
||||
if err := repositories.DeleteProduct(productID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
)
|
||||
|
||||
type RequestPickupService struct {
|
||||
repository repositories.RequestPickupRepository
|
||||
}
|
||||
|
||||
func NewRequestPickupService(repository repositories.RequestPickupRepository) *RequestPickupService {
|
||||
return &RequestPickupService{repository: repository}
|
||||
}
|
||||
|
||||
func (s *RequestPickupService) CreateRequestPickup(request *domain.RequestPickup) error {
|
||||
return s.repository.Create(request)
|
||||
}
|
||||
|
||||
func (s *RequestPickupService) GetRequestPickupByID(id string) (*domain.RequestPickup, error) {
|
||||
return s.repository.GetByID(id)
|
||||
}
|
||||
|
||||
func (s *RequestPickupService) GetRequestPickupsByUser(userID string) ([]domain.RequestPickup, error) {
|
||||
return s.repository.GetByUserID(userID)
|
||||
}
|
||||
|
||||
func (s *RequestPickupService) DeleteRequestPickupByID(id string) error {
|
||||
|
||||
exists, err := s.repository.ExistsByID(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
return fmt.Errorf("request pickup with id %s not found", id)
|
||||
}
|
||||
|
||||
return s.repository.DeleteByID(id)
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
)
|
||||
|
||||
func GetUserRoleByID(id string) (domain.UserRole, error) {
|
||||
role, err := repositories.GetUserRoleByID(id)
|
||||
if err != nil {
|
||||
return role, errors.New("userRole tidak ditemukan")
|
||||
}
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func GetAllUserRoles() ([]domain.UserRole, error) {
|
||||
roles, err := repositories.GetAllUserRoles()
|
||||
if err != nil {
|
||||
return nil, errors.New("gagal mengambil data UserRole")
|
||||
}
|
||||
return roles, nil
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetStoreByID(storeID string) (dto.StoreResponseDTO, error) {
|
||||
store, err := repositories.GetStoreByID(storeID)
|
||||
if err != nil {
|
||||
return dto.StoreResponseDTO{}, err
|
||||
}
|
||||
|
||||
return dto.StoreResponseDTO{
|
||||
ID: store.ID,
|
||||
UserID: store.UserID,
|
||||
StoreName: store.StoreName,
|
||||
StoreLogo: store.StoreLogo,
|
||||
StoreBanner: store.StoreBanner,
|
||||
StoreDesc: store.StoreDesc,
|
||||
Follower: store.Follower,
|
||||
StoreRating: store.StoreRating,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(store.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(store.UpdatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func GetStoresByUserID(userID string, limit, page int) ([]dto.StoreResponseDTO, error) {
|
||||
offset := (page - 1) * limit
|
||||
stores, err := repositories.GetStoresByUserID(userID, limit, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var storeResponses []dto.StoreResponseDTO
|
||||
for _, store := range stores {
|
||||
storeResponses = append(storeResponses, dto.StoreResponseDTO{
|
||||
ID: store.ID,
|
||||
UserID: store.UserID,
|
||||
StoreName: store.StoreName,
|
||||
StoreLogo: store.StoreLogo,
|
||||
StoreBanner: store.StoreBanner,
|
||||
StoreDesc: store.StoreDesc,
|
||||
Follower: store.Follower,
|
||||
StoreRating: store.StoreRating,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(store.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(store.UpdatedAt),
|
||||
})
|
||||
}
|
||||
|
||||
return storeResponses, nil
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
)
|
||||
|
||||
func GetTrashCategories() ([]domain.TrashCategory, error) {
|
||||
return repositories.GetTrashCategories()
|
||||
}
|
||||
|
||||
func GetTrashCategoryDetail(id string) (domain.TrashCategory, error) {
|
||||
return repositories.GetTrashCategoryDetail(id)
|
||||
}
|
||||
|
||||
func CreateTrashCategory(name string) (domain.TrashCategory, error) {
|
||||
category := domain.TrashCategory{Name: name}
|
||||
err := repositories.CreateTrashCategory(&category)
|
||||
if err != nil {
|
||||
return category, err
|
||||
}
|
||||
return category, nil
|
||||
}
|
||||
|
||||
func CreateTrashDetail(categoryID, description string, price int) (domain.TrashDetail, error) {
|
||||
detail := domain.TrashDetail{
|
||||
CategoryID: categoryID,
|
||||
Description: description,
|
||||
Price: price,
|
||||
}
|
||||
err := repositories.CreateTrashDetail(&detail)
|
||||
if err != nil {
|
||||
return detail, err
|
||||
}
|
||||
return detail, nil
|
||||
}
|
||||
|
||||
func UpdateTrashCategory(id, name string) (domain.TrashCategory, error) {
|
||||
category, err := repositories.GetTrashCategoryDetail(id)
|
||||
if err != nil {
|
||||
return domain.TrashCategory{}, err
|
||||
}
|
||||
category.Name = name
|
||||
if err := repositories.UpdateTrashCategory(&category); err != nil {
|
||||
return domain.TrashCategory{}, err
|
||||
}
|
||||
return category, nil
|
||||
}
|
||||
|
||||
func UpdateTrashDetail(id, description string, price int) (domain.TrashDetail, error) {
|
||||
|
||||
detail, err := repositories.GetTrashDetailByID(id)
|
||||
if err != nil {
|
||||
|
||||
return domain.TrashDetail{}, err
|
||||
}
|
||||
|
||||
detail.Description = description
|
||||
detail.Price = price
|
||||
|
||||
if err := repositories.UpdateTrashDetail(&detail); err != nil {
|
||||
|
||||
return domain.TrashDetail{}, err
|
||||
}
|
||||
|
||||
return detail, nil
|
||||
}
|
||||
|
||||
func DeleteTrashCategory(id string) error {
|
||||
|
||||
err := repositories.DeleteTrashCategory(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteTrashDetail(id string) error {
|
||||
|
||||
err := repositories.DeleteTrashDetail(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func GetUsers() ([]dto.UserResponseDTO, error) {
|
||||
users, err := repositories.GetUsers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var userResponses []dto.UserResponseDTO
|
||||
for _, user := range users {
|
||||
userResponses = append(userResponses, dto.UserResponseDTO{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Name: user.Name,
|
||||
Email: user.Email,
|
||||
Phone: user.Phone,
|
||||
RoleId: user.RoleID,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(user.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(user.UpdatedAt),
|
||||
})
|
||||
}
|
||||
return userResponses, nil
|
||||
}
|
||||
|
||||
func GetUsersByRole(roleID string) ([]dto.UserResponseDTO, error) {
|
||||
users, err := repositories.GetUsersByRole(roleID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var userResponses []dto.UserResponseDTO
|
||||
for _, user := range users {
|
||||
userResponses = append(userResponses, dto.UserResponseDTO{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Name: user.Name,
|
||||
Email: user.Email,
|
||||
Phone: user.Phone,
|
||||
RoleId: user.RoleID,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(user.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(user.UpdatedAt),
|
||||
})
|
||||
}
|
||||
return userResponses, nil
|
||||
}
|
||||
|
||||
func GetUserByUserID(userID string) (dto.UserResponseDTO, error) {
|
||||
user, err := repositories.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return dto.UserResponseDTO{}, err
|
||||
}
|
||||
|
||||
userResponse := dto.UserResponseDTO{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Name: user.Name,
|
||||
Email: user.Email,
|
||||
Phone: user.Phone,
|
||||
RoleId: user.RoleID,
|
||||
CreatedAt: utils.FormatDateToIndonesianFormat(user.CreatedAt),
|
||||
UpdatedAt: utils.FormatDateToIndonesianFormat(user.UpdatedAt),
|
||||
}
|
||||
|
||||
return userResponse, nil
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/pahmiudahgede/senggoldong/domain"
|
||||
"github.com/pahmiudahgede/senggoldong/dto"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func CreatePin(userID string, input dto.PinInput) (domain.UserPin, error) {
|
||||
|
||||
hashedPin, err := bcrypt.GenerateFromPassword([]byte(input.Pin), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return domain.UserPin{}, err
|
||||
}
|
||||
|
||||
pin := domain.UserPin{
|
||||
UserID: userID,
|
||||
Pin: string(hashedPin),
|
||||
}
|
||||
|
||||
err = repositories.CreatePin(&pin)
|
||||
if err != nil {
|
||||
return domain.UserPin{}, err
|
||||
}
|
||||
|
||||
return pin, nil
|
||||
}
|
||||
|
||||
func GetPinByUserID(userID string) (domain.UserPin, error) {
|
||||
|
||||
pin, err := repositories.GetPinByUserID(userID)
|
||||
if err != nil {
|
||||
return pin, errors.New("PIN tidak ditemukan")
|
||||
}
|
||||
return pin, nil
|
||||
}
|
||||
|
||||
func UpdatePin(userID string, oldPin string, newPin string) (domain.UserPin, error) {
|
||||
|
||||
pin, err := repositories.GetPinByUserID(userID)
|
||||
if err != nil {
|
||||
return pin, errors.New("PIN tidak ditemukan")
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(pin.Pin), []byte(oldPin)); err != nil {
|
||||
return pin, errors.New("PIN lama salah")
|
||||
}
|
||||
|
||||
updatedPin, err := repositories.UpdatePin(userID, newPin)
|
||||
if err != nil {
|
||||
return updatedPin, err
|
||||
}
|
||||
|
||||
return updatedPin, nil
|
||||
}
|
||||
|
||||
func CheckPin(storedPinHash string, inputPin string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(storedPinHash), []byte(inputPin))
|
||||
return err == nil
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/utils"
|
||||
)
|
||||
|
||||
func APIKeyMiddleware(c *fiber.Ctx) error {
|
||||
|
||||
apiKey := c.Get("x-api-key")
|
||||
|
||||
validAPIKey := os.Getenv("API_KEY")
|
||||
|
||||
if apiKey != validAPIKey {
|
||||
log.Printf("Invalid API Key: %s", apiKey)
|
||||
|
||||
return utils.GenericErrorResponse(c, fiber.StatusUnauthorized, "Unauthorized: api key yang anda masukkan tidak valid")
|
||||
}
|
||||
|
||||
return c.Next()
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package domain
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
|
@ -11,11 +11,6 @@ type User struct {
|
|||
Email string `gorm:"not null" json:"email"`
|
||||
EmailVerified bool `gorm:"default:false" json:"emailVerified"`
|
||||
Password string `gorm:"not null" json:"password"`
|
||||
Pin UserPin `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"pin"`
|
||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||
RoleID string `gorm:"not null" json:"roleId"`
|
||||
Role UserRole `gorm:"foreignKey:RoleID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"role"`
|
||||
AddressId *string `gorm:"default:null" json:"addressId"`
|
||||
Addresses []Address `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"addresses"`
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package presentation
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/handler"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||
)
|
||||
|
||||
func AuthRouter(app *fiber.App) {
|
||||
api := app.Group("/apirijikid")
|
||||
|
||||
secretKey := os.Getenv("SECRET_KEY")
|
||||
if secretKey == "" {
|
||||
panic("SECRET_KEY is not set in the environment variables")
|
||||
}
|
||||
|
||||
userRepo := repositories.NewUserRepository(config.DB)
|
||||
userService := services.NewUserService(userRepo, secretKey)
|
||||
userHandler := handler.NewUserHandler(userService)
|
||||
|
||||
api.Post("/login", userHandler.Login)
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
"github.com/pahmiudahgede/senggoldong/internal/api"
|
||||
)
|
||||
|
||||
func init() {
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
log.Fatal("error saat memuat file .env")
|
||||
}
|
||||
|
||||
config.InitConfig()
|
||||
config.InitDatabase()
|
||||
config.InitRedis()
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := fiber.New()
|
||||
|
||||
api.AppRouter(app)
|
||||
|
||||
log.Fatal(app.Listen(":" + os.Getenv("SERVER_PORT")))
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
setup
|
|
@ -1,21 +1,22 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
func FormatDateToIndonesianFormat(t time.Time) string {
|
||||
func FormatDateToIndonesianFormat(t time.Time) (string, error) {
|
||||
|
||||
utcTime := t.UTC()
|
||||
|
||||
loc, err := time.LoadLocation("Asia/Jakarta")
|
||||
if err != nil {
|
||||
log.Printf("Error loading timezone: %v", err)
|
||||
return ""
|
||||
return "", fmt.Errorf("could not load location 'Asia/Jakarta'")
|
||||
}
|
||||
|
||||
indonesianTime := utcTime.In(loc)
|
||||
|
||||
return indonesianTime.Format("02-01-2006 15:04")
|
||||
return indonesianTime.Format("02-01-2006 15:04"), nil
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/pahmiudahgede/senggoldong/config"
|
||||
)
|
||||
|
||||
func SetData(key string, value interface{}, expiration time.Duration) error {
|
||||
|
||||
err := config.RedisClient.Set(context.Background(), key, value, expiration).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error setting data to Redis: %v", err)
|
||||
return err
|
||||
}
|
||||
log.Printf("Data stored in Redis with key: %s", key)
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetData(key string) (string, error) {
|
||||
|
||||
val, err := config.RedisClient.Get(context.Background(), key).Result()
|
||||
if err == redis.Nil {
|
||||
log.Printf("No data found for key: %s", key)
|
||||
return "", nil
|
||||
} else if err != nil {
|
||||
log.Printf("Error getting data from Redis: %v", err)
|
||||
return "", err
|
||||
}
|
||||
log.Printf("Data retrieved from Redis for key: %s", key)
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func DeleteData(key string) error {
|
||||
|
||||
err := config.RedisClient.Del(context.Background(), key).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error deleting data from Redis: %v", err)
|
||||
return err
|
||||
}
|
||||
log.Printf("Data deleted from Redis with key: %s", key)
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetDataWithExpire(key string, value interface{}, expiration time.Duration) error {
|
||||
|
||||
err := config.RedisClient.Set(context.Background(), key, value, expiration).Err()
|
||||
if err != nil {
|
||||
log.Printf("Error setting data with expiration to Redis: %v", err)
|
||||
return err
|
||||
}
|
||||
log.Printf("Data stored in Redis with key: %s and expiration: %v", key, expiration)
|
||||
return nil
|
||||
}
|
||||
|
||||
func CheckKeyExists(key string) (bool, error) {
|
||||
|
||||
val, err := config.RedisClient.Exists(context.Background(), key).Result()
|
||||
if err != nil {
|
||||
log.Printf("Error checking if key exists in Redis: %v", err)
|
||||
return false, err
|
||||
}
|
||||
return val > 0, nil
|
||||
}
|
|
@ -1,30 +1,96 @@
|
|||
package utils
|
||||
|
||||
type Meta struct {
|
||||
StatusCode int `json:"statusCode"`
|
||||
Message string `json:"message"`
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type MetaData struct {
|
||||
Status int `json:"status"`
|
||||
Page int `json:"page,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Total int `json:"total,omitempty"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type ApiResponse struct {
|
||||
Meta Meta `json:"meta"`
|
||||
type APIResponse struct {
|
||||
Meta MetaData `json:"meta"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func FormatResponse(statusCode int, message string, data interface{}) ApiResponse {
|
||||
return ApiResponse{
|
||||
Meta: Meta{
|
||||
StatusCode: statusCode,
|
||||
Message: message,
|
||||
func PaginatedResponse(c *fiber.Ctx, data interface{}, page, limit, total int, message string) error {
|
||||
response := APIResponse{
|
||||
Meta: MetaData{
|
||||
Status: fiber.StatusOK,
|
||||
Page: page,
|
||||
Limit: limit,
|
||||
Total: total,
|
||||
Message: message,
|
||||
},
|
||||
Data: data,
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(response)
|
||||
}
|
||||
|
||||
func ErrorResponse(statusCode int, message string) ApiResponse {
|
||||
return ApiResponse{
|
||||
Meta: Meta{
|
||||
StatusCode: statusCode,
|
||||
Message: message,
|
||||
func NonPaginatedResponse(c *fiber.Ctx, data interface{}, total int, message string) error {
|
||||
response := APIResponse{
|
||||
Meta: MetaData{
|
||||
Status: fiber.StatusOK,
|
||||
Total: total,
|
||||
Message: message,
|
||||
},
|
||||
Data: data,
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(response)
|
||||
}
|
||||
|
||||
func ErrorResponse(c *fiber.Ctx, message string) error {
|
||||
response := APIResponse{
|
||||
Meta: MetaData{
|
||||
Status: fiber.StatusNotFound,
|
||||
Message: message,
|
||||
},
|
||||
}
|
||||
return c.Status(fiber.StatusNotFound).JSON(response)
|
||||
}
|
||||
|
||||
func ValidationErrorResponse(c *fiber.Ctx, errors map[string][]string) error {
|
||||
response := APIResponse{
|
||||
Meta: MetaData{
|
||||
Status: fiber.StatusBadRequest,
|
||||
Message: "invalid user request",
|
||||
},
|
||||
Data: errors,
|
||||
}
|
||||
return c.Status(fiber.StatusBadRequest).JSON(response)
|
||||
}
|
||||
|
||||
func InternalServerErrorResponse(c *fiber.Ctx, message string) error {
|
||||
response := APIResponse{
|
||||
Meta: MetaData{
|
||||
Status: fiber.StatusInternalServerError,
|
||||
Message: message,
|
||||
},
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(response)
|
||||
}
|
||||
|
||||
func GenericErrorResponse(c *fiber.Ctx, status int, message string) error {
|
||||
response := APIResponse{
|
||||
Meta: MetaData{
|
||||
Status: status,
|
||||
Message: message,
|
||||
},
|
||||
}
|
||||
return c.Status(status).JSON(response)
|
||||
}
|
||||
|
||||
func LogResponse(c *fiber.Ctx, data interface{}, message string) error {
|
||||
response := APIResponse{
|
||||
Meta: MetaData{
|
||||
Status: fiber.StatusOK,
|
||||
Message: message,
|
||||
},
|
||||
Data: data,
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(response)
|
||||
}
|
Loading…
Reference in New Issue