Repository navigation
fix(marketing): a campaign member who responded keeps the response when they unsubscribe (#2365) - #2372
Merged
Conversation
…ount num_responses by has_responded (#2365) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAoe2SeiEpzJxGKKf5e
…cs and changeset (#2365) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAoe2SeiEpzJxGKKf5e
…sent (#2365) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAoe2SeiEpzJxGKKf5e
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
Author
席位核对Verdict: ACCEPT ·
Generated by Claude Code |
This was referenced Oct 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Irene · project thread
Fixes #2365
维护者速读
src/marketing/objects/campaign_member.hook.ts(清除条件改为「目标是已发送」)、src/marketing/objects/campaign.hook.ts(四份重算之一,num_responses 改数标识)、test/campaign-member-lifecycle.test.ts(新增 5 个用例)。npx vitest run test/campaign-member-lifecycle.test.ts,预期 36 个全绿,其中「an unsubscribe keeps num_responses; a reset to sent lowers it」通过。What changes
campaign_member_lifecycle(src/marketing/objects/campaign_member.hook.ts): the clear now fires only when the target status issentand the member had a response (prior status responded/converted, or the storedhas_responded). A move tounsubscribedkeepshas_responded: trueand the originalresponse_date. Responded, then unsubscribed, then reset tosentstill clears.campaign_metrics_refresh,campaign_member_metrics_refresh,campaign_lead_conversion_refresh,campaign_attribution_refresh): the member read takeshas_respondedinstead ofstatus, andnum_responsescountshas_responded === true. The four blocks stay character-identical (the existing identity test is green).has_respondedand the campaign's seedednum_responsesderive fromrespondedDaysAgo. One existing unsubscribed member (Developer Content Marketing Push, lead Mira Costa) now carries a response 29 days ago, so the seed exercises the new rule; that campaign's seedednum_responsesgoes 4 to 5. The seed is insert-once, so existing databases keep their rows.test/seed-consistency.test.ts: the old "track the responded status exactly" rule becomes: responded/converted carry the flag,sentnever does,unsubscribedmay be either, andresponse_dategoes with the flag. A new case asserts the seed holds at least one responded-then-unsubscribed member. The metric no-op check counts the flag.src/marketing/docs/crm_marketing_campaigns.mdand.zh.md, the Number of Responses bullet). The docs-site pages this change made false are corrected in en, zh-Hans and zh-Hant:content/docs/marketing/campaigns*.mdx(Number of Responses) andcontent/docs/marketing/campaign-members*.mdx(the move-back sentence, the Has Responded row, the Responses formula, "computed live from member status").campaign_member.object.ts(has_responded),campaign.actions.ts(mark_responded header),task.hook.ts(a cross-reference to the lifecycle clear)..changeset/campaign-response-kept-on-unsubscribe.md(patch).Readers of
num_responses/has_responded(git grep -n "num_responses\|has_responded" src/)campaign.object.tsresponse_rateformula (num_responses / num_sent)campaign.view.tslist columnnum_responsescampaign_member_lifecyclemarketing.seed.tsderivationcampaign_member.object.ts,campaign.actions.tssrc/sales/translations/*/objects.marketing.ts)response_datereaders (highlightFields, the member related-list columns on the campaign and onlead_detail.page.ts) are display only; an unsubscribed member who had responded now shows the date.Tests
New in
test/campaign-member-lifecycle.test.ts, run on the booted app:The existing "clears the summary when a member is reset out of a responded state" covers responded to sent.
Ablations (on-disk mutation, anchor counted, restored by
git checkout HEAD,git diff HEADempty after each):Acceptance notes
num_sentstays as it was everywhere.Verification
pnpm verifyon7e4d8d8: exit 0; validate passed, typecheck, lint, hygiene, build, tests 242 files / 4618 passed, 1 skipped.06e7ee6adds one comment line intask.hook.ts; re-ranpnpm typecheck(0),pnpm lint(0), and the two affected suites (79 passed).🤖 Generated with Claude Code
https://claude.ai/code/session_01J8VVAoe2SeiEpzJxGKKf5e
Generated by Claude Code