2b85735006
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d6096fe1f8 |
feat(campaigns): apply real TARGO brand + auto-route FR/EN by Customer.language
Brand audit against the official guide (Feb 2026 v1.0) caught several inconsistencies in the email template: - Wrong primary green: was #019547, should be #00C853 (Targo Green from brand palette). Globally replaced. - Wrong gradient: was #019547→#06a04d, should be 135deg #00C853→#005026 (the official Gradient Targo from the brand). Now using Outlook-safe background-image + bgcolor fallback for solid green on Outlook desktop. - Wrong contact info: facturation@targointernet.com / 514 242-1500 → support@targo.ca / 514 448-0773 / 1 855 888-2746 (per §11 of guide). - Wrong website: targointernet.com + gigafibre.ca → www.targo.ca. - Missing slogan + green dot: footer now ends with the trademark tagline "Services de confiance, tout-en-un, près de chez vous." with the obligatory green period (always FR — it's the trademark, not a marketing line, so stays untranslated in EN template too). - Missing brand fonts: added Space Grotesk (display) + Plus Jakarta Sans (body) via Google Fonts. Wrapped in MSO conditional comments so Outlook desktop skips the request and falls back to Helvetica via the explicit font-family stack on every element. - Wrong body bg / text colors: now #F5FAF7 (Muted) / #1B2E24 (Foreground) per brand semantic palette. - Wrong info-pill bg: was #f3f4f3 → #F5FAF7 (Muted). - Added official dark footer band #1C1E26 (Targo Dark) with white inverted wordmark, slogan, address, copyright. Multilang routing (FR/EN): - lib/campaigns.js matchCustomer now fetches Customer.language (14k FR / 1k EN distribution confirmed on prod). Default 'fr' for unmatched contacts. - New templateForLanguage(lang) helper picks gift-email-<lang>.html, falls back to FR. Resolves 'fr-CA' → 'fr' etc. - sendCampaignAsync pre-loads templates per recipient with an in-memory cache to avoid re-reading from disk on every send. - gift-email-en.html created — English translation of the full FR template, keeping the slogan in French (it's the trademark tagline). - year variable now injected (replaces hardcoded © year). UI (CampaignNewPage): - New "Langue" column in the Step 2 recipient table. Shows a clickable chip (FR primary green / EN blue-grey) that toggles language inline, so a campaign manager can override the ERPNext-resolved language per recipient. - Step 3 recap now shows "Répartition par langue: 145 × FR, 12 × EN" before confirming the send. Spell-check: - TemplateEditorPage HTML mode now has spellcheck="true" + dynamic lang attribute on the textarea, picked from the template name suffix (gift-email-fr → fr, gift-email-en → en). Browser's native dictionary flags typos in real time. AI-grade rewrites deferred to the future /campaigns/ai/rewrite endpoint discussed previously. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
5d763f12ff |
feat(hub): gift-campaign module — CSV parse, customer match, async send + webhook
- lib/campaigns.js (new): full backend for the gift campaign flow.
• Two CSV parsers: parseMapCsv handles the pipe-delimited legacy export
with title preamble; parseGiftbitCsv auto-detects the URL column.
• Multi-strategy customer match against ERPNext: email → phone → civic
+ postal_code on Service Location. Returns confidence score (1.0 /
0.9 / 0.8) and match method. Addresses the 25%-match limitation of
the legacy_delivery_id approach by fanning out to address-based
lookup when email/phone miss.
• Storage: JSON files at data/campaigns/<id>.json with embedded
recipients array. Counters auto-recomputed from recipient statuses
on every save (single source of truth).
• Async send worker: setImmediate fire-and-forget loop, throttle
configurable, broadcasts recipient-update events over SSE topic
campaign:<id> for live UI progress.
• Mailjet webhook handler at POST /campaigns/webhook: matches events
to recipients via X-MJ-CustomID = "<campaign-id>:<recipient-index>"
for O(1) lookup, falls back to MessageID scan if CustomID absent.
• Template CRUD endpoints (GET/PUT /campaigns/templates/:name) with
automatic timestamped backups before overwrite. Path-traversal
guarded by an allow-list (only gift-email-fr editable).
• Mustache section renderer ({{#var}}...{{/var}}) shared with the CLI.
- lib/email.js: accept opts.from override (campaign sender differs from
default MAIL_FROM) and opts.headers passthrough (needed for the
X-MJ-CustomID header that drives webhook → recipient correlation).
Return the nodemailer info object on success instead of a bare bool so
callers can capture info.messageId — legacy truthy checks still work.
- server.js: register /campaigns/* route on the hub router.
- templates/gift-email-fr.html: bundled copy of the campaign template
inside the hub so it's deployable without scripts/ on the path. Kept
in sync manually with scripts/campaigns/templates/gift-email-fr.html.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
41d9b5f316 |
feat: flow editor, Gemini QR scanner with offline queue, dispatch planning v2
Major additions accumulated over 9 days — single commit per request. Flow editor (new): - Generic visual editor for step trees, usable by project wizard + agent flows - PROJECT_KINDS / AGENT_KINDS catalogs decouple UI from domain - Drag-and-drop reorder via vuedraggable with scope isolation per peer group - Chain-aware depends_on rewrite on reorder (sequential only — DAGs preserved) - Variable picker with per-applies_to catalog (Customer / Quotation / Service Contract / Issue / Subscription), insert + copy-clipboard modes - trigger_condition helper with domain-specific JSONLogic examples - Global FlowEditorDialog mounted once in MainLayout, Odoo inline pattern - Server: targo-hub flow-runtime.js, flow-api.js, flow-templates.js - ERPNext: Flow Template/Run doctypes, scheduler, 5 seeded system templates - depends_on chips resolve to step labels instead of opaque "s4" ids QR/OCR scanner (field app): - Camera capture → Gemini Vision via targo-hub with 8s timeout - IndexedDB offline queue retries photos when signal returns - Watcher merges late-arriving scan results into the live UI Dispatch: - Planning mode (draft → publish) with offer pool for unassigned jobs - Shared presets, recurrence selector, suggested-slots dialog - PublishScheduleModal, unassign confirmation Ops app: - ClientDetailPage composables extraction (useClientData, useDeviceStatus, useWifiDiagnostic, useModemDiagnostic) - Project wizard: shared detail sections, wizard catalog/publish composables - Address pricing composable + pricing-mock data - Settings redesign hosting flow templates Targo-hub: - Contract acceptance (JWT residential + DocuSeal commercial tracks) - Referral system - Modem-bridge diagnostic normalizer - Device extractors consolidated Migration scripts: - Invoice/quote print format setup, Jinja rendering - Additional import + fix scripts (reversals, dates, customers, payments) Docs: - Consolidated: old scattered MDs → HANDOFF, ARCHITECTURE, DATA_AND_FLOWS, FLOW_EDITOR_ARCHITECTURE, BILLING_AND_PAYMENTS, CPE_MANAGEMENT, APP_DESIGN_GUIDELINES - Archived legacy wizard PHP for reference - STATUS snapshots for 2026-04-18/19 Cleanup: - Removed ~40 generated PDFs/HTMLs (invoice_preview*, rendered_jinja*) - .gitignore now covers invoice preview output + nested .DS_Store Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |