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, "" } }