// Package membership handles growth membership status and mock commerce orders. package membership import ( "context" "errors" "time" "github.com/google/uuid" "github.com/yuxingu/digital-psychology/apps/api/internal/repository" ) // Service is membership + order use-cases (extracted from report service). type Service struct { Reports *repository.ReportRepo } // CreateOrderInput for commerce. type CreateOrderInput struct { Kind string Plan string ReportID *uuid.UUID } // CreateOrder starts membership or deep_access order. func (s *Service) CreateOrder(ctx context.Context, userID uuid.UUID, in CreateOrderInput) (uuid.UUID, error) { if in.Kind != "membership" && in.Kind != "deep_access" { return uuid.Nil, errors.New("invalid kind") } if in.Kind == "deep_access" && in.ReportID == nil { return uuid.Nil, errors.New("report_id required") } amount := 990 if in.Kind == "membership" { amount = 2500 } return s.Reports.CreateOrder(ctx, userID, in.Kind, in.Plan, in.ReportID, amount) } // PayMock completes mock payment. func (s *Service) PayMock(ctx context.Context, userID, orderID uuid.UUID) error { return s.Reports.PayMock(ctx, userID, orderID) } // Me is the public membership snapshot. type Me struct { Active bool `json:"active"` Plan string `json:"plan,omitempty"` Status string `json:"status"` ExpiresAt *time.Time `json:"expires_at,omitempty"` AskQuotaLeft int `json:"ask_quota_left,omitempty"` } // Get returns current growth membership for the user. func (s *Service) Get(ctx context.Context, userID uuid.UUID) (*Me, error) { row, err := s.Reports.GetMembership(ctx, userID) if err != nil { return nil, err } return &Me{ Active: row.Active, Plan: row.Plan, Status: row.Status, ExpiresAt: row.ExpiresAt, AskQuotaLeft: row.AskQuotaLeft, }, nil }