package db import ( "errors" "fmt" "time" "gorm.io/gorm" "gorm.io/gorm/clause" ) func CanInitializeSystem() (bool, error) { users, _ := GetAllUsers() if len(*users) != 0 { // db.MigrateClarkson("root:password@tcp(192.168.0.117:3306)/clarkson?charset=utf8mb4&parseTime=True&loc=Local") return false, fmt.Errorf("there are already users in the database. Migration can only be done on an empty database") } return true, nil } func CreateUser(user *User) error { tx := DB.Create(&user) return tx.Error } func UpdateUser(user *User) error { tx := DB.Omit(clause.Associations).Save(&user) return tx.Error } func FindOneUser(condition interface{}) (User, error) { var model User err := DB.Where(condition).First(&model).Error return model, err } func SetDisabledStatusForUser(userId string, isDisabled bool) error { //Cannot do this for admin tx := DB.Debug().Model(&User{}).Where("id= ? and role=?", userId, USER).Update("is_disabled", isDisabled) return tx.Error } func GetAllUsers() (*[]User, error) { sorting := "created_at desc" var users []User result := DB.Order(sorting).Find(&users) return &users, result.Error } func GetAllVehicles(sorting string) (*[]Vehicle, error) { if sorting == "" { sorting = "created_at desc" } var vehicles []Vehicle result := DB.Preload("Fillups", func(db *gorm.DB) *gorm.DB { return db.Order("fillups.date DESC") }).Preload("Expenses", func(db *gorm.DB) *gorm.DB { return db.Order("expenses.date DESC") }).Order(sorting).Find(&vehicles) return &vehicles, result.Error } func GetVehicleOwner(vehicleId string) (string, error) { var mapping UserVehicle tx := DB.Where("vehicle_id = ? AND is_owner = 1", vehicleId).First(&mapping) if tx.Error != nil { return "", tx.Error } return mapping.UserID, nil } func GetVehicleUsers(vehicleId string) (*[]UserVehicle, error) { var mapping []UserVehicle tx := DB.Debug().Preload("User").Where("vehicle_id = ?", vehicleId).Find(&mapping) if tx.Error != nil { return nil, tx.Error } return &mapping, nil } func ShareVehicle(vehicleId, userId string) error { var mapping UserVehicle tx := DB.Where("vehicle_id = ? AND user_id = ?", vehicleId, userId).First(&mapping) if errors.Is(tx.Error, gorm.ErrRecordNotFound) { newMapping := UserVehicle{ UserID: userId, VehicleID: vehicleId, IsOwner: false, } tx = DB.Create(&newMapping) return tx.Error } return nil } func TransferVehicle(vehicleId, ownerId, newUserID string) error { tx := DB.Model(&UserVehicle{}).Where("vehicle_id = ? AND user_id = ?", vehicleId, ownerId).Update("is_owner", false) if tx.Error != nil { return tx.Error } tx = DB.Model(&UserVehicle{}).Where("vehicle_id = ? AND user_id = ?", vehicleId, newUserID).Update("is_owner", true) return tx.Error } func UnshareVehicle(vehicleId, userId string) error { var mapping UserVehicle tx := DB.Where("vehicle_id = ? AND user_id = ?", vehicleId, userId).First(&mapping) if errors.Is(tx.Error, gorm.ErrRecordNotFound) { return nil } if mapping.IsOwner { return fmt.Errorf("cannot unshare owner") } result := DB.Where("id=?", mapping.ID).Delete(&UserVehicle{}) return result.Error } func GetUserVehicles(id string) (*[]Vehicle, error) { var toReturn []Vehicle user, err := GetUserById(id) if err != nil { return nil, err } err = DB.Preload("Fillups", func(db *gorm.DB) *gorm.DB { return db.Order("fillups.date DESC") }).Preload("Expenses", func(db *gorm.DB) *gorm.DB { return db.Order("expenses.date DESC") }).Model(user).Select("vehicles.*,user_vehicles.is_owner").Association("Vehicles").Find(&toReturn) if err != nil { return nil, err } return &toReturn, nil } func GetUserById(id string) (*User, error) { var data User result := DB.Preload(clause.Associations).First(&data, "id=?", id) return &data, result.Error } func GetVehicleById(id string) (*Vehicle, error) { var vehicle Vehicle result := DB.Preload(clause.Associations).First(&vehicle, "id=?", id) return &vehicle, result.Error } func GetFillupById(id string) (*Fillup, error) { var obj Fillup result := DB.Preload(clause.Associations).First(&obj, "id=?", id) return &obj, result.Error } func GetFillupsByVehicleId(id string) (*[]Fillup, error) { var obj []Fillup result := DB.Preload(clause.Associations).Order("date desc").Find(&obj, &Fillup{VehicleID: id}) return &obj, result.Error } func GetLatestFillupsByVehicleId(id string) (*Fillup, error) { var obj Fillup result := DB.Preload(clause.Associations).Order("date desc").First(&obj, &Fillup{VehicleID: id}) return &obj, result.Error } func GetFillupsByVehicleIdSince(id string, since time.Time) (*[]Fillup, error) { var obj []Fillup result := DB.Where("date >= ? AND vehicle_id = ?", since, id).Preload(clause.Associations).Order("date desc").Find(&obj) return &obj, result.Error } func FindFillups(condition interface{}) (*[]Fillup, error) { var model []Fillup err := DB.Where(condition).Find(&model).Error return &model, err } func FindFillupsForDateRange(vehicleIds []string, start, end time.Time) (*[]Fillup, error) { var model []Fillup err := DB.Where("date <= ? AND date >= ? AND vehicle_id in ?", end, start, vehicleIds).Find(&model).Error return &model, err } func FindExpensesForDateRange(vehicleIds []string, start, end time.Time) (*[]Expense, error) { var model []Expense err := DB.Where("date <= ? AND date >= ? AND vehicle_id in ?", end, start, vehicleIds).Find(&model).Error return &model, err } func GetExpensesByVehicleId(id string) (*[]Expense, error) { var obj []Expense result := DB.Preload(clause.Associations).Order("date desc").Find(&obj, &Expense{VehicleID: id}) return &obj, result.Error } func GetLatestExpenseByVehicleId(id string) (*Expense, error) { var obj Expense result := DB.Preload(clause.Associations).Order("date desc").First(&obj, &Expense{VehicleID: id}) return &obj, result.Error } func GetExpenseById(id string) (*Expense, error) { var obj Expense result := DB.Preload(clause.Associations).First(&obj, "id=?", id) return &obj, result.Error } func DeleteVehicleById(id string) error { result := DB.Where("id=?", id).Delete(&Vehicle{}) return result.Error } func DeleteFillupById(id string) error { result := DB.Where("id=?", id).Delete(&Fillup{}) return result.Error } func DeleteExpenseById(id string) error { result := DB.Where("id=?", id).Delete(&Expense{}) return result.Error } func DeleteFillupByVehicleId(id string) error { result := DB.Where("vehicle_id=?", id).Delete(&Fillup{}) return result.Error } func DeleteExpenseByVehicleId(id string) error { result := DB.Where("vehicle_id=?", id).Delete(&Expense{}) return result.Error } func GetAllQuickEntries(sorting string) (*[]QuickEntry, error) { if sorting == "" { sorting = "created_at desc" } var quickEntries []QuickEntry result := DB.Preload(clause.Associations).Order(sorting).Find(&quickEntries) return &quickEntries, result.Error } func GetQuickEntriesForUser(userId, sorting string) (*[]QuickEntry, error) { if sorting == "" { sorting = "created_at desc" } var quickEntries []QuickEntry result := DB.Preload(clause.Associations).Where("user_id = ?", userId).Order(sorting).Find(&quickEntries) return &quickEntries, result.Error } func GetQuickEntryById(id string) (*QuickEntry, error) { var quickEntry QuickEntry result := DB.Preload(clause.Associations).First(&quickEntry, "id=?", id) return &quickEntry, result.Error } func DeleteQuickEntryById(id string) error { result := DB.Where("id=?", id).Delete(&QuickEntry{}) return result.Error } func UpdateQuickEntry(entry *QuickEntry) error { return DB.Save(entry).Error } func SetQuickEntryAsProcessed(id string, processDate time.Time) error { result := DB.Model(QuickEntry{}).Where("id=?", id).Update("process_date", processDate) return result.Error } func GetAttachmentById(id string) (*Attachment, error) { var entry Attachment result := DB.Preload(clause.Associations).First(&entry, "id=?", id) return &entry, result.Error } func GetVehicleAttachments(vehicleId string) (*[]Attachment, error) { var attachments []Attachment vehicle, err := GetVehicleById(vehicleId) if err != nil { return nil, err } err = DB.Debug().Model(vehicle).Select("attachments.*,vehicle_attachments.title").Preload("User").Association("Attachments").Find(&attachments) if err != nil { return nil, err } return &attachments, nil } func GeAlertById(id string) (*VehicleAlert, error) { var alert VehicleAlert result := DB.Preload(clause.Associations).First(&alert, "id=?", id) return &alert, result.Error } func GetAlertOccurenceByAlertId(id string) (*[]AlertOccurance, error) { var alertOccurance []AlertOccurance result := DB.Preload(clause.Associations).Order("created_at desc").Find(&alertOccurance, "vehicle_alert_id=?", id) return &alertOccurance, result.Error } func GetUnprocessedAlertOccurances() (*[]AlertOccurance, error) { var alertOccurance []AlertOccurance result := DB.Preload(clause.Associations).Order("created_at desc").Find(&alertOccurance, "process_date is NULL") return &alertOccurance, result.Error } func MarkAlertOccuranceAsProcessed(id string, alertProcessType AlertType, date time.Time) error { tx := DB.Debug().Model(&AlertOccurance{}).Where("id= ?", id). Update("alert_process_type", alertProcessType). Update("process_date", date) return tx.Error } func UpdateSettings(setting *Setting) error { tx := DB.Save(&setting) return tx.Error } func GetOrCreateSetting() *Setting { var setting Setting result := DB.First(&setting) if errors.Is(result.Error, gorm.ErrRecordNotFound) { DB.Save(&Setting{}) DB.First(&setting) } return &setting } func GetLock(name string) *JobLock { var jobLock JobLock result := DB.Where("name = ?", name).First(&jobLock) if errors.Is(result.Error, gorm.ErrRecordNotFound) { return &JobLock{ Name: name, } } return &jobLock } func Lock(name string, duration int) { jobLock := GetLock(name) if jobLock == nil { jobLock = &JobLock{ Name: name, } } jobLock.Duration = duration jobLock.Date = time.Now() if jobLock.ID == "" { DB.Create(&jobLock) } else { DB.Save(&jobLock) } } func Unlock(name string) { jobLock := GetLock(name) if jobLock == nil { return } jobLock.Duration = 0 jobLock.Date = time.Time{} DB.Save(&jobLock) } func UnlockMissedJobs() { var jobLocks []JobLock result := DB.Find(&jobLocks) if result.Error != nil { return } for _, job := range jobLocks { if (job.Date == time.Time{}) { continue } var duration = time.Duration(job.Duration) d := job.Date.Add(time.Minute * duration) if d.Before(time.Now()) { fmt.Println(job.Name + " is unlocked") Unlock(job.Name) } } }