落地埋点 ingest/数据看板、首页宫格 CMS 与测评上下架;含账号引导、问答流式与免责声明去重,以及 review P1 审计同事务修复。 Co-authored-by: Cursor <cursoragent@cursor.com>
132 lines
4.1 KiB
Go
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)
|
|
}
|
|
}
|