package m2mcore import ( "errors" "fmt" ) // State — конечное состояние сделки M2M. type State string const ( StateDraft State = "draft" StateValidated State = "validated" StateSubmittedToNSD State = "submitted_to_nsd" StateAwaitingDecision State = "awaiting_decision" StateConfirmed State = "confirmed" StateAwaitingSUB16 State = "awaiting_sub16" StateDone State = "done" StateRejected State = "rejected" StateTimedOut State = "timed_out" StateManualApproval State = "manual_approval" ) // ErrInvalidTransition возвращается при попытке перейти в состояние, // которое не разрешено из текущего. var ErrInvalidTransition = errors.New("m2mcore: недопустимый переход FSM") // allowedTransitions — карта разрешённых переходов FSM сделки. // Любая попытка перейти в state, отсутствующее в списке для текущего, // заканчивается ErrInvalidTransition. var allowedTransitions = map[State]map[State]struct{}{ StateDraft: { StateValidated: {}, StateRejected: {}, StateManualApproval: {}, }, StateValidated: { StateSubmittedToNSD: {}, StateRejected: {}, StateManualApproval: {}, }, StateSubmittedToNSD: { StateAwaitingDecision: {}, StateRejected: {}, }, StateAwaitingDecision: { StateConfirmed: {}, StateRejected: {}, StateTimedOut: {}, StateManualApproval: {}, }, StateConfirmed: { StateAwaitingSUB16: {}, StateDone: {}, }, StateAwaitingSUB16: { StateDone: {}, }, StateManualApproval: { StateValidated: {}, StateConfirmed: {}, StateRejected: {}, }, // Завершающие состояния — без выходов. StateDone: {}, StateRejected: {}, StateTimedOut: {}, } // IsTerminal возвращает true для завершающих состояний. func IsTerminal(s State) bool { switch s { case StateDone, StateRejected, StateTimedOut: return true } return false } // CanTransition сообщает, разрешён ли переход from -> to. func CanTransition(from, to State) bool { allowed, ok := allowedTransitions[from] if !ok { return false } _, ok = allowed[to] return ok } // transition проверяет переход и возвращает обёрнутую ошибку с // контекстом, если он недопустим. func transition(from, to State) error { if !CanTransition(from, to) { return fmt.Errorf("%w: %s -> %s", ErrInvalidTransition, from, to) } return nil }