Skip to content

Commit 890656e

Browse files
committed
refactor(purchase): extract applyAccountOutcome to drop executeForAccount below gocyclo 10
The gocyclo pre-commit hook (-over 10) failed: executeForAccount was at cyclomatic complexity 11. Extract the per-account status-resolution switch (partially_completed / failed / completed stamping, #642) and the committed gate (#1014) into a cohesive applyAccountOutcome helper, dropping the function below the threshold without a //nolint or a threshold bump. Behavior is unchanged: same status transitions, same error-note appending, same committed semantics (anyRecPurchased is now evaluated once and reused for the partial flag). The OfferingClass typed-enum validation and no-silent-fallback behavior are untouched.
1 parent 0ee9319 commit 890656e

1 file changed

Lines changed: 38 additions & 28 deletions

File tree

‎internal/purchase/execution.go‎

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -254,34 +254,9 @@ func (m *Manager) executeForAccount(ctx context.Context, baseExec *config.Purcha
254254
return false, procErr
255255
}
256256

257-
// #642: a per-account run can be a partial success — some recs committed
258-
// to purchase_history (Purchased=true) while others failed. Marking the
259-
// row "failed" in that case is wrong (it hides the real commitments and
260-
// invites a re-approve that double-buys). Record "partially_completed"
261-
// instead so the row reflects reality, and still send the confirmation
262-
// for the recs that did purchase.
263-
partial := len(purchaseErrors) > 0 && anyRecPurchased(acctExec.Recommendations)
264-
switch {
265-
case partial:
266-
now := time.Now()
267-
acctExec.Status = "partially_completed"
268-
// Append so any audit-gap note already stamped by
269-
// aggregatePurchaseOutcomes (issue #621) survives alongside the
270-
// per-rec failure list.
271-
acctExec.Error = appendErrNote(acctExec.Error, strings.Join(purchaseErrors, "; "))
272-
acctExec.CompletedAt = &now
273-
case len(purchaseErrors) > 0:
274-
acctExec.Status = "failed"
275-
acctExec.Error = appendErrNote(acctExec.Error, strings.Join(purchaseErrors, "; "))
276-
default:
277-
now := time.Now()
278-
acctExec.Status = "completed"
279-
acctExec.CompletedAt = &now
280-
}
281-
282-
// committed is the gate executeMultiAccount uses to distinguish a partial
283-
// run from a flat failure (issue #1014): true when any rec purchased.
284-
committed = anyRecPurchased(acctExec.Recommendations)
257+
// Resolve the final status/error/completion stamp from the per-rec outcome
258+
// (#642), and learn whether any rec committed (#1014).
259+
partial, committed := applyAccountOutcome(&acctExec, purchaseErrors)
285260

286261
if saveErr := m.config.SavePurchaseExecution(ctx, &acctExec); saveErr != nil {
287262
return committed, fmt.Errorf("AUDIT LOSS: failed to save execution record for account %s: %w", account.ID, saveErr)
@@ -306,6 +281,41 @@ func (m *Manager) executeForAccount(ctx context.Context, baseExec *config.Purcha
306281
return committed, nil
307282
}
308283

284+
// applyAccountOutcome stamps the final Status / Error / CompletedAt on acctExec
285+
// from the per-rec purchase outcome and reports whether the run was a partial
286+
// success and whether any rec committed.
287+
//
288+
// A per-account run can be a partial success (#642): some recs committed to
289+
// purchase_history (Purchased=true) while others failed. Marking the row
290+
// "failed" in that case is wrong (it hides the real commitments and invites a
291+
// re-approve that double-buys), so record "partially_completed" instead and let
292+
// the caller still send the confirmation for the recs that did purchase.
293+
//
294+
// committed is the gate executeMultiAccount uses to distinguish a partial run
295+
// from a flat failure (#1014): true when any rec purchased.
296+
func applyAccountOutcome(acctExec *config.PurchaseExecution, purchaseErrors []string) (partial, committed bool) {
297+
committed = anyRecPurchased(acctExec.Recommendations)
298+
partial = len(purchaseErrors) > 0 && committed
299+
switch {
300+
case partial:
301+
now := time.Now()
302+
acctExec.Status = "partially_completed"
303+
// Append so any audit-gap note already stamped by
304+
// aggregatePurchaseOutcomes (issue #621) survives alongside the
305+
// per-rec failure list.
306+
acctExec.Error = appendErrNote(acctExec.Error, strings.Join(purchaseErrors, "; "))
307+
acctExec.CompletedAt = &now
308+
case len(purchaseErrors) > 0:
309+
acctExec.Status = "failed"
310+
acctExec.Error = appendErrNote(acctExec.Error, strings.Join(purchaseErrors, "; "))
311+
default:
312+
now := time.Now()
313+
acctExec.Status = "completed"
314+
acctExec.CompletedAt = &now
315+
}
316+
return partial, committed
317+
}
318+
309319
// resolveSingleAccountProvider derives per-account credentials for the
310320
// single-account execution path. Returns (nil, "", nil) when no account can be
311321
// identified (ambient credentials are used in that case), or when no recs are

0 commit comments

Comments
 (0)