WiiCITMS/process/oa/schedule.go
2025-11-07 14:14:34 +08:00

279 lines
8.3 KiB
Go

package oa
import (
"fmt"
"time"
"WiiCITMS/models/oa"
"WiiGenerates/WiiCITMS/generates/v1/go/types"
"WiiGoLibrary/apply/middle/process/v1"
"WiiGoLibrary/framework/db/v1/utils/mssql/unique"
"WiiGoLibrary/framework/hub/v1/dblib"
)
// CreateScheduleRequest 创建日程请求
type CreateScheduleRequest struct {
OwnerStaffGuid string `json:"ownerStaffGuid"`
Title string `json:"title"`
Description string `json:"description"`
Location string `json:"location"`
StartTime string `json:"startTime"` // RFC3339
EndTime string `json:"endTime"` // RFC3339
AllDay bool `json:"allDay"`
RemindMinutesBefore int `json:"remindMinutesBefore"`
}
// CreateSchedule 创建日程
func CreateSchedule(req CreateScheduleRequest) (*oa.ScheduleModel, *process.Process) {
if req.OwnerStaffGuid == "" || req.Title == "" || req.StartTime == "" || req.EndTime == "" {
return nil, process.FailError(types.InvalidParamError, fmt.Errorf("缺少必填参数"))
}
owner, err := unique.FromString(req.OwnerStaffGuid)
if err != nil {
return nil, process.FailError(types.InvalidParamError, err)
}
start, err := time.Parse(time.RFC3339, req.StartTime)
if err != nil {
return nil, process.FailError(types.InvalidParamError, err)
}
end, err := time.Parse(time.RFC3339, req.EndTime)
if err != nil {
}
if !end.After(start) {
return nil, process.FailError(types.InvalidParamError, fmt.Errorf("结束时间必须晚于开始时间"))
}
// 冲突检查(不阻断创建)
if _, _, proc := checkConflictsInternal(conflictCheckReq{OwnerStaffGuid: req.OwnerStaffGuid, Start: start, End: end, ExcludeGuid: ""}); proc.IsError() {
return nil, proc
}
m := &oa.ScheduleModel{}
m.OwnerStaffGuid = owner
m.Title = req.Title
m.Description = req.Description
m.Location = req.Location
m.StartTime = start
m.EndTime = end
m.AllDay = req.AllDay
m.RemindMinutesBefore = req.RemindMinutesBefore
m.Reminded = false
m.Status = 0
r := dblib.DBIns.DB.Create(m)
if r.Error != nil {
return nil, process.FailError(types.CreateWorkflowError, r.Error)
}
return m, process.Success(200)
}
// CheckScheduleConflicts 冲突检查,返回冲突列表
func CheckScheduleConflicts(ownerStaffGuid, startISO, endISO, excludeGuid string) ([]*oa.ScheduleModel, bool, *process.Process) {
start, err := time.Parse(time.RFC3339, startISO)
if err != nil {
return nil, false, process.FailError(types.InvalidParamError, err)
}
end, err := time.Parse(time.RFC3339, endISO)
if err != nil {
return nil, false, process.FailError(types.InvalidParamError, err)
}
res := make([]*oa.ScheduleModel, 0)
owner, err := unique.FromString(ownerStaffGuid)
if err != nil {
return res, false, process.FailError(types.InvalidParamError, err)
}
db := dblib.DBIns.DB.Model(&oa.ScheduleModel{}).
Where("OwnerStaffGuid = ? AND Status = 0 AND (RecordStatus & 524288) = 0", owner).
Where("StartTime < ? AND EndTime > ?", end, start)
if excludeGuid != "" {
if guid, e := unique.FromString(excludeGuid); e == nil {
db = db.Where("RecordGuid <> ?", guid)
}
}
r := db.Find(&res)
if r.Error != nil {
return res, false, process.FailError(types.QueryWorkflowError, r.Error)
}
return res, len(res) > 0, process.Success(200)
}
// CancelSchedule 取消日程
func CancelSchedule(scheduleGuid string) *process.Process {
guid, err := unique.FromString(scheduleGuid)
if err != nil {
return process.FailError(types.InvalidParamError, err)
}
r := dblib.DBIns.DB.Model(&oa.ScheduleModel{}).Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", guid).Update("Status", 1)
if r.Error != nil {
return process.FailError(types.UpdateWorkflowError, r.Error)
}
return process.Success(200)
}
// checkConflictsInternal 内部冲突检查实现
type conflictCheckReq struct {
OwnerStaffGuid string
Start time.Time
End time.Time
ExcludeGuid string
}
func checkConflictsInternal(req conflictCheckReq) ([]*oa.ScheduleModel, bool, *process.Process) {
res := make([]*oa.ScheduleModel, 0)
owner, err := unique.FromString(req.OwnerStaffGuid)
if err != nil {
return res, false, process.FailError(types.InvalidParamError, err)
}
db := dblib.DBIns.DB.Model(&oa.ScheduleModel{}).
Where("OwnerStaffGuid = ? AND Status = 0 AND (RecordStatus & 524288) = 0", owner).
Where("StartTime < ? AND EndTime > ?", req.End, req.Start)
if req.ExcludeGuid != "" {
if eg, e := unique.FromString(req.ExcludeGuid); e == nil {
db = db.Where("RecordGuid <> ?", eg)
}
}
r := db.Find(&res)
if r.Error != nil {
return res, false, process.FailError(types.QueryWorkflowError, r.Error)
}
return res, len(res) > 0, process.Success(200)
}
// UpdateSchedule 更新日程
type UpdateScheduleRequest struct {
Title string `json:"title"`
Description string `json:"description"`
Location string `json:"location"`
StartTime string `json:"startTime"`
EndTime string `json:"endTime"`
AllDay *bool `json:"allDay"`
RemindMinutesBefore *int `json:"remindMinutesBefore"`
}
func UpdateSchedule(scheduleGuid string, req UpdateScheduleRequest) (*oa.ScheduleModel, *process.Process) {
guid, err := unique.FromString(scheduleGuid)
if err != nil {
return nil, process.FailError(types.InvalidParamError, err)
}
m := &oa.ScheduleModel{}
r := dblib.DBIns.DB.Where("RecordGuid = ? AND (RecordStatus & 524288) = 0", guid).First(m)
if r.Error != nil {
return nil, process.FailError(types.QueryWorkflowError, r.Error)
}
if req.Title != "" {
m.Title = req.Title
}
if req.Description != "" {
m.Description = req.Description
}
if req.Location != "" {
m.Location = req.Location
}
var (
newStart time.Time
newEnd time.Time
hasTimeChange bool
)
if req.StartTime != "" {
v, e := time.Parse(time.RFC3339, req.StartTime)
if e != nil {
return nil, process.FailError(types.InvalidParamError, e)
}
newStart = v
hasTimeChange = true
}
if req.EndTime != "" {
v, e := time.Parse(time.RFC3339, req.EndTime)
if e != nil {
return nil, process.FailError(types.InvalidParamError, e)
}
newEnd = v
hasTimeChange = true
}
if hasTimeChange {
if req.StartTime == "" {
newStart = m.StartTime
}
if req.EndTime == "" {
newEnd = m.EndTime
}
if !newEnd.After(newStart) {
return nil, process.FailError(types.InvalidParamError, fmt.Errorf("结束时间必须晚于开始时间"))
}
if _, _, proc := checkConflictsInternal(conflictCheckReq{OwnerStaffGuid: m.OwnerStaffGuid.String(), Start: newStart, End: newEnd, ExcludeGuid: m.RecordGuid.String()}); proc.IsError() {
return nil, proc
}
m.StartTime, m.EndTime = newStart, newEnd
m.Reminded = false
}
if req.AllDay != nil {
m.AllDay = *req.AllDay
}
if req.RemindMinutesBefore != nil {
m.RemindMinutesBefore = *req.RemindMinutesBefore
m.Reminded = false
}
r = dblib.DBIns.DB.Save(m)
if r.Error != nil {
return nil, process.FailError(types.UpdateWorkflowError, r.Error)
}
return m, process.Success(200)
}
// ListSchedules 列表
type ListSchedulesRequest struct {
OwnerStaffGuid string `json:"ownerStaffGuid"`
From string `json:"from"`
To string `json:"to"`
Limit int `json:"limit"`
Offset int `json:"offset"`
}
func ListSchedules(req ListSchedulesRequest) ([]*oa.ScheduleModel, *process.Process) {
res := make([]*oa.ScheduleModel, 0)
if req.OwnerStaffGuid == "" {
return res, process.FailError(types.InvalidParamError, fmt.Errorf("ownerStaffGuid 必填"))
}
owner, err := unique.FromString(req.OwnerStaffGuid)
if err != nil {
return res, process.FailError(types.InvalidParamError, err)
}
from := time.Now()
to := from.AddDate(0, 1, 0)
if req.From != "" {
if v, e := time.Parse(time.RFC3339, req.From); e == nil {
from = v
}
}
if req.To != "" {
if v, e := time.Parse(time.RFC3339, req.To); e == nil {
to = v
}
}
if to.Before(from) {
from, to = to, from
}
limit := req.Limit
if limit <= 0 {
limit = 20
}
offset := req.Offset
if offset < 0 {
offset = 0
}
db := dblib.DBIns.DB.Model(&oa.ScheduleModel{}).
Where("OwnerStaffGuid = ? AND Status = 0 AND (RecordStatus & 524288) = 0", owner).
Where("StartTime < ? AND EndTime > ?", to, from).
Order("StartTime ASC").
Limit(limit).Offset(offset)
r := db.Find(&res)
if r.Error != nil {
return res, process.FailError(types.QueryWorkflowError, r.Error)
}
return res, process.Success(200)
}