Files
digital-psychology/apps/api/internal/service/bootstrap/service.go
T
jackyu66gitandCursor 7ab9add5dd
ci / h5 (push) Canceled after 0s
ci / api (push) Canceled after 0s
ci / ess-docs (push) Canceled after 0s
feat(ops): ECR-007 行为分析与 ECR-008 内容运营后台
落地埋点 ingest/数据看板、首页宫格 CMS 与测评上下架;含账号引导、问答流式与免责声明去重,以及 review P1 审计同事务修复。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 02:26:16 +08:00

132 lines
4.1 KiB
Go

package bootstrap
import (
"context"
"encoding/json"
"log"
"time"
"github.com/google/uuid"
"github.com/yuxingu/digital-psychology/apps/api/internal/model"
"github.com/yuxingu/digital-psychology/apps/api/internal/portrait"
releng "github.com/yuxingu/digital-psychology/apps/api/internal/relation"
"github.com/yuxingu/digital-psychology/apps/api/internal/repository"
"github.com/yuxingu/digital-psychology/apps/api/internal/rhythm"
"github.com/yuxingu/digital-psychology/apps/api/internal/star"
"github.com/yuxingu/digital-psychology/apps/api/internal/star/synastry"
)
// Service generates birthday-derived report bundles for a profile.
type Service struct {
Profiles *repository.ProfileRepo
Reports *repository.ReportRepo
Relations *repository.RelationRepo
}
// GenerateForProfile rebuilds solo reports for p and pair reports with counterparts.
func (s *Service) GenerateForProfile(ctx context.Context, userID uuid.UUID, p *model.Profile) {
if p == nil {
return
}
s.genSolo(ctx, userID, p)
list, err := s.Profiles.ListByUser(ctx, userID)
if err != nil {
log.Printf("bootstrap list profiles: %v", err)
return
}
var self *model.Profile
others := make([]*model.Profile, 0)
for i := range list {
item := list[i]
if item.Relation == "self" {
cp := item
self = &cp
} else if item.Relation == "other" {
cp := item
others = append(others, &cp)
}
}
if self == nil {
return
}
if p.Relation == "self" {
for _, o := range others {
s.genPair(ctx, userID, self, o)
}
return
}
s.genPair(ctx, userID, self, p)
}
func (s *Service) genSolo(ctx context.Context, userID uuid.UUID, p *model.Profile) {
outP := portrait.Build(p.BirthDate, p.DisplayName)
sum, _ := json.Marshal(outP.Summary)
det, _ := json.Marshal(outP.Detail)
if _, err := s.Reports.UpsertWithPeer(ctx, userID, p.ID, nil, "portrait", sum, det); err != nil {
log.Printf("bootstrap portrait: %v", err)
}
outS, err := star.BuildWith(star.BuildOpts{
Birth: p.BirthDate, BirthTime: p.BirthTime, BirthPlace: p.BirthPlace, Name: p.DisplayName,
})
if err != nil {
log.Printf("bootstrap star: %v", err)
} else {
sum, _ = json.Marshal(outS.Summary)
det, _ = json.Marshal(outS.Detail)
if _, err := s.Reports.UpsertWithPeer(ctx, userID, p.ID, nil, "star", sum, det); err != nil {
log.Printf("bootstrap star save: %v", err)
}
}
outR := rhythm.Build(p.BirthDate, p.DisplayName)
sum, _ = json.Marshal(outR.Summary)
det, _ = json.Marshal(outR.Detail)
if _, err := s.Reports.UpsertWithPeer(ctx, userID, p.ID, nil, "rhythm", sum, det); err != nil {
log.Printf("bootstrap rhythm: %v", err)
}
}
func (s *Service) genPair(ctx context.Context, userID uuid.UUID, self, other *model.Profile) {
if self == nil || other == nil || self.ID == other.ID {
return
}
peer := other.ID
relType := ""
if other.RelationType != nil {
relType = *other.RelationType
}
rel := releng.BuildFull(self.BirthDate, other.BirthDate, self.BirthTime, other.BirthTime, self.BirthPlace, other.BirthPlace, self.DisplayName, other.DisplayName, relType)
sum, _ := json.Marshal(rel.Summary)
det, _ := json.Marshal(rel.Detail)
rep, err := s.Reports.UpsertWithPeer(ctx, userID, self.ID, &peer, "relation", sum, det)
if err != nil {
log.Printf("bootstrap relation: %v", err)
} else if s.Relations != nil {
_, _ = s.Relations.Create(ctx, userID, self.ID, other.ID, sum, rep.ID)
}
ca, err := star.NatalChart(self.BirthDate, self.BirthTime, self.BirthPlace)
if err != nil {
log.Printf("bootstrap synastry natal a: %v", err)
return
}
cb, err := star.NatalChart(other.BirthDate, other.BirthTime, other.BirthPlace)
if err != nil {
log.Printf("bootstrap synastry natal b: %v", err)
return
}
when := time.Now().In(time.FixedZone("CST", 8*3600))
out, err := synastry.BuildReport(ca, cb, self.DisplayName, other.DisplayName, when)
if err != nil {
log.Printf("bootstrap synastry: %v", err)
return
}
sum, _ = json.Marshal(out.Summary)
det, _ = json.Marshal(out.Detail)
if _, err := s.Reports.UpsertWithPeer(ctx, userID, self.ID, &peer, "synastry", sum, det); err != nil {
log.Printf("bootstrap synastry save: %v", err)
}
}