44 lines
1.2 KiB
Go
44 lines
1.2 KiB
Go
|
|
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, ""
|
||
|
|
}
|
||
|
|
}
|