Add User Partner and Product
This commit is contained in:
parent
67f1dbc850
commit
8a23e72230
@ -30,6 +30,3 @@ deploy_to_staging:
|
|||||||
- kubectl apply -f k8s/staging/ingress.yaml
|
- kubectl apply -f k8s/staging/ingress.yaml
|
||||||
only:
|
only:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
# tes bintang 4
|
|
||||||
|
|
||||||
|
|||||||
4
Makefile
4
Makefile
@ -1,9 +1,9 @@
|
|||||||
PROJECT_NAME = "furtuna-backend"
|
PROJECT_NAME = "furtuna-backend"
|
||||||
DB_USERNAME := furtuna_admin
|
DB_USERNAME := fortuna_admin
|
||||||
DB_PASSWORD := Z4G827t9428QFQ%5ESZXW%2343dB%25%214Bmh80
|
DB_PASSWORD := Z4G827t9428QFQ%5ESZXW%2343dB%25%214Bmh80
|
||||||
DB_HOST := 103.96.146.124
|
DB_HOST := 103.96.146.124
|
||||||
DB_PORT := 1960
|
DB_PORT := 1960
|
||||||
DB_NAME := furtuna-staging
|
DB_NAME := fortuna-staging
|
||||||
|
|
||||||
DB_URL = postgres://$(DB_USERNAME):$(DB_PASSWORD)@$(DB_HOST):$(DB_PORT)/$(DB_NAME)?sslmode=disable
|
DB_URL = postgres://$(DB_USERNAME):$(DB_PASSWORD)@$(DB_HOST):$(DB_PORT)/$(DB_NAME)?sslmode=disable
|
||||||
|
|
||||||
|
|||||||
1
furtuna-frontend
Submodule
1
furtuna-frontend
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 19af799abdd523522fad579044d55f5d764f87a3
|
||||||
@ -72,6 +72,9 @@ func (s *ServiceException) MapErrorsToHTTPCode() int {
|
|||||||
case errInvalidLogin:
|
case errInvalidLogin:
|
||||||
return http.StatusBadRequest
|
return http.StatusBadRequest
|
||||||
|
|
||||||
|
case errUserIsNotFound:
|
||||||
|
return http.StatusBadRequest
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return http.StatusInternalServerError
|
return http.StatusInternalServerError
|
||||||
}
|
}
|
||||||
@ -89,6 +92,9 @@ func (s *ServiceException) MapErrorsToCode() Code {
|
|||||||
case errBadRequest:
|
case errBadRequest:
|
||||||
return BadRequest
|
return BadRequest
|
||||||
|
|
||||||
|
case errUserIsNotFound:
|
||||||
|
return BadRequest
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return ServerError
|
return ServerError
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ type Context interface {
|
|||||||
|
|
||||||
RequestedBy() int64
|
RequestedBy() int64
|
||||||
IsSuperAdmin() bool
|
IsSuperAdmin() bool
|
||||||
|
GetPartnerID() *int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type MyContextImpl struct {
|
type MyContextImpl struct {
|
||||||
@ -20,7 +21,7 @@ type MyContextImpl struct {
|
|||||||
|
|
||||||
requestedBy int64
|
requestedBy int64
|
||||||
requestID string
|
requestID string
|
||||||
branchID int64
|
partnerID int64
|
||||||
roleID int
|
roleID int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,11 +33,18 @@ func (m *MyContextImpl) IsSuperAdmin() bool {
|
|||||||
return m.roleID == int(role.SuperAdmin)
|
return m.roleID == int(role.SuperAdmin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MyContextImpl) GetPartnerID() *int64 {
|
||||||
|
if m.partnerID != 0 {
|
||||||
|
return &m.partnerID
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewMyContext(parent context.Context, claims *entity.JWTAuthClaims) (*MyContextImpl, error) {
|
func NewMyContext(parent context.Context, claims *entity.JWTAuthClaims) (*MyContextImpl, error) {
|
||||||
return &MyContextImpl{
|
return &MyContextImpl{
|
||||||
Context: parent,
|
Context: parent,
|
||||||
requestedBy: claims.UserID,
|
requestedBy: claims.UserID,
|
||||||
branchID: claims.BranchID,
|
partnerID: claims.PartnerID,
|
||||||
roleID: claims.Role,
|
roleID: claims.Role,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,8 @@ type Role int64
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
SuperAdmin Role = 1
|
SuperAdmin Role = 1
|
||||||
BranchAdmin Role = 2
|
Admin Role = 2
|
||||||
CasheerAdmin Role = 3
|
PartnerAdmin Role = 3
|
||||||
|
SiteAdmin Role = 4
|
||||||
|
Casheer Role = 5
|
||||||
)
|
)
|
||||||
|
|||||||
@ -3,8 +3,8 @@ package studio
|
|||||||
type StudioStatus string
|
type StudioStatus string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Active StudioStatus = "Active"
|
Active StudioStatus = "active"
|
||||||
Inactive StudioStatus = "Inactive"
|
Inactive StudioStatus = "inactive"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b StudioStatus) toString() string {
|
func (b StudioStatus) toString() string {
|
||||||
|
|||||||
@ -14,23 +14,24 @@ type AuthData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UserDB struct {
|
type UserDB struct {
|
||||||
ID int64 `gorm:"primary_key;column:id" json:"id"`
|
ID int64 `gorm:"primary_key;column:id" json:"id"`
|
||||||
Name string `gorm:"column:name" json:"name"`
|
Name string `gorm:"column:name" json:"name"`
|
||||||
Email string `gorm:"column:email" json:"email"`
|
Email string `gorm:"column:email" json:"email"`
|
||||||
Password string `gorm:"column:password" json:"-"`
|
Password string `gorm:"column:password" json:"-"`
|
||||||
Status userstatus.UserStatus `gorm:"column:status" json:"status"`
|
Status userstatus.UserStatus `gorm:"column:status" json:"status"`
|
||||||
UserType string `gorm:"column:user_type" json:"user_type"`
|
UserType string `gorm:"column:user_type" json:"user_type"`
|
||||||
PhoneNumber string `gorm:"column:phone_number" json:"phone_number"`
|
PhoneNumber string `gorm:"column:phone_number" json:"phone_number"`
|
||||||
NIK string `gorm:"column:nik" json:"nik"`
|
NIK string `gorm:"column:nik" json:"nik"`
|
||||||
RoleID int64 `gorm:"column:role_id" json:"role_id"`
|
RoleID int64 `gorm:"column:role_id" json:"role_id"`
|
||||||
RoleName string `gorm:"column:role_name" json:"role_name"`
|
RoleName string `gorm:"column:role_name" json:"role_name"`
|
||||||
BranchID *int64 `gorm:"column:partner_id" json:"partner_id"`
|
PartnerID *int64 `gorm:"column:partner_id" json:"partner_id"`
|
||||||
BranchName string `gorm:"column:partner_name" json:"partner_name"`
|
PartnerName string `gorm:"column:partner_name" json:"partner_name"`
|
||||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
PartnerStatus string `gorm:"column:partner_status" json:"partner_status"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||||
DeletedAt *time.Time `gorm:"column:deleted_at" json:"deleted_at"`
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||||
CreatedBy int64 `gorm:"column:created_by" json:"created_by"`
|
DeletedAt *time.Time `gorm:"column:deleted_at" json:"deleted_at"`
|
||||||
UpdatedBy int64 `gorm:"column:updated_by" json:"updated_by"`
|
CreatedBy int64 `gorm:"column:created_by" json:"created_by"`
|
||||||
|
UpdatedBy int64 `gorm:"column:updated_by" json:"updated_by"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserDB) ToUser() *User {
|
func (u *UserDB) ToUser() *User {
|
||||||
@ -39,16 +40,16 @@ func (u *UserDB) ToUser() *User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
userEntity := &User{
|
userEntity := &User{
|
||||||
ID: u.ID,
|
ID: u.ID,
|
||||||
Name: u.Name,
|
Name: u.Name,
|
||||||
Email: u.Email,
|
Email: u.Email,
|
||||||
Status: u.Status,
|
Status: u.Status,
|
||||||
CreatedAt: u.CreatedAt,
|
CreatedAt: u.CreatedAt,
|
||||||
UpdatedAt: u.UpdatedAt,
|
UpdatedAt: u.UpdatedAt,
|
||||||
RoleID: role.Role(u.RoleID),
|
RoleID: role.Role(u.RoleID),
|
||||||
RoleName: u.RoleName,
|
RoleName: u.RoleName,
|
||||||
PartnerID: u.BranchID,
|
PartnerID: u.PartnerID,
|
||||||
BranchName: u.BranchName,
|
PartnerName: u.PartnerName,
|
||||||
}
|
}
|
||||||
|
|
||||||
return userEntity
|
return userEntity
|
||||||
@ -63,7 +64,7 @@ func (u *UserDB) ToUserRoleDB() *UserRoleDB {
|
|||||||
ID: 0,
|
ID: 0,
|
||||||
UserID: u.ID,
|
UserID: u.ID,
|
||||||
RoleID: u.RoleID,
|
RoleID: u.RoleID,
|
||||||
PartnerID: u.BranchID,
|
PartnerID: u.PartnerID,
|
||||||
CreatedAt: u.CreatedAt,
|
CreatedAt: u.CreatedAt,
|
||||||
UpdatedAt: u.UpdatedAt,
|
UpdatedAt: u.UpdatedAt,
|
||||||
}
|
}
|
||||||
@ -77,12 +78,13 @@ func (UserDB) TableName() string {
|
|||||||
|
|
||||||
func (u *UserDB) ToUserAuthenticate(signedToken string) *AuthenticateUser {
|
func (u *UserDB) ToUserAuthenticate(signedToken string) *AuthenticateUser {
|
||||||
return &AuthenticateUser{
|
return &AuthenticateUser{
|
||||||
Token: signedToken,
|
Token: signedToken,
|
||||||
Name: u.Name,
|
Name: u.Name,
|
||||||
RoleID: role.Role(u.RoleID),
|
RoleID: role.Role(u.RoleID),
|
||||||
RoleName: u.RoleName,
|
RoleName: u.RoleName,
|
||||||
BranchID: u.BranchID,
|
PartnerID: u.PartnerID,
|
||||||
BranchName: u.BranchName,
|
PartnerName: u.PartnerName,
|
||||||
|
PartnerStatus: u.PartnerStatus,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +118,7 @@ func (u *UserDB) ToUpdatedUser(req User) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if *req.PartnerID > 0 {
|
if *req.PartnerID > 0 {
|
||||||
u.BranchID = req.PartnerID
|
u.PartnerID = req.PartnerID
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.RoleID > 0 {
|
if req.RoleID > 0 {
|
||||||
|
|||||||
@ -3,10 +3,10 @@ package entity
|
|||||||
import "github.com/golang-jwt/jwt"
|
import "github.com/golang-jwt/jwt"
|
||||||
|
|
||||||
type JWTAuthClaims struct {
|
type JWTAuthClaims struct {
|
||||||
UserID int64 `json:"id"`
|
UserID int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Role int `json:"role"`
|
Role int `json:"role"`
|
||||||
BranchID int64 `json:"branch_id"`
|
PartnerID int64 `json:"partner_id"`
|
||||||
jwt.StandardClaims
|
jwt.StandardClaims
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,42 @@
|
|||||||
package entity
|
package entity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"furtuna-be/internal/constants/role"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type CreatePartnerRequest struct {
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Username string `json:"username" validate:"required"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Password string `json:"password" validate:"required"`
|
||||||
|
NIK string `json:"nik"`
|
||||||
|
PhoneNumber string `json:"phone_number"`
|
||||||
|
BankName string `json:"bank_name"`
|
||||||
|
BankAccountNumber string `json:"bank_account_number"`
|
||||||
|
BankAccountHolderName string `json:"bank_account_holder_name"`
|
||||||
|
}
|
||||||
|
|
||||||
type Partner struct {
|
type Partner struct {
|
||||||
ID int64
|
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
|
||||||
Name string
|
Name string `gorm:"type:varchar(255);not null;column:name"`
|
||||||
Status string
|
Status string `gorm:"type:varchar(50);column:status"`
|
||||||
Address string
|
LicenseExpiredDate *time.Time `gorm:"type:date;column:license_expired_date"`
|
||||||
CreatedAt time.Time
|
Address string `gorm:"type:varchar(255);column:address"`
|
||||||
UpdatedAt time.Time
|
BankName string `gorm:"type:varchar(255);column:bank_name"`
|
||||||
DeletedAt *time.Time
|
BankAccountNumber string `gorm:"type:varchar(50);column:bank_account_number"`
|
||||||
CreatedBy int64
|
BankAccountHolderName string `gorm:"type:varchar(255);column:bank_account_holder_name"`
|
||||||
UpdatedBy int64
|
CreatedAt time.Time `gorm:"autoCreateTime;column:created_at"`
|
||||||
|
UpdatedAt time.Time `gorm:"autoUpdateTime;column:updated_at"`
|
||||||
|
DeletedAt *time.Time `gorm:"column:deleted_at"`
|
||||||
|
CreatedBy int64 `gorm:"type:int;column:created_by"`
|
||||||
|
UpdatedBy int64 `gorm:"type:int;column:updated_by"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Partner) TableName() string {
|
||||||
|
return "partners"
|
||||||
}
|
}
|
||||||
|
|
||||||
type PartnerSearch struct {
|
type PartnerSearch struct {
|
||||||
@ -80,3 +103,46 @@ func (o *PartnerDB) SetDeleted(updatedBy int64) {
|
|||||||
o.DeletedAt = ¤tTime
|
o.DeletedAt = ¤tTime
|
||||||
o.UpdatedBy = updatedBy
|
o.UpdatedBy = updatedBy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CreatePartnerRequest) ToUserAdmin(partnerID int64) *User {
|
||||||
|
return &User{
|
||||||
|
Name: c.FullName,
|
||||||
|
Password: c.Password,
|
||||||
|
Email: c.Email,
|
||||||
|
NIK: c.NIK,
|
||||||
|
Status: "active",
|
||||||
|
RoleID: role.PartnerAdmin,
|
||||||
|
PartnerID: &partnerID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *CreatePartnerRequest) ToPartnerDB(createdBy int64) *PartnerDB {
|
||||||
|
twoDays := 48 * time.Hour
|
||||||
|
licenseExpiredDate := time.Now().Add(twoDays)
|
||||||
|
|
||||||
|
return &PartnerDB{
|
||||||
|
Partner: Partner{
|
||||||
|
Name: e.Name,
|
||||||
|
Status: "inactive",
|
||||||
|
Address: e.Address,
|
||||||
|
CreatedBy: createdBy,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
BankAccountHolderName: e.BankAccountHolderName,
|
||||||
|
BankAccountNumber: e.BankAccountNumber,
|
||||||
|
BankName: e.BankName,
|
||||||
|
LicenseExpiredDate: &licenseExpiredDate,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *CreatePartnerRequest) ToWallet(partnerID int64) *Wallet {
|
||||||
|
return &Wallet{
|
||||||
|
PartnerID: partnerID,
|
||||||
|
Balance: 0,
|
||||||
|
Currency: "IDR",
|
||||||
|
Status: "active",
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -6,20 +6,25 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Product struct {
|
type Product struct {
|
||||||
ID int64
|
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
|
||||||
Name string
|
PartnerID int64 `gorm:"type:int;column:partner_id"`
|
||||||
Type product.ProductType
|
SiteID int64 `gorm:"type:int;column:site_id"`
|
||||||
Price float64
|
Name string `gorm:"type:varchar(255);not null;column:name"`
|
||||||
Status product.ProductStatus
|
Type string `gorm:"type:varchar;column:type"`
|
||||||
Description string
|
Price float64 `gorm:"type:decimal;column:price"`
|
||||||
Image string
|
IsWeekendTicket bool `gorm:"type:bool;column:is_weekend_ticket"`
|
||||||
BranchID int64
|
IsSeasonTicket bool `gorm:"type:bool;column:is_season_ticket"`
|
||||||
StockQty int64
|
Status string `gorm:"type:varchar;column:status"`
|
||||||
CreatedAt time.Time
|
Description string `gorm:"type:varchar(255);not null;column:description"`
|
||||||
UpdatedAt time.Time
|
CreatedAt time.Time `gorm:"autoCreateTime;column:created_at"`
|
||||||
DeletedAt *time.Time
|
UpdatedAt time.Time `gorm:"autoUpdateTime;column:updated_at"`
|
||||||
CreatedBy int64
|
DeletedAt *time.Time `gorm:"column:deleted_at"`
|
||||||
UpdatedBy int64
|
CreatedBy int64 `gorm:"type:int;column:created_by"`
|
||||||
|
UpdatedBy int64 `gorm:"type:int;column:updated_by"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Product) TableName() string {
|
||||||
|
return "products"
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductSearch struct {
|
type ProductSearch struct {
|
||||||
@ -56,9 +61,7 @@ func (e *ProductDB) ToProduct() *Product {
|
|||||||
Price: e.Price,
|
Price: e.Price,
|
||||||
Status: e.Status,
|
Status: e.Status,
|
||||||
Description: e.Description,
|
Description: e.Description,
|
||||||
Image: e.Image,
|
PartnerID: e.PartnerID,
|
||||||
BranchID: e.BranchID,
|
|
||||||
StockQty: e.StockQty,
|
|
||||||
CreatedAt: e.CreatedAt,
|
CreatedAt: e.CreatedAt,
|
||||||
UpdatedAt: e.UpdatedAt,
|
UpdatedAt: e.UpdatedAt,
|
||||||
DeletedAt: e.DeletedAt,
|
DeletedAt: e.DeletedAt,
|
||||||
@ -97,14 +100,6 @@ func (o *ProductDB) ToUpdatedProduct(updatedby int64, req Product) {
|
|||||||
if req.Description != "" {
|
if req.Description != "" {
|
||||||
o.Description = req.Description
|
o.Description = req.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Image != "" {
|
|
||||||
o.Image = req.Image
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.StockQty > 0 {
|
|
||||||
o.StockQty = req.StockQty
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *ProductDB) SetDeleted(updatedby int64) {
|
func (o *ProductDB) SetDeleted(updatedby int64) {
|
||||||
|
|||||||
145
internal/entity/sites.go
Normal file
145
internal/entity/sites.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Site struct {
|
||||||
|
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
|
||||||
|
Name string `gorm:"type:varchar(255);not null;column:name"`
|
||||||
|
PartnerID int64 `gorm:"type:int;column:partner_id"`
|
||||||
|
Image string `gorm:"type:varchar;column:image"`
|
||||||
|
Address string `gorm:"type:varchar;column:address"`
|
||||||
|
LocationLink string `gorm:"type:varchar;column:location_link"`
|
||||||
|
Description string `gorm:"type:varchar;column:description"`
|
||||||
|
Highlight string `gorm:"type:varchar;column:highlight"`
|
||||||
|
ContactPerson string `gorm:"type:varchar;column:contact_person"`
|
||||||
|
TnC string `gorm:"type:varchar;column:tnc"`
|
||||||
|
AdditionalInfo string `gorm:"type:varchar;column:additional_info"`
|
||||||
|
Status string `gorm:"type:varchar;column:status"`
|
||||||
|
IsSeasonTicket bool `gorm:"type:bool;column:is_season_ticket"`
|
||||||
|
IsDiscountActive bool `gorm:"type:bool;column:is_discount_active"`
|
||||||
|
CreatedAt time.Time `gorm:"autoCreateTime;column:created_at"`
|
||||||
|
UpdatedAt time.Time `gorm:"autoUpdateTime;column:updated_at"`
|
||||||
|
DeletedAt *time.Time `gorm:"column:deleted_at"`
|
||||||
|
CreatedBy int64 `gorm:"type:int;column:created_by"`
|
||||||
|
UpdatedBy int64 `gorm:"type:int;column:updated_by"`
|
||||||
|
Products []Product `gorm:"foreignKey:SiteID;constraint:OnDelete:CASCADE;"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SiteSearch struct {
|
||||||
|
Search string
|
||||||
|
Name string
|
||||||
|
Limit int
|
||||||
|
Offset int
|
||||||
|
}
|
||||||
|
|
||||||
|
type SiteList []*SiteDB
|
||||||
|
|
||||||
|
type SiteDB struct {
|
||||||
|
Site
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Site) ToSiteDB() *SiteDB {
|
||||||
|
return &SiteDB{
|
||||||
|
Site: *s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (SiteDB) TableName() string {
|
||||||
|
return "sites"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SiteDB) ToSite() *Site {
|
||||||
|
return &Site{
|
||||||
|
ID: e.ID,
|
||||||
|
Name: e.Name,
|
||||||
|
PartnerID: e.PartnerID,
|
||||||
|
Image: e.Image,
|
||||||
|
Address: e.Address,
|
||||||
|
LocationLink: e.LocationLink,
|
||||||
|
Description: e.Description,
|
||||||
|
Highlight: e.Highlight,
|
||||||
|
ContactPerson: e.ContactPerson,
|
||||||
|
TnC: e.TnC,
|
||||||
|
AdditionalInfo: e.AdditionalInfo,
|
||||||
|
Status: e.Status,
|
||||||
|
IsSeasonTicket: e.IsSeasonTicket,
|
||||||
|
IsDiscountActive: e.IsDiscountActive,
|
||||||
|
CreatedAt: e.CreatedAt,
|
||||||
|
UpdatedAt: e.UpdatedAt,
|
||||||
|
DeletedAt: e.DeletedAt,
|
||||||
|
CreatedBy: e.CreatedBy,
|
||||||
|
UpdatedBy: e.UpdatedBy,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SiteList) ToSiteList() []*Site {
|
||||||
|
var sites []*Site
|
||||||
|
for _, site := range *s {
|
||||||
|
sites = append(sites, site.ToSite())
|
||||||
|
}
|
||||||
|
return sites
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *SiteDB) ToUpdatedSite(updatedBy int64, req Site) {
|
||||||
|
o.UpdatedBy = updatedBy
|
||||||
|
|
||||||
|
if req.Name != "" {
|
||||||
|
o.Name = req.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.PartnerID != 0 {
|
||||||
|
o.PartnerID = req.PartnerID
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Image != "" {
|
||||||
|
o.Image = req.Image
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Address != "" {
|
||||||
|
o.Address = req.Address
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.LocationLink != "" {
|
||||||
|
o.LocationLink = req.LocationLink
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Description != "" {
|
||||||
|
o.Description = req.Description
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Highlight != "" {
|
||||||
|
o.Highlight = req.Highlight
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.ContactPerson != "" {
|
||||||
|
o.ContactPerson = req.ContactPerson
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.TnC != "" {
|
||||||
|
o.TnC = req.TnC
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.AdditionalInfo != "" {
|
||||||
|
o.AdditionalInfo = req.AdditionalInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Status != "" {
|
||||||
|
o.Status = req.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.IsSeasonTicket {
|
||||||
|
o.IsSeasonTicket = req.IsSeasonTicket
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.IsDiscountActive {
|
||||||
|
o.IsDiscountActive = req.IsDiscountActive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *SiteDB) SetDeleted(updatedBy int64) {
|
||||||
|
currentTime := time.Now()
|
||||||
|
o.DeletedAt = ¤tTime
|
||||||
|
o.UpdatedBy = updatedBy
|
||||||
|
}
|
||||||
@ -10,27 +10,28 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int64
|
ID int64
|
||||||
Name string
|
Name string
|
||||||
Email string
|
Email string
|
||||||
Password string
|
Password string
|
||||||
Status userstatus.UserStatus
|
Status userstatus.UserStatus
|
||||||
NIK string
|
NIK string
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
RoleID role.Role
|
RoleID role.Role
|
||||||
RoleName string
|
RoleName string
|
||||||
PartnerID *int64
|
PartnerID *int64
|
||||||
BranchName string
|
PartnerName string
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthenticateUser struct {
|
type AuthenticateUser struct {
|
||||||
Token string
|
Token string
|
||||||
Name string
|
Name string
|
||||||
RoleID role.Role
|
RoleID role.Role
|
||||||
RoleName string
|
RoleName string
|
||||||
BranchID *int64
|
PartnerID *int64
|
||||||
BranchName string
|
PartnerName string
|
||||||
|
PartnerStatus string
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserRoleDB struct {
|
type UserRoleDB struct {
|
||||||
@ -53,7 +54,7 @@ func (u *User) ToUserDB(createdBy int64) (*UserDB, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.RoleID == role.BranchAdmin && u.PartnerID == nil {
|
if u.RoleID == role.Admin && u.PartnerID == nil {
|
||||||
return nil, errors.New("invalid request")
|
return nil, errors.New("invalid request")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ func (u *User) ToUserDB(createdBy int64) (*UserDB, error) {
|
|||||||
Email: u.Email,
|
Email: u.Email,
|
||||||
Password: hashedPassword,
|
Password: hashedPassword,
|
||||||
RoleID: int64(u.RoleID),
|
RoleID: int64(u.RoleID),
|
||||||
BranchID: u.PartnerID,
|
PartnerID: u.PartnerID,
|
||||||
Status: userstatus.Active,
|
Status: userstatus.Active,
|
||||||
CreatedBy: createdBy,
|
CreatedBy: createdBy,
|
||||||
}, nil
|
}, nil
|
||||||
|
|||||||
17
internal/entity/wallet.go
Normal file
17
internal/entity/wallet.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Wallet struct {
|
||||||
|
ID int64 `gorm:"primaryKey;autoIncrement;column:id"`
|
||||||
|
PartnerID int64 `gorm:"type:int;not null;column:partner_id"`
|
||||||
|
Balance float64 `gorm:"type:decimal(18,2);not null;default:0.00;column:balance"`
|
||||||
|
Currency string `gorm:"type:varchar(3);not null;column:currency"`
|
||||||
|
Status string `gorm:"type:varchar(50);column:status"`
|
||||||
|
CreatedAt time.Time `gorm:"autoCreateTime;column:created_at"`
|
||||||
|
UpdatedAt time.Time `gorm:"autoUpdateTime;column:updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Wallet) TableName() string {
|
||||||
|
return "wallets"
|
||||||
|
}
|
||||||
@ -51,19 +51,20 @@ func (h *AuthHandler) AuthLogin(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var branch *response.Branch
|
var partner *response.Partner
|
||||||
|
|
||||||
if authUser.RoleID != role.SuperAdmin {
|
if authUser.RoleID != role.SuperAdmin {
|
||||||
branch = &response.Branch{
|
partner = &response.Partner{
|
||||||
ID: authUser.BranchID,
|
ID: authUser.PartnerID,
|
||||||
Name: authUser.BranchName,
|
Name: authUser.PartnerName,
|
||||||
|
Status: authUser.PartnerStatus,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := response.LoginResponse{
|
resp := response.LoginResponse{
|
||||||
Token: authUser.Token,
|
Token: authUser.Token,
|
||||||
Branch: branch,
|
Partner: partner,
|
||||||
Name: authUser.Name,
|
Name: authUser.Name,
|
||||||
Role: response.Role{
|
Role: response.Role{
|
||||||
ID: int64(authUser.RoleID),
|
ID: int64(authUser.RoleID),
|
||||||
Role: authUser.RoleName,
|
Role: authUser.RoleName,
|
||||||
|
|||||||
@ -51,7 +51,7 @@ func NewHandler(service services.Partner) *Handler {
|
|||||||
func (h *Handler) Create(c *gin.Context) {
|
func (h *Handler) Create(c *gin.Context) {
|
||||||
ctx := request.GetMyContext(c)
|
ctx := request.GetMyContext(c)
|
||||||
|
|
||||||
var req request.Partner
|
var req request.CreatePartnerRequest
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -246,9 +246,6 @@ func (h *Handler) toProductResponse(resp *entity.Product) response.Product {
|
|||||||
Price: resp.Price,
|
Price: resp.Price,
|
||||||
Status: resp.Status,
|
Status: resp.Status,
|
||||||
Description: resp.Description,
|
Description: resp.Description,
|
||||||
Image: resp.Image,
|
|
||||||
BranchID: resp.BranchID,
|
|
||||||
StockQty: resp.StockQty,
|
|
||||||
CreatedAt: resp.CreatedAt.Format(time.RFC3339),
|
CreatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||||
UpdatedAt: resp.CreatedAt.Format(time.RFC3339),
|
UpdatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||||
}
|
}
|
||||||
|
|||||||
299
internal/handlers/http/sites/sites.go
Normal file
299
internal/handlers/http/sites/sites.go
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
package site
|
||||||
|
|
||||||
|
import (
|
||||||
|
"furtuna-be/internal/common/errors"
|
||||||
|
"furtuna-be/internal/entity"
|
||||||
|
"furtuna-be/internal/handlers/request"
|
||||||
|
"furtuna-be/internal/handlers/response"
|
||||||
|
"furtuna-be/internal/services"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Handler struct {
|
||||||
|
service services.Site
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) Route(group *gin.RouterGroup, jwt gin.HandlerFunc) {
|
||||||
|
route := group.Group("/site")
|
||||||
|
|
||||||
|
route.POST("/", jwt, h.Create)
|
||||||
|
route.GET("/list", jwt, h.GetAll)
|
||||||
|
route.PUT("/:id", jwt, h.Update)
|
||||||
|
route.GET("/:id", jwt, h.GetByID)
|
||||||
|
route.DELETE("/:id", jwt, h.Delete)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHandler(service services.Site) *Handler {
|
||||||
|
return &Handler{
|
||||||
|
service: service,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create handles the creation of a new Site.
|
||||||
|
// @Summary Create a new Site
|
||||||
|
// @Description Create a new Site based on the provided data.
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param Authorization header string true "JWT token"
|
||||||
|
// @Param req body request.Site true "New Site details"
|
||||||
|
// @Success 200 {object} response.BaseResponse{data=response.Site} "Site created successfully"
|
||||||
|
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||||
|
// @Failure 401 {object} response.BaseResponse{data=errors.Error} "Unauthorized"
|
||||||
|
// @Router /api/v1/site [post]
|
||||||
|
// @Tags Site APIs
|
||||||
|
func (h *Handler) Create(c *gin.Context) {
|
||||||
|
ctx := request.GetMyContext(c)
|
||||||
|
|
||||||
|
var req request.Site
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ctx.IsSuperAdmin() {
|
||||||
|
req.PartnerID = ctx.GetPartnerID()
|
||||||
|
}
|
||||||
|
|
||||||
|
validate := validator.New()
|
||||||
|
if err := validate.Struct(req); err != nil {
|
||||||
|
response.ErrorWrapper(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := h.service.Create(ctx, req.ToEntity(ctx.RequestedBy()))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
response.ErrorWrapper(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, response.BaseResponse{
|
||||||
|
Success: true,
|
||||||
|
Status: http.StatusOK,
|
||||||
|
Data: h.toSiteResponse(res),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update handles the update of an existing Site.
|
||||||
|
// @Summary Update an existing Site
|
||||||
|
// @Description Update the details of an existing Site based on the provided ID.
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param Authorization header string true "JWT token"
|
||||||
|
// @Param id path int64 true "Site ID to update"
|
||||||
|
// @Param req body request.Site true "Updated Site details"
|
||||||
|
// @Success 200 {object} response.BaseResponse{data=response.Site} "Site updated successfully"
|
||||||
|
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||||
|
// @Failure 401 {object} response.BaseResponse{data=errors.Error} "Unauthorized"
|
||||||
|
// @Router /api/v1/site/{id} [put]
|
||||||
|
// @Tags Site APIs
|
||||||
|
func (h *Handler) Update(c *gin.Context) {
|
||||||
|
ctx := request.GetMyContext(c)
|
||||||
|
|
||||||
|
id := c.Param("id")
|
||||||
|
|
||||||
|
SiteID, err := strconv.ParseInt(id, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req request.Site
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
validate := validator.New()
|
||||||
|
if err := validate.Struct(req); err != nil {
|
||||||
|
response.ErrorWrapper(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedSite, err := h.service.Update(ctx, SiteID, req.ToEntity(ctx.RequestedBy()))
|
||||||
|
if err != nil {
|
||||||
|
response.ErrorWrapper(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, response.BaseResponse{
|
||||||
|
Success: true,
|
||||||
|
Status: http.StatusOK,
|
||||||
|
Data: h.toSiteResponse(updatedSite),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAll retrieves a list of Sites.
|
||||||
|
// @Summary Get a list of Sites
|
||||||
|
// @Description Get a paginated list of Sites based on query parameters.
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param Authorization header string true "JWT token"
|
||||||
|
// @Param Limit query int false "Number of items to retrieve (default 10)"
|
||||||
|
// @Param Offset query int false "Offset for pagination (default 0)"
|
||||||
|
// @Success 200 {object} response.BaseResponse{data=response.SiteList} "List of Sites"
|
||||||
|
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||||
|
// @Failure 401 {object} response.BaseResponse{data=errors.Error} "Unauthorized"
|
||||||
|
// @Router /api/v1/site/list [get]
|
||||||
|
// @Tags Site APIs
|
||||||
|
func (h *Handler) GetAll(c *gin.Context) {
|
||||||
|
var req request.SiteParam
|
||||||
|
if err := c.ShouldBindQuery(&req); err != nil {
|
||||||
|
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Sites, total, err := h.service.GetAll(c.Request.Context(), req.ToEntity())
|
||||||
|
if err != nil {
|
||||||
|
response.ErrorWrapper(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, response.BaseResponse{
|
||||||
|
Success: true,
|
||||||
|
Status: http.StatusOK,
|
||||||
|
Data: h.toSiteResponseList(Sites, int64(total), req),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete handles the deletion of a Site by ID.
|
||||||
|
// @Summary Delete a Site by ID
|
||||||
|
// @Description Delete a Site based on the provided ID.
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param Authorization header string true "JWT token"
|
||||||
|
// @Param id path int64 true "Site ID to delete"
|
||||||
|
// @Success 200 {object} response.BaseResponse "Site deleted successfully"
|
||||||
|
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||||
|
// @Failure 401 {object} response.BaseResponse{data=errors.Error} "Unauthorized"
|
||||||
|
// @Router /api/v1/site/{id} [delete]
|
||||||
|
// @Tags Site APIs
|
||||||
|
func (h *Handler) Delete(c *gin.Context) {
|
||||||
|
ctx := request.GetMyContext(c)
|
||||||
|
id := c.Param("id")
|
||||||
|
|
||||||
|
// Parse the ID into a uint
|
||||||
|
SiteID, err := strconv.ParseInt(id, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.service.Delete(ctx, SiteID)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, response.BaseResponse{
|
||||||
|
Success: false,
|
||||||
|
Status: http.StatusInternalServerError,
|
||||||
|
Message: err.Error(),
|
||||||
|
Data: nil,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, response.BaseResponse{
|
||||||
|
Success: true,
|
||||||
|
Status: http.StatusOK,
|
||||||
|
Data: nil,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByID retrieves details of a specific Site by ID.
|
||||||
|
// @Summary Get details of a Site by ID
|
||||||
|
// @Description Get details of a Site based on the provided ID.
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param Authorization header string true "JWT token"
|
||||||
|
// @Param id path int64 true "Site ID to retrieve"
|
||||||
|
// @Success 200 {object} response.BaseResponse{data=response.Site} "Site details"
|
||||||
|
// @Failure 400 {object} response.BaseResponse{data=errors.Error} "Bad request"
|
||||||
|
// @Failure 401 {object} response.BaseResponse{data=errors.Error} "Unauthorized"
|
||||||
|
// @Router /api/v1/site/{id} [get]
|
||||||
|
// @Tags Site APIs
|
||||||
|
func (h *Handler) GetByID(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
|
||||||
|
// Parse the ID into a uint
|
||||||
|
SiteID, err := strconv.ParseInt(id, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
response.ErrorWrapper(c, errors.ErrorBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := h.service.GetByID(c.Request.Context(), SiteID)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, response.BaseResponse{
|
||||||
|
Success: false,
|
||||||
|
Status: http.StatusInternalServerError,
|
||||||
|
Message: err.Error(),
|
||||||
|
Data: nil,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, response.BaseResponse{
|
||||||
|
Success: true,
|
||||||
|
Status: http.StatusOK,
|
||||||
|
Data: h.toSiteResponse(res),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) toSiteResponse(resp *entity.Site) response.Site {
|
||||||
|
return response.Site{
|
||||||
|
ID: &resp.ID,
|
||||||
|
Name: resp.Name,
|
||||||
|
PartnerID: resp.PartnerID,
|
||||||
|
Image: resp.Image,
|
||||||
|
Address: resp.Address,
|
||||||
|
LocationLink: resp.LocationLink,
|
||||||
|
Description: resp.Description,
|
||||||
|
Highlight: resp.Highlight,
|
||||||
|
ContactPerson: resp.ContactPerson,
|
||||||
|
TnC: resp.TnC,
|
||||||
|
AdditionalInfo: resp.AdditionalInfo,
|
||||||
|
Status: resp.Status,
|
||||||
|
IsSeasonTicket: resp.IsSeasonTicket,
|
||||||
|
IsDiscountActive: resp.IsDiscountActive,
|
||||||
|
CreatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||||
|
UpdatedAt: resp.UpdatedAt.Format(time.RFC3339),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) toSiteResponseList(resp []*entity.Site, total int64, req request.SiteParam) response.SiteList {
|
||||||
|
var Sites []response.Site
|
||||||
|
for _, b := range resp {
|
||||||
|
Sites = append(Sites, h.toSiteResponse(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.SiteList{
|
||||||
|
Sites: Sites,
|
||||||
|
Total: total,
|
||||||
|
Limit: req.Limit,
|
||||||
|
Offset: req.Offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) toProductResponseList(products []entity.Product) []response.Product {
|
||||||
|
var res []response.Product
|
||||||
|
for _, product := range products {
|
||||||
|
res = append(res, response.Product{
|
||||||
|
ID: product.ID,
|
||||||
|
PartnerID: product.PartnerID,
|
||||||
|
SiteID: product.SiteID,
|
||||||
|
Name: product.Name,
|
||||||
|
Type: product.Type,
|
||||||
|
Price: product.Price,
|
||||||
|
IsWeekendTicket: product.IsWeekendTicket,
|
||||||
|
IsSeasonTicket: product.IsSeasonTicket,
|
||||||
|
Status: product.Status,
|
||||||
|
Description: product.Description,
|
||||||
|
CreatedAt: product.CreatedAt.Format(time.RFC3339),
|
||||||
|
UpdatedAt: product.UpdatedAt.Format(time.RFC3339),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
@ -56,13 +56,15 @@ func (h *Handler) Create(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req.PartnerID = ctx.GetPartnerID()
|
||||||
if err := req.Validate(); err != nil {
|
if err := req.Validate(); err != nil {
|
||||||
response.ErrorWrapper(c, errors.ErrorInvalidRequest)
|
response.ErrorWrapper(c, errors.ErrorInvalidRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := h.service.Create(ctx, req.ToEntity())
|
ctx.IsSuperAdmin()
|
||||||
|
|
||||||
|
res, err := h.service.Create(ctx, req.ToEntity())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ErrorWrapper(c, err)
|
response.ErrorWrapper(c, err)
|
||||||
return
|
return
|
||||||
@ -260,16 +262,16 @@ func (h *Handler) Delete(c *gin.Context) {
|
|||||||
|
|
||||||
func (h *Handler) toUserResponse(resp *entity.User) response.User {
|
func (h *Handler) toUserResponse(resp *entity.User) response.User {
|
||||||
return response.User{
|
return response.User{
|
||||||
ID: resp.ID,
|
ID: resp.ID,
|
||||||
Name: resp.Name,
|
Name: resp.Name,
|
||||||
Email: resp.Email,
|
Email: resp.Email,
|
||||||
Status: string(resp.Status),
|
Status: string(resp.Status),
|
||||||
RoleID: int64(resp.RoleID),
|
RoleID: int64(resp.RoleID),
|
||||||
RoleName: resp.RoleName,
|
RoleName: resp.RoleName,
|
||||||
PartnerID: resp.PartnerID,
|
PartnerID: resp.PartnerID,
|
||||||
BranchName: resp.BranchName,
|
PartnerName: resp.PartnerName,
|
||||||
CreatedAt: resp.CreatedAt.Format(time.RFC3339),
|
CreatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||||
UpdatedAt: resp.CreatedAt.Format(time.RFC3339),
|
UpdatedAt: resp.CreatedAt.Format(time.RFC3339),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,36 @@ type Partner struct {
|
|||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CreatePartnerRequest struct {
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Username string `json:"username" validate:"required"`
|
||||||
|
FullName string `json:"full_name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Password string `json:"password" validate:"required"`
|
||||||
|
NIK string `json:"nik"`
|
||||||
|
PhoneNumber string `json:"phone_number"`
|
||||||
|
BankName string `json:"bank_name"`
|
||||||
|
BankAccountNumber string `json:"bank_account_number"`
|
||||||
|
BankAccountHolderName string `json:"bank_account_holder_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *CreatePartnerRequest) ToEntity() *entity.CreatePartnerRequest {
|
||||||
|
return &entity.CreatePartnerRequest{
|
||||||
|
Name: e.Name,
|
||||||
|
Address: e.Address,
|
||||||
|
Username: e.Username,
|
||||||
|
FullName: e.FullName,
|
||||||
|
Email: e.Email,
|
||||||
|
Password: e.Password,
|
||||||
|
NIK: e.NIK,
|
||||||
|
PhoneNumber: e.PhoneNumber,
|
||||||
|
BankName: e.BankName,
|
||||||
|
BankAccountNumber: e.BankAccountNumber,
|
||||||
|
BankAccountHolderName: e.BankAccountHolderName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Partner) ToEntity() *entity.Partner {
|
func (e *Partner) ToEntity() *entity.Partner {
|
||||||
return &entity.Partner{
|
return &entity.Partner{
|
||||||
Name: e.Name,
|
Name: e.Name,
|
||||||
|
|||||||
@ -28,14 +28,15 @@ func (p *ProductParam) ToEntity() entity.ProductSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Product struct {
|
type Product struct {
|
||||||
Name string `json:"name" validate:"required"`
|
ID int64 `json:"id,omitempty"`
|
||||||
Type product.ProductType `json:"type" validate:"required"`
|
PartnerID int64 `json:"partner_id"`
|
||||||
Price float64 `json:"price" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
Status product.ProductStatus `json:"status" validate:"required"`
|
Type string `json:"type"`
|
||||||
Description string `json:"description" `
|
Price float64 `json:"price" validate:"required"`
|
||||||
Image string `json:"image" `
|
IsWeekendTicket bool `json:"is_weekend_ticket"`
|
||||||
BranchID int64 `json:"branch_id" validate:"required"`
|
IsSeasonTicket bool `json:"is_season_ticket"`
|
||||||
StockQty int64 `json:"stock_qty" `
|
Status string `json:"status"`
|
||||||
|
Description string `json:"description" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Product) ToEntity() *entity.Product {
|
func (e *Product) ToEntity() *entity.Product {
|
||||||
@ -45,8 +46,5 @@ func (e *Product) ToEntity() *entity.Product {
|
|||||||
Price: e.Price,
|
Price: e.Price,
|
||||||
Status: e.Status,
|
Status: e.Status,
|
||||||
Description: e.Description,
|
Description: e.Description,
|
||||||
Image: e.Image,
|
|
||||||
BranchID: e.BranchID,
|
|
||||||
StockQty: e.StockQty,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
75
internal/handlers/request/site.go
Normal file
75
internal/handlers/request/site.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package request
|
||||||
|
|
||||||
|
import (
|
||||||
|
"furtuna-be/internal/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Site struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
PartnerID *int64 `json:"partner_id"`
|
||||||
|
Image string `json:"image"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
LocationLink string `json:"location_link"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Highlight string `json:"highlight"`
|
||||||
|
ContactPerson string `json:"contact_person"`
|
||||||
|
TnC string `json:"tnc"`
|
||||||
|
AdditionalInfo string `json:"additional_info"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
IsSeasonTicket bool `json:"is_season_ticket"`
|
||||||
|
IsDiscountActive bool `json:"is_discount_active"`
|
||||||
|
Products []Product `json:"products"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Site) ToEntity(createdBy int64) *entity.Site {
|
||||||
|
var products []entity.Product
|
||||||
|
for _, p := range r.Products {
|
||||||
|
products = append(products, entity.Product{
|
||||||
|
ID: p.ID,
|
||||||
|
PartnerID: *r.PartnerID,
|
||||||
|
Name: p.Name,
|
||||||
|
Type: p.Type,
|
||||||
|
Price: p.Price,
|
||||||
|
IsWeekendTicket: p.IsWeekendTicket,
|
||||||
|
IsSeasonTicket: p.IsSeasonTicket,
|
||||||
|
Status: p.Status,
|
||||||
|
Description: p.Description,
|
||||||
|
CreatedBy: createdBy,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &entity.Site{
|
||||||
|
ID: r.ID,
|
||||||
|
Name: r.Name,
|
||||||
|
PartnerID: *r.PartnerID,
|
||||||
|
Image: r.Image,
|
||||||
|
Address: r.Address,
|
||||||
|
LocationLink: r.LocationLink,
|
||||||
|
Description: r.Description,
|
||||||
|
Highlight: r.Highlight,
|
||||||
|
ContactPerson: r.ContactPerson,
|
||||||
|
TnC: r.TnC,
|
||||||
|
AdditionalInfo: r.AdditionalInfo,
|
||||||
|
Status: r.Status,
|
||||||
|
IsSeasonTicket: r.IsSeasonTicket,
|
||||||
|
IsDiscountActive: r.IsDiscountActive,
|
||||||
|
Products: products,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type SiteParam struct {
|
||||||
|
Search string `form:"search"`
|
||||||
|
Name string `form:"name"`
|
||||||
|
Limit int `form:"limit,default=10"`
|
||||||
|
Offset int `form:"offset,default=0"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SiteParam) ToEntity() entity.SiteSearch {
|
||||||
|
return entity.SiteSearch{
|
||||||
|
Search: r.Search,
|
||||||
|
Name: r.Name,
|
||||||
|
Limit: r.Limit,
|
||||||
|
Offset: r.Offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,10 @@
|
|||||||
package response
|
package response
|
||||||
|
|
||||||
type LoginResponse struct {
|
type LoginResponse struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Role Role `json:"role"`
|
Role Role `json:"role"`
|
||||||
Branch *Branch `json:"branch"`
|
Partner *Partner `json:"partner"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Role struct {
|
type Role struct {
|
||||||
|
|||||||
@ -4,9 +4,9 @@ type Partner struct {
|
|||||||
ID *int64 `json:"id"`
|
ID *int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Address string `json:"address"`
|
Address string `json:"address,omitempty"`
|
||||||
CreatedAt string `json:"created_at"`
|
CreatedAt string `json:"created_at,omitempty"`
|
||||||
UpdatedAt string `json:"updated_at"`
|
UpdatedAt string `json:"updated_at,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PartnerList struct {
|
type PartnerList struct {
|
||||||
|
|||||||
@ -1,19 +1,18 @@
|
|||||||
package response
|
package response
|
||||||
|
|
||||||
import "furtuna-be/internal/constants/product"
|
|
||||||
|
|
||||||
type Product struct {
|
type Product struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
PartnerID int64 `json:"partner_id"`
|
||||||
Type product.ProductType `json:"type"`
|
SiteID int64 `json:"site_id"`
|
||||||
Price float64 `json:"price"`
|
Name string `json:"name"`
|
||||||
Status product.ProductStatus `json:"status"`
|
Type string `json:"type"`
|
||||||
Description string `json:"description" `
|
Price float64 `json:"price"`
|
||||||
Image string `json:"image" `
|
IsWeekendTicket bool `json:"is_weekend_ticket"`
|
||||||
BranchID int64 `json:"branch_id"`
|
IsSeasonTicket bool `json:"is_season_ticket"`
|
||||||
StockQty int64 `json:"stock_qty"`
|
Status string `json:"status"`
|
||||||
CreatedAt string `json:"created_at"`
|
Description string `json:"description"`
|
||||||
UpdatedAt string `json:"updated_at"`
|
CreatedAt string `json:"created_at"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductList struct {
|
type ProductList struct {
|
||||||
|
|||||||
27
internal/handlers/response/site.go
Normal file
27
internal/handlers/response/site.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package response
|
||||||
|
|
||||||
|
type Site struct {
|
||||||
|
ID *int64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
PartnerID int64 `json:"partner_id"`
|
||||||
|
Image string `json:"image"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
LocationLink string `json:"location_link"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Highlight string `json:"highlight"`
|
||||||
|
ContactPerson string `json:"contact_person"`
|
||||||
|
TnC string `json:"tnc"`
|
||||||
|
AdditionalInfo string `json:"additional_info"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
IsSeasonTicket bool `json:"is_season_ticket"`
|
||||||
|
IsDiscountActive bool `json:"is_discount_active"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SiteList struct {
|
||||||
|
Sites []Site `json:"sites"`
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
Limit int `json:"limit"`
|
||||||
|
Offset int `json:"offset"`
|
||||||
|
}
|
||||||
@ -1,16 +1,16 @@
|
|||||||
package response
|
package response
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
RoleID int64 `json:"role_id"`
|
RoleID int64 `json:"role_id"`
|
||||||
RoleName string `json:"role_name"`
|
RoleName string `json:"role_name"`
|
||||||
PartnerID *int64 `json:"partner_id"`
|
PartnerID *int64 `json:"partner_id"`
|
||||||
BranchName string `json:"partner_name"`
|
PartnerName string `json:"partner_name"`
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
CreatedAt string `json:"created_at,omitempty"`
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
UpdatedAt string `json:"updated_at,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserList struct {
|
type UserList struct {
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
@ -27,13 +26,17 @@ func (r *AuthRepository) CheckExistsUserAccount(ctx context.Context, email strin
|
|||||||
|
|
||||||
err := r.db.
|
err := r.db.
|
||||||
Table("users").
|
Table("users").
|
||||||
Select("users.*, user_roles.role_id, user_roles.partner_id, roles.role_name, partners.name as partner_name").
|
Select("users.*, user_roles.role_id, user_roles.partner_id, roles.role_name, partners.name as partner_name, partners.status as partner_status").
|
||||||
Where("users.email = ?", email).
|
Where("users.email = ?", email).
|
||||||
Joins("left join user_roles on users.id = user_roles.user_id").
|
Joins("left join user_roles on users.id = user_roles.user_id").
|
||||||
Joins("left join roles on user_roles.role_id = roles.role_id").
|
Joins("left join roles on user_roles.role_id = roles.role_id").
|
||||||
Joins("left join partners on user_roles.partner_id = partners.id").
|
Joins("left join partners on user_roles.partner_id = partners.id").
|
||||||
First(&user).Error
|
First(&user).Error
|
||||||
|
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, fmt.Errorf("user with email %s does not exist", email) // or use a custom error type
|
return nil, fmt.Errorf("user with email %s does not exist", email) // or use a custom error type
|
||||||
|
|||||||
@ -44,9 +44,9 @@ func (c *CryptoImpl) ValidateWT(tokenString string) (*jwt.Token, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *CryptoImpl) GenerateJWT(user *entity.User) (string, error) {
|
func (c *CryptoImpl) GenerateJWT(user *entity.User) (string, error) {
|
||||||
branchID := int64(0)
|
partnerID := int64(0)
|
||||||
if user.PartnerID != nil {
|
if user.PartnerID != nil {
|
||||||
branchID = *user.PartnerID
|
partnerID = *user.PartnerID
|
||||||
}
|
}
|
||||||
|
|
||||||
claims := &entity.JWTAuthClaims{
|
claims := &entity.JWTAuthClaims{
|
||||||
@ -56,11 +56,11 @@ func (c *CryptoImpl) GenerateJWT(user *entity.User) (string, error) {
|
|||||||
IssuedAt: time.Now().Unix(),
|
IssuedAt: time.Now().Unix(),
|
||||||
NotBefore: time.Now().Unix(),
|
NotBefore: time.Now().Unix(),
|
||||||
},
|
},
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
Name: user.Name,
|
Name: user.Name,
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
Role: int(user.RoleID),
|
Role: int(user.RoleID),
|
||||||
BranchID: branchID,
|
PartnerID: partnerID,
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := jwt.
|
token, err := jwt.
|
||||||
|
|||||||
@ -28,6 +28,15 @@ func (b *PartnerRepository) Create(ctx context.Context, Partner *entity.PartnerD
|
|||||||
return Partner, nil
|
return Partner, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *PartnerRepository) CreateWithTx(ctx context.Context, tx *gorm.DB, Partner *entity.PartnerDB) (*entity.PartnerDB, error) {
|
||||||
|
err := tx.Create(Partner).Error
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when create Partner", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return Partner, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *PartnerRepository) Update(ctx context.Context, Partner *entity.PartnerDB) (*entity.PartnerDB, error) {
|
func (b *PartnerRepository) Update(ctx context.Context, Partner *entity.PartnerDB) (*entity.PartnerDB, error) {
|
||||||
if err := b.db.Save(Partner).Error; err != nil {
|
if err := b.db.Save(Partner).Error; err != nil {
|
||||||
logger.ContextLogger(ctx).Error("error when update Partner", zap.Error(err))
|
logger.ContextLogger(ctx).Error("error when update Partner", zap.Error(err))
|
||||||
|
|||||||
@ -2,14 +2,17 @@ package repository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
"furtuna-be/internal/repository/branches"
|
"furtuna-be/internal/repository/branches"
|
||||||
"furtuna-be/internal/repository/orders"
|
"furtuna-be/internal/repository/orders"
|
||||||
"furtuna-be/internal/repository/oss"
|
"furtuna-be/internal/repository/oss"
|
||||||
"furtuna-be/internal/repository/partners"
|
"furtuna-be/internal/repository/partners"
|
||||||
"furtuna-be/internal/repository/products"
|
"furtuna-be/internal/repository/products"
|
||||||
|
"furtuna-be/internal/repository/sites"
|
||||||
"furtuna-be/internal/repository/studios"
|
"furtuna-be/internal/repository/studios"
|
||||||
|
"furtuna-be/internal/repository/trx"
|
||||||
"furtuna-be/internal/repository/users"
|
"furtuna-be/internal/repository/users"
|
||||||
|
repository "furtuna-be/internal/repository/wallet"
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
@ -31,6 +34,9 @@ type RepoManagerImpl struct {
|
|||||||
Order Order
|
Order Order
|
||||||
OSS OSSRepository
|
OSS OSSRepository
|
||||||
Partner PartnerRepository
|
Partner PartnerRepository
|
||||||
|
Site SiteRepository
|
||||||
|
Trx TransactionManager
|
||||||
|
Wallet WalletRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
|
func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
|
||||||
@ -45,6 +51,9 @@ func NewRepoManagerImpl(db *gorm.DB, cfg *config.Config) *RepoManagerImpl {
|
|||||||
Order: orders.NewOrderRepository(db),
|
Order: orders.NewOrderRepository(db),
|
||||||
OSS: oss.NewOssRepositoryImpl(cfg.OSSConfig),
|
OSS: oss.NewOssRepositoryImpl(cfg.OSSConfig),
|
||||||
Partner: partners.NewPartnerRepository(db),
|
Partner: partners.NewPartnerRepository(db),
|
||||||
|
Site: sites.NewSiteRepository(db),
|
||||||
|
Trx: trx.NewGormTransactionManager(db),
|
||||||
|
Wallet: repository.NewWalletRepository(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +78,7 @@ type Crypto interface {
|
|||||||
|
|
||||||
type User interface {
|
type User interface {
|
||||||
Create(ctx context.Context, user *entity.UserDB) (*entity.UserDB, error)
|
Create(ctx context.Context, user *entity.UserDB) (*entity.UserDB, error)
|
||||||
|
CreateWithTx(ctx context.Context, tx *gorm.DB, user *entity.UserDB) (*entity.UserDB, error)
|
||||||
GetAllUsers(ctx context.Context, req entity.UserSearch) (entity.UserList, int, error)
|
GetAllUsers(ctx context.Context, req entity.UserSearch) (entity.UserList, int, error)
|
||||||
GetUserByID(ctx context.Context, id int64) (*entity.UserDB, error)
|
GetUserByID(ctx context.Context, id int64) (*entity.UserDB, error)
|
||||||
GetUserByEmail(ctx context.Context, email string) (*entity.UserDB, error)
|
GetUserByEmail(ctx context.Context, email string) (*entity.UserDB, error)
|
||||||
@ -115,8 +125,28 @@ type OSSRepository interface {
|
|||||||
|
|
||||||
type PartnerRepository interface {
|
type PartnerRepository interface {
|
||||||
Create(ctx context.Context, branch *entity.PartnerDB) (*entity.PartnerDB, error)
|
Create(ctx context.Context, branch *entity.PartnerDB) (*entity.PartnerDB, error)
|
||||||
|
CreateWithTx(ctx context.Context, tx *gorm.DB, Partner *entity.PartnerDB) (*entity.PartnerDB, error)
|
||||||
Update(ctx context.Context, branch *entity.PartnerDB) (*entity.PartnerDB, error)
|
Update(ctx context.Context, branch *entity.PartnerDB) (*entity.PartnerDB, error)
|
||||||
GetByID(ctx context.Context, id int64) (*entity.PartnerDB, error)
|
GetByID(ctx context.Context, id int64) (*entity.PartnerDB, error)
|
||||||
GetAll(ctx context.Context, req entity.PartnerSearch) (entity.PartnerList, int, error)
|
GetAll(ctx context.Context, req entity.PartnerSearch) (entity.PartnerList, int, error)
|
||||||
Delete(ctx context.Context, id int64) error
|
Delete(ctx context.Context, id int64) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SiteRepository interface {
|
||||||
|
Upsert(ctx context.Context, site *entity.Site) (*entity.Site, error)
|
||||||
|
Create(ctx context.Context, branch *entity.SiteDB) (*entity.SiteDB, error)
|
||||||
|
Update(ctx context.Context, branch *entity.SiteDB) (*entity.SiteDB, error)
|
||||||
|
GetByID(ctx context.Context, id int64) (*entity.SiteDB, error)
|
||||||
|
GetAll(ctx context.Context, req entity.SiteSearch) (entity.SiteList, int, error)
|
||||||
|
Delete(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransactionManager interface {
|
||||||
|
Begin(ctx context.Context, opts ...*sql.TxOptions) (*gorm.DB, error)
|
||||||
|
Commit(session *gorm.DB) *gorm.DB
|
||||||
|
Rollback(session *gorm.DB) *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
type WalletRepository interface {
|
||||||
|
Create(ctx context.Context, tx *gorm.DB, wallet *entity.Wallet) (*entity.Wallet, error)
|
||||||
|
}
|
||||||
|
|||||||
131
internal/repository/sites/sites.go
Normal file
131
internal/repository/sites/sites.go
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
package sites
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"furtuna-be/internal/common/logger"
|
||||||
|
"furtuna-be/internal/entity"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SiteRepository struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSiteRepository(db *gorm.DB) *SiteRepository {
|
||||||
|
return &SiteRepository{
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SiteRepository) Upsert(ctx context.Context, site *entity.Site) (*entity.Site, error) {
|
||||||
|
err := r.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if site.ID != 0 {
|
||||||
|
// Update site
|
||||||
|
if err := tx.Save(site).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create new site
|
||||||
|
if err := tx.Create(site).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(site.Products) > 0 {
|
||||||
|
for i := range site.Products {
|
||||||
|
site.Products[i].SiteID = site.ID
|
||||||
|
if site.Products[i].ID != 0 {
|
||||||
|
// Update existing product
|
||||||
|
if err := tx.Save(&site.Products[i]).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create new product
|
||||||
|
if err := tx.Create(&site.Products[i]).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when upserting site", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return site, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SiteRepository) Create(ctx context.Context, site *entity.SiteDB) (*entity.SiteDB, error) {
|
||||||
|
err := r.db.Create(site).Error
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when creating site", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return site, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SiteRepository) Update(ctx context.Context, site *entity.SiteDB) (*entity.SiteDB, error) {
|
||||||
|
if err := r.db.Save(site).Error; err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when updating site", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return site, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SiteRepository) GetByID(ctx context.Context, id int64) (*entity.SiteDB, error) {
|
||||||
|
site := new(entity.SiteDB)
|
||||||
|
if err := r.db.First(site, id).Error; err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when getting site by ID", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return site, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SiteRepository) GetAll(ctx context.Context, req entity.SiteSearch) (entity.SiteList, int, error) {
|
||||||
|
var sites []*entity.SiteDB
|
||||||
|
var total int64
|
||||||
|
|
||||||
|
query := r.db
|
||||||
|
query = query.Where("deleted_at IS NULL")
|
||||||
|
|
||||||
|
if req.Search != "" {
|
||||||
|
query = query.Where("name ILIKE ?", "%"+req.Search+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Name != "" {
|
||||||
|
query = query.Where("name ILIKE ?", "%"+req.Name+"%")
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Limit > 0 {
|
||||||
|
query = query.Limit(req.Limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Offset > 0 {
|
||||||
|
query = query.Offset(req.Offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := query.Find(&sites).Error; err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when getting all sites", zap.Error(err))
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.db.Model(&entity.SiteDB{}).Where(query).Count(&total).Error; err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when counting sites", zap.Error(err))
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sites, int(total), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SiteRepository) Delete(ctx context.Context, id int64) error {
|
||||||
|
site := new(entity.SiteDB)
|
||||||
|
site.ID = id
|
||||||
|
if err := r.db.Delete(site).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
33
internal/repository/trx/trx.go
Normal file
33
internal/repository/trx/trx.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package trx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GormTransactionManager struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGormTransactionManager(db *gorm.DB) *GormTransactionManager {
|
||||||
|
return &GormTransactionManager{
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *GormTransactionManager) Begin(ctx context.Context, opts ...*sql.TxOptions) (*gorm.DB, error) {
|
||||||
|
tx := tm.db.Begin(opts...)
|
||||||
|
if tx.Error != nil {
|
||||||
|
return nil, tx.Error
|
||||||
|
}
|
||||||
|
return tx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *GormTransactionManager) Commit(tx *gorm.DB) *gorm.DB {
|
||||||
|
return tx.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *GormTransactionManager) Rollback(tx *gorm.DB) *gorm.DB {
|
||||||
|
return tx.Rollback()
|
||||||
|
}
|
||||||
@ -51,6 +51,29 @@ func (r *UserRepository) Create(ctx context.Context, user *entity.UserDB) (*enti
|
|||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *UserRepository) CreateWithTx(ctx context.Context, tx *gorm.DB, user *entity.UserDB) (*entity.UserDB, error) {
|
||||||
|
user.ID = 0
|
||||||
|
if err := tx.Select("name", "email", "password", "status", "created_by", "nik", "user_type", "phone_number").Create(user).Error; err != nil {
|
||||||
|
logError(ctx, "creating user", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.First(user, user.ID).Error; err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
logError(ctx, "retrieving user", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userRole := user.ToUserRoleDB()
|
||||||
|
if err := tx.Create(userRole).Error; err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
logError(ctx, "creating user role", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *UserRepository) GetAllUsers(ctx context.Context, req entity.UserSearch) (entity.UserList, int, error) {
|
func (b *UserRepository) GetAllUsers(ctx context.Context, req entity.UserSearch) (entity.UserList, int, error) {
|
||||||
var users []*entity.UserDB
|
var users []*entity.UserDB
|
||||||
var total int64
|
var total int64
|
||||||
|
|||||||
65
internal/repository/wallet/wallet.go
Normal file
65
internal/repository/wallet/wallet.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"furtuna-be/internal/common/logger"
|
||||||
|
"furtuna-be/internal/entity"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WalletRepository struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWalletRepository(db *gorm.DB) *WalletRepository {
|
||||||
|
return &WalletRepository{
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *WalletRepository) Create(ctx context.Context, tx *gorm.DB, wallet *entity.Wallet) (*entity.Wallet, error) {
|
||||||
|
err := tx.Create(wallet).Error
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when creating wallet", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return wallet, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *WalletRepository) Update(ctx context.Context, wallet *entity.Wallet) (*entity.Wallet, error) {
|
||||||
|
if err := r.db.Save(wallet).Error; err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when updating wallet", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return wallet, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *WalletRepository) GetByID(ctx context.Context, id int64) (*entity.Wallet, error) {
|
||||||
|
wallet := new(entity.Wallet)
|
||||||
|
if err := r.db.First(wallet, id).Error; err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when getting wallet by id", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return wallet, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *WalletRepository) GetAll(ctx context.Context) ([]*entity.Wallet, error) {
|
||||||
|
var wallets []*entity.Wallet
|
||||||
|
if err := r.db.Find(&wallets).Error; err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when getting all wallets", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return wallets, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *WalletRepository) Delete(ctx context.Context, id int64) error {
|
||||||
|
wallet := new(entity.Wallet)
|
||||||
|
wallet.ID = id
|
||||||
|
if err := r.db.Delete(wallet).Error; err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when deleting wallet", zap.Error(err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import (
|
|||||||
"furtuna-be/internal/handlers/http/oss"
|
"furtuna-be/internal/handlers/http/oss"
|
||||||
"furtuna-be/internal/handlers/http/partner"
|
"furtuna-be/internal/handlers/http/partner"
|
||||||
"furtuna-be/internal/handlers/http/product"
|
"furtuna-be/internal/handlers/http/product"
|
||||||
|
site "furtuna-be/internal/handlers/http/sites"
|
||||||
"furtuna-be/internal/handlers/http/studio"
|
"furtuna-be/internal/handlers/http/studio"
|
||||||
"furtuna-be/internal/handlers/http/user"
|
"furtuna-be/internal/handlers/http/user"
|
||||||
swaggerFiles "github.com/swaggo/files"
|
swaggerFiles "github.com/swaggo/files"
|
||||||
@ -52,6 +53,7 @@ func RegisterPrivateRoutes(app *app.Server, serviceManager *services.ServiceMana
|
|||||||
order.NewHandler(serviceManager.OrderSvc),
|
order.NewHandler(serviceManager.OrderSvc),
|
||||||
oss.NewOssHandler(serviceManager.OSSSvc),
|
oss.NewOssHandler(serviceManager.OSSSvc),
|
||||||
partner.NewHandler(serviceManager.PartnerSvc),
|
partner.NewHandler(serviceManager.PartnerSvc),
|
||||||
|
site.NewHandler(serviceManager.SiteSvc),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, handler := range serverRoutes {
|
for _, handler := range serverRoutes {
|
||||||
|
|||||||
@ -6,31 +6,68 @@ import (
|
|||||||
"furtuna-be/internal/common/mycontext"
|
"furtuna-be/internal/common/mycontext"
|
||||||
"furtuna-be/internal/entity"
|
"furtuna-be/internal/entity"
|
||||||
"furtuna-be/internal/repository"
|
"furtuna-be/internal/repository"
|
||||||
|
"furtuna-be/internal/services/users"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PartnerService struct {
|
type PartnerService struct {
|
||||||
repo repository.PartnerRepository
|
repo repository.PartnerRepository
|
||||||
|
trx repository.TransactionManager
|
||||||
|
userSvc *users.UserService
|
||||||
|
walletRepo repository.WalletRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPartnerService(repo repository.PartnerRepository) *PartnerService {
|
func NewPartnerService(repo repository.PartnerRepository,
|
||||||
|
userSvc *users.UserService, repoManager repository.TransactionManager,
|
||||||
|
walletRepo repository.WalletRepository) *PartnerService {
|
||||||
return &PartnerService{
|
return &PartnerService{
|
||||||
repo: repo,
|
repo: repo,
|
||||||
|
userSvc: userSvc,
|
||||||
|
trx: repoManager,
|
||||||
|
walletRepo: walletRepo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PartnerService) Create(ctx mycontext.Context, PartnerReq *entity.Partner) (*entity.Partner, error) {
|
func (s *PartnerService) Create(ctx mycontext.Context, partnerReq *entity.CreatePartnerRequest) (*entity.Partner, error) {
|
||||||
PartnerDB := PartnerReq.ToPartnerDB()
|
var err error
|
||||||
PartnerDB.CreatedBy = ctx.RequestedBy()
|
|
||||||
|
|
||||||
PartnerDB, err := s.repo.Create(ctx, PartnerDB)
|
tx, err := s.trx.Begin(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.ContextLogger(ctx).Error("error when create Partner", zap.Error(err))
|
logger.ContextLogger(ctx).Error("error when starting transaction", zap.Error(err))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return PartnerDB.ToPartner(), nil
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
s.trx.Rollback(tx)
|
||||||
|
panic(r)
|
||||||
|
} else if err != nil {
|
||||||
|
s.trx.Rollback(tx)
|
||||||
|
} else {
|
||||||
|
err = s.trx.Commit(tx).Error
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Create Partner
|
||||||
|
partnerDB := partnerReq.ToPartnerDB(ctx.RequestedBy())
|
||||||
|
if partnerDB, err = s.repo.CreateWithTx(ctx, tx, partnerDB); err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when creating partner", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
adminUser := partnerReq.ToUserAdmin(partnerDB.ID)
|
||||||
|
if adminUser, err = s.userSvc.CreateWithTx(ctx, tx, adminUser); err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when creating admin user", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
partnerWallet := partnerReq.ToWallet(partnerDB.ID)
|
||||||
|
if partnerWallet, err = s.walletRepo.Create(ctx, tx, partnerWallet); err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when creating wallet", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return partnerDB.ToPartner(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PartnerService) Update(ctx mycontext.Context, id int64, PartnerReq *entity.Partner) (*entity.Partner, error) {
|
func (s *PartnerService) Update(ctx mycontext.Context, id int64, PartnerReq *entity.Partner) (*entity.Partner, error) {
|
||||||
|
|||||||
@ -8,8 +8,10 @@ import (
|
|||||||
"furtuna-be/internal/services/oss"
|
"furtuna-be/internal/services/oss"
|
||||||
"furtuna-be/internal/services/partner"
|
"furtuna-be/internal/services/partner"
|
||||||
"furtuna-be/internal/services/product"
|
"furtuna-be/internal/services/product"
|
||||||
|
"furtuna-be/internal/services/sites"
|
||||||
"furtuna-be/internal/services/studio"
|
"furtuna-be/internal/services/studio"
|
||||||
"furtuna-be/internal/services/users"
|
"furtuna-be/internal/services/users"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"furtuna-be/config"
|
"furtuna-be/config"
|
||||||
"furtuna-be/internal/entity"
|
"furtuna-be/internal/entity"
|
||||||
@ -28,6 +30,7 @@ type ServiceManagerImpl struct {
|
|||||||
OrderSvc Order
|
OrderSvc Order
|
||||||
OSSSvc OSSService
|
OSSSvc OSSService
|
||||||
PartnerSvc Partner
|
PartnerSvc Partner
|
||||||
|
SiteSvc Site
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl) *ServiceManagerImpl {
|
func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl) *ServiceManagerImpl {
|
||||||
@ -40,7 +43,9 @@ func NewServiceManagerImpl(cfg *config.Config, repo *repository.RepoManagerImpl)
|
|||||||
ProductSvc: product.NewProductService(repo.Product),
|
ProductSvc: product.NewProductService(repo.Product),
|
||||||
OrderSvc: order.NewOrderService(repo.Order, repo.Product, repo.Studio),
|
OrderSvc: order.NewOrderService(repo.Order, repo.Product, repo.Studio),
|
||||||
OSSSvc: oss.NewOSSService(repo.OSS),
|
OSSSvc: oss.NewOSSService(repo.OSS),
|
||||||
PartnerSvc: partner.NewPartnerService(repo.Partner),
|
PartnerSvc: partner.NewPartnerService(
|
||||||
|
repo.Partner, users.NewUserService(repo.User, repo.Branch), repo.Trx, repo.Wallet),
|
||||||
|
SiteSvc: site.NewSiteService(repo.Site),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +63,7 @@ type Event interface {
|
|||||||
|
|
||||||
type User interface {
|
type User interface {
|
||||||
Create(ctx mycontext.Context, userReq *entity.User) (*entity.User, error)
|
Create(ctx mycontext.Context, userReq *entity.User) (*entity.User, error)
|
||||||
|
CreateWithTx(ctx mycontext.Context, tx *gorm.DB, userReq *entity.User) (*entity.User, error)
|
||||||
GetAll(ctx mycontext.Context, search entity.UserSearch) ([]*entity.User, int, error)
|
GetAll(ctx mycontext.Context, search entity.UserSearch) ([]*entity.User, int, error)
|
||||||
Update(ctx mycontext.Context, id int64, userReq *entity.User) (*entity.User, error)
|
Update(ctx mycontext.Context, id int64, userReq *entity.User) (*entity.User, error)
|
||||||
GetByID(ctx mycontext.Context, id int64) (*entity.User, error)
|
GetByID(ctx mycontext.Context, id int64) (*entity.User, error)
|
||||||
@ -102,9 +108,17 @@ type OSSService interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Partner interface {
|
type Partner interface {
|
||||||
Create(ctx mycontext.Context, branchReq *entity.Partner) (*entity.Partner, error)
|
Create(ctx mycontext.Context, branchReq *entity.CreatePartnerRequest) (*entity.Partner, error)
|
||||||
Update(ctx mycontext.Context, id int64, branchReq *entity.Partner) (*entity.Partner, error)
|
Update(ctx mycontext.Context, id int64, branchReq *entity.Partner) (*entity.Partner, error)
|
||||||
GetByID(ctx context.Context, id int64) (*entity.Partner, error)
|
GetByID(ctx context.Context, id int64) (*entity.Partner, error)
|
||||||
GetAll(ctx context.Context, search entity.PartnerSearch) ([]*entity.Partner, int, error)
|
GetAll(ctx context.Context, search entity.PartnerSearch) ([]*entity.Partner, int, error)
|
||||||
Delete(ctx mycontext.Context, id int64) error
|
Delete(ctx mycontext.Context, id int64) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Site interface {
|
||||||
|
Create(ctx mycontext.Context, branchReq *entity.Site) (*entity.Site, error)
|
||||||
|
Update(ctx mycontext.Context, id int64, branchReq *entity.Site) (*entity.Site, error)
|
||||||
|
GetByID(ctx context.Context, id int64) (*entity.Site, error)
|
||||||
|
GetAll(ctx context.Context, search entity.SiteSearch) ([]*entity.Site, int, error)
|
||||||
|
Delete(ctx mycontext.Context, id int64) error
|
||||||
|
}
|
||||||
|
|||||||
89
internal/services/sites/sites.go
Normal file
89
internal/services/sites/sites.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package site
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"furtuna-be/internal/common/logger"
|
||||||
|
"furtuna-be/internal/common/mycontext"
|
||||||
|
"furtuna-be/internal/entity"
|
||||||
|
"furtuna-be/internal/repository"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SiteService struct {
|
||||||
|
repo repository.SiteRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSiteService(repo repository.SiteRepository) *SiteService {
|
||||||
|
return &SiteService{
|
||||||
|
repo: repo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SiteService) Create(ctx mycontext.Context, siteReq *entity.Site) (*entity.Site, error) {
|
||||||
|
siteDB := siteReq
|
||||||
|
siteDB.CreatedBy = ctx.RequestedBy()
|
||||||
|
|
||||||
|
siteDB, err := s.repo.Upsert(ctx, siteDB)
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when creating site", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return siteDB, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SiteService) Update(ctx mycontext.Context, id int64, siteReq *entity.Site) (*entity.Site, error) {
|
||||||
|
existingSite, err := s.repo.GetByID(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
existingSite.ToUpdatedSite(ctx.RequestedBy(), *siteReq)
|
||||||
|
|
||||||
|
updatedSiteDB, err := s.repo.Update(ctx, existingSite.ToSiteDB())
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when updating site", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedSiteDB.ToSite(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SiteService) GetByID(ctx context.Context, id int64) (*entity.Site, error) {
|
||||||
|
siteDB, err := s.repo.GetByID(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when getting site by ID", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return siteDB.ToSite(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SiteService) GetAll(ctx context.Context, search entity.SiteSearch) ([]*entity.Site, int, error) {
|
||||||
|
sites, total, err := s.repo.GetAll(ctx, search)
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when getting all sites", zap.Error(err))
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sites.ToSiteList(), total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SiteService) Delete(ctx mycontext.Context, id int64) error {
|
||||||
|
siteDB, err := s.repo.GetByID(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when getting site by ID", zap.Error(err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
siteDB.SetDeleted(ctx.RequestedBy())
|
||||||
|
|
||||||
|
_, err = s.repo.Update(ctx, siteDB)
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when updating site", zap.Error(err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package users
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"furtuna-be/internal/common/mycontext"
|
"furtuna-be/internal/common/mycontext"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
@ -48,6 +49,31 @@ func (s *UserService) Create(ctx mycontext.Context, userReq *entity.User) (*enti
|
|||||||
return userDB.ToUser(), nil
|
return userDB.ToUser(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *UserService) CreateWithTx(ctx mycontext.Context, tx *gorm.DB, userReq *entity.User) (*entity.User, error) {
|
||||||
|
//check
|
||||||
|
userExist, err := s.repo.GetUserByEmail(ctx, userReq.Email)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if userExist != nil {
|
||||||
|
return nil, fmt.Errorf("Email already exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
userDB, err := userReq.ToUserDB(ctx.RequestedBy())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userDB, err = s.repo.CreateWithTx(ctx, tx, userDB)
|
||||||
|
if err != nil {
|
||||||
|
logger.ContextLogger(ctx).Error("error when create user", zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return userDB.ToUser(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *UserService) GetAll(ctx mycontext.Context, search entity.UserSearch) ([]*entity.User, int, error) {
|
func (s *UserService) GetAll(ctx mycontext.Context, search entity.UserSearch) ([]*entity.User, int, error) {
|
||||||
|
|
||||||
users, total, err := s.repo.GetAllUsers(ctx, search)
|
users, total, err := s.repo.GetAllUsers(ctx, search)
|
||||||
@ -82,7 +108,7 @@ func (s *UserService) Update(ctx mycontext.Context, id int64, userReq *entity.Us
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
existingUser.BranchName = branch.Name
|
existingUser.PartnerName = branch.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
err = existingUser.ToUpdatedUser(*userReq)
|
err = existingUser.ToUpdatedUser(*userReq)
|
||||||
|
|||||||
@ -3,4 +3,9 @@ CREATE TABLE roles (
|
|||||||
role_name VARCHAR(255) NOT NULL
|
role_name VARCHAR(255) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO roles(role_id, role_name) VALUES (1, 'super_admin'), (2, 'branch_admin');
|
INSERT INTO roles(role_id, role_name)
|
||||||
|
VALUES (1, 'super_admin'),
|
||||||
|
(2, 'admin'),
|
||||||
|
(3, 'admin_partner'),
|
||||||
|
(4, 'admin_site'),
|
||||||
|
(5, 'cashier');
|
||||||
|
|||||||
@ -1,12 +1,16 @@
|
|||||||
CREATE TABLE partners
|
CREATE TABLE partners
|
||||||
(
|
(
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
name VARCHAR(255) NOT NULL,
|
name VARCHAR(255) NOT NULL,
|
||||||
status varchar,
|
status VARCHAR(50),
|
||||||
Address varchar,
|
license_expired_date DATE,
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
address VARCHAR(255),
|
||||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
bank_name VARCHAR(255),
|
||||||
created_by INTEGER,
|
bank_account_number VARCHAR(50),
|
||||||
updated_by INTEGER,
|
bank_account_holder_name VARCHAR(255),
|
||||||
deleted_at timestamp
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
created_by INTEGER,
|
||||||
|
updated_by INTEGER,
|
||||||
|
deleted_at TIMESTAMP
|
||||||
);
|
);
|
||||||
@ -1,15 +1,18 @@
|
|||||||
CREATE TABLE products
|
CREATE TABLE products
|
||||||
(
|
(
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
site_id INTEGER,
|
partner_id INTEGER,
|
||||||
name VARCHAR(255) NOT NULL,
|
site_id INTEGER,
|
||||||
type VARCHAR,
|
name VARCHAR(255) NOT NULL,
|
||||||
prices INTEGER[],
|
type VARCHAR,
|
||||||
status VARCHAR,
|
price decimal,
|
||||||
description VARCHAR(255) NOT NULL,
|
is_weekend_ticket boolean,
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
is_season_ticket boolean,
|
||||||
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
status VARCHAR,
|
||||||
deleted_at TIMESTAMP,
|
description VARCHAR(255) NOT NULL,
|
||||||
created_by INTEGER,
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
updated_by INTEGER
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
deleted_at TIMESTAMP,
|
||||||
|
created_by INTEGER,
|
||||||
|
updated_by INTEGER
|
||||||
);
|
);
|
||||||
0
migrations/000009_add_wallet.down.sql
Normal file
0
migrations/000009_add_wallet.down.sql
Normal file
11
migrations/000009_add_wallet.up.sql
Normal file
11
migrations/000009_add_wallet.up.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
CREATE TABLE public.wallets
|
||||||
|
(
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
partner_id INTEGER NOT NULL,
|
||||||
|
balance DECIMAL(18, 2) NOT NULL DEFAULT 0.00,
|
||||||
|
currency VARCHAR(3) NOT NULL,
|
||||||
|
status VARCHAR(50),
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
FOREIGN KEY (partner_id) REFERENCES partners (id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
Loading…
x
Reference in New Issue
Block a user