增加任意送礼增加亲密度
This commit is contained in:
parent
f4eee4db4c
commit
f995d80610
@ -758,10 +758,8 @@ func roomGiftCPEventFromRoomMessage(body []byte) (cpdomain.GiftEvent, bool, erro
|
||||
if err := proto.Unmarshal(envelope.GetBody(), &sent); err != nil {
|
||||
return cpdomain.GiftEvent{}, false, err
|
||||
}
|
||||
// 只有明确标记 cp_relation_type 的礼物才进入关系逻辑;普通礼物仍由其他读模型消费。
|
||||
if strings.TrimSpace(sent.GetCpRelationType()) == "" {
|
||||
return cpdomain.GiftEvent{}, false, nil
|
||||
}
|
||||
// CP worker 必须接收所有送礼事实:没有 active 关系时仓储层只让 CP/兄弟/姐妹礼物生成申请;
|
||||
// 已有 active 关系时,普通、幸运和超级幸运礼物都按 wallet 已结算的 GiftValue 增加亲密值。
|
||||
return cpdomain.GiftEvent{
|
||||
AppCode: appcode.Normalize(envelope.GetAppCode()),
|
||||
EventID: envelope.GetEventId(),
|
||||
|
||||
49
services/user-service/internal/app/app_test.go
Normal file
49
services/user-service/internal/app/app_test.go
Normal file
@ -0,0 +1,49 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
roomeventsv1 "hyapp.local/api/proto/events/room/v1"
|
||||
"hyapp/pkg/roommq"
|
||||
)
|
||||
|
||||
func TestRoomGiftCPEventFromRoomMessageIncludesNormalGift(t *testing.T) {
|
||||
body, err := proto.Marshal(&roomeventsv1.RoomGiftSent{
|
||||
SenderUserId: 1001,
|
||||
TargetUserId: 1002,
|
||||
GiftId: "rose",
|
||||
GiftCount: 1,
|
||||
GiftValue: 100,
|
||||
BillingReceiptId: "receipt-normal",
|
||||
CommandId: "cmd-normal",
|
||||
GiftTypeCode: "normal",
|
||||
GiftName: "Rose",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("marshal room gift sent failed: %v", err)
|
||||
}
|
||||
encoded, err := roommq.EncodeRoomOutboxMessage(&roomeventsv1.EventEnvelope{
|
||||
AppCode: "lalu",
|
||||
EventId: "room_evt_normal_gift",
|
||||
EventType: "RoomGiftSent",
|
||||
RoomId: "room-1",
|
||||
RoomVersion: 7,
|
||||
OccurredAtMs: 1700000000000,
|
||||
Body: body,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("encode room outbox message failed: %v", err)
|
||||
}
|
||||
|
||||
event, ok, err := roomGiftCPEventFromRoomMessage(encoded)
|
||||
if err != nil {
|
||||
t.Fatalf("convert room gift event failed: %v", err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatal("normal gifts must reach CP consumer so active relationships can gain intimacy")
|
||||
}
|
||||
if event.CPRelationType != "" || event.GiftTypeCode != "normal" || event.GiftValue != 100 || event.TargetUserID != 1002 {
|
||||
t.Fatalf("normal gift event mismatch: %+v", event)
|
||||
}
|
||||
}
|
||||
@ -514,7 +514,7 @@ func (r *Repository) ConsumeGiftEvent(ctx context.Context, event cpdomain.GiftEv
|
||||
return cpdomain.ConsumeResult{}, xerr.New(xerr.Unavailable, "mysql repository is not configured")
|
||||
}
|
||||
relationType := normalizeRelationType(event.CPRelationType)
|
||||
if relationType == "" || event.SenderUserID <= 0 || event.TargetUserID <= 0 || event.SenderUserID == event.TargetUserID {
|
||||
if event.SenderUserID <= 0 || event.TargetUserID <= 0 || event.SenderUserID == event.TargetUserID {
|
||||
return cpdomain.ConsumeResult{Consumed: false}, nil
|
||||
}
|
||||
if strings.TrimSpace(event.EventID) == "" {
|
||||
@ -540,7 +540,7 @@ func (r *Repository) ConsumeGiftEvent(ctx context.Context, event cpdomain.GiftEv
|
||||
return cpdomain.ConsumeResult{Consumed: false}, tx.Commit()
|
||||
}
|
||||
userAID, userBID := orderedPair(event.SenderUserID, event.TargetUserID)
|
||||
// 已有 active 关系时,任何关系礼物都只增加这对关系的亲密值,不再生成新的申请。
|
||||
// 已有 active 关系时,任意礼物都只增加这对关系的亲密值;GiftValue 已由 wallet-service 按普通/幸运/超级幸运比例结算。
|
||||
if relationship, found, err := lockActiveRelationshipTx(ctx, tx, appCode, userAID, userBID); err != nil {
|
||||
return cpdomain.ConsumeResult{}, err
|
||||
} else if found {
|
||||
@ -556,6 +556,10 @@ func (r *Repository) ConsumeGiftEvent(ctx context.Context, event cpdomain.GiftEv
|
||||
}
|
||||
return cpdomain.ConsumeResult{Consumed: true, Relationship: updated}, tx.Commit()
|
||||
}
|
||||
if relationType == "" {
|
||||
// 普通礼物在双方还没有 active 关系时不能创建申请;这类事件不写消费位点,后续若 MQ 重投仍然是无副作用 no-op。
|
||||
return cpdomain.ConsumeResult{Consumed: false}, tx.Commit()
|
||||
}
|
||||
// 没有 active 关系时,CP/兄弟/姐妹礼物只生成 pending 申请;真正建立关系必须由 B 显式同意。
|
||||
if err := ensurePairHasNoActiveRelationshipTx(ctx, tx, appCode, userAID, userBID, event.TargetUserID); err != nil {
|
||||
if err := insertConsumptionTx(ctx, tx, appCode, event.EventID, "skipped", "", "", "existing_relationship", nowMs); err != nil {
|
||||
|
||||
@ -176,6 +176,101 @@ func TestListActiveIntimacyLeaderboardEntriesOrdersAndIncludesBothUsers(t *testi
|
||||
}
|
||||
}
|
||||
|
||||
func TestConsumeGiftEventAddsIntimacyForNormalGiftWhenRelationshipExists(t *testing.T) {
|
||||
schema := mysqlschema.New(t)
|
||||
repo := New(schema.DB)
|
||||
ctx := appcode.WithContext(context.Background(), appcode.Default)
|
||||
nowMS := int64(1700000000000)
|
||||
|
||||
seedCPTestUser(t, schema.DB, 4201, "Normal Gift Alice", nowMS)
|
||||
seedCPTestUser(t, schema.DB, 4202, "Normal Gift Bob", nowMS)
|
||||
seedCPLevelRules(t, schema.DB, cpdomain.RelationTypeCP, []int64{0, 100, 300}, nowMS)
|
||||
seedActiveCPRelationship(t, schema.DB, "normal_gift_cp", cpdomain.RelationTypeCP, 4201, 4202, 90, 1, nowMS)
|
||||
|
||||
result, err := repo.ConsumeGiftEvent(ctx, cpdomain.GiftEvent{
|
||||
AppCode: appcode.Default,
|
||||
EventID: "room_evt_normal_gift_cp",
|
||||
RoomID: "room-normal",
|
||||
RoomVersion: 3,
|
||||
OccurredAtMS: nowMS + 1,
|
||||
SenderUserID: 4201,
|
||||
TargetUserID: 4202,
|
||||
GiftID: "rose",
|
||||
GiftCount: 1,
|
||||
GiftValue: 37,
|
||||
BillingReceiptID: "receipt-normal-gift-cp",
|
||||
CommandID: "cmd-normal-gift-cp",
|
||||
GiftTypeCode: "normal",
|
||||
}, nowMS+2)
|
||||
if err != nil {
|
||||
t.Fatalf("consume normal gift for active cp failed: %v", err)
|
||||
}
|
||||
if !result.Consumed || result.Relationship.RelationshipID != "normal_gift_cp" {
|
||||
t.Fatalf("normal gift must update existing relationship: %+v", result)
|
||||
}
|
||||
if result.Relationship.IntimacyValue != 127 || result.Relationship.Level != 2 {
|
||||
t.Fatalf("relationship intimacy/level mismatch: %+v", result.Relationship)
|
||||
}
|
||||
|
||||
var status string
|
||||
if err := schema.DB.QueryRowContext(ctx, `
|
||||
SELECT status
|
||||
FROM user_cp_gift_event_consumption
|
||||
WHERE app_code = ? AND room_event_id = ?`,
|
||||
appcode.Default, "room_evt_normal_gift_cp",
|
||||
).Scan(&status); err != nil {
|
||||
t.Fatalf("read gift consumption failed: %v", err)
|
||||
}
|
||||
if status != "relationship_intimacy_added" {
|
||||
t.Fatalf("normal gift consumption status mismatch: %s", status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConsumeGiftEventIgnoresNormalGiftWithoutRelationship(t *testing.T) {
|
||||
schema := mysqlschema.New(t)
|
||||
repo := New(schema.DB)
|
||||
ctx := appcode.WithContext(context.Background(), appcode.Default)
|
||||
nowMS := int64(1700000000000)
|
||||
|
||||
seedCPTestUser(t, schema.DB, 4301, "No CP Alice", nowMS)
|
||||
seedCPTestUser(t, schema.DB, 4302, "No CP Bob", nowMS)
|
||||
|
||||
result, err := repo.ConsumeGiftEvent(ctx, cpdomain.GiftEvent{
|
||||
AppCode: appcode.Default,
|
||||
EventID: "room_evt_normal_no_cp",
|
||||
RoomID: "room-normal",
|
||||
RoomVersion: 3,
|
||||
OccurredAtMS: nowMS + 1,
|
||||
SenderUserID: 4301,
|
||||
TargetUserID: 4302,
|
||||
GiftID: "rose",
|
||||
GiftCount: 1,
|
||||
GiftValue: 37,
|
||||
BillingReceiptID: "receipt-normal-no-cp",
|
||||
CommandID: "cmd-normal-no-cp",
|
||||
GiftTypeCode: "normal",
|
||||
}, nowMS+2)
|
||||
if err != nil {
|
||||
t.Fatalf("consume normal gift without cp failed: %v", err)
|
||||
}
|
||||
if result.Consumed {
|
||||
t.Fatalf("normal gift without active relationship must be ignored: %+v", result)
|
||||
}
|
||||
|
||||
var applicationCount int64
|
||||
if err := schema.DB.QueryRowContext(ctx, `
|
||||
SELECT COUNT(*)
|
||||
FROM user_cp_applications
|
||||
WHERE app_code = ? AND requester_user_id = ? AND target_user_id = ?`,
|
||||
appcode.Default, 4301, 4302,
|
||||
).Scan(&applicationCount); err != nil {
|
||||
t.Fatalf("count cp applications failed: %v", err)
|
||||
}
|
||||
if applicationCount != 0 {
|
||||
t.Fatalf("normal gift without relationship must not create application, got %d", applicationCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBreakRelationshipPrepareConfirmIsIdempotent(t *testing.T) {
|
||||
schema := mysqlschema.New(t)
|
||||
repo := New(schema.DB)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user