fix(18-04): short-circuit own-campaign re-match to stop report_count double-increment
- OwnReportRow now selects campaign_id::text; match branch no-ops (created: false, no UPDATE) when the tiered match resolves to the report's own current campaign_id via a sibling row - Closes CAMP-02 gap / CR-01: /analyze can be re-run indefinitely without inflating campaigns.report_count
This commit is contained in:
parent
afd7af70c8
commit
9ca2ccf1c7
1 changed files with 12 additions and 1 deletions
|
|
@ -66,6 +66,7 @@ interface OwnReportRow {
|
||||||
requester_contact_id: number | null;
|
requester_contact_id: number | null;
|
||||||
company_id: number | null;
|
company_id: number | null;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
|
campaign_id: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OwnMessageRow {
|
interface OwnMessageRow {
|
||||||
|
|
@ -154,7 +155,7 @@ export async function groupReportIntoCampaign(
|
||||||
|
|
||||||
return await postgresClient.transaction(async (client) => {
|
return await postgresClient.transaction(async (client) => {
|
||||||
const ownReportRes = await client.query<OwnReportRow>(
|
const ownReportRes = await client.query<OwnReportRow>(
|
||||||
`SELECT title, requester_contact_id, company_id, created_at
|
`SELECT title, requester_contact_id, company_id, created_at, campaign_id::text AS campaign_id
|
||||||
FROM reports
|
FROM reports
|
||||||
WHERE id = $1`,
|
WHERE id = $1`,
|
||||||
[reportId]
|
[reportId]
|
||||||
|
|
@ -321,6 +322,16 @@ export async function groupReportIntoCampaign(
|
||||||
// Find-or-create against `campaigns` (CAMP-02).
|
// Find-or-create against `campaigns` (CAMP-02).
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
if (matchCampaignId && matchGroupMethod) {
|
if (matchCampaignId && matchGroupMethod) {
|
||||||
|
// CR-01/CAMP-02 no-op guard: tier queries only exclude the report's
|
||||||
|
// OWN row (`r.id != $x`), not its siblings already in the same
|
||||||
|
// campaign. Since `/analyze` re-runs grouping unconditionally
|
||||||
|
// (D-08), a report already linked to campaign X can re-match X via
|
||||||
|
// a sibling row on every repeat call, inflating `report_count`
|
||||||
|
// without bound. If the match resolves to the report's own current
|
||||||
|
// campaign, it's already correctly linked — skip both UPDATEs.
|
||||||
|
if (matchCampaignId === ownReport.campaign_id) {
|
||||||
|
return { campaignId: matchCampaignId, groupMethod: matchGroupMethod, created: false };
|
||||||
|
}
|
||||||
await client.query(
|
await client.query(
|
||||||
`UPDATE campaigns
|
`UPDATE campaigns
|
||||||
SET report_count = report_count + 1, last_seen_at = NOW(), updated_at = NOW()
|
SET report_count = report_count + 1, last_seen_at = NOW(), updated_at = NOW()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue