gigafibre-fsm/apps/ops
louispaulb 5c55087198 fix(campaigns/parse): keep no-name rows + surface skip breakdown
Map CSV rows that had a valid email but no name in the source column
were silently dropped at parsing — that's why a campaign would end up
with N unpaired Giftbit shortlinks for N "missing" contacts that
weren't actually missing, just nameless.

The send worker already handles a missing firstname by substituting
"cher client" / "dear customer", so dropping the row was wasteful.
Now we keep the contact and surface a name_warning on the row so the
operator can either edit the firstname in Step 2 or accept the
default.

Also added counters for previously-silent skip paths:
- duplicate: row's email was already seen above (1 gift / household
  consolidation, depending on the multi setting)
- multi_skip: couple skipped because multi='skip' was selected

Wizard Step 2 imbalance banner now ventilates the skip breakdown so
the operator understands exactly where the N "missing" contacts went:

  Ventilation des contacts droppés au parsing du Map CSV (sur 213
  lignes brutes) : 8 sans email valide · 5 emails en double · 0
  couples ignorés · 3 sans nom (gardés, utilisent "cher client" à
  l'envoi)

Unrelated reassurance on the question that triggered this: language
fallback to French is already in place (matchCustomer returns
language:'fr' on miss, worker reads (r.language || 'fr')) so any
unmatched recipient gets the FR template, never an English one by
default.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 11:43:22 -04:00
..
.quasar feat(ops/client): edit/delete/reorder subscriptions + rebate nesting 2026-04-23 11:21:41 -04:00
infra docs: reorganize into architecture/features/reference/archive folders 2026-04-22 11:51:33 -04:00
public/icons feat: add ops app + CONTEXT.md, simplify URL to /ops/ 2026-03-30 22:41:58 -04:00
src fix(campaigns/parse): keep no-name rows + surface skip breakdown 2026-05-22 11:43:22 -04:00
src-pwa feat: nested tasks, project wizard, n8n webhooks, inline task editing 2026-04-01 13:01:20 -04:00
.env.example feat(hub+ops): user invite flow sends temp password via Mailjet + dev .env.example 2026-05-05 19:50:06 -04:00
deploy.sh feat: nested tasks, project wizard, n8n webhooks, inline task editing 2026-04-01 13:01:20 -04:00
index.html feat: add ops app + CONTEXT.md, simplify URL to /ops/ 2026-03-30 22:41:58 -04:00
package-lock.json feat(ops/campaigns): pivot template editor to Unlayer (vue-email-editor) 2026-05-22 06:14:06 -04:00
package.json feat(ops/campaigns): pivot template editor to Unlayer (vue-email-editor) 2026-05-22 06:14:06 -04:00
quasar.config.js feat: contract → chain → subscription → prorated invoice lifecycle + tech group claim 2026-04-22 20:40:54 -04:00