wip
This commit is contained in:
@@ -1,13 +1,54 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"GoMembership/pkg/logger"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Insurance struct {
|
||||
ID uint `gorm:"primary_key" json:"id"`
|
||||
OwnerID uint `gorm:"not null" json:"owner_id" binding:"numeric"`
|
||||
Cars []Car `gorm:"many2many:car_insurances;" json:"-"`
|
||||
Company string `json:"company" binding:"safe_content"`
|
||||
Reference string `json:"reference" binding:"safe_content"`
|
||||
Notes string `json:"notes" binding:"safe_content"`
|
||||
StartDate time.Time `json:"start_date"`
|
||||
EndDate time.Time `json:"end_date"`
|
||||
}
|
||||
|
||||
func (i *Insurance) Create(db *gorm.DB) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// Create the base User record (omit associations to handle them separately)
|
||||
if err := tx.Create(i).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Info.Printf("Insurance created: %#v", i)
|
||||
// Preload all associations to return the fully populated User
|
||||
return tx.
|
||||
First(i, i.ID).Error // Refresh the user object with all associations
|
||||
})
|
||||
}
|
||||
|
||||
func (i *Insurance) Update(db *gorm.DB) error {
|
||||
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// Check if the user exists in the database
|
||||
var existingInsurance Insurance
|
||||
|
||||
logger.Info.Printf("updating Insurance: %#v", i)
|
||||
if err := tx.First(&existingInsurance, i.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Model(&existingInsurance).Updates(i).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.First(i, i.ID).Error
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (i *Insurance) Delete(db *gorm.DB) error {
|
||||
return db.Delete(&i).Error
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"GoMembership/internal/config"
|
||||
"GoMembership/pkg/logger"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@@ -48,3 +50,10 @@ func (b *BankAccount) Update(db *gorm.DB) error {
|
||||
func (b *BankAccount) Delete(db *gorm.DB) error {
|
||||
return db.Delete(&b).Error
|
||||
}
|
||||
|
||||
func (b *BankAccount) GenerateMandateReference(id uint) string {
|
||||
if b.IBAN == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s-%s%d-%s", config.Company.SepaPrefix, time.Now().Format("20060102"), id, b.IBAN[len(b.IBAN)-4:])
|
||||
}
|
||||
|
||||
@@ -1,123 +1,151 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"GoMembership/pkg/errors"
|
||||
"GoMembership/pkg/logger"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
type Car struct {
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt *time.Time
|
||||
Status uint `json:"status"`
|
||||
Name string `json:"name"`
|
||||
Brand string `gorm:"not null" json:"brand"`
|
||||
Model string `gorm:"not null" json:"model"`
|
||||
Color string `gorm:"not null" json:"color"`
|
||||
LicencePlate string `gorm:"not null,unique" json:"licence_plate"`
|
||||
Price float32 `json:"price"`
|
||||
Rate float32 `json:"rate"`
|
||||
StartDate time.Time `json:"start_date"`
|
||||
EndDate time.Time `json:"end_date"`
|
||||
Location Location `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"location"`
|
||||
LocationID uint
|
||||
Damages *[]Damage `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"damages"`
|
||||
Insurances *[]Insurance `gorm:"foreignkey:OwnerID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"insurance"`
|
||||
Notes string `json:"notes"`
|
||||
}
|
||||
|
||||
type Location struct {
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt *time.Time
|
||||
Latitude float32 `json:"latitude"`
|
||||
Longitude float32 `json:"longitude"`
|
||||
}
|
||||
|
||||
type Damage struct {
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
CarID uint `json:"car_id"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt *time.Time
|
||||
Opponent *User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"opponent"`
|
||||
OpponentID uint
|
||||
Insurance *Insurance `gorm:"foreignkey:OwnerID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"insurance"`
|
||||
InsuranceID uint
|
||||
Notes string `json:"notes"`
|
||||
Status uint `json:"status"`
|
||||
Name string `json:"name"`
|
||||
Brand string `gorm:"not null" json:"brand"`
|
||||
Model string `gorm:"not null" json:"model"`
|
||||
Color string `gorm:"not null" json:"color"`
|
||||
LicencePlate string `gorm:"not null,unique" json:"licence_plate"`
|
||||
Price float32 `gorm:"type:decimal(10,2)" json:"price"`
|
||||
Rate float32 `gorm:"type:decimal(10,2)" json:"rate"`
|
||||
StartDate time.Time `json:"start_date"`
|
||||
EndDate time.Time `json:"end_date"`
|
||||
Location *Location `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"location"`
|
||||
Damages []Damage `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"damages"`
|
||||
Insurances []Insurance `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;many2many:car_insurances" json:"insurances"`
|
||||
Notes string `json:"notes"`
|
||||
}
|
||||
|
||||
func (c *Car) Create(db *gorm.DB) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// Create the base User record (omit associations to handle them separately)
|
||||
if err := tx.Create(c).Error; err != nil {
|
||||
if err := tx.Preload(clause.Associations).Create(c).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Replace associated Categories (assumes Categories already exist)
|
||||
if c.Insurances != nil {
|
||||
if err := tx.Model(c).Association("Insurances").Replace(c.Insurances); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
logger.Info.Printf("car created: %#v", c)
|
||||
// Preload all associations to return the fully populated User
|
||||
return tx.
|
||||
Preload("Insurances").
|
||||
First(c, c.ID).Error // Refresh the user object with all associations
|
||||
Preload(clause.Associations).
|
||||
First(c, c.ID).Error
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Car) Update(db *gorm.DB) error {
|
||||
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// Check if the user exists in the database
|
||||
var existingCar Car
|
||||
|
||||
logger.Info.Printf("updating car: %#v", c)
|
||||
if err := tx.
|
||||
Preload("Insurances").
|
||||
if err := tx.Preload("Damages.Insurance").
|
||||
Preload("Damages.Opponent").
|
||||
First(&existingCar, c.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
result := tx.Session(&gorm.Session{FullSaveAssociations: true}).Updates(c)
|
||||
if result.Error != nil {
|
||||
logger.Error.Printf("car update error: %#v", result.Error)
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return errors.ErrNoRowsAffected
|
||||
}
|
||||
|
||||
if c.Insurances != nil {
|
||||
if err := tx.Save(*c.Insurances).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Session(&gorm.Session{FullSaveAssociations: true}).Updates(c).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
// if err := tx.Model(c).Association("Damages").Replace(c.Damages); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// if err := tx.Model(c).Association("Insurances").Replace(c.Insurances); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// Calculate damage IDs to delete
|
||||
// existingDamageIDs := make(map[uint]bool)
|
||||
// for _, d := range existingCar.Damages {
|
||||
// existingDamageIDs[d.ID] = true
|
||||
// }
|
||||
|
||||
// newDamageIDs := make(map[uint]bool)
|
||||
// for _, d := range c.Damages {
|
||||
// if d.ID != 0 {
|
||||
// newDamageIDs[d.ID] = true
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Find IDs to delete
|
||||
// var toDelete []uint
|
||||
// for id := range existingDamageIDs {
|
||||
// if !newDamageIDs[id] {
|
||||
// toDelete = append(toDelete, id)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Batch delete orphaned damages
|
||||
// if len(toDelete) > 0 {
|
||||
// if err := tx.Where("id IN ?", toDelete).Delete(&Damage{}).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// if len(c.Insurances) > 0 {
|
||||
// logger.Info.Printf("updating insurances: %#v", c.Insurances)
|
||||
// if err := tx.Model(&existingCar).Association("Insurances").Replace(c.Insurances); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Upsert new damages
|
||||
// for _, damage := range c.Damages {
|
||||
// // Process relationships
|
||||
// if damage.Opponent != nil {
|
||||
// if err := tx.Save(damage.Opponent).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// damage.OpponentID = damage.Opponent.ID
|
||||
// }
|
||||
|
||||
// if damage.Insurance != nil {
|
||||
// if err := tx.Save(damage.Insurance).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// damage.InsuranceID = damage.Insurance.ID
|
||||
// }
|
||||
|
||||
// // Create or update damage
|
||||
// if err := tx.Save(damage).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Update associations
|
||||
// if err := tx.Model(&existingCar).Association("Damages").Replace(c.Damages); err != nil {
|
||||
// return err
|
||||
// }
|
||||
return tx.
|
||||
Preload(clause.Associations).
|
||||
Preload("Damages").
|
||||
Preload("Insurances").
|
||||
First(c, c.ID).Error
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return db.
|
||||
Preload("Insurances").
|
||||
First(&c, c.ID).Error
|
||||
}
|
||||
|
||||
func (c *Car) Delete(db *gorm.DB) error {
|
||||
return db.Delete(&c).Error
|
||||
return db.Select(clause.Associations).Delete(&c).Error
|
||||
}
|
||||
|
||||
func GetAllCars(db *gorm.DB) ([]Car, error) {
|
||||
var cars []Car
|
||||
if err := db.Find(&cars).Error; err != nil {
|
||||
if err := db.
|
||||
Preload(clause.Associations).
|
||||
Preload("Damages").
|
||||
Preload("Insurances").
|
||||
Find(&cars).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cars, nil
|
||||
@@ -125,7 +153,11 @@ func GetAllCars(db *gorm.DB) ([]Car, error) {
|
||||
|
||||
func (c *Car) FromID(db *gorm.DB, id uint) error {
|
||||
var car Car
|
||||
if err := db.Preload("Insurances").First(&car, id).Error; err != nil {
|
||||
if err := db.
|
||||
Preload(clause.Associations).
|
||||
Preload("Damages").
|
||||
Preload("Insurances").
|
||||
First(&car, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
*c = car
|
||||
|
||||
58
go-backend/internal/models/damage.go
Normal file
58
go-backend/internal/models/damage.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"GoMembership/pkg/logger"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Damage struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
CarID uint `json:"car_id"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt *time.Time
|
||||
Name string `json:"name"`
|
||||
Date time.Time `json:"date"`
|
||||
Opponent *User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"opponent"`
|
||||
OpponentID uint `json:"opponent_id"`
|
||||
Driver *User `json:"driver"`
|
||||
DriverID uint `json:"driver_id"`
|
||||
Insurance *Insurance `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"insurance"`
|
||||
InsuranceID uint `json:"insurance_id"`
|
||||
Notes string `json:"notes"`
|
||||
}
|
||||
|
||||
func (d *Damage) Create(db *gorm.DB) error {
|
||||
// Create the base User record (omit associations to handle them separately)
|
||||
if err := db.Create(d).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Info.Printf("Damage created: %#v", d)
|
||||
// Preload all associations to return the fully populated User
|
||||
return db.First(d, d.ID).Error // Refresh the user object with all associations
|
||||
}
|
||||
|
||||
func (d *Damage) Update(db *gorm.DB) error {
|
||||
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// Check if the user exists in the database
|
||||
var existingDamage Damage
|
||||
|
||||
logger.Info.Printf("updating Damage: %#v", d)
|
||||
if err := tx.First(&existingDamage, d.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Model(&existingDamage).Updates(d).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.First(d, d.ID).Error
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (d *Damage) Delete(db *gorm.DB) error {
|
||||
return db.Delete(&d).Error
|
||||
}
|
||||
54
go-backend/internal/models/location.go
Normal file
54
go-backend/internal/models/location.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"GoMembership/pkg/logger"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Location struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt *time.Time
|
||||
CarID uint `gorm:"index" json:"car_id"`
|
||||
Latitude float32 `json:"latitude"`
|
||||
Longitude float32 `json:"longitude"`
|
||||
}
|
||||
|
||||
func (l *Location) Create(db *gorm.DB) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// Create the base User record (omit associations to handle them separately)
|
||||
if err := tx.Create(l).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Info.Printf("Location created: %#v", l)
|
||||
// Preload all associations to return the fully populated User
|
||||
return tx.
|
||||
First(l, l.ID).Error // Refresh the user object with all associations
|
||||
})
|
||||
}
|
||||
|
||||
func (l *Location) Update(db *gorm.DB) error {
|
||||
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// Check if the user exists in the database
|
||||
var existingLocation Location
|
||||
|
||||
logger.Info.Printf("updating Location: %#v", l)
|
||||
if err := tx.First(&existingLocation, l.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Model(&existingLocation).Updates(l).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.First(l, l.ID).Error
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (l *Location) Delete(db *gorm.DB) error {
|
||||
return db.Delete(&l).Error
|
||||
}
|
||||
@@ -8,20 +8,20 @@ import (
|
||||
)
|
||||
|
||||
type Membership struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
UserID uint `gorm:"index" json:"user_id"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
StartDate time.Time `json:"start_date"`
|
||||
EndDate time.Time `json:"end_date"`
|
||||
Status int8 `json:"status" binding:"number,safe_content"`
|
||||
SubscriptionModel SubscriptionModel `gorm:"foreignKey:SubscriptionModelID" json:"subscription"`
|
||||
SubscriptionModelID uint `json:"subsription_model_id"`
|
||||
ParentMembershipID uint `json:"parent_member_id" binding:"omitempty,omitnil,number"`
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
UserID uint `gorm:"index" json:"user_id"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
StartDate time.Time `json:"start_date"`
|
||||
EndDate time.Time `json:"end_date"`
|
||||
Status int8 `json:"status" binding:"number,safe_content"`
|
||||
Subscription Subscription `gorm:"foreignKey:SubscriptionID" json:"subscription"`
|
||||
SubscriptionID uint `json:"subscription_id"`
|
||||
ParentMembershipID uint `json:"parent_member_id" binding:"omitempty,omitnil,number"`
|
||||
}
|
||||
|
||||
func (m *Membership) BeforeSave(tx *gorm.DB) error {
|
||||
m.SubscriptionModelID = m.SubscriptionModel.ID
|
||||
m.SubscriptionID = m.Subscription.ID
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func (m *Membership) Create(db *gorm.DB) error {
|
||||
}
|
||||
logger.Info.Printf("Membership created: %#v", m)
|
||||
|
||||
return db.Preload("SubscriptionModel").First(m, m.ID).Error // Refresh the user object with SubscriptionModel
|
||||
return db.Preload("Subscription").First(m, m.ID).Error // Refresh the user object with Subscription
|
||||
}
|
||||
|
||||
func (m *Membership) Update(db *gorm.DB) error {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type SubscriptionModel struct {
|
||||
type Subscription struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
@@ -21,31 +21,31 @@ type SubscriptionModel struct {
|
||||
IncludedPerMonth int16 `json:"included_hours_per_month"`
|
||||
}
|
||||
|
||||
func (s *SubscriptionModel) Create(db *gorm.DB) error {
|
||||
func (s *Subscription) Create(db *gorm.DB) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// Create the base User record (omit associations to handle them separately)
|
||||
if err := tx.Create(s).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Info.Printf("SubscriptionModel created: %#v", s)
|
||||
logger.Info.Printf("Subscription created: %#v", s)
|
||||
// Preload all associations to retuvn the fully populated User
|
||||
return tx.
|
||||
First(s, s.ID).Error // Refresh the user object with all associations
|
||||
})
|
||||
}
|
||||
|
||||
func (s *SubscriptionModel) Update(db *gorm.DB) error {
|
||||
func (s *Subscription) Update(db *gorm.DB) error {
|
||||
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// Check if the user exists in the database
|
||||
var existingSubscriptionModel SubscriptionModel
|
||||
var existingSubscription Subscription
|
||||
|
||||
logger.Info.Printf("updating SubscriptionModel: %#v", s)
|
||||
if err := tx.First(&existingSubscriptionModel, s.ID).Error; err != nil {
|
||||
logger.Info.Printf("updating Subscription: %#v", s)
|
||||
if err := tx.First(&existingSubscription, s.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Model(&existingSubscriptionModel).Updates(s).Error; err != nil {
|
||||
if err := tx.Model(&existingSubscription).Updates(s).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.First(s, s.ID).Error
|
||||
@@ -53,6 +53,6 @@ func (s *SubscriptionModel) Update(db *gorm.DB) error {
|
||||
|
||||
}
|
||||
|
||||
func (s *SubscriptionModel) Delete(db *gorm.DB) error {
|
||||
func (s *Subscription) Delete(db *gorm.DB) error {
|
||||
return db.Delete(&s).Error
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package models
|
||||
import (
|
||||
"GoMembership/internal/config"
|
||||
"GoMembership/internal/constants"
|
||||
"GoMembership/internal/utils"
|
||||
"GoMembership/pkg/errors"
|
||||
"GoMembership/pkg/logger"
|
||||
"fmt"
|
||||
@@ -45,7 +44,7 @@ type User struct {
|
||||
|
||||
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
|
||||
if u.BankAccount != nil && u.BankAccount.MandateReference == "" {
|
||||
u.BankAccount.MandateReference = u.GenerateMandateReference()
|
||||
u.BankAccount.MandateReference = u.BankAccount.GenerateMandateReference(u.ID)
|
||||
u.BankAccount.Update(tx)
|
||||
}
|
||||
return nil
|
||||
@@ -53,38 +52,16 @@ func (u *User) AfterCreate(tx *gorm.DB) (err error) {
|
||||
|
||||
func (u *User) BeforeSave(tx *gorm.DB) (err error) {
|
||||
u.Email = strings.ToLower(u.Email)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) GenerateMandateReference() string {
|
||||
return fmt.Sprintf("%s%d%s", time.Now().Format("20060102"), u.ID, u.BankAccount.IBAN)
|
||||
}
|
||||
|
||||
func (u *User) SetPassword(plaintextPassword string) error {
|
||||
if plaintextPassword == "" {
|
||||
return nil
|
||||
if u.Password != "" {
|
||||
hash, err := argon2id.CreateHash(u.Password, argon2id.DefaultParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.Password = hash
|
||||
}
|
||||
|
||||
hash, err := argon2id.CreateHash(plaintextPassword, argon2id.DefaultParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.Password = hash
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) PasswordMatches(plaintextPassword string) (bool, error) {
|
||||
return argon2id.ComparePasswordAndHash(plaintextPassword, u.Password)
|
||||
}
|
||||
|
||||
func (u *User) PasswordExists() bool {
|
||||
return u.Password != ""
|
||||
}
|
||||
|
||||
func (u *User) Delete(db *gorm.DB) error {
|
||||
return db.Delete(&User{}, "id = ?", u.ID).Error
|
||||
}
|
||||
|
||||
func (u *User) Create(db *gorm.DB) error {
|
||||
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
@@ -96,118 +73,6 @@ func (u *User) Create(db *gorm.DB) error {
|
||||
})
|
||||
}
|
||||
|
||||
// return db.Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
// // Initialize slices/pointers if nil
|
||||
// if u.Verifications == nil {
|
||||
// u.Verifications = &[]Verification{}
|
||||
// }
|
||||
|
||||
// // Create base user first
|
||||
// if err := tx.Omit(clause.Associations).Create(u).Error; err != nil {
|
||||
// return fmt.Errorf("failed to create user: %w", err)
|
||||
// }
|
||||
|
||||
// // Handle BankAccount
|
||||
// if u.BankAccount != (BankAccount{}) {
|
||||
// u.BankAccount.MandateReference = u.GenerateMandateReference()
|
||||
// if err := tx.Create(&u.BankAccount).Error; err != nil {
|
||||
// return fmt.Errorf("failed to create bank account: %w", err)
|
||||
// }
|
||||
// if err := tx.Model(u).Update("bank_account_id", u.BankAccount.ID).Error; err != nil {
|
||||
// return fmt.Errorf("failed to link bank account: %w", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Handle Membership and SubscriptionModel
|
||||
// if u.Membership != (Membership{}) {
|
||||
// if err := tx.Create(&u.Membership).Error; err != nil {
|
||||
// return fmt.Errorf("failed to create membership: %w", err)
|
||||
// }
|
||||
// if err := tx.Model(u).Update("membership_id", u.Membership.ID).Error; err != nil {
|
||||
// return fmt.Errorf("failed to link membership: %w", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Handle Licence and Categories
|
||||
// if u.Licence != nil {
|
||||
// u.Licence.UserID = u.ID
|
||||
// if err := tx.Create(u.Licence).Error; err != nil {
|
||||
// return fmt.Errorf("failed to create licence: %w", err)
|
||||
// }
|
||||
|
||||
// if len(u.Licence.Categories) > 0 {
|
||||
// if err := tx.Model(u.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
|
||||
// return fmt.Errorf("failed to link categories: %w", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// if err := tx.Model(u).Update("licence_id", u.Licence.ID).Error; err != nil {
|
||||
// return fmt.Errorf("failed to link licence: %w", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Handle Consents
|
||||
// for i := range u.Consents {
|
||||
// u.Consents[i].UserID = u.ID
|
||||
// }
|
||||
// if len(u.Consents) > 0 {
|
||||
// if err := tx.Create(&u.Consents).Error; err != nil {
|
||||
// return fmt.Errorf("failed to create consents: %w", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Handle Verifications
|
||||
// for i := range *u.Verifications {
|
||||
// (*u.Verifications)[i].UserID = u.ID
|
||||
// }
|
||||
// if len(*u.Verifications) > 0 {
|
||||
// if err := tx.Create(u.Verifications).Error; err != nil {
|
||||
// return fmt.Errorf("failed to create verifications: %w", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Reload the complete user with all associations
|
||||
// return tx.Preload(clause.Associations).
|
||||
// Preload("Membership.SubscriptionModel").
|
||||
// Preload("Licence.Categories").
|
||||
// First(u, u.ID).Error
|
||||
// })
|
||||
// }
|
||||
|
||||
// func (u *User) Create(db *gorm.DB) error {
|
||||
// return db.Transaction(func(tx *gorm.DB) error {
|
||||
// // Create the base User record (omit associations to handle them separately)
|
||||
// if err := tx.Create(u).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// for i := range u.Consents {
|
||||
// u.Consents[i].UserID = u.ID
|
||||
// }
|
||||
|
||||
// for i := range *u.Verifications {
|
||||
// (*u.Verifications)[i].UserID = u.ID
|
||||
// }
|
||||
|
||||
// if err := tx.Session(&gorm.Session{FullSaveAssociations: true}).Updates(u).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// // Replace associated Categories (assumes Categories already exist)
|
||||
// if u.Licence != nil && len(u.Licence.Categories) > 0 {
|
||||
// if err := tx.Model(u.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// logger.Info.Printf("user created: %#v", u.Safe())
|
||||
// // Preload all associations to return the fully populated User
|
||||
// return tx.
|
||||
// Preload(clause.Associations).
|
||||
// Preload("Membership.SubscriptionModel").
|
||||
// Preload("Licence.Categories").
|
||||
// First(u, u.ID).Error // Refresh the user object with all associations
|
||||
// })
|
||||
// }
|
||||
|
||||
func (u *User) Update(db *gorm.DB) error {
|
||||
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
@@ -220,7 +85,7 @@ func (u *User) Update(db *gorm.DB) error {
|
||||
return err
|
||||
}
|
||||
// Update the user's main fields
|
||||
result := tx.Session(&gorm.Session{FullSaveAssociations: true}).Omit("Password", "Verifications", "Licence.Categories").Updates(u)
|
||||
result := tx.Session(&gorm.Session{FullSaveAssociations: true}).Omit("Verifications", "Licence.Categories").Updates(u)
|
||||
if result.Error != nil {
|
||||
logger.Error.Printf("User update error in update user: %#v", result.Error)
|
||||
return result.Error
|
||||
@@ -229,57 +94,6 @@ func (u *User) Update(db *gorm.DB) error {
|
||||
return errors.ErrNoRowsAffected
|
||||
}
|
||||
|
||||
if u.Password != "" {
|
||||
if err := tx.Model(&existingUser).
|
||||
Update("Password", u.Password).Error; err != nil {
|
||||
logger.Error.Printf("Password update error in update user: %#v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// // Update the Membership if provided
|
||||
// if u.Membership.ID != 0 {
|
||||
// if err := tx.Model(&existingUser.Membership).Updates(u.Membership).Where("id = ?", existingUser.Membership.ID).Error; err != nil {
|
||||
// logger.Error.Printf("Membership update error in update user: %#v", err)
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// if u.Licence != nil {
|
||||
// u.Licence.UserID = existingUser.ID
|
||||
|
||||
// if err := tx.Save(u.Licence).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// if err := tx.Model(&existingUser).Update("LicenceID", u.Licence.ID).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// if err := tx.Model(u.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// if u.Licence != nil {
|
||||
// if existingUser.Licence == nil || existingUser.LicenceID == 0 {
|
||||
// u.Licence.UserID = existingUser.ID // Ensure Licence belongs to User
|
||||
// if err := tx.Create(u.Licence).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// existingUser.Licence = u.Licence
|
||||
// existingUser.LicenceID = u.Licence.ID
|
||||
// if err := tx.Model(&existingUser).Update("LicenceID", u.Licence.ID).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// if err := tx.Model(existingUser.Licence).Updates(u.Licence).Error; err != nil {
|
||||
// return err
|
||||
// }
|
||||
// // Update Categories association
|
||||
// if err := tx.Model(existingUser.Licence).Association("Categories").Replace(u.Licence.Categories); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
if u.Verifications != nil {
|
||||
if err := tx.Save(u.Verifications).Error; err != nil {
|
||||
return err
|
||||
@@ -300,16 +114,20 @@ func (u *User) Update(db *gorm.DB) error {
|
||||
|
||||
return db.
|
||||
Preload(clause.Associations).
|
||||
Preload("Membership.SubscriptionModel").
|
||||
Preload("Membership.Subscription").
|
||||
Preload("Licence.Categories").
|
||||
First(&u, u.ID).Error
|
||||
}
|
||||
|
||||
func (u *User) Delete(db *gorm.DB) error {
|
||||
return db.Delete(&User{}, "id = ?", u.ID).Error
|
||||
}
|
||||
|
||||
func (u *User) FromID(db *gorm.DB, userID *uint) error {
|
||||
var user User
|
||||
result := db.
|
||||
Preload(clause.Associations).
|
||||
Preload("Membership.SubscriptionModel").
|
||||
Preload("Membership.Subscription").
|
||||
Preload("Licence.Categories").
|
||||
First(&user, userID)
|
||||
if result.Error != nil {
|
||||
@@ -326,7 +144,7 @@ func (u *User) FromEmail(db *gorm.DB, email *string) error {
|
||||
var user User
|
||||
result := db.
|
||||
Preload(clause.Associations).
|
||||
Preload("Membership.SubscriptionModel").
|
||||
Preload("Membership.Subscription").
|
||||
Preload("Licence.Categories").
|
||||
Where("email = ?", email).First(&user)
|
||||
if result.Error != nil {
|
||||
@@ -354,6 +172,14 @@ func (u *User) FromContext(db *gorm.DB, c *gin.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) PasswordMatches(plaintextPassword string) (bool, error) {
|
||||
return argon2id.ComparePasswordAndHash(plaintextPassword, u.Password)
|
||||
}
|
||||
|
||||
func (u *User) PasswordExists() bool {
|
||||
return u.Password != ""
|
||||
}
|
||||
|
||||
func (u *User) IsVerified() bool {
|
||||
return u.Status > constants.DisabledStatus
|
||||
}
|
||||
@@ -378,24 +204,20 @@ func (u *User) SetVerification(verificationType string) (*Verification, error) {
|
||||
if u.Verifications == nil {
|
||||
u.Verifications = []Verification{}
|
||||
}
|
||||
token, err := utils.GenerateVerificationToken()
|
||||
v, err := CreateVerification(verificationType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v := Verification{
|
||||
UserID: u.ID,
|
||||
VerificationToken: token,
|
||||
Type: verificationType,
|
||||
}
|
||||
v.UserID = u.ID
|
||||
if vi := slices.IndexFunc(u.Verifications, func(vsl Verification) bool { return vsl.Type == v.Type }); vi > -1 {
|
||||
u.Verifications[vi] = v
|
||||
u.Verifications[vi] = *v
|
||||
} else {
|
||||
u.Verifications = append(u.Verifications, v)
|
||||
u.Verifications = append(u.Verifications, *v)
|
||||
}
|
||||
return &v, nil
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (u *User) GetVerification(verificationType string) (*Verification, error) {
|
||||
func (u *User) FindVerification(verificationType string) (*Verification, error) {
|
||||
if u.Verifications == nil {
|
||||
return nil, errors.ErrNoData
|
||||
}
|
||||
@@ -406,10 +228,10 @@ func (u *User) GetVerification(verificationType string) (*Verification, error) {
|
||||
return &u.Verifications[vi], nil
|
||||
}
|
||||
|
||||
func (u *User) Verify(token string, verificationType string) bool {
|
||||
func (u *User) Verify(token string, verificationType string) error {
|
||||
if token == "" || verificationType == "" {
|
||||
logger.Error.Printf("token or verification type are empty in user.Verify")
|
||||
return false
|
||||
return errors.ErrNoData
|
||||
}
|
||||
|
||||
vi := slices.IndexFunc(u.Verifications, func(vsl Verification) bool {
|
||||
@@ -418,17 +240,9 @@ func (u *User) Verify(token string, verificationType string) bool {
|
||||
|
||||
if vi == -1 {
|
||||
logger.Error.Printf("Couldn't find verification in users verifications")
|
||||
return false
|
||||
return errors.ErrNotFound
|
||||
}
|
||||
|
||||
if u.Verifications[vi].VerifiedAt != nil {
|
||||
logger.Error.Printf("VerifiedAt is not nil, already verified?: %#v", u.Verifications[vi])
|
||||
return false
|
||||
}
|
||||
|
||||
t := time.Now()
|
||||
u.Verifications[vi].VerifiedAt = &t
|
||||
return true
|
||||
return u.Verifications[vi].Validate()
|
||||
}
|
||||
|
||||
func (u *User) Safe() map[string]interface{} {
|
||||
@@ -442,14 +256,14 @@ func (u *User) Safe() map[string]interface{} {
|
||||
"end_date": u.Membership.EndDate,
|
||||
"status": u.Membership.Status,
|
||||
"subscription": map[string]interface{}{
|
||||
"id": u.Membership.SubscriptionModel.ID,
|
||||
"name": u.Membership.SubscriptionModel.Name,
|
||||
"details": u.Membership.SubscriptionModel.Details,
|
||||
"conditions": u.Membership.SubscriptionModel.Conditions,
|
||||
"monthly_fee": u.Membership.SubscriptionModel.MonthlyFee,
|
||||
"hourly_rate": u.Membership.SubscriptionModel.HourlyRate,
|
||||
"included_per_year": u.Membership.SubscriptionModel.IncludedPerYear,
|
||||
"included_per_month": u.Membership.SubscriptionModel.IncludedPerMonth,
|
||||
"id": u.Membership.Subscription.ID,
|
||||
"name": u.Membership.Subscription.Name,
|
||||
"details": u.Membership.Subscription.Details,
|
||||
"conditions": u.Membership.Subscription.Conditions,
|
||||
"monthly_fee": u.Membership.Subscription.MonthlyFee,
|
||||
"hourly_rate": u.Membership.Subscription.HourlyRate,
|
||||
"included_per_year": u.Membership.Subscription.IncludedPerYear,
|
||||
"included_per_month": u.Membership.Subscription.IncludedPerMonth,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -543,7 +357,7 @@ func GetUsersWhere(db *gorm.DB, where map[string]interface{}) (*[]User, error) {
|
||||
var users []User
|
||||
result := db.
|
||||
Preload(clause.Associations).
|
||||
Preload("Membership.SubscriptionModel").
|
||||
Preload("Membership.Subscription").
|
||||
Preload("Licence.Categories").
|
||||
Where(where).Find(&users)
|
||||
if result.Error != nil {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"GoMembership/internal/utils"
|
||||
"GoMembership/pkg/errors"
|
||||
"GoMembership/pkg/logger"
|
||||
"time"
|
||||
|
||||
@@ -46,3 +48,31 @@ func (v *Verification) Update(db *gorm.DB) error {
|
||||
func (v *Verification) Delete(db *gorm.DB) error {
|
||||
return db.Delete(&v).Error
|
||||
}
|
||||
|
||||
func (v *Verification) Validate() error {
|
||||
if v.VerifiedAt != nil {
|
||||
return errors.ErrAlreadyVerified
|
||||
}
|
||||
|
||||
t := time.Now()
|
||||
v.VerifiedAt = &t
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateVerification(verificationType string) (*Verification, error) {
|
||||
token, err := GenerateVerificationToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v := Verification{
|
||||
UserID: 0,
|
||||
VerificationToken: token,
|
||||
Type: verificationType,
|
||||
}
|
||||
|
||||
return &v, nil
|
||||
}
|
||||
|
||||
func GenerateVerificationToken() (string, error) {
|
||||
return utils.GenerateRandomString(32)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user