163 lines
5.8 KiB
Go
163 lines
5.8 KiB
Go
package domain
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
|
|
contract "git.cin.su/m/Assistant/contracts/continuity"
|
|
)
|
|
|
|
var (
|
|
ErrProspectiveNotFound = errors.New("prospective item not found")
|
|
ErrProspectiveRevision = errors.New("prospective item revision conflict")
|
|
ErrInvalidTransition = errors.New("invalid prospective item transition")
|
|
ErrInvalidSatisfaction = errors.New("invalid delivered satisfaction command")
|
|
ErrInvalidReminder = errors.New("invalid reminder request")
|
|
ErrInvalidAttention = errors.New("invalid attention item")
|
|
)
|
|
|
|
type Store struct {
|
|
items map[contract.ProspectiveItemID]contract.ProspectiveItem
|
|
}
|
|
|
|
func ValidateSatisfyDelivered(command contract.SatisfyDeliveredCommand) error {
|
|
if command.ActionIntentID == "" || command.AuthorizedActionID == "" || command.OwnerPrincipalID == "" ||
|
|
command.Subject.ProspectiveItemID == "" || command.Subject.ExpectedRevision == 0 ||
|
|
command.Subject.FromState != contract.ProspectiveDelivered || command.Subject.ToState != contract.ProspectiveSatisfied ||
|
|
strings.TrimSpace(command.Subject.EvidenceRef) == "" {
|
|
return ErrInvalidSatisfaction
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func BuildReminder(request contract.ScheduleReminderRequest, id contract.ProspectiveItemID) (contract.ProspectiveItem, error) {
|
|
if id == "" || request.OwnerPrincipalID == "" || request.ScopeID == "" || strings.TrimSpace(request.SourceIntentID) == "" ||
|
|
strings.TrimSpace(request.SourceUtteranceID) == "" || strings.TrimSpace(request.Summary) == "" ||
|
|
request.TriggerAtUnixMillis <= request.RequestedAtUnixMillis || request.RequestedAtUnixMillis < 1 {
|
|
return contract.ProspectiveItem{}, ErrInvalidReminder
|
|
}
|
|
return contract.ProspectiveItem{
|
|
ID: id,
|
|
CommitmentID: contract.CommitmentID(""),
|
|
OwnerPrincipalID: request.OwnerPrincipalID,
|
|
ScopeID: request.ScopeID,
|
|
GoalID: "",
|
|
SourceIntentID: strings.TrimSpace(request.SourceIntentID),
|
|
SourceUtteranceID: strings.TrimSpace(request.SourceUtteranceID),
|
|
Summary: strings.TrimSpace(request.Summary),
|
|
TriggerAtUnixMillis: request.TriggerAtUnixMillis,
|
|
State: contract.ProspectiveArmed,
|
|
Revision: 1,
|
|
}, nil
|
|
}
|
|
|
|
func BuildDueReminderAttention(item contract.ProspectiveItem, id contract.AttentionItemID, nowUnixMillis int64) (contract.AttentionItem, error) {
|
|
if id == "" || item.ID == "" || item.OwnerPrincipalID == "" || item.ScopeID == "" ||
|
|
strings.TrimSpace(item.Summary) == "" || item.TriggerAtUnixMillis < 1 || nowUnixMillis < 1 {
|
|
return contract.AttentionItem{}, ErrInvalidAttention
|
|
}
|
|
if item.State != contract.ProspectiveDelivered && item.State != contract.ProspectiveRevalidating {
|
|
return contract.AttentionItem{}, ErrInvalidAttention
|
|
}
|
|
return contract.AttentionItem{
|
|
ID: id,
|
|
OwnerPrincipalID: item.OwnerPrincipalID,
|
|
ScopeID: item.ScopeID,
|
|
SourceKind: contract.AttentionSourceProspectiveReminder,
|
|
SourceProspectiveID: item.ID,
|
|
Level: contract.AttentionDue,
|
|
State: contract.AttentionPending,
|
|
Summary: item.Summary,
|
|
DueAtUnixMillis: item.TriggerAtUnixMillis,
|
|
CreatedAtUnixMillis: nowUnixMillis,
|
|
Revision: 1,
|
|
}, nil
|
|
}
|
|
|
|
func (s *Store) SatisfyDelivered(id contract.ProspectiveItemID, revision contract.ProspectiveRevision, evidenceRef string) (contract.ProspectiveItem, error) {
|
|
item, err := s.current(id, revision)
|
|
if err != nil {
|
|
return contract.ProspectiveItem{}, err
|
|
}
|
|
if item.State != contract.ProspectiveDelivered || strings.TrimSpace(evidenceRef) == "" {
|
|
return contract.ProspectiveItem{}, ErrInvalidTransition
|
|
}
|
|
item.State = contract.ProspectiveSatisfied
|
|
item.Revision++
|
|
s.items[id] = item
|
|
return item, nil
|
|
}
|
|
|
|
func Recover(items []contract.ProspectiveItem) Store {
|
|
stored := make(map[contract.ProspectiveItemID]contract.ProspectiveItem, len(items))
|
|
for _, item := range items {
|
|
stored[item.ID] = item
|
|
}
|
|
return Store{items: stored}
|
|
}
|
|
|
|
func (s *Store) Snapshot() []contract.ProspectiveItem {
|
|
items := make([]contract.ProspectiveItem, 0, len(s.items))
|
|
for _, item := range s.items {
|
|
items = append(items, item)
|
|
}
|
|
return items
|
|
}
|
|
|
|
func (s *Store) Trigger(id contract.ProspectiveItemID, revision contract.ProspectiveRevision) (contract.ProspectiveItem, error) {
|
|
item, err := s.current(id, revision)
|
|
if err != nil {
|
|
return contract.ProspectiveItem{}, err
|
|
}
|
|
if item.State != contract.ProspectiveArmed {
|
|
return contract.ProspectiveItem{}, ErrInvalidTransition
|
|
}
|
|
item.State = contract.ProspectiveTriggered
|
|
item.Revision++
|
|
s.items[id] = item
|
|
return item, nil
|
|
}
|
|
|
|
func (s *Store) BeginRevalidation(id contract.ProspectiveItemID, revision contract.ProspectiveRevision) (contract.ProspectiveItem, error) {
|
|
item, err := s.current(id, revision)
|
|
if err != nil {
|
|
return contract.ProspectiveItem{}, err
|
|
}
|
|
if item.State != contract.ProspectiveTriggered {
|
|
return contract.ProspectiveItem{}, ErrInvalidTransition
|
|
}
|
|
item.State = contract.ProspectiveRevalidating
|
|
item.Revision++
|
|
s.items[id] = item
|
|
return item, nil
|
|
}
|
|
|
|
func (s *Store) FinishRevalidation(id contract.ProspectiveItemID, revision contract.ProspectiveRevision, relevant bool) (contract.ProspectiveItem, error) {
|
|
item, err := s.current(id, revision)
|
|
if err != nil {
|
|
return contract.ProspectiveItem{}, err
|
|
}
|
|
if item.State != contract.ProspectiveRevalidating {
|
|
return contract.ProspectiveItem{}, ErrInvalidTransition
|
|
}
|
|
if relevant {
|
|
item.State = contract.ProspectiveDelivered
|
|
} else {
|
|
item.State = contract.ProspectiveSuppressed
|
|
}
|
|
item.Revision++
|
|
s.items[id] = item
|
|
return item, nil
|
|
}
|
|
|
|
func (s *Store) current(id contract.ProspectiveItemID, revision contract.ProspectiveRevision) (contract.ProspectiveItem, error) {
|
|
item, ok := s.items[id]
|
|
if !ok {
|
|
return contract.ProspectiveItem{}, ErrProspectiveNotFound
|
|
}
|
|
if item.Revision != revision {
|
|
return contract.ProspectiveItem{}, ErrProspectiveRevision
|
|
}
|
|
return item, nil
|
|
}
|