thread-master/apps/backend/internal/module/radar/domain/opportunity_review.go

44 lines
1.2 KiB
Go
Raw Permalink Normal View History

2026-08-13 02:22:24 +00:00
package domain
import "strings"
// ReviewEvent is append-only audit data for the inbox workflow. It is kept
// separate from Opportunity so a transition never rewrites history.
type ReviewEvent struct {
ID string `bson:"_id" json:"id"`
OwnerUID int64 `bson:"owner_uid" json:"owner_uid"`
OpportunityID string `bson:"opportunity_id" json:"opportunity_id"`
From string `bson:"from" json:"from"`
To string `bson:"to" json:"to"`
Reason string `bson:"reason,omitempty" json:"reason,omitempty"`
Note string `bson:"note,omitempty" json:"note,omitempty"`
ActorUID int64 `bson:"actor_uid" json:"actor_uid"`
At int64 `bson:"at" json:"at"`
}
func (e *ReviewEvent) Normalize() error {
e.Reason = strings.TrimSpace(e.Reason)
e.Note = strings.TrimSpace(e.Note)
if e.ID == "" {
e.ID = NewID()
}
if e.At == 0 {
e.At = NowNano()
}
if e.OwnerUID <= 0 || e.OpportunityID == "" || !IsReviewState(e.To) {
return ErrValidation
}
return nil
}
func LegacyReviewState(status string) (state, reason string) {
switch status {
case OppAccepted:
return ReviewCompleted, ""
case OppDismissed:
return ReviewRemoved, RemovalLegacy
default:
return ReviewPending, ""
}
}