VTG · Lead → Invoice Process Map
E-Rate + Commercial tracks · All swim lanes · Workers included · Updated Oct 1 2026 · vtg-process-map.pages.dev ↗
Live
In Progress
Planned
Manual
Gap
Decision
Flow Diagram
Data Flow
Written SOP
Gap Analysis
Workers
Glossary
Automations
Dashboards
Changelog
0 · CRM Setup
1 · Lead / Intake
2 · Bid Building
3 · Post-Sale
4 · Delivery
5 · Invoice
E-RATE TRACK (VTG-06) ▾
Automation
Account + Contact Created
El Nova pushes on own timing · dedup logic
Live
⚡ El Nova integration
Salesforce Account Sync
Account + Contact upserted to SF · UID written back to monday
Live
⚡ vtg-sf-account-sync
Lead Opportunity Score
Customer Summary PDF → Opportunity Score on the lead
Live
⚡ vtg-lead-score
ScopeStack Proposal + SOW
Blueprint in intake form → proposal + SOW auto-generated + delivered to Bids #3
Live
⚡ ScopeStack API
⚡ vtg-scopestack-doc-sync
Generate Proposal → Proposal PDF
Injects client logo + bid due date onto SOW cover page → uploads merged PDF to Bids #3
Live
⚡ vtg-proposal-builder
🔘 Proposal Status column
El Nova → Bids #3 Item
Intake form submit → Account/Contact linked → item created
Live
⚡ vtg-bid-intake (patched Sep 3)
Addendum → Live Bid
New lead or new file on an accepted lead → bid’s Addenda + SharePoint · owner notified
Live
⚡ vtg-bid-intake
⚡ vtg-sp-folders /addenda
Accepted Monitor Board
El Nova creates item · polls USAC funding on schedule
LiveParallel
⚡ El Nova polling
SharePoint Bid Folder
Folder Creation → folder + Base Bid Docs + 470/RFP · link written · both subitems closed
Live
⚡ vtg-sp-folders
Subitem Due Dates
Business days back from Bid Due Date → date3 · reminders fire
Live
⚡ vtg-bid-task-dates
Deal Reg Automation
Playwright → manufacturer portal
In Progress
⚡ dealreg.py
SOV Builder
SOV PDF + Excel → SOV PDF column → SharePoint copy
Live
⚡ vtg-sov-builder
⚡ vtg-sp-folders /sov
Salesforce Sync
Every Bids #3 stage change → SF Opportunity
Live
⚡ vtg-monday-sf-sync
CS Order Form + New Client → NetSuite
Post-Sale → CSOP PDF + subitems · new client created or linked in NetSuite
Live
⚡ vtg-cs-form
⚡ vtg-ns-so-backfill (NS customer)
⚡ automation 482374746
CW Sell / CPQ
Paused Sep 29 2026 — not part of VTG’s plan
Paused
⚡ vtg-monday-cpq (still called by vtg-cs-form)
PO Sync
NS Vendor PO # + status → Projects #4
Live
⚡ vtg-po-sync
Revenue Month
Follows Timeline end · stamped + locked at Ready for Invoicing / Closed
Live
⚡ vtg-revenue-month
Meeting Notes → Subitems
Sembly action items matched to Projects #4 subitems · notes posted
Live
⚡ vtg-meeting-sync
Materials Log → Ready to Invoice
PM submits → stage auto-advances + email
Live
⚡ vtg-materials-log
⚡ vtg-billing-ready
NS Invoice Creation
Manual today → vtg-ns-mcp-sync planned
Manual→ Planned
⚡ vtg-ns-mcp-sync
Invoiced / Remaining to Bill
NS invoices → Invoiced to Date + Remaining to Bill on Projects #4 · every 4h
Live
⚡ vtg-ns-so-backfill
Sales Rep
Click accept_470
Opens vtg-bid-intake form in new tab
Manual
Fill Intake Form
Sales Exec · Blueprints · delivery · partner · mfr · due date · bond
Manual
Fill Bid Intake Form
Delivery, partner, mfr, due date, bond
Manual
Confirm PO / Award
FCDL received; moves Bid to Post-Sale
Manual
Bid Team
Deal Registration
Branden → manufacturer portals
Manual → Auto
Bid Build + Compile
Mark (BOM/cabling) → Dylan (compile + submit) · auto-subitems with business-day due dates
Manual
Jon (PM)
Projects #4 Setup + Delivery
New → Installing stages; oversees field
Manual
Finance
Billing Notification Received
eratebilling@vtgus.com via vtg-billing-ready
Live
Create NS Invoice
Cari / Kevin — manual today
ManualGap
E-RATE OP SYSTEM (Deals + Projects · Financial / Scheduling Layer) ▾
Automation
E-Rate Deals Item Created
Post-Monday → item on E-Rate Deals board
Live
⚡ automation 559103546
E-Rate Projects Item Created
E-Rate Deals Status: Pipeline → Awarded
Live
⚡ automation 7917669964
Status → Booked · Booking Date Stamped
E-Rate Deals Status → Booked → today's date auto-set
Live
⚡ automation 7917670450
Jon (PM)
Manage E-Rate Projects Execution
Execution Status · Billing Status · Risk Flag · Planned Start
Manual
COMMERCIAL TRACK (VTG-10 Cabling + Non-E-Rate) ▾
Automation
MSP Portal CSOP → Projects #4
Form submission → item + task list created directly in Projects #4
Live
⚡ vtg-msp-csop
No Bids #3 step
Bypasses bid workflow
Task List Built by CSOP Form
Subitems auto-created on Projects #4 item
Live
⚡ vtg-msp-csop
Install → Ready for Invoicing
Stage advance → billing notification fires
Live
⚡ vtg-billing-ready
NS Invoice Creation
Manual today → vtg-ns-mcp-sync planned
Manual→ Planned
⚡ vtg-ns-mcp-sync
Invoiced / Remaining to Bill
NS invoices → Invoiced to Date + Remaining to Bill on Projects #4 · every 4h
Live
⚡ vtg-ns-so-backfill
Jon (PM)
Manage Delivery + Task List
Works subitems in Projects #4; advances stage when complete
Manual
Finance
Billing Notification Received
eratebilling@vtgus.com · same flow as E-Rate
Live
Create NS Invoice
Manual today
ManualGap

Click any step to open detail panel →

Data Flow — what runs today

Which system holds which record, and what moves between them, for a bid that is being worked right now. Everything drawn here is built and deployed. Steps done by hand are marked as such rather than left out — they are the honest picture, and they are where the planned work goes. Nothing planned or agreed-but-unbuilt appears on this page; that lives in Gap Analysis.

The two routes differ because commercial work goes through the Salesforce sales cycle and E-Rate does not.

E-Rate
Commercial
monday.comLeads, bids, projects
NetSuiteCustomers, orders, invoices
SalesforceReporting · issues the UID
Lead intake
1
Lead, account + contactsEl Nova reads the 470
No NetSuite record at this point
2
account + contact
3
Account + contact upsertedvtg-sf-account-sync
UID (Salesforce UID__c)
4
UID stamped on the accounttext_mm6s8adk
Bid in progress
5
New lead, or new file on a lead, screened for an addendumvtg-bid-intake /lead-created + /lead-files-changed · live
6
Rep accepts the 470bid created · vtg-bid-intake · SharePoint folder by vtg-sp-folders · subitem dates by vtg-bid-task-dates
7
Stage or value changesBids #3
opportunity
Opportunity upsertedvtg-monday-sf-sync
Bid won · post-sale
8
Bid wonmoves to Post-Sale
stage
Opportunity stage → Post-Salevtg-monday-sf-sync stage map
9
CS Order formvtg-cs-form · CSOP PDF emailed · Projects #4 item + UID · tax certificate · PO number hard-blocked · New Client Setup when the account has no NS ID
new client
10
Customer created or linkedvtg-ns-so-backfill · externalId mon-<account id> · since Sep 28 2026
NS ID
11
NS Customer ID on the accountAccounts text_mm7m8z67 · the match key
Order to invoice
12
Sales order enteredby hand in NetSuite
SO #
13
SO # on the projectvtg-ns-so-backfill · every 4h · project → account → NS Customer ID → SO · fuzzy name off · SO Check
14
Materials log submittedvtg-materials-log · PM, at Installing
materials
SO lines + item fulfillmentvtg-materials-log
15
Ready for Invoicingvtg-billing-ready → email to finance · vtg-revenue-month locks Revenue Month
16
Invoice createdby hand in NetSuite
invoiced amounts
17
Invoiced to Date + Remaining to Billvtg-ns-so-backfill billing sync · every 4h
Automated
Feeds Salesforce reporting
UID
Done by hand
Does not happen
monday.comProjects
NetSuiteCustomers, orders, invoices
SalesforceCommercial pipeline
Intake
1
CSOP form via the MSP portalvtg-msp-csop → Projects #4 item + task subitems
No automated link — commercial pipeline is keyed in Salesforce by the sales team
2
No Bids #3 item, no bid buildthe CSOP task list is the scope from day one
No NetSuite record at this point
Delivery
3
Jon works the subitemsProjects #4 · New → Installing
4
Materials log submittedvtg-materials-log · at Installing
materials
SO lines + item fulfillmentvtg-materials-log
Invoice
5
Ready for Invoicingvtg-billing-ready → email to finance · same chain as E-Rate
6
Invoice createdby hand in NetSuite
invoiced amounts
7
Invoiced to Date + Remaining to Billvtg-ns-so-backfill · by Customer PO or SO · every 4h
Automated
Done by hand
Does not happen

NetSuite customer — created from the CS Order form

Since Sep 28 2026 the CS Order form’s New Client Setup creates or links the NetSuite customer and writes the NS ID back to Accounts #1. The Sep 29 check that found no NetSuite code had read the Sep 24 copy of vtg-cs-form; the Sep 28 build calls /api/ns-customer, which reaches vtg-ns-so-backfill over a service binding.

Salesforce stage map — settled

Read from the live code (version dc33a840): Bid Building → Stage 3, Awaiting Results → Stage 6, plus Post-Sale, Post-Monday and Lost. Folder Creation, Deal Reg, Bid Compilation, Bid Submittal and the other stages send no stage — that is the open stage-map gap.

The UID is reference only now

Salesforce issues the UID and it is stamped on the monday account, but as of Sep 28 2026 it is no longer the match key — the NetSuite Customer Internal ID is. The UID had not held stable, Salesforce had been duplicating accounts, and it never matched NetSuite’s own custentity_acs_unique_entity_identifier anyway. New NS customers created from the CS form carry externalId mon-<monday item id> instead. One dependency is left: vtg-ns-so-backfill’s auto-sync still links project to account by UID. See the UID gap.

Where the hand-keyed steps go

Two by-hand steps are left — sales order and invoice. They are the target of the planned monday → NetSuite order push and the Ready-for-Invoicing invoice flow, both coded in vtg-ns-mcp-sync, whose cron currently fails on every run; the invoice flow also waits on the NetSuite service item ID from finance. Gap Analysis carries the detail.

E-Rate Track · VTG-06
El Nova Leads → Bids #3 → Projects #4 → NetSuite
0
CRM Setup — Account & Contact Creation
Runs independently · El Nova integration + vtg-sf-account-sync · E-Rate only
0.1 · El Nova Pushes Account + Contact RecordsAutomation (El Nova)Live
On its own schedule — not tied to the accept_470 click — El Nova pushes district and contact data into the CRM. It checks for existing records first; new Accounts (board 18176632844) and Contacts (board 18176633260) are only created if they don't already exist (dedup logic). Sales reps never manually create these records.
⚡ El Nova integration · Austin Novakowski's original webhook automations
0.2 · vtg-bid-intake Waits for These RecordsAutomationLive
When vtg-bid-intake fires after accept_470, it performs a district name search to auto-link the Account and Contact to the new Bids #3 item. The 5-second retry loop in vtg-bid-intake exists specifically because El Nova may not have written the Account/Contact yet at the exact moment the bid item is being created. This is the dependency between Phase 0 and Phase 1.
⚠ Note: Commercial / MSP portal track does not create Accounts or Contacts — E-Rate only
0.3 · vtg-sf-account-sync Upserts Account + Contact to SalesforceAutomationLive — Sep 12 2026
⚠ Runs when called — today that is only backfill.mjs, run by hand. No monday automation triggers it (checked Oct 1 2026). When it does run, vtg-sf-account-sync upserts both the Account and Contact objects into Salesforce using Monday_Item_ID__c as the external ID — creating new SF records or updating existing ones idempotently. After the SF upsert, the Worker writes the Salesforce Account ID back to the UID column (text_mm6s8adk) on the monday.com Accounts board, completing the cross-system link. A backfill script (backfill.mjs) ran against all 791 existing accounts to populate Salesforce and stamp the UID column. Complements vtg-monday-sf-sync which syncs Bids — this Worker handles the CRM Account/Contact layer.
⚡ vtg-sf-account-sync · SF Client Credentials OAuth · Monday_Item_ID__c external ID · KV: SF_ACCOUNT_TOKEN_KV
1
Lead Intake
El Nova Leads Board → Bids #3 · Sales Rep + Automation
1.1 · 470# Arrives on El Nova Leads BoardAutomationLive
El Nova pushes inbound Form 470 opportunities to the El Nova Leads board (ID 18181651809). Each lead carries a district name, 470#, and Opportunity Score extracted from the USAC PDF via two-layer decode (ASCII85 + FlateDecode) — done by vtg-lead-score when the Customer Summary PDF lands, writing Opportunity Score (numeric_mm5w3j).
⚡ vtg-lead-score · Leads webhook 617748761 (Customer Summary column)
1.1a · Addendum Screen — Is This Lead Actually a New Opportunity?AutomationLive — Sep 24 2026
Every new Leads item is screened before anyone works it. vtg-bid-intake POST /lead-created compares the lead name (the bare 470 number) against Bids #3 470__. One 470 never covers two separately-bid RFPs — so a 470 already on a live bid means this lead is an addendum, not a new opportunity, and working it produces a duplicate bid. On a match the Worker attaches the addendum document to the bid’s Addenda column, increments Addendum #, stamps Last Addendum Date and sets Addendum Status to Received - Unreviewed, then posts a courtesy update on the lead so nobody clicks accept_470 on it. The bid’s stage never moves — it stays where it is and gets flagged. If a district cancels a 470 it issues a whole new one, which is a genuine new opportunity (old bid → Lost); and by law no addendum can arrive after the submittal date, so there is no post-submittal path. Currently running with ADDENDUM_DRY_RUN = true: matches are logged, nothing is written.
⚡ monday webhook 642139356 (Leads create_item) → vtg-bid-intake /lead-created
1.1b · Addendum Added to an Existing LeadAutomationLive — Oct 1 2026
The 470 feed usually adds an addendum to the existing lead’s RFP Documents or Form 470 column rather than creating a new lead. vtg-bid-intake POST /lead-files-changed checks whether the lead’s 470 belongs to exactly one live bid; if so, only the new files are copied to the bid’s Addenda column, the bid is flagged, the bid owner and the lead’s Sales Executive are notified, and the lead goes back to Accepted Leads — no second intake form. vtg-sp-folders then copies the addendum into the bid’s SharePoint folder. Leads with no live bid are left alone. Dylan’s two “Accepted Leads → New Leads” addendum automations were deactivated Oct 1.
⚡ Leads webhooks 645545831 (RFP Documents) + 645545840 (Form 470) → vtg-bid-intake /lead-files-changed · Bids #3 webhook 645561102 → vtg-sp-folders /addenda
1.2 · Rep Clicks accept_470 → vtg-bid-intake Form OpensSales Rep (Alan / Jake / Kevin)Manual
Rep clicks accept_470. Automation 7920733007 sets Status → Pending Intake, which fires webhook 632506055 to vtg-bid-intake; the Worker writes the 📋 Intake Form link onto the lead and the rep opens the form from it in a new tab. Rejected leads simply close the lead — no webhook fires, no Bids item created.
⚡ Automation 7920733007 → Status → Pending Intake → webhook 632506055 → vtg-bid-intake · webhook 608965294 (Status → Accepted) is deactivated
1.3 · Rep Fills Intake Form (incl. Sales Exec + Blueprints)Sales Rep (Alan / Jake / Kevin)Manual
The vtg-bid-intake form now includes all intake fields in one place: Sales Executive, ScopeStack Blueprint(s), delivery method, partner, manufacturer, distributor, bid due date, and bond required. Blueprint selection inside the form triggers the ScopeStack API to auto-create a proposal. On submit, the Worker patches all columns to Bids #3, writes the SOV Builder link to link_mm591mdg, and creates a bond subitem + email if bond is required. The accept also sends a trigger to El Nova, which creates the Accepted Monitor board item.
⚡ ScopeStack API · Blueprint → proposal auto-created · live end-to-end
⚡ vtg-scopestack-doc-sync (LIVE Sep 8 2026) · ScopeStack document_status_changed webhook → .docx SOW auto-uploaded to Bids #3 SOW Document column (file_mm6wm4hn) · Generate SOW button (button_mm70vvrb) on Bids #3 triggers programmatic generation
1.3b · Accepted Monitor Board (Parallel)El Nova / AutomationLiveParallel Track
The accept trigger sent to El Nova causes El Nova to create an item on the Accepted Monitor board. This board runs in parallel to the main bid flow — it polls USAC automatically on a schedule to watch whether the 470 is funded. It is an FYI / watchdog board; the main Bids #3 flow does not gate on it. Rejected leads do not appear here — reject simply closes the lead.
⚡ El Nova · USAC funding polling · parallel to main flow · does not block Bids #3 progression
1.4 · vtg-bid-intake Creates Bids #3 ItemAutomationLive
Worker creates a new item in Bids #3 (board 18176633000) under New Bid Folder Creation. Auto-links Account (18176632844) and Contact (18176633260) via district name search with 5s retry. Writes the "📋 Open Intake Form" link and the 📊 SOV Builder link (link_mm6vbks) to the bid item.
⚡ vtg-bid-intake · vectorfi-admin.workers.dev
1.4b · SharePoint Bid Folder CreatedAutomationLive — Sep 24 2026
When the bid is created at Folder Creation, vtg-sp-folders builds its SharePoint folder in cust_ERATE{FY}RFPs: named after the bid without the colon, the Base Bid Docs folders copied in with their files, and the Lead’s 470, RFP and Customer Summary in the folder root. It writes the SharePoint Link column and sets both Folder Creation subitems to Complete. If anything fails, the subitem goes to Stuck with an update explaining why. Bids that already have a SharePoint Link are skipped.
⚡ vtg-sp-folders · webhooks 641680795 (item created) + 641680804 (Bid Stage) · Microsoft Graph
1.5 · Rep Fills Bid Intake FormSales RepManual
Rep opens the form link and completes: delivery method, partner, manufacturer, distributor, bid due date, bond required. Worker patches all columns. If bond required, subitem created and email fires to bonds@vtgus.com + CHC-Surety@alliant.com.
⚡ vtg-bid-intake · dual jsPDF (intake + Alliant bond forms)
2
Bid Building
Bids #3 stages: Deal Reg → Bid Building → Bid Compilation → Bid Submittal → Awaiting Results
2.1 · Deal RegistrationBrandenAutomating
Branden submits to manufacturer portals (Ruckus, Cisco, etc.). dealreg.py (Playwright) is built and field-mapped but not fully live — dynamic portal elements on Ruckus are causing failures.
⚠ Gap: dealreg.py not yet live · Branden still submitting manually
2.2 · Subitem Task System Activated on New BidAutomationLive
When a bid item is created, automation 482374765 immediately creates 23 subitems covering every stage from Folder Creation through Awaiting Results. Each task is pre-tagged with its Bid Stage, pre-assigned to the relevant person, and given a due date counted back from the bid due date in business days by vtg-bid-task-dates (bids created after Sep 24 2026). Tasks are never re-created per stage — the full lifecycle checklist exists from day one, with future tasks in "Still To Do" or "Create Item" status until needed. The three per-person parent columns (Alan / Jake / Dylan Subitem Status) are driven by automations: they flip to Due Today at 11am ET when a task's date arrives, and clear when the task is marked Complete.
⚡ automation 482374765 · subitem board 18176633598 · due dates written to date3 by vtg-bid-task-dates (business days, federal holidays skipped)
2.3 · Bid Build — Cabling, Disty, SOVMarkManual
Mark pulls distribution pricing and builds cabling scope. vtg-sov-builder is available for multi-tab SOV creation — generates the SOV as a PDF and an Excel workbook, versioned, into the Bids #3 SOV PDF column; vtg-sp-folders copies each version into the bid’s SharePoint folder (Base Bid Docs/3 -SOV). SOV payload includes vendorPOs array pre-grouped by vendor for future NS PO creation.
⚡ vtg-sov-builder · KV: SOV_FORMS + SKU_CATALOG
2.4 · Bid Compile + SubmittalDylanManual
Dylan compiles all components and submits on the USAC EPC portal. Each stage change syncs to Salesforce via vtg-monday-sf-sync (upsert on Monday_Item_ID__c).
⚡ vtg-monday-sf-sync · Bids #3 stage → SF Opportunity
2.5 · Award DecisionSales RepManual
USAC issues FCDL. Won bids → Post-Sale. Lost bids → Lost sub-board. Wins also archived in Wins Archive sub-board.
3
Post-Sale
Bids #3 stage: Post-Sale · Sales Rep + Automation
3.1 · CS Order Form GeneratedAutomationLive
When Bids #3 → Post-Sale (webhooks 562741747 + 483153616), vtg-cs-form generates a CSOP PDF, emails to erateops@vectortechgroup.com and Sales@vtgus.com (both TO) with KV deduplication, and auto-creates a monday subitem checklist. On form submit, vtg-cs-form creates a Projects #4 item, appends 6 PM subitems (Project Kickoff Meeting, Site Access Coordination, Installation Scheduling, Weekly Status Updates, Project Documentation, Project Closeout) tagged 'Project Management — E-Rate' — skipped only for Equipment Only bids or when Network Infrastructure Deployment – PM is already selected — and stamps the UID on the new Projects #4 item by reading the Account's UID (text_mm6s8adk) and writing it to text_mm76zvbz. Updated Sep 10 2026; UID stamp added Sep 14 2026. New Client Setup (live Sep 28 2026): when the account has no NetSuite Customer ID, Section 1B collects Cari’s new-client fields and the submit creates or links the NetSuite customer through vtg-ns-so-backfill, writing the NS ID back to Accounts #1. Simultaneously, automation 482374746 creates 6 Post-Sale subitems on the bid item: (1) Letter of Intent signed + uploaded to SharePoint (Jon), (2) Create Contract in ConnectWise Sell — CW Sell paused Sep 29 2026, (3) If SPI: FCDL uploaded to SharePoint or N/A if BEAR (Alan+Jake), (4) If SPI: FCDL templated email sent or N/A if BEAR (Alan+Jake), (5) Purchase Order issued by customer + uploaded to SharePoint (Alan+Jake), (6) Update SOV, get Disty quote to match, upload to SharePoint (Alan+Jake).
⚡ vtg-cs-form · SMTP2GO via noreply@vtgus.com · automation 482374746 (6 Post-Sale subitems)
⚡ vtg-cs-form /api/ns-customer → vtg-ns-so-backfill /api/customer-from-account (NS_WRITE_ENABLED=1)
⏸ "Create Contract in ConnectWise Sell" subitem — CW Sell work paused Sep 29 2026
3.2 · CPQ / ConnectWise Sell — Paused—Paused — Sep 29 2026
ConnectWise Sell is not part of VTG’s plan, so CPQ work is paused unless that changes. vtg-cs-form still calls vtg-monday-cpq on every CS Order submit (it clones the E-Rate Contract template and writes Quote # / CPQ Status back to Bids #3 when the call completes); line items were never built. Direct-to-NetSuite ordering stays on the Planned list.
⏸ vtg-monday-cpq · vtg-cw-sync — paused
3.3 · PO / Funding ConfirmedSales Rep / KevinManual
Rep or Kevin confirms customer PO and E-Rate funding. vtg-po-sync (live Aug 25 2026) syncs the NetSuite Vendor PO # and PO Status back to Projects #4 via cron every 4h + webhook on NS SO# column change.
⚡ vtg-po-sync · KV: PO_SYNC_KV (2c487e21…)
4
Project Delivery
Projects #4 stages: New → Installing → Ready for Invoicing · Jon (PM) + Field Crew
4.1 · Project Setup on Projects #4JonManual
Jon creates the Projects #4 item (board 18176626554) linked to the winning bid. Project Year dropdown auto-set by vtg-set-project-year. Stages advance (live labels): Accept → Procurement → Installing → Closeout → Ready for Invoicing → Closed. Deactivated but still on the board: Waiting for Product → All Product Received → Kick Off → Pre-Install Staging → Installing.
⚡ vtg-set-project-year · dropdown_mkqz1ay (1=2024, 2=2025, 3=2026) · no FY2027 (2700…) mapping
4.1b · Revenue Month Follows the TimelineAutomationLive
vtg-revenue-month keeps Revenue Month (date_mm39fh8x) equal to the end of the project Timeline. When the stage reaches Ready for Invoicing or Closed, it stamps that day’s date and ticks Revenue Month Locked (boolean_mm7a4044), so later timeline edits no longer move it. A daily cron re-syncs unlocked projects that have drifted.
⚡ vtg-revenue-month · Projects #4 webhooks 639640003 (Timeline) + 639640004 (Project Stage) · cron 15 6 * * *
4.2 · Field InstallationField Crew / JonManual
Field crew installs. When stage → Installing, automation (ID 7922447604) auto-populates the Materials Log link column (link_mm6mhdcx). Jon or PM opens vtg-materials-log, selects fiber/copper parts from SKU_CATALOG, and submits. The project card shows Client, Stage, UID, NS Sales Order #, and Monday Item ID pulled live from Projects #4. v4 (Sep 16 2026): On submit, cabling lines are PATCHed directly onto the NS Sales Order and an Item Fulfillment is created — drop-ship SOs get a warehouse note instead. NS result (IF# or confirmation) is posted to the monday thread and stored in KV. Re-push to NS button available on the locked page for retries.
⚡ vtg-materials-log v4 · 1,031 SKUs (951 copper C- + 80 fiber F-) · vtg-sku-catalog KV · On Hand badges from INVENTORY_CACHE KV (NS location 41) · NS SO writeback via OAuth M2M (same cert as vtg-ns-mcp-sync)
4.2b · Meeting Action Items → Project SubitemsAutomationLive
vtg-meeting-sync receives Sembly meeting output. Each action item is matched to a Projects #4 subitem (fuzzy match, scoped to one project when a project code is in the text) and that subitem’s Status is updated, with a note posted on its project. Meeting notes that carry a project code are posted as an update on that project.
⚡ vtg-meeting-sync · Sembly webhook → /meeting-webhook
4.3 · Stage → Ready for InvoicingAutomationLive
Materials log submission advances stage to Ready for Invoicing, stamps date_mm54qwps, posts thread update, and triggers vtg-billing-ready → email to eratebilling@vtgus.com. Automations: 7920569056, 7920172789, 7917999463, 7920230690.
⚡ vtg-billing-ready · vtg-materials-log · SMTP2GO
5
Invoicing
Ready for Invoicing → Closed · Finance (Cari / Kevin)
5.1 · Manual NS Invoice (Current State)Cari / KevinManualGap
Finance receives billing notification email and manually creates the NetSuite invoice. No automated handoff from monday.com to NS for invoice creation today.
⚠ Gap: no automated monday → NS invoice creation
5.1b · Invoiced to Date / Remaining to BillAutomationLive
Every 4 hours vtg-ns-so-backfill finds each project’s NetSuite invoices — by Customer PO, else by the project’s SO — and writes Invoiced to Date (numeric_mm7d9sf4), Remaining to Bill (numeric_mm7db7yk = Total Project Amount − invoiced), Last Invoice Date and Billing Match. Invoiced only — no AR, no credit memos. Projects that SO Check flags as Duplicate project, Mismatch or Cannot verify are skipped until they are cleaned up.
⚡ vtg-ns-so-backfill /api/billing-sync · cron every 4h · Projects #4 billing columns
5.2 · Planned: vtg-ns-mcp-sync Invoice FlowAutomationPlanned
When Projects #4 → Ready for Invoicing, vtg-ns-mcp-sync fires the Ready to Invoice → NS Invoice flow. Auth is live (prod cert ID _Xm9jPsUb1H7DXPj5SmbJQNNKy3l7VU05MVPgGG4TSk). Blocked by: the NS service item internal ID needed from Kevin/Cari. The Worker’s 15-minute cron currently fails on every run (the integration role cannot read transaction). vtg-ns-compare was deleted Oct 1 2026; customer mapping is now the NS Customer Internal ID on Accounts #1, which this Worker does not read yet.
📋 vtg-ns-mcp-sync · cron every 15 min · 6 flows coded
5.3 · Project ClosedJon / FinanceManual
Once invoiced and paid, Projects #4 → Closed. Stage-change automation populates Actual Revenue Month (date_mm4tatyy) feeding the Forecast vs. Actual widget on the Pipeline dashboard (board 18419943586).
E-Rate Op System · Financial & Scheduling Layer
E-Rate Deals (18406412794) + E-Rate Projects (18406413755) · Workspace: E-Rate Operating System (14860884)
1
Post-Monday → E-Rate Deals Item Created
Runs in parallel to Projects #4 · Automation
1.1 · Bids #3 Post-Monday Fires E-Rate Deals CreationAutomationLive
When a Bids #3 item enters the Post-Monday group, automation 559103546 creates an item on the E-Rate Deals board (18406412794) in the E-Rate Operating System workspace. Fields populated: District, FRN, Contract Value, Funding Year, Category, Sales Owner. Status starts at Pipeline. This is the current active flow — the older automations that created a Projects #4 item directly (482374713) and notified CS/PM (482374738) are both inactive.
⚡ automation 559103546 · E-Rate Deals board 18406412794
1.2 · E-Rate Deals Status MaintainedUnknown / GapGap
The E-Rate Deals status (Pipeline → Submitted → Awarded → Booked) is not consistently maintained — it's unclear who updates it and when. This status is the trigger for the next step, so inconsistent updates mean the E-Rate Projects item may not be created reliably.
⚠ Gap: no defined owner or automation for E-Rate Deals status progression
2
Awarded → E-Rate Projects Item Created
E-Rate Deals Status: Pipeline → Awarded · Automation
2.1 · E-Rate Projects Item Auto-CreatedAutomationLive
When E-Rate Deals Status changes from Pipeline → Awarded, automation 7917669964 creates an item on the E-Rate Projects board (18406413755). The item mirrors data from both Bids #3 (Account, Contact, Bid Value, 470#, SharePoint Link, Projects #4 link, Bid Name) and E-Rate Deals (District, Booking Date, Contract Value, Funding Year).
⚡ automation 7917669964 · E-Rate Projects board 18406413755
2.2 · Jon Manages Execution in E-Rate ProjectsJonManual
Jon maintains the E-Rate Projects item as the financial and scheduling view of the project — distinct from Projects #4 which tracks physical delivery. Fields managed: Execution Status (In Execution / Ready / Substantial Completion / Complete / Billed), Billing Status (Ready / Sent / Paid / Not Ready), Planned Start Window (Q1/Q2/Q3/Q4/Summer/Post-Funding), Planned + Actual Start Dates, Completion Date, Risk Flag (Delayed / At Risk / Missing Start / None), PM, Project Owner, Notes.
2.3 · Status → Booked Stamps Booking DateAutomationLive
When E-Rate Deals Status → Booked, automation 7917670450 automatically stamps today's date into the Booking Date column, which mirrors into E-Rate Projects via the Linked Deal relation.
⚡ automation 7917670450 · Booking Date column (date_mm1ye0md)
Commercial Track · VTG-10 Cabling + Non-E-Rate
MSP Portal CSOP Form → Projects #4 directly → NetSuite
1
Lead Intake via MSP Portal
Bypasses El Nova and Bids #3 entirely · Automation
1.0 · Where Commercial Pipeline Lives — SalesforceSalesPolicy — Sep 18 2026Revised Sep 24Order set Sep 28
For the sales team, Salesforce is the system of record for commercial (non-E-Rate) pipeline — "If it's not in Salesforce, it didn't happen." Routing: no E-Rate / FCC funding → Salesforce; E-Rate work → monday.com; on a split-funded deal the non-E-Rate portion is tracked in Salesforce separately. Written up in the VTG Salesforce SOP (VTG_Salesforce_SOP.html, v2.1 — Sep 9 2026).

⚠ Revised Sep 24 2026 — Salesforce is a reporting layer, not a link in this chain. It exists to give the sales team a view of pipeline; it is not part of the order-to-invoice flow, and no step below should depend on it. Salesforce integration work is stopped until Salesforce settles its final product. The replacement direction: the monday client form creates the new customer directly in NetSuite, taking Salesforce out of the middle. The existing sync Workers keep running — they are how the UID gets written back — but nothing new is being built on them.

Account creation order, agreed Sep 28 2026: the account is created in monday first, then the customer is created in NetSuite, then Salesforce, and the Salesforce UID comes back to both monday and NetSuite. The NetSuite customer is created at won/order, not at lead — no NS record for something that may never become an order. Salesforce still receives the data, but last and for reporting; that is also what satisfies Bill’s new-client checklist automation. This reconciles the two positions above: Salesforce is not in the critical path, but it is not cut off either. Worth knowing why it matters — sales reps do not want to create accounts in Salesforce and only do it when forced to, which is non-E-Rate jobs; an automated flow is what keeps SF populated at all.
⚡ vtg-sf-account-sync · vtg-monday-sf-sync · UID written back to monday — running, not being extended
1.1 · CSOP Form Submitted via MSP PortalAutomationLive
Commercial leads come through the MSP portal, which triggers the vtg-msp-csop Worker. Unlike E-Rate, this flow bypasses Bids #3 entirely and lands directly in Projects #4. The CSOP form auto-builds the task list (subitems) for the project.
⚡ vtg-msp-csop · Projects #4 item created with task list subitems
1.2 · No Deal Reg or Bid Build PhaseN/A
Commercial track skips the entire Bid Building phase. Task list built by the CSOP form serves as the project scope and work order from day one.
2
Project Delivery
Projects #4 stages: New → Installing → Ready for Invoicing · Jon (PM)
2.1 · Jon Manages Delivery via Task ListJonManual
Jon works the subitems in Projects #4 as a task checklist. No separate bid compilation or SOV step. Stage advances through the same Projects #4 stages as E-Rate (New → Installing).
2.2 · Stage → Ready for InvoicingAutomationLive
Same flow as E-Rate: stage → Ready for Invoicing fires vtg-billing-ready → billing email to eratebilling@vtgus.com. Ready for Invoicing Date stamped (date_mm54qwps).
⚡ vtg-billing-ready · same automations 7920569056 + chain
3
Invoicing
Same as E-Rate track · Finance (Cari / Kevin)
3.1 · Manual NS Invoice → Planned AutoCari / KevinManual→ Planned
Finance receives billing notification and manually creates the NS invoice. Same planned automation path as E-Rate: vtg-ns-mcp-sync Ready to Invoice → NS Invoice flow once unblocked.
⚠ Same gap as E-Rate: NS service item ID needed · vtg-ns-mcp-sync cron failing
⚡ Invoiced to Date / Remaining to Bill filled by vtg-ns-so-backfill for any Projects #4 item it can match by Customer PO or SO
Show
🔴 Active Gaps — Need Resolution
Subitem task schedule never activated — resolved
Resolved
✅ Fixed by vtg-bid-task-dates, live Sep 24 2026. The seven reminder and auto-assign automations trigger on date3 Task Due Date, which nothing used to fill — monday formula columns cannot fire automations. The Worker now writes date3 on every new subitem, counting business days back from Bid Due Date and skipping weekends and federal holidays. Applies to bids created after Sep 24 2026 21:07 UTC; older bids were deliberately left alone. Verified on Kent ISD and Lincoln Township.
vtg-bid-task-dates · date3 · webhooks 642315663 / 642315682 / 642315687
Salesforce CloseDate was always in the past — resolved
Resolved
✅ Fixed 21 Sep 2026, both paths verified in production. CloseDate came from deal_creation_date, so every Opportunity was created already closed in the past. New column date_mm7dfkx Actual Close Date on Bids #3; the Worker stamps it with today’s date when the bid reaches Post-Sale, and that value then wins. Precedence: Actual Close Date → Bid Due + 65 days → Creation + 65 (logged as a warning) → the old 2027-06-30 fallback. One-way monday → Salesforce, never read back.

The obvious fix would have broken it. Switching to the existing date_mm2c6t1k Expected Award Date column was the first suggestion — measurement killed it: 0 of 500 bids have that column set, so the sync would have sent a null to a required Salesforce field. 498 of 500 have Bid Due Date, which is why the fallback chain is built on it. Amount still comes straight from Bid Value and is unchanged — a placeholder bid value still becomes a real forecast number.
vtg-monday-sf-sync · date_mm7dfkx Actual Close Date · patch_close_date.py · version 1f7be6d6
vtg-monday-sf-sync endpoint was unauthenticated — resolved
Resolved
✅ Fixed Oct 1 2026 · version dc33a840. monday’s "send a webhook" automation sends no signature at all, so signature checking was the wrong mechanism. The Worker now requires a shared key in the webhook URL (?key=), checked before anything else — requests without it get 401. It also rejects non-numeric item IDs and any item that is not on Bids #3. Both Bids #3 automations were switched to the keyed connection.

The original check had two independent reasons it could never pass: the header never arrives, and the code read WEBHOOK_SECRET while the deployed secret was named MONDAY_WEBHOOK_SECRET. Either alone was fatal. Verified with a 401 on an unkeyed request and a live sync of Clinton Macomb Public Library.
vtg-monday-sf-sync · ?key= · version dc33a840
vtg-sf-account-sync endpoints were unauthenticated — resolved
Resolved
✅ Fixed Oct 1 2026 · version e6d28b50. /sync/:itemId and /backfill had no authentication at all, and /webhook checked an Authorization header that monday never sends — the same class of mistake as vtg-monday-sf-sync, found while fixing it. Every route except /health now requires ?key=. /webhook accepts numeric IDs only, and a sync by ID runs only for Accounts #1 items. backfill.mjs reads the key from ACCOUNT_SYNC_KEY. The misnamed secret binding and the old WEBHOOK_SECRET were both deleted. Verified with a 401 on an unkeyed request.
vtg-sf-account-sync · ?key= on every route but /health · version e6d28b50
New and edited Accounts do not reach Salesforce on their own
Low
The Account → Salesforce path runs only when something calls it, and today the only caller is backfill.mjs, run by hand. No monday automation was found that triggers the Worker: the Accounts #1 board’s only two webhooks were created Jul 28 and both feed the logo Worker, and vtg-sf-account-sync recorded zero invocations in the last seven days (checked Oct 1 2026). So an account created or edited today sits in monday until someone remembers to run the backfill. Low priority only because Salesforce integration work is paused — it is not a small gap if that changes.
vtg-sf-account-sync · backfill.mjs · Accounts #1 webhooks
Salesforce stage map is incomplete
Medium
Bid Building sends StageName: "Stage 3: Bid Building", but Folder Creation, Deal Reg and Bid Compilation send no stage at all — they log active: false and the field is omitted. So the Opportunity keeps reporting the last mapped stage while monday has moved on. If sales reads stage off Salesforce, they are looking at a bid one or more steps behind reality. Separately, skip: true only suppresses StageName; the Opportunity is still written on every column change.

The write volume has a cause, found Sep 30 2026. The "any column changes" webhook fires on subitems too, so every subitem creation is another Salesforce write: one Post-Sale transition produces 8, and creating a bid with its 22 subitems produces roughly 22. That — not users editing columns — is what the 414-run count was. The fix is a one-line early return on event.columnId === "subitems". (An earlier single-column test came back 1:1 and the conclusion drawn from it, that there was no amplification, was wrong.)
vtg-monday-sf-sync · stage map · skip logic · event.columnId === "subitems"
SOW and SOV generators don’t close their own subitems
Low
The reporting half is fixed: since Sep 24 2026 Generate SOW sets SOW Status (color_mm7f9qc2) — Working on it, then Done, or Stuck with the reason posted as an update — and the doubled district name in the SOW filename is stripped. Generate Proposal already worked this way. Still open: neither generator closes its own Create SOW / Create SOV subitem, so both are ticked by hand.
vtg-scopestack-doc-sync · SOW Status color_mm7f9qc2 · Create SOW / Create SOV subitems
SOV Builder link not written on new bids — resolved
Resolved
✅ vtg-bid-intake writes link_mm6vbks (…/?item=<itemId>) when it creates the bid. Every bid created Sep 30 – Oct 1 2026 carries it.
vtg-bid-intake · link_mm6vbks · vtg-sov-builder
No automated monday → NS invoice creation
High
vtg-billing-ready fires but finance still creates the NS invoice manually. vtg-ns-mcp-sync has auth live and the invoice flow coded — needs to be wired to the Ready for Invoicing stage-change webhook. Blocked by: the NS service item internal ID from Kevin/Cari, and vtg-ns-mcp-sync's cron fails on every run (see below). vtg-ns-compare was deleted Oct 1 2026; customer mapping is now the NetSuite Customer Internal ID on Accounts #1 (text_mm7m8z67), which vtg-ns-mcp-sync does not read yet.
vtg-ns-mcp-sync · Ready to Invoice → NS Invoice flow
vtg-ns-mcp-sync cron fails on every run
Medium
Observed Sep 18 2026: the 15-minute cron fails each run with SuiteQL Record 'transaction' was not found — the NetSuite integration role cannot read transaction (the same limit was recorded again Sep 30). That is roughly 96 failures a day, and none of the six coded flows reaches a monday write. The source has not changed since Sep 17. An older build, vtg-ns-mcp-sync-staging, still runs its own 15-minute cron (Sep 19 2026 snapshot).
vtg-ns-mcp-sync · vtg-ns-mcp-sync-staging · NS role permissions
Customer PO # required on the CS Order form — resolved
Resolved
✅ Resolved Sep 20 2026. Customer PO Number is now a hard block on vtg-cs-form — no PO, no submission — validated before anything reaches monday, alongside the existing Target / Deadline Date check. Both required fields now carry a visible asterisk; neither did before. Placeholder answers are rejected as well as blanks: the value is compared on letters and digits only, so N/A, n.a., N / A, TBD, pending, XXXX and 0000 are all refused. A PO of "N/A" is worse than an empty one — it looks like a value and verifies nothing. The PO is the human-readable key finance reconciles the NetSuite order against, alongside UID matching.
vtg-cs-form · Projects #4 · NetSuite order verification
The UID has not proved stable — reference only, no longer a match key
High
Sep 28 2026. The UID (Salesforce UID__c auto-number) was adopted as the cross-system key. Salesforce duplicates contacts — 69 SF duplicate accounts sent to Merlin for review — the UID has not been stable, and SF requirements keep changing. Two problems: legacy Accounts, Bids and Projects rows carry a blank or stale UID (17 Projects #4 rows "Cannot verify" as of Sep 28; fuzzy-name fallback is off), and a newly issued UID can’t be trusted either. The UID also does not match NetSuite’s custentity_acs_unique_entity_identifier — different numbering.

Current state: the NS Customer Internal ID is the matching key. New NS customers created from the CS form use externalId mon-<monday item id>, live since Sep 28. Remaining dependency: vtg-ns-so-backfill’s auto-sync still links project → account via UID.
UID · Accounts text_mm6s8adk · Projects #4 text_mm76zvbz · NS ID Accounts text_mm7m8z67
NetSuite data cleanup has no owner
Medium
NetSuite needs significant cleanup — customer records, item data, duplicate and stale entities — before anything downstream of it can be fully trusted. This is not a program Jon owns or intends to own. It needs an owner on the finance / NS side; until it has one, every monday ↔ NS matching strategy is working around known-dirty data.
NetSuite · ownership decision needed
CPQ / quoting path — paused
Paused
⏸ Paused Sep 29 2026. ConnectWise Sell is not part of VTG's plan, so all CPQ work is paused unless that changes. Direct-to-NetSuite is on the Planned list. Still running: vtg-cs-form calls vtg-monday-cpq on every CS Order submit.
vtg-monday-cpq · vtg-cw-sync · vtg-cs-form (CPQ call)
vtg-sf-account-sync: UID write-back needs verification at scale
Low
Backfill.mjs ran against 791 accounts. UID column (text_mm6s8adk) should now be populated on all Accounts board items. Spot-check that the Salesforce UID__c values (the Worker writes UID__c, not the Account ID) were written back and that no items were skipped due to MONDAY_TOKEN auth issues (backfill.mjs requires MONDAY_TOKEN env var set explicitly before running).
vtg-sf-account-sync · backfill.mjs · Accounts board text_mm6s8adk
vtg-monday-cpq fire-and-forget not reliable — paused
Paused
⏸ Paused Sep 29 2026 with the rest of the CPQ work. For the record: the call from vtg-cs-form is fire-and-forget and is not wrapped in ctx.waitUntil, so Cloudflare may cancel it once the form response has been returned. The call still runs on every CS Order submit.
vtg-monday-cpq · vtg-cs-form
CPQ line items not populated from SOV — paused
Paused
⏸ Paused Sep 29 2026. vtg-monday-cpq creates the quote shell only; the line-item POSTs to CW Sell were never built. The SOV payload still carries vendorPOs grouped by vendor.
vtg-monday-cpq · SOV_FORMS KV
Deal reg still manual (Ruckus)
Medium
dealreg.py is built and field-mapped but not live. Ruckus portal dynamic elements are causing Playwright failures. Branden still submitting manually. Needs targeted debugging of the Ruckus portal form flow.
dealreg.py · Playwright
E-Rate Deals status has no defined owner or automation
High
The E-Rate Deals board (18406412794) status (Pipeline → Submitted → Awarded → Booked) drives creation of the E-Rate Projects item and stamps the Booking Date. No one is consistently updating it and there's no automation to advance it. If Awarded is never set, the E-Rate Projects item is never created.
E-Rate Deals board · automation 7917669964 (blocked by this)
"Create Contract in CW Sell" subitem — paused
Paused
⏸ Paused Sep 29 2026 with the CPQ work. Automation 482374746 creates a "Create Contract in ConnectWise Sell for order processing" subitem on every Post-Sale bid; it is unassigned and marked N/A.
automation 482374746 · Bids #3 subitem board 18176633598
vtg-materials-log: copper SKU catalog + NS item sync — resolved
Resolved
✅ Resolved Sep 13–16 2026. 951 copper SKUs (C- prefix) loaded from Mark's inventory list — catalog now 1,031 total (+ 80 fiber F- prefix). All merged into vtg-sku-catalog KV key. 621 missing NS inventory items bulk-written via vtg-ns-sku-writer.mjs (template item C-101017BK) on Sep 16 2026 — 96% SKU match rate achieved. 40 partial matches remain for review.
vtg-materials-log · vtg-ns-sku-writer.mjs · vtg-sku-catalog KV
customworkflow42 not in NS production
Medium
Item receipt email workflow is fully built and tested in NS sandbox. Not deployed to production. Nobody gets an automated notification when product arrives. Needs Joe Trecokas / Cari to deploy.
NetSuite · customworkflow42
vtg-ns-compare — deleted
Retired
Deleted Oct 1 2026. It had been paused since the NetSuite sandbox refresh. Customer mapping now lives on Accounts #1 as the NetSuite Customer Internal ID (text_mm7m8z67), filled by vtg-ns-so-backfill.
vtg-ns-compare (deleted Oct 1 2026)
vtg-scopestack-doc-sync: multiple button clicks create duplicate SOW docs
Medium
Each click of the Generate SOW button on Bids #3 triggers a new ScopeStack document generation — no idempotency or deduplication logic yet. A rep clicking twice creates two documents in ScopeStack. Fix: write a KV lock key on first /generate call per item, clear after webhook confirms delivery.
vtg-scopestack-doc-sync · /generate endpoint · KV lock needed
Hardcoded credentials in vtg_sov_import_v4.py — rotate
High
Four credentials sit in plaintext in vtg_sov_import_v4.py, and there are three copies of that file in a OneDrive-synced folder — so they are replicated to every machine the folder syncs to and to OneDrive’s version history. Rotate all four, move them to environment variables or wrangler secret, and delete the stale copies rather than editing them.
vtg_sov_import_v4.py · ×3 copies · VTG Flows (OneDrive-synced)
Addendum detection is live — resolved
Resolved
✅ ADDENDUM_DRY_RUN is "false", so matches are written. Notifications are built on the Oct 1 path: when a lead that already has a live bid gets a new RFP Documents or Form 470 file, the bid owner and the lead's Sales Executive are notified. Still to see: the first real addendum end to end.
vtg-bid-intake · /lead-created · /lead-files-changed · ADDENDUM_DRY_RUN = "false"
vtg-bid-intake pins a deprecated monday API version
Medium
File uploads still send API-Version: 2024-01. Current is 2026-07. Deprecated versions are retired on monday’s schedule, not VTG’s — when it goes, every intake PDF, bond form and addendum attachment fails at once, in season. Bump and re-test the upload path.
vtg-bid-intake · file upload · API-Version header
vtg-logo-probe still deployed
Low
Temporary read-only diagnostic built Sep 20 to work out why the logo extractor was only finding six logos. It mutates nothing, but it is a live endpoint with no purpose. Delete when the backfill work is done: npx wrangler delete --name vtg-logo-probe.
vtg-logo-probe · diagnostic · delete when done
vtg-logo-backfill still runs the old scraper
Low
The deployed copy (Jul 28 2026) uses the <img src>-only scraper that found 6 logos in two months; vtg-account-logo moved to the new extractor on Sep 20. It runs on a 2-minute cron. The backfill of the 331 addressable accounts with the new extractor is still open (Sep 2026 sweep), as is the KV progress being written only after a whole batch.
vtg-logo-backfill · BACKFILL_KV · cron */2
vtg-set-project-year has no FY2027 mapping
Low
The deployed Worker maps 470 prefixes 2400, 2500 and 2600 to Project Year labels 2024–2026. A Projects #4 item whose 470 starts 2700 gets no Project Year from it. (AI automations 578063979 / 578063986 also categorize Project Year from the 470 text.)
vtg-set-project-year · dropdown_mkqz1ay
Unused bid subitems are deleted by hand on every bid
Medium
Every bid is created with the full subitem set, and the team then deletes the ones that do not apply — on every single bid, all season. The intake form already knows which ones apply: delivery method, bond required, blueprint selection and the rest are all captured at intake. Wanted next: create the subtasks from those intake selections instead of creating everything and pruning. Sits behind the date engine in the queue.
vtg-bid-intake selections → Bids #3 subitem creation
The PO validator accepts its own placeholder
Medium
The Customer PO Number hard block rejects known junk — N/A, TBD, all-x, all-zero. A PO needs no particular format; anything genuinely filled in is acceptable. But the form’s own hint text, PO-XXXX, normalises to poxxxx, which is not in the reject list — so a rep who types the placeholder they are being shown sails through the check that exists to stop exactly that. One word in the reject list closes it.
vtg-cs-form · PO number validator · reject list
An addendum made reps decline the lead — resolved
Resolved
✅ Fixed Oct 1 2026. Found at Kent ISD: the automation sent the lead back to New Leads, so a rep had to fill out a whole new intake form to re-accept a bid they were already working, and reps declined the lead instead. Now vtg-bid-intake handles addendum files added to an existing lead that has a live bid (/lead-files-changed, Leads webhooks 645545831 / 645545840): only the new files go to the bid's Addenda, the bid is flagged, the owner and Sales Executive are notified, and the lead goes back to Accepted Leads. Dylan's two "Accepted Leads → New Leads" addendum automations (493350968, 493351900) were deactivated Oct 1. To confirm on the first real addendum.
vtg-bid-intake /lead-files-changed · automations 493350968 / 493351900 (deactivated)
DKIM not configured for vtgus.com
Low
All Workers send via SMTP2GO / noreply@vtgus.com. DKIM not set up — deliverability risk on billing notifications, CSOP emails, bond emails as volume grows.
SMTP2GO · vtgus.com DNS
vtg-scopestack-doc-sync: template routing updated to V3 — resolved
Resolved
✅ vtg-scopestack-doc-sync routes the "Vector eRate SOW" template (ID 7085) to the Bids #3 SOW Document column (file_mm6wm4hn). The vtg-cs-form half is done — all 6 PM task subitems (Project Kickoff Meeting, Site Access Coordination, Installation Scheduling, Weekly Status Updates, Project Documentation, Project Closeout) are live in the Worker, verified Sep 17 2026.
vtg-scopestack-doc-sync · vtg-cs-form · ScopeStack eRate Template V3
SOV Builder discount tier selector not yet built
Medium
All 4 Ruckus discount tiers (Bidder VAR RKS-0436, Driver VAR RKS-0437, RSD VAR RKS-0438, E-Rate Takeout IDC017) are now stored per-SKU in vtg-sku-catalog. However, the SOV Builder UI has no bid-level selector to switch between tiers — it currently always uses Bidder as the default. A per-bid program selector needs to be added to the SOV Builder header so reps can flip to Driver/RSD/Takeout pricing for the right deal type.
vtg-sov-builder · SKU_CATALOG KV · discTier field
Vertiv and TP-Link Omada catalogs — resolved
Resolved
✅ Both are in the live SKU catalog: TP-Link 132 parts, with Omada labor rates added Oct 1 2026, and Vertiv 48. The catalog holds 5,392 parts in total, including the Ruckus Feb 2026 E-Rate list.
vtg-sku-catalog KV · SKU_CATALOG
monday client form → NetSuite customer — live
Live
✅ Live Sep 28 2026. vtg-cs-form Section 1B "New Client Setup" appears when the bid's account has no NetSuite Customer ID and carries Cari's new-client fields. On submit, vtg-ns-so-backfill creates or links the NetSuite customer — externalId mon-<account id>, so a retry cannot duplicate — and writes the NS ID to Accounts #1 text_mm7m8z67. A similar-name hit goes to Review instead of creating. A requested credit limit of $1M or more flags the account and does not block. Salesforce is not in this path.
vtg-cs-form /api/ns-customer · vtg-ns-so-backfill /api/customer-from-account · NS_WRITE_ENABLED=1
"Remaining to invoice" on Projects #4 — live
Live
✅ Projects #4 carries Invoiced to Date (numeric_mm7d9sf4), Remaining to Bill (numeric_mm7db7yk), Last Invoice Date and Billing Match, filled by vtg-ns-so-backfill's billing sync every 4 hours. Invoices are found by Customer PO, else by the project's SO; Remaining = Total Project Amount − invoiced. Invoiced only — no AR, no credit-memo netting. 89 projects carry values as of Oct 1 2026; projects that SO Check flags as Duplicate project, Mismatch or Cannot verify are not filled until they are cleaned up.
vtg-ns-so-backfill /api/billing-sync · Projects #4 Invoiced to Date / Remaining to Bill
Tax-exempt certificates pulled from SharePoint — done
Done
✅ 85 accounts on Accounts #1 carry their tax-exempt certificate in file_mm79y1x5, pulled from SharePoint Customers\<customer>\Accounting Documents. vtg-cs-form attaches the account's certificate to the CS Order automatically.
SharePoint All Company Documentation · Accounts file_mm79y1x5
Addenda attach to the live bid, not a fresh lead — live
Live
✅ Live Oct 1 2026 — see "An addendum made reps decline the lead". The bid stays where it is and the addendum lands on it; the two lead-reset automations are deactivated.
vtg-bid-intake /lead-files-changed
Addenda copied into the bid’s SharePoint folder — live
Live
✅ Live Oct 1 2026. Every file in a bid's Addenda column (file_mm7get0y) is copied to the bid folder root, next to the RFP and the 470, via webhook 645561102 → /addenda on vtg-sp-folders. Files added to Addenda by hand are copied the same way, and re-runs leave existing files alone. The route takes no key by design: it accepts only a Bids #3 item ID and can only re-copy files already on that bid into its own folder.
vtg-sp-folders /addenda · webhook 645561102
🟣 Planned / Not Yet Started
Push the order from monday.com directly into NetSuite
High
The structural fix for monday ↔ NS matching. Today the link between a monday project and its NetSuite order is reconstructed after the fact — vtg-ns-so-backfill matches on identifiers after the order exists, and vtg-po-sync reads back from whatever it finds. That is a stopgap. Updated Sep 28 2026: the fuzzy-name fallback is off, the UID is no longer the match key, and the NS Customer Internal ID took its place — so the stopgap is now narrower and stricter, but it is still reconstruction after the fact. Planned direction: create the order in NetSuite from monday at order time, so the NS record carries the monday item and UID identity from creation. Matching then becomes 100% accurate by construction, the backfill and reconciliation Workers drop back to being a safety net rather than the mechanism, and the customer ID mapping that currently blocks the invoice flow stops being a separate problem. Pairs with making the customer PO # required on the CS Order form as the verification key.
vtg-ns-mcp-sync · vtg-cs-form · retires the vtg-ns-so-backfill fuzzy path
Group-wide quote-to-cash consolidation
Medium
Bigger than this map, but it will reshape what sits under it. Bill Loiacano ran a Quote-to-Cash discovery across the group — Comm Core, VTG logistics, Quotient and JJ’s — and it is heading from discovery into decision and execution, with Kevin F. wanting Jon, Bill and Radde to fix the group’s Q2C processes. Open feasibility question on the table: drop Rev.io (Comm Core) in favour of NetSuite billing with monday for PM — how much work, and is it worth it. The VoIP business is staying and will be integrated rather than retired.
Group Q2C · Rev.io → NetSuite feasibility · Comm Core / Quotient / JJ’s
Account flow: monday → NetSuite → Salesforce
High
Sequence agreed Sep 28 2026. Account created in monday → customer created in NetSuite → then Salesforce → SF UID returned to both monday and NS. The NS customer is created at won/order, not at lead. Build notes: the NetSuite API work runs under "VTG API Sync", an integration identity with no GUI login but full API access — an existing Worker already holds its keys and secrets, so no new credential is needed. On the new-client form, a requested credit limit over the threshold flags but does not block the NetSuite create — finance reviews it rather than the order stalling at intake.
monday client form · NetSuite (VTG API Sync) · Salesforce UID return
TD Synnex live pricing not wired into SOV Builder
High
The vtg-tdsynnex Worker is deployed — OAuth 2.0 client credentials, TOKEN_CACHE KV, /api/lookup live. That half shipped Sep 3 2026. The consuming half never did: vtg-sov-builder declares the [[services]] TDSYNNEX binding and never calls it. Verified Sep 17 against worker-combined.js — zero references to tdsynnex, TDSYNNEX or /api/price, and no LIVE badge exists. Step 6 of the vtg-tdsynnex deploy guide ("Update vtg-sov-builder") is the outstanding work; prefer env.TDSYNNEX.fetch() over the public URL that guide suggests.
vtg-tdsynnex · vtg-sov-builder env binding
Cloudflare Access + Azure AD for portal
Low
vtg-portal admin route is password-gated. Cloudflare Access + Azure AD Entra ID SSO scoped but on hold pending IT. Also needs monday.com plan upgrade for Azure AD SSO on CRM side.
vtg-portal · Cloudflare Access · Azure AD
🟢 Live Workers
vtg-bid-intake
vtg-bid-intake.vectorfi-admin.workers.dev
Live
Triggered when a rep clicks accept_470 on the El Nova Leads board: automation 7920733007 sets Status → Pending Intake, webhook 632506055 calls the Worker, and it writes the 📋 Intake Form link onto the lead. The rep opens the form from that link. Rep fills: Sales Executive, ScopeStack Blueprint(s), delivery method, partner, manufacturer, distributor, bid due date, bond required — all in one form. Blueprint selection triggers ScopeStack API to auto-create a proposal. On submit: patches all bid columns to Bids #3, links Account and Contact, generates a PDF of the completed intake form onto file_mm5bhcw7, writes the Intake Form link to link_mm591mdg and the SOV Builder link to link_mm6vbks, and creates a bond subitem + email if required. Patched Sep 19–20 2026: the Account/Contact lookup declared its GraphQL variable as [ItemsQuery!] where monday expects [ItemsQueryRule!] — every lookup failed validation, an empty catch swallowed it, and bids were created with both relations blank. Contact selection was then rewritten to draw candidates from the Account's own Contacts relation, drop billed_entity placeholders, collapse duplicate emails keeping the most recently updated, and score the rest. The E-Rate Primary Contact dropdown now reads its options live from the Bids #3 column instead of a hardcoded list.
Triggeraccept_470 → automation 7920733007 → Status → Pending Intake → monday webhook 632506055 · webhook 608965294 (Status → Accepted) is deactivated
OutputsBids #3 item, Account/Contact linked, completed intake form PDF, SOV Builder link written, ScopeStack proposal created, bond subitem + email (if needed)
Bug fixSep 19–20 2026 — GraphQL type error broke every Account/Contact lookup; contact selection rewritten and scored; dropdown reads from monday; intake PDF added
LoggingEmits [contact-match] and [intake-pdf] per submit — visible in wrangler tail
Contacts sectionBuilt Sep 24 2026 — replaced the single delivery field. Three role relations to Contacts #2: board_relation_mm7gf0s2 End User · board_relation_mm7g1dbz Consultant · board_relation_mm7g72h8 eRate, plus text_mm7gb8eg Additional Recipients (joined with "; "). Named contacts are linked to Contacts #2 rather than duplicated as columns on the bid. Suggestions: consultant = the best-scoring contact that looks like one, end user = the best that does not, eRate = whoever filed the 470 either way. "+ Add someone else" requires name and email; write-back matches on email first to reuse an existing record, links it to the Account and types it Customer / Consultant, so the scorer gets better with every bid — and a failed CRM write never fails the bid. Additional recipients are deliberately not written back; they would dilute the contact data. Pre-change copy: worker.pre-contacts.js.
Delivery recipientsBid delivery allows multiple recipients — checkboxes across the three roles plus "a different address". Rows disable as roles empty, nothing is pre-ticked (the confirmation gate stays deliberate), and addresses de-duplicate since the consultant is often also the eRate contact. monday’s email column holds one address, so email_mm7gr1ce Bid Delivery Email keeps the first recipient for a clickable value and text_mm7gt2na Bid Delivery Recipients holds the full "; " joined list.
Bid bondsLive Sep 25 2026. VTG’s surety is Alliant. When the bond toggle is on the form now requires a delivery choice — Electronic (Surety2000 / BidExpress / Other) or Physical, which is the default; physical ship-to defaults to the VTG office and stays editable, with an instructions field. That delivery instruction was the only real gap: Alliant confirmed system-generated requests are fine and that a lost-bid notice is enough to release a bond. Bond Type is fixed at Surety bond — VTG uses surety bonds only. Needed-by defaults to 7 business days after submission, editable. On request the bid’s "Get bid bond - TOTAL = $" subitem is set to Requested. A bid set to Lost auto-cancels its bond, and a separate Not Needed bond status sends the same cancellation.
EmailIntake/bond: To CHC-Surety@alliant.com + bonds@vtgus.com · Cc Danny Rose (daniel.rose@alliant.com), Nicholas Manning (Nicholas.Manning@alliant.com) and the sales rep — all on one send
Addendum detectionShipped Sep 24 2026. New POST /lead-created endpoint, fired by monday webhook 642139356 on Leads create_item. Matches the Leads item name (the bare 470 number) against Bids #3 470__ — one 470 never covers two separately-bid RFPs, so a repeat 470 is an addendum, not a new opportunity. On a match it attaches the document, stamps the addendum columns and posts a courtesy update on the lead so nobody clicks Accept 470 on it. It never moves the bid’s stage. Acts only on exactly one match in a live stage; zero matches, closed-stage matches and multiple live matches all log and do nothing. Dedupe strips monday’s <assetId>- filename prefix, without which each lead’s copy of the same certified 470 PDF re-copies forever. Gated by ADDENDUM_DRY_RUN in wrangler.toml — set to "false" (live).
New Bids #3 columnsfile_mm7get0y Addenda · numeric_mm7gj7zz Addendum # · date_mm7gbfs7 Last Addendum Date · color_mm7ghh94 Addendum Status (Received - Unreviewed / Reviewed) · email_mm7gr1ce Bid Delivery Email · date_mm7gj5zp Delivery Contact Confirmed — all created Sep 24 2026
Bid Delivery ContactShipped Sep 24 2026. The form now suggests the delivery contact from the account record and hard-blocks submit until the rep confirms it — required whatever the delivery method, because that contact also fields bid questions. Three states: suggestion with Yes/No radios, consultant suggestion with a warning, or no contact on file (radios gone, email required). contactCandidates() was split out of pickContact() so the form’s suggestion and the contact linked at submit use the same scorer; the candidate fetch is single-pass with no retries so a missing account record can never hang the form. Validated in the browser and again in /submit — format plus placeholder rejection, same pattern as vtg-cs-form’s PO number. The confirmed address lands in the archived intake PDF.
FilesVTG Flows\vtg-bid-intake\ · wrangler main = "worker.js" · pre-patch copy kept as worker.pre-addendum.js
Addendum on an existing leadLive Oct 1 2026. The 470 feed adds an addendum to the existing lead's RFP Documents / Form 470 rather than creating a new lead. Leads webhooks 645545831 (RFP Documents) and 645545840 (Form 470) → POST /lead-files-changed. If the lead's 470 belongs to exactly one live bid, only the new files are copied to the bid's Addenda column, the bid is flagged, the bid owner and the lead's Sales Executive are notified, and the lead goes back to Accepted Leads. Leads with no live bid are left alone. Dylan's two "Accepted Leads → New Leads" addendum automations (493350968, 493351900) were deactivated Oct 1. Pre-change copy: worker.pre-lead-files.js.
vtg-sp-folders
vtg-sp-folders.vectorfi-admin.workers.dev
Live — Sep 24 2026
Creates the bid's SharePoint folder when a bid is created or moved to Folder Creation on Bids #3. Site cust_ERATE{FY}RFPs, with FY from the first two digits of the 470# (2026 maps to cust_ERATE2026RFP). Folder name is the bid name with the colon removed, e.g. Noblesville Schools - 470# 270000673. The folders of 1- STANDARD BID FORMS AND DOCS/Base Bid Docs (1-Cover Page … 9-Product Support Info) are copied with their files into a Base Bid Docs subfolder; the Lead's Form 470, RFP Documents and Customer Summary go in the bid folder root. Fills the SharePoint Link column and sets both Folder Creation subitems to Complete. Bids that already have a SharePoint Link are left alone, and a re-run reuses the folder and leaves existing files alone. Since Oct 1 2026 it also copies the Addenda column and every SOV version into the folder.
Triggermonday webhooks 641680795 (item created) + 641680804 (Bid Stage changed) · 120 s delay so the subitems and 470# land first
AddendaWebhook 645561102 on Addenda (file_mm7get0y) → /addenda → bid folder root, next to the RFP and 470 · live Oct 1 2026
SOVWebhook 645821765 on SOV PDF (file_mm749nna) → /sov → Base Bid Docs/3 -SOV, 60 s delay · each version lands once, so SharePoint keeps V1, V2, V3… · live Oct 1 2026, verified on Ubly
APIMicrosoft Graph, app-only — Entra app registration with Sites.Selected and a write grant on the FY site
FailuresSubitem → Stuck and an update on the bid · transient errors retried 3× through the vtg-sp-folders-jobs queue · one [sp-folders] log line per run
Verified12 of the 13 bids created Sep 24 – Oct 1 2026 have a Worker-made folder and both Folder Creation subitems Complete; the 13th, a test bid with 470# 2134, went Stuck with an update as designed
Known gapAddenda and SOV copy read plain /sites/…/Shared Documents/… links only; bids with browser-copied /:f:/r/ links (hand-made folders) are handled by hand
Each new FYCreate the cust_ERATE{FY}RFPs site, copy in Base Bid Docs, grant the app
FilesVTG Flows\vtg-sp-folders\ · src/worker.js · tests in test/
vtg-bid-task-dates
vtg-bid-task-dates.vectorfi-admin.workers.dev
Live — Sep 24 2026
Business-day date engine for Bids #3 subitems. Writes each subitem's Task Due Date (date3) by counting business days back from the bid's Bid Due Date, skipping weekends and US federal holidays only; the offset is the subitem's Days to Subtract (numbers0). date3 is the column the due-today notification, the three row highlights and the auto-assign automations watch, so those now fire. Re-dates a subitem when its offset changes, and every subitem on a bid when the Bid Due Date changes. Runs on subitems after creation, so Dylan's subitem-creation automation is unchanged.
TriggerWebhooks 642315663 (subitem created) · 642315682 (subitem column change) · 642315687 (Bid Due Date change)
RolloutBids created after Sep 24 2026 21:07 UTC (GO_LIVE_AFTER); older bids are left alone · DRY_RUN = "false"
VerifiedKent ISD and Lincoln Township subitems carry business-day dates (follow-up at −15 lands Nov 18 / Nov 19)
Delivery rulesEmail bids: compile can be the day before the bid is emailed · Mailed bids: mail out 5 days before due, Appendix C on the day of or the day after SOV/SOW
Short-fuse bidsBids with less runway than the plan are left as-is — their first tasks can be dated before the bid was created
FilesVTG Flows\vtg-bid-task-dates\ · worker.js + test.mjs
vtg-sov-builder
vtg-sov-builder.vectorfi-admin.workers.dev
Live
Excel-like Scope of Value (SOV) quoting tool for the sales team. Opened from a link column on Bids #3 with ?item={monday_item_id}. Supports multi-tab buildings, ADD-ALTS tab, Summary tab, section type picker (Wired/Wireless/Firewall/UPS/Cable/MIBS/BMIC/Fiber/Other), SKU dropdown, per-row labor, markup overrides, and bond toggle. Save & Submit generates the SOV as a PDF and an Excel workbook, versioned _V<n>, and uploads both to the Bids #3 SOV PDF column (file_mm749nna), keeping the newest two versions there; vtg-sp-folders copies every version to the bid's SharePoint folder. Saved payload includes a vendorPOs array pre-grouped by vendor — ready for future NetSuite PO creation.
TriggerManual — rep opens from the 📊 SOV Builder column on Bids #3 (link_mm6vbks). Since the Sep 3 restructure link_mm591mdg is the Customer Intake Form column, not this one.
KVSOV_FORMS (7a5b99d8bc134fd6959cc481752ede56) · SKU_CATALOG (17083b01a7524801a236dd4a71f50164)
Live pricing⚠ Not built. The [[services]] TDSYNNEX binding is declared in wrangler.toml but env.TDSYNNEX is never called — no /api/price route, no reference to tdsynnex anywhere in worker-combined.js. All pricing comes from SKU_CATALOG KV. See the TD Synnex gap.
SKU filteringBy section type, not a category bar. Each of the 9 section types maps to catalog categories (Wired → switches/transceivers/cables/accessories; Other → all) and narrows that section’s SKU dropdown.
Routes/ · /api/skus · /api/monday-item · /api/forms/:id (GET/POST/submit) · /api/debug-monday. There is no /admin/skus route in this Worker.
OutputsSOV PDF + Excel → Bids #3 SOV PDF column (file_mm749nna) + thread update; SOV Builder link stamped to link_mm6vbks
RecentEditable Unit Cost column with markup recalc · Unit Price rounds up to nearest $10 · label rows for MDF/IDF headings · pointer-based drag-and-drop row reorder · bond default 5%
FilesVTG Flows\vtg-sov-builder\ · worker-combined.js
Sep 30 – Oct 1 2026Excel export (toolbar + on Submit) · versioned uploads, newest 2 kept on monday · drafts keyed by monday item ID (form:item-<id>, with a fallback to the old 470# key) · red banner blocks Save/Submit when the monday lookup or draft load fails · submit double-click guard · current deploy 260aa104
Catalog5,392 parts live in SKU_CATALOG (Oct 1 2026): Ruckus 3,801 (Feb 2026 E-Rate list) · VTG Cabling 1,031 · Fortinet 318 · TP-Link 132 (with Omada labor rates) · N1C 62 · Vertiv 48
SharePointEvery SOV version copied to Base Bid Docs/3 -SOV by vtg-sp-folders (webhook 645821765 on file_mm749nna) — nothing in this Worker changed for that
vtg-scopestack-doc-sync
vtg-scopestack-doc-sync.vectorfi-admin.workers.dev
Live — Sep 8 2026
Two-endpoint Worker that fully automates ScopeStack SOW delivery into monday.com Bids #3. Endpoint 1 (POST /): catches ScopeStack document_status_changed webhook when a SOW finishes generating, downloads the .docx, and routes by template name — routes the "Vector eRate SOW" template (ID 7085) to the Bids #3 SOW Document column (file_mm6wm4hn); anything else goes to El Nova Leads Customer Summary (file_mkw7hy4z). Endpoint 2 (POST /generate): triggered by a "Generate SOW" button click on a Bids #3 item — reads the 470# from the item, finds the matching ScopeStack project, and triggers programmatic SOW generation; the webhook then auto-delivers the doc. 470# extracted from filename or via project API lookup when filename is null. ⚠ Pending: template routing update to V3; vtg-cs-form needs 6 PM task subitems added (Project Kickoff, Site Access, Install Scheduling, Weekly Status, Documentation, Closeout).
Webhook triggerScopeStack Settings → Webhooks → Document Status Changed
Button triggerBids #3 Generate SOW button (button_mm70vvrb) → monday.com automation → POST /generate
TemplateVector eRate SOW (ID: 7085) → Bids #3 file_mm6wm4hn; other templates → El Nova Leads file_mkw7hy4z
AuthScopeStack service account: worker-service@vtgus.com · Client ID: SH0E9m3bedl_efy_QWjXICH3… · slug: vector
New Bids #3 colsSOW Document (file_mm6wm4hn) · Generate SOW button (button_mm70vvrb)
ConfirmedFirst end-to-end delivery confirmed: North Branch Area Schools, 470# 260005778 — .docx uploaded to Bids #3 SOW Document column successfully
GapMultiple button clicks create multiple ScopeStack documents — idempotency/dedup not yet built
AI customer summarySep 2026. The team used to log into ScopeStack and write the project Customer Summary there with Claude/ChatGPT or ScopeStack’s built-in AI writer. That now runs from monday instead, inside this Worker — which already holds the ScopeStack API credentials. ScopeStack’s own generator was enabled first (Generate Executive Summary: Create on the Admin role) and produced poor output, leaking "missing the JSON" text into the summary, so the writing is done by Claude via the Anthropic API instead. VTG organization key stored as ANTHROPIC_API_KEY on this Worker.
Summary triggerRuns as part of the existing Generate SOW button — the separate "Write Summary" button was built and then removed, so there is one button, not two
Format constraintScopeStack’s SOW template prints Markdown symbols literally, so summary text written back to ScopeStack must be plain text — no asterisks, no hashes
Futurevtg-sow-builder pricing sheet integration · blueprint → datasheet auto-selection
FilesVTG Flows\vtg-scopestack-doc-sync\
SOW Statuscolor_mm7f9qc2 — Working on it on click, then Done, or Stuck with a reason posted as an update (since Sep 24 2026). The doubled district name in the filename is stripped (dedupeFilename).
Not doneDoes not close the bid's Create SOW subitem
vtg-proposal-builder
vtg-proposal-builder.vectorfi-admin.workers.dev
Live — Sep 14 2026
Triggered by "Generate Proposal" button on Bids #3. Fetches the ScopeStack SOW PDF via assets API, fetches the client logo from Accounts #1, and injects the logo + bid due date onto the SOW cover page using pdf-lib. If a SOV PDF exists in column file_mm749nna, fetches it and merges SOW+SOV via iLoveAPI. Uploads final PDF to Proposal PDF column (file_mm739vxe). Updates a Proposal Status column (orange → green/red) so reps can see progress without re-clicking.

Trigger: button_mm732fyx → automation 636065801 → POST /generate
Logo box: 192×144pt, centered between district name and "Statement of Work" on cover
Status column: color_mm74qsfe ("Working on it" / "Done" / "Stuck")
Vector logo: hardcoded base64 JPEG in Worker — no network dependency
SOV PDF: uploads to file_mm749nna via SOV Builder submit  |  Phase 3: SharePoint standard docs + data sheets
SecretsMONDAY_TOKEN, ILOVEAPI_SECRET_KEY, SHAREPOINT_CLIENT_ID/TENANT_ID/SECRET
KVSOV_FORMS (7a5b99d8bc134fd6959cc481752ede56)
Depspdf-lib 1.17.1 (bundled, 847KB)
OutputBids #3 → file_mm739vxe (Proposal PDF)
Version4.0.0 — ef64840c
vtg-cs-form
vectorfi-admin.workers.dev
Live
Fires when a Bids #3 item enters Post-Sale stage (webhooks 562741747 + 483153616). Generates a CS Order Processing (CSOP) PDF and emails it to erateops@vectortechgroup.com and Sales@vtgus.com (both TO — there is no CC). Uses KV-based deduplication to prevent double-fires. Also fires a server-side call to vtg-monday-cpq (unreliable — see gap). Creates a monday subitem as a checklist task.
TriggerBids #3 stage → Post-Sale (webhooks 562741747 + 483153616)
Emailerateops@vectortechgroup.com + Sales@vtgus.com (both TO) via SMTP2GO
Tax exemptSection 1 Yes/No radio, defaults Yes. Reads any certificate on the Account (🏢 Accounts #1 file_mm79y1x5) and auto-attaches it; a cert uploaded through the form replaces the Account copy. The cert rides along to the CS Order subitem and the email. Added Sep 17 2026.
PrefillFrom 📡 Controller Serials: controller serial, 2nd serial, registered email, and licensing email (email_mm799qya) on Licensing Orders. Licensing prefill added Sep 17 2026.
New Client SetupLive Sep 28 2026. Section 1B appears when the bid's account has no NetSuite Customer ID, with Cari's new-client fields. On submit → /api/ns-customer → vtg-ns-so-backfill (service binding NS_SYNC) creates or links the NetSuite customer and writes the NS ID to Accounts #1 (text_mm7m8z67). Order: already linked → prior externalId → exact name + ZIP (link) → similar name (Review, no create) → create with externalId mon-<account id>. One attempt per account per 10 minutes (KV lock). Requested credit of $1M or more flags the account; it does not block.
CPQ callStill fires vtg-monday-cpq on every CS Order submit (fire-and-forget, not wrapped in ctx.waitUntil, so Cloudflare may cancel it once the form response returns). CW Sell work is paused — see the vtg-monday-cpq card.
vtg-monday-sf-sync
vectorfi-admin.workers.dev
Live — Aug 13 2026
🔒 Key required — the webhook URL carries ?key=, checked before anything else; unkeyed requests get 401. Non-numeric item IDs and items that are not on Bids #3 are rejected. Version dc33a840, Oct 1 2026. Syncs Bids #3 items to Salesforce as an Opportunity upsert, using Monday_Item_ID__c as the external ID for idempotent creates/updates. SF token cached in KV.

Fired by two Bids #3 automations — "when an item is created, send a webhook" and "when any column changes, send a webhook". It is not limited to deal_stage, deal_value or deal_creation_date; any column change on the item reaches it, which is why subitem activity amplifies the write count.

Stage map, read from the live code (version dc33a840): only Bid Building → "Stage 3: Bid Building", Awaiting Results → "Stage 6: Awaiting Results", plus Post-Sale, Post-Monday and Lost. Folder Creation, Deal Reg, Bid Compilation, Bid Submittal, Bidding and Wins Archive send no stage at all — see the stage-map gap.
TriggerTwo Bids #3 automations — item created, and any column changes → keyed webhook
AuthSF Client Credentials OAuth · integration@vtgus.com.prod · VTG Integration Permissions permission set
KVSF_TOKEN_KV (afcf72c9f5ed44ff97adced0f714ad93) · key: sf_token
FilesVTG Flows\worker.js + wrangler.toml
vtg-ns-so-backfill
vtg-ns-so-backfill.vectorfi-admin.workers.dev
Live — v18 Sep 28 2026
monday ↔ NetSuite matching and billing for Projects #4 and Accounts #1. Customers match on the NetSuite Customer Internal ID (Accounts text_mm7m8z67); project → account still goes through the UID (see the UID gap) and the fuzzy-name fallback is off. A 4-hour cron runs SO auto-sync (one SO per project, Customer PO cross-check), SO Check, and the billing sync that fills Invoiced to Date, Remaining to Bill and Last Invoice Date. Also creates or links new NetSuite customers for vtg-cs-form's New Client Setup (live Sep 28 2026).
CronEvery 4h — auto-sync → SO Check → billing sync
SO Checkcolor_mm7m1x6z + detail text_mm7md8rh: Verified · Customer only · Review amount · Duplicate project · Mismatch · Cannot verify · (Manual in v19, staged)
BillingProjects #4 numeric_mm7d9sf4 Invoiced to Date · numeric_mm7db7yk Remaining to Bill · date_mm7d365w Last Invoice Date · color_mm7dng1 Billing Match. By Customer PO, else by the project's SO. Invoiced only — no AR, no credit memos. 89 projects carry values (Oct 1 2026).
NS customer/api/customer-from-account, called by vtg-cs-form over a service binding · externalId mon-<account id> so retries cannot duplicate · similar name → Review, no create · credit ≥ $1M flags only · NS_WRITE_ENABLED=1 since Sep 28 2026
AlsoNS Opportunity link fill (link_mm7dampw) · account match (dry run unless applied) · SO diagnostics
NS accessRecord views only (salesOrder, invoice, customer); the role cannot read transaction
Target boardProjects #4 (18176626554) · NS SO# text_mm6hv20b · Customer PO text_mm7dxvwd
FilesVTG Flows\vtg-ns-so-backfill\ · worker.js (= v18); v6–v19 copies alongside
vtg-po-sync
vectorfi-admin.workers.dev
Live — Aug 25 2026
Syncs NetSuite PO numbers and approval status back to the Projects #4 board. Runs on a webhook triggered by changes to the NS Sales Order # column, plus a cron every 4 hours as a safety net. Writes Vendor PO # (text_mm76antg) and PO Status (color_mm766mdj) on the Projects #4 item. (Customer PO, text_mm7dxvwd, is a separate column written by vtg-cs-form.)
TriggerNS SO# column change webhook + cron every 4h
KVPO_SYNC_KV (2c487e21b1324f5b8dbfc754db7b2622)
OutputsProjects #4: Vendor PO # (text_mm76antg) + PO Status (color_mm766mdj)
FilesVTG Flows\vtg-po-sync\
vtg-materials-log
vtg-materials-log.vectorfi-admin.workers.dev
Live — v4 Sep 16 2026
Cabling materials accounting tool for Projects #4. PM opens via a link column on a Projects #4 item (auto-populated when stage → Installing by automation 7922447604). v4 (Sep 16 2026): NS SO writeback live — cabling lines are PATCHed onto the NetSuite Sales Order and an Item Fulfillment is created on submit. Drop-ship SOs skip fulfillment and leave a warehouse note. Re-push to NS button on locked page for retries. NS result (IF# or lines-added confirmation) posted to monday thread. v3 (Sep 15): NS Inventory On Hand badges (green/yellow/red) from NS location 41 via INVENTORY_CACHE KV; UID + NS SO# on project card. v2: Save Draft system with daily accumulation, running totals, confirmation modal.
TriggerManual — PM opens from Projects #4 link column (link_mm6mhdcx)
KVMATERIALS_LOG (7694ae82ef4540799e64aa3ade3ad10e) · SKU_CATALOG (17083b01a7524801a236dd4a71f50164) · INVENTORY_CACHE (0233a14225194cbd81a49601f448963b, shared with vtg-ns-mcp-sync)
NS AuthOAuth 2.0 M2M — same cert as vtg-ns-mcp-sync · Secrets: NS_CLIENT_ID, NS_CERTIFICATE_ID, NS_PRIVATE_KEY_PEM · Role perms: Transactions → Sales Order / Fulfill Orders / Item Fulfillment (Full)
Emaileratebilling@vtgus.com via SMTP2GO
Catalog1,031 SKUs live — 951 copper (C- prefix) + 80 fiber (F- prefix) · key: vtg-sku-catalog in SKU_CATALOG KV · 96% NS item match rate after Sep 16 bulk write of 621 missing SKUs via vtg-ns-sku-writer.mjs
FilesVTG Flows\vtg-materials-log\ · worker.js + import-catalog.mjs + backfill-links.mjs
vtg-billing-ready
vectorfi-admin.workers.dev
Live
Sends a billing notification email to finance when a Projects #4 item reaches the Ready for Invoicing stage. Triggered by monday.com stage-change automations (IDs: 7920569056, 7920172789, 7917999463, 7920230690). Stamps the Ready for Invoicing Date column (date_mm54qwps). Used by both E-Rate and Commercial tracks.
TriggerProjects #4 stage → Ready for Invoicing (4 monday automations)
Emaileratebilling@vtgus.com via SMTP2GO / noreply@vtgus.com
GapDKIM not configured for vtgus.com — deliverability risk
vtg-revenue-month
vtg-revenue-month.vectorfi-admin.workers.dev
Live — Sep 18 2026
Keeps Revenue Month (date_mm39fh8x) on Projects #4 equal to the end date of the project Timeline (timerange_mm1q29se). When the Project Stage reaches Ready for Invoicing or Closed, it stamps Revenue Month with that day's date and ticks Revenue Month Locked (boolean_mm7a4044), so later timeline edits no longer move it. A daily cron re-syncs any unlocked project whose Revenue Month has drifted from its timeline.
TriggerProjects #4 webhooks 639640003 (Timeline changed) + 639640004 (Project Stage changed) · cron 15 6 * * * (daily resync)
WritesRevenue Month · Revenue Month Locked
AuthShared secret on every route except /health
SourceSep 19 2026 deployed copy (_deployed) · no folder in VTG Flows
vtg-set-project-year
vectorfi-admin.workers.dev
Live
Sets the Project Year dropdown (dropdown_mkqz1ay) on Projects #4 items. Label mapping: 1 = 2024, 2 = 2025, 3 = 2026. Runs on new item creation in Projects #4.
TriggerProjects #4 new item creation
OutputsProject Year dropdown set on Projects #4 item
FY2027Maps 470 prefixes 2400 / 2500 / 2600 only (Sep 19 2026 deployed copy) — a 2700… (FY2027) project gets no Project Year from this Worker
vtg-msp-csop
vectorfi-admin.workers.dev
Live
Handles commercial / non-E-Rate lead intake via the MSP portal CSOP form. Bypasses Bids #3 and El Nova entirely — creates a Projects #4 item directly with a task list (subitems) auto-built from the CSOP form fields. The task list serves as the project scope and work order from day one.
TriggerMSP portal CSOP form submission
OutputsProjects #4 item + task list subitems
NoteCommercial track only — no Accounts/Contacts created
vtg-meeting-sync
vtg-meeting-sync.vectorfi-admin.workers.dev
Live — v3.0
Applies Sembly meeting output to Projects #4. An action item is matched to a Projects #4 subitem (fuzzy match, threshold 0.55, scoped to one project when a project code appears in the text); the matched subitem's Status is updated and a note is posted on its project. Meeting notes that carry a project code are posted as an update on that project; notes without one are skipped.
TriggerSembly webhook → POST /meeting-webhook
BoardsProjects #4 (18176626554) · subitems board 18176626756 · project code matched against text_mkqz3hww
SourceSep 19 2026 deployed copy (v3.0) · source folder sits outside VTG Flows (home folder vtg-meeting-sync)
vtg-lead-score
vtg-lead-score.vectorfi-admin.workers.dev
Live — Aug 3 2026
Reads the Opportunity Score out of the Customer Summary PDF on the El Nova Leads board (ASCII85 + FlateDecode stream decode) and writes it to Opportunity Score (numeric_mm5w3j). Runs when a file lands in Customer Summary (file_mkw7hy4z). This is the score extraction described at SOP step 1.1.
TriggerLeads webhook 617748761 (Customer Summary column changes) → POST /webhook
Routes/webhook · /bulk (token-protected, one-time run over all leads) · /health
NoteThe Leads board also has a separate Opp Score column (numeric_mm5wkd7d) that this Worker does not write
FilesVTG Flows\vtg-lead-score\ · index.js
vtg-account-logo
vectorfi-admin.workers.dev
Live
Scrapes the district website for a logo and uploads it to the Account logo file column, setting logo_status to Logo Found / Needs Manual Logo / No Website. Fires on Account creation and when website_url changes, so an account that arrives without a website gets a second attempt once El Nova fills it in. Rewritten Sep 20 2026 — the original only read <img src>, which Finalsite and ParentSquare sites never emit (the URLs sit in data-image-sizes as percent-encoded JSON), and its Clearbit fallback had been dead since 8 Dec 2025. In two months it had found 6 logos. The replacement reads lazy-load attributes, scores candidates, prefers a wordmark over an icon mark, and only writes at 70+ — anything less confident is flagged Needs Manual Logo rather than guessed at.
TriggerWebhook 615242921 (item created) + 615244207 (website_url changed)
Outputslogo (file column) + Logo Status on Accounts #1
Measured331 accounts need a logo and have a website; the new extractor finds one for 242
LoggingEmits [logo-match] with URL, score and reasons on every path
FilesVTG Flows\vtg-account-logo-live\
vtg-logo-backfill
vtg-logo-backfill.vectorfi-admin.workers.dev
Live — cron every 2 min
Cron Worker that walks Accounts #1 in batches of 15, looks for each district's logo, uploads it and sets Logo Status (color_mm5phbaj). Progress — cursor, processed IDs, stats and a done flag — is kept in KV so each run resumes where the last one stopped. The deployed copy (Jul 28 2026) still uses the original <img src>-only scraper that vtg-account-logo replaced on Sep 20.
TriggerCron */2 * * * * · status and manual run from the Worker URL
KVBACKFILL_KV — cursor · processed_ids · stats · done
ObservedSep 2026: cursor and processed IDs are written only after the whole batch loop finishes
FilesNo local source folder (Sep 2026 sweep)
vtg-sf-account-sync
vtg-sf-account-sync.vectorfi-admin.workers.dev
Live — Sep 14 2026
Syncs monday.com Accounts (#1) and Contacts (#2) to Salesforce as Account and Contact objects. Uses Monday_Item_ID__c as the external ID for idempotent upserts on both objects. After upserting, writes the Salesforce UID__c auto-number (not the Account ID) back to the UID column (text_mm6s8adk) on the Accounts board. A backfill script (backfill.mjs) ran against all 791 existing accounts to populate Salesforce and stamp the UID column. Complements vtg-monday-sf-sync which syncs Bids — this Worker handles the CRM Account/Contact layer.
Trigger⚠ Called by hand via backfill.mjs → POST /sync/:itemId (key required). No monday automation triggers it (checked Oct 1 2026).
AuthSF Client Credentials OAuth · integration@vtgus.com.prod · VTG Integration Permissions permission set
KVSF_ACCOUNT_TOKEN_KV — token cache for SF OAuth
SF fieldsMonday_Item_ID__c (External ID, Text 20, Unique) on both Account and Contact objects
Write-backSF UID__c auto-number → Accounts board UID column (text_mm6s8adk) — not the Account ID
Auth🔒 Key required — every route except /health needs ?key=; unkeyed requests get 401. /webhook takes numeric IDs only; sync-by-ID is restricted to Accounts #1. backfill.mjs reads ACCOUNT_SYNC_KEY. Version e6d28b50, Oct 1 2026.
Backfillbackfill.mjs ran against all 791 accounts — requires MONDAY_TOKEN env var set before running
FilesVTG Flows\vtg-sf-account-sync\ · worker.js + wrangler.toml + backfill.mjs
vtg-inventory
vtg-inventory.pages.dev
Live — Sep 15 2026
Company-wide NetSuite inventory dashboard hosted on Cloudflare Pages (GitHub repo vtg-portal/vtg-inventory). Fetches live from vtg-ns-mcp-sync /api/inventory/all and displays all NS locations: 41 Cabling Warehouse (blue), 42 Secondary Warehouse (green), 4 Grand Rapids Office (yellow). Password protected (VTG2026 — Azure AD SSO planned). Features: search, location filter pills, sortable columns, light/dark mode toggle, CSV export.
Data sourcevtg-ns-mcp-sync /api/inventory/all · INVENTORY_CACHE KV (0233a14225194cbd81a49601f448963b) refreshed every 15 min
AuthPassword: VTG2026 (placeholder) · Azure AD SSO planned
FilesGitHub: vtg-portal/vtg-inventory · single index.html, auto-deploys on push to main
NoteAfter any vtg-ns-mcp-sync redeployment, seed INVENTORY_CACHE with: curl /api/inventory/all
vtg-portal
vtg-portal.vectorfi-admin.workers.dev
Live
Internal staff portal with sections for Tools (sales/finance/field/admin), Docs (replacing OneNote), and Admin. Admin route is password-gated temporarily until Cloudflare Access + Azure AD is configured. GitHub repo vtg-portal/vtg-portal (private) — config/tools.json is source of truth for tool entries. Docs backed by GitHub markdown files.
Plannedtools.vtgus.com CNAME + Cloudflare Access + Azure AD SSO
FilesGitHub: vtg-portal/vtg-portal
vtg-tdsynnex
vtg-tdsynnex.vectorfi-admin.workers.dev
Live — Sep 3 2026
TD Synnex Partner API integration. Authenticates via OAuth 2.0 client credentials against sso.us.tdsynnex.com, caches the token in KV with auto-refresh, and exposes a /api/lookup?pn=PARTNUMBER endpoint. Handles both numeric part numbers (synnexSKU) and alphanumeric (mfgPN). Falls back to SKU_CATALOG KV for VTG-specific items (labor, Cloudpath). vtg-sov-builder declares a [[services]] TDSYNNEX binding to it, but nothing calls it yet (checked Oct 1 2026 against worker-combined.js) — see the TD Synnex gap. Key bug fixed at build: TD Synnex returns HTTP 200 with status: "Not found" for unknown SKUs (not a 404), requiring an explicit status-string check to trigger the KV fallback.
TriggerBinding declared in vtg-sov-builder · not called by any Worker yet · /api/lookup?pn= answers direct requests
AuthOAuth 2.0 client credentials · sso.us.tdsynnex.com · secrets: TDSYNNEX_CLIENT_ID + TDSYNNEX_CLIENT_SECRET (never in files)
KVTOKEN_CACHE (8f111c8118014937b77d42c62c521fe9) · TTL = expires_in − 60s
FallbackSKU_CATALOG KV for labor rates, Cloudpath, and any non-TD Synnex items
Health/health endpoint shows token cache state
AccountTD Synnex account #132973
vtg-deck-builder
vtg-deck-builder.vectorfi-admin.workers.dev
Live — Jun 22 2026
Monthly Review deck builder. Serves a form where each of the ten division leads (Managed Services, Infrastructure Engineering, Event Logistics, Service Desk, Professional Services, Vector B2B, E-Rate, Whitlock MS, Whitlock ESM, AI & Automation) enters their section; entries are stored in KV and the browser builds the PowerPoint with PptxGenJS. The deployed copy makes no monday.com calls. Also listed under Dashboards.
Routes/ form · /api/divisions · /api/divisions/:id (GET / POST / DELETE)
KVDECK_DATA — one key per division
SourceSep 19 2026 deployed copy (_deployed)
vsz-lldp-neighbors.py
Local Python script (not a Cloudflare Worker)
Live — Sep 4 2026
Local Python script that SSHes into a Ruckus SmartZone controller and runs LLDP neighbor discovery across all APs in a selected zone. Queries all APs via SmartZone REST API, runs remote ap-cli <MAC> "get lldp neighbors" on each via SSH, parses output to extract switch hostname, port, chassis MAC, and management IP, displays as a formatted console table, exports to a timestamped CSV, and optionally writes LLDP data back to each AP's description field via controller CLI. Built to run locally because remote sites lack public-facing IPs on the controller. Uses prompt-based SSH waiting (_wait_for()) rather than blind sleeps. Added to VTG portal as tool #23.
RuntimeLocal Python — requires SSH access to SmartZone controller
AuthSmartZone SSH credentials + separate enable password + REST API credentials entered at runtime
Pagination fixFetches all APs with no zone filter using start/limit as URL query params, then filters client-side by zoneId
Write-backAP description field updated via controller CLI (config → ap <MAC> → description → exit); REST API PATCH returns 403
Portalvtg-portal tool #23 — listed as local script with GitHub repo link
🟡 In Progress
vtg-ns-mcp-sync
vtg-ns-mcp-sync.vectorfi-admin.workers.dev
In Progress
Bidirectional monday.com ↔ NetSuite sync. Auth is live in production as of Aug 13 2026. Six flows coded: (1) Bid Win → NS Sales Order, (2) Ready to Invoice → NS Invoice, (3) NS Invoice Paid → monday Closed, (4) NS SO Created → monday SO#, (5) NS PO → monday PO#, (6) NS Customer → monday Account. Cron every 15 min + webhook triggers. Waiting on the NS service item internal ID; its cron fails on every run (see Cron result). Sep 15 2026: Inventory cache endpoints added — /api/inventory (location 41, feeds vtg-materials-log On Hand) and /api/inventory/all (all locations, feeds vtg-inventory dashboard). INVENTORY_CACHE KV shared with vtg-materials-log. Cron refreshes both every 15 min.
AuthOAuth 2.0 M2M · CLIENT_ID: d7bb3d03… · Cert ID: _Xm9jPsUb1H7DX…
CronEvery 15 min + webhook on stage changes
Blocked byNS service item ID from Kevin/Cari · NS role cannot read transaction
FilesVTG Flows\vtg-ns-mcp-sync\ · wrangler.toml + worker.js
Cron resultObserved Sep 18 2026: the 15-minute cron fails on every run with SuiteQL Record 'transaction' was not found — the NetSuite integration role cannot read transaction (the same limit was recorded again Sep 30). None of the six flows reach a monday write. Source unchanged since Sep 17.
Customer mappingvtg-ns-compare was deleted Oct 1 2026. The NetSuite Customer Internal ID now on Accounts #1 (text_mm7m8z67, filled by vtg-ns-so-backfill) is the customer mapping; this Worker does not read it yet.
vtg-ns-mcp-sync-staging
vtg-ns-mcp-sync-staging.vectorfi-admin.workers.dev
Deployed — staging
An earlier staging build of vtg-ns-mcp-sync, still deployed with its own 15-minute cron that polls NetSuite. Its column map still carries placeholder IDs marked "CREATE if missing" (text_so_number, text_invoice, text_po_number …), and its monday route checks x-monday-signature, which monday's "send a webhook" automations do not send.
Cron*/15 * * * * (Sep 19 2026 snapshot)
Routes/webhook/monday · /poll/netsuite · /health
SourceSep 19 2026 deployed copy only — no local folder
dealreg.py
Playwright script (not a CF Worker)
In Progress
Playwright automation to submit deal registrations to manufacturer portals (Ruckus, Cisco, etc.) directly from Bids #3 field data. Field map is built. Dynamic portal elements on the Ruckus form are causing failures — Branden is still submitting manually.
TriggerBids #3 stage → Deal Reg
GapRuckus portal dynamic element handling not resolved
⏸ Paused
ConnectWise Sell / CPQ — paused Sep 29 2026 unless the direction changes.
vtg-monday-cpq
vectorfi-admin.workers.dev
Paused — Sep 29 2026
Creates a ConnectWise Sell (CPQ) quote by cloning the E-Rate Contract template (ID: c0f2a401…) and patching customer and project details. Quote # and CPQ Status are written back to Bids #3. Fired by vtg-cs-form as a server-side call. Paused Sep 29 2026: ConnectWise Sell is not VTG's direction — no further work unless that changes. vtg-cs-form still calls this Worker on every CS Order submit.
TriggerFire-and-forget call from vtg-cs-form on Post-Sale
PausedThe call from vtg-cs-form is fire-and-forget without ctx.waitUntil; line items from the SOV KV were never built
StatusPaused Sep 29 2026 — CW Sell not VTG's direction
vtg-cw-sync
vectorfi-admin.workers.dev
Paused — Sep 29 2026
ConnectWise Sell sync Worker. Scaffolded, never deployed. Paused Sep 29 2026 — CW Sell is not VTG's direction.
Blocked byAPI credentials from Josh + CPQ/NS direction decision
🧪 Test / Diagnostic (deployed)
vtg-ns-test
vtg-ns-test.vectorfi-admin.workers.dev
Deployed — test
One-off NetSuite REST connection test deployed Jul 31 2026. Not part of any flow on this map.
SourceSep 19 2026 deployed copy only — no local folder
📋 E-Rate Program Terms
E-Rate E-Rate
The Schools and Libraries Program of the Universal Service Fund, administered by USAC. Provides funding to eligible schools and libraries for broadband connectivity, networking equipment, and related services. VTG's primary government funding vertical (VTG-06).
USAC USAC
Universal Service Administrative Company. The non-profit that administers the E-Rate program on behalf of the FCC. USAC issues funding decisions, maintains the EPC portal, and processes reimbursements.
Form 470 470
The Description of Services Requested and Certification Form. Filed by a school or library to announce they are seeking competitive bids for E-Rate eligible services. VTG discovers these via El Nova and responds with a Form 471. The 470# is the unique identifier for each opportunity.
RFP Addendum Addendum
A revision or clarification issued by the applicant against an existing 470 — corrected specs, an extended due date, answers to bidder questions. It arrives on the Leads board looking like a fresh opportunity, which is how one 470 used to end up worked as two bids. The 470 number is the constant: one 470 never covers two separately-bid RFPs, so a repeat 470 is an addendum. A cancelled 470 is different — the district issues a whole new number, that is a genuine new opportunity, and the old bid moves to Lost. By law an addendum cannot arrive after the submittal date. Screened automatically at lead creation by vtg-bid-intake’s /lead-created endpoint (webhook 642139356); an addendum flags the existing bid and never moves its stage.
Form 471 471
The Services Ordered and Certification Form. Filed by the applicant (school/library) after selecting a vendor. It requests the actual E-Rate funding and references a specific 470. VTG helps applicants file the 471 after a bid is awarded.
FCDL FCDL
Funding Commitment Decision Letter. Issued by USAC to notify applicants whether their funding request has been approved, denied, or modified. Receiving an FCDL for an approved bid is the trigger for moving a Bids #3 item to Post-Sale and beginning project execution.
FRN FRN
Funding Request Number. A unique identifier assigned by USAC to each funding request within a Form 471. Tracked on the E-Rate Deals board as a reference for reporting and reimbursement.
EPC EPC
E-Rate Productivity Center. USAC's online portal where applicants and service providers submit forms, manage applications, and track funding status. Dylan submits bids here during the Bid Submittal stage.
SPI SPI
Service Provider Invoice. One of two E-Rate payment methods. Under SPI, the service provider (VTG) invoices USAC directly for the E-Rate-funded portion, and separately invoices the customer for their co-pay. VTG then gets paid by both parties. Contrast with BEAR.
BEAR BEAR
Billed Entity Applicant Reimbursement. The alternative E-Rate payment method. Under BEAR, the customer pays VTG the full invoice amount upfront, then files a BEAR form with USAC to be reimbursed for the E-Rate-funded portion. VTG signs off on the BEAR. Post-Sale subitems are marked N/A for BEAR bids where SPI-specific tasks don't apply.
Funding Year FY
E-Rate funding is allocated in annual cycles running July 1 – June 30. A project funded in FY2025 covers July 2025–June 2026. VTG tracks funding year on both the E-Rate Deals board and the E-Rate Historical Awards board (FY2017–FY2025 imported).
Co-pay / Non-discounted Share
The portion of the project cost the customer pays themselves. E-Rate covers a discount percentage (based on poverty level and urban/rural status); the customer's co-pay is the remainder. Affects bid pricing and SOV structure.
LOI LOI
Letter of Intent. A signed document from the customer confirming they intend to proceed with VTG as their vendor post-award. Collected in Post-Sale and uploaded to SharePoint. First subitem in the Post-Sale checklist (assigned to Jon).
PO PO
Purchase Order. Issued by the customer authorizing VTG to proceed with the project and invoice for services. PO issuance and upload to SharePoint is a Post-Sale subitem (Alan/Jake). PO numbers are synced from NetSuite to Projects #4 via vtg-po-sync.
🏗️ VTG Process & Board Terms
SOV SOV
Schedule of Values. The itemized pricing document submitted with a bid, listing every line item (equipment, labor, cabling, etc.) with quantities, unit costs, and extended costs. Built using the vtg-sov-builder Worker. Required for bid submittal and Post-Sale SOV reconciliation.
SOW SOW
Statement of Work. Describes the scope of services VTG will perform — installation, configuration, testing, etc. Paired with the SOV in the bid package. Created during Bid Building by the sales rep.
BOM BOM
Bill of Materials. A detailed list of hardware components required for a project, used for deal registration with manufacturers. Created by the sales rep as a Deal Reg subitem task when the bid is hardware-based.
CSOP CSOP
Customer Service Order Processing form. Generated automatically by vtg-cs-form when a bid moves to Post-Sale. Emailed to erateops@vectortechgroup.com to initiate the order processing workflow.
Deal Reg DR
Deal Registration. The process of registering a sales opportunity with a manufacturer (e.g. Ruckus, Cisco) to protect pricing and partner status. Handled by Branden; being automated via dealreg.py. Registration # is tracked in Bids #3.
Disty
Short for Distributor. The wholesale distribution partner VTG purchases equipment through (TD Synnex, Ingram Micro, N1C, WAV, etc.). Selected during bid intake; appears on the SOV vendor column and drives PO routing.
Post-Monday
The final stage in Bids #3 after a project has been handed off to delivery. Indicates a Projects #4 item exists and the E-Rate Operating System has been notified (via automation 559103546 → E-Rate Deals board). The bid stays in Post-Monday as a permanent reference; all active work moves to Projects #4 and the E-Rate Op System.
Wins Archive
A Bids #3 group for historical won bids. Items are moved here (with a completion update) when stage → Wins Archive. Separate from Post-Monday — Wins Archive is for fully closed/billed historical records; Post-Monday is for active post-award projects.
You're Up!
A subitem status label in Bids #3. When set, triggers a monday.com automation (482374707) that sends a notification to the task assignee: "You're Up! [task] is due [date] for [bid name]. You're not waiting on anyone." Used to signal sequential handoffs in the bid task checklist.
Bid Stage Subitem
A status column on Bids #3 subitems that tags each task with the bid stage it belongs to (Folder Creation / Deal Reg / Bid Building / etc.). All 23+ tasks are created on new item creation and tagged from day one — the tag indicates when in the lifecycle each task should be worked, not when it was created.
SPI / BEAR Subitem (N/A)
Several Post-Sale subitems are conditionally applicable depending on payment method. For BEAR bids, tasks related to FCDL filing and SPI invoicing are marked N/A — this triggers the N/A automation (482374711) which clears the assignee and due date, effectively removing the task from the active queue.
UID (Salesforce UID__c)
The Salesforce UID__c auto-number (not the Account ID) written back to the monday.com Accounts board UID column (text_mm6s8adk) by the vtg-sf-account-sync Worker after a successful Account upsert. Intended as the permanent cross-system identifier linking a monday.com Account to its Salesforce counterpart; the external ID field Monday_Item_ID__c on the SF Account object is the join key used for idempotent upserts — UID is what comes back. Superseded as a key, Sep 28 2026: the UID is reference only now. Salesforce had been duplicating accounts (69 sent to Merlin for review), the value did not hold stable, and it never matched NetSuite’s custentity_acs_unique_entity_identifier. The NS Customer Internal ID (text_mm7m8z67 on Accounts) is the matching key; new NS customers from the CS form carry externalId mon-<monday item id>. See the UID gap.
Ready for Invoicing Date RFID
The date column (date_mm54qwps) on Projects #4 automatically stamped when a project reaches Ready for Invoicing stage. Used to populate the Forecast vs. Actual Revenue dashboard and feed the billing notification email to finance.
⚙️ Technical & Integration Terms
Cloudflare Worker
VTG's primary middleware layer. Serverless JavaScript functions deployed at the edge via Cloudflare. All Workers live under vectorfi-admin.workers.dev. Deployed via wrangler deploy from Command Prompt (not PowerShell — blocked by Norton). Source files at OneDrive\VTG Flows\<worker-name>\.
KV Store KV
Cloudflare Workers KV — a global key-value store used by Workers for persistent data: form state (SOV_FORMS), SKU catalogs (SKU_CATALOG), materials logs (MATERIALS_LOG), PO sync state (PO_SYNC_KV), Salesforce token cache (SF_TOKEN_KV). KV reads are eventually consistent globally; writes propagate within seconds.
Webhook
An HTTP POST sent by monday.com to a Worker URL when a specific event occurs (status change, item creation, etc.). monday.com webhooks must be registered in Integrations before being available as Automation actions. VTG uses webhooks to trigger all real-time Worker flows.
SMTP2GO
VTG's email relay service. All Worker-sent emails go through SMTP2GO using the noreply@vtgus.com sender address. Used for CSOP emails, billing notifications, bond emails, and task notifications. DKIM for vtgus.com is not yet configured — deliverability risk.
OAuth 2.0 M2M M2M
Machine-to-Machine OAuth flow used for NetSuite integration. Uses EC P-256 JWT client credentials (no user login). VTG generates an EC cert/key pair, uploads the cert to NetSuite, and embeds the private key in the Cloudflare Worker secret. Token endpoint: https://{accountId}.suitetalk.api.netsuite.com/…/oauth2/v1/token.
SuiteQL
NetSuite's SQL-like query language for reading data via the REST API. Used by vtg-ns-mcp-sync and vtg-ns-so-backfill to query customers, sales orders, and invoices (vtg-ns-compare also used it before it was deleted Oct 1 2026). Requires SuiteAnalytics Workbook to be enabled at the account level AND in the API role's Reports subtab.
Mirror Column
A monday.com column type that displays a value from a connected board without duplicating data. VTG uses mirrors extensively: Bids #3 mirrors Account region, Project Stage from Projects #4, and Blueprint name from El Nova Leads. E-Rate Projects mirrors most of its data from Bids #3 and E-Rate Deals.
El Nova
VTG's E-Rate opportunity discovery and lead management platform. Monitors USAC for new Form 470 filings and pushes them to the monday.com El Nova Leads board. Also creates Account and Contact records with dedup logic. VTG's accept/reject actions are sent back to El Nova, which creates the Accepted Monitor board item on accept.
ScopeStack
A scoping and proposal platform. Reps select Blueprints (pre-built scope templates) during the El Nova lead review — before clicking accept_470. Blueprint selection triggers the ScopeStack API to auto-create a proposal. The proposal stays in ScopeStack and is pulled manually when needed downstream (e.g. for bid building or quoting).
Wrangler
Cloudflare's CLI tool for deploying and managing Workers. Used to deploy all vtg-* Workers (wrangler deploy), manage KV keys (wrangler kv key put/get/delete), and set secrets (wrangler secret put). Must be run from Command Prompt (not PowerShell — blocked by Norton AV).
jsPDF
A JavaScript library for generating PDF files in the browser or in a Worker. Used by vtg-bid-intake (intake form + Alliant bond form) and vtg-sov-builder (SOV PDF). PDFs are generated client-side and either downloaded or uploaded to monday.com via the Files column API.
TD Synnex TDSYNNEX
VTG's primary hardware distributor and Partner API integration. The vtg-tdsynnex Worker connects to the TD Synnex Partner API via OAuth 2.0 and answers part-number lookups. Account #132973. The SOV Builder declares a binding to it but does not call it yet, so SOV pricing comes from the SKU_CATALOG KV — see the TD Synnex gap.
SKU Catalog Admin /admin/skus
A browser-based admin UI for the product catalog. Note (Sep 17): it is not part of vtg-sov-builder — that Worker has no /admin/skus route — and the vtg-sku-catalog project folder is empty, so the serving source has not been located. Lets Jon manage the product catalog without touching code or running wrangler commands: browse all vendor SKUs, add individual parts, upload JSON catalog files, and see the wrangler CLI commands for bulk pushes. Vendor catalogs loaded: Ruckus switches/APs, N1C UPS (62 SKUs at 2026-27 Platinum pricing), VTG cabling (shared with Materials Log).
monday.com File Upload (multipart spec)
Uploading files to monday.com requires the GraphQL multipart spec with exactly four form fields: query (the GraphQL mutation), variables (JSON with {"file": null}), map (JSON with {"0": ["variables.file"]}), and the file itself as field "0". The simpler variables[file] form-append approach silently returns a 200 OK but does not actually persist the file. Endpoint: https://api.monday.com/v2/file (not the standard /v2 endpoint). Used by vtg-scopestack-doc-sync to attach SOW .docx files to board items.
Idempotent
An operation that produces the same result no matter how many times it runs. VTG Workers use idempotency to prevent double-fires: vtg-cs-form checks a KV key before creating the CSOP, vtg-materials-log sets a lock key (materials_lock:{item_id}) after first submission. Critical for webhook-triggered Workers that may fire more than once.
NS Customer Internal ID
NetSuite's internal ID for a customer, stored on Accounts #1 (text_mm7m8z67). The match key between monday and NetSuite since Sep 28 2026 — written by vtg-ns-so-backfill (auto match or New Client Setup) or by a person resolving a Review. New customers created from monday carry externalId mon-<account id>.
SO Check
Status on Projects #4 (color_mm7m1x6z) set by vtg-ns-so-backfill after comparing the project with its NetSuite sales order: Verified, Customer only, Review amount, Duplicate project, Mismatch or Cannot verify. Billing figures are filled only for Verified / Customer only projects or a Customer PO match.
Remaining to Bill
Projects #4 numeric_mm7db7yk = Total Project Amount (monday, the source of truth for contract value) − Invoiced to Date (from NetSuite invoices). Invoiced only — no AR, no credit memos. Filled every 4 hours by vtg-ns-so-backfill.
Revenue Month Locked
Projects #4 checkbox (boolean_mm7a4044) that vtg-revenue-month ticks when a project reaches Ready for Invoicing or Closed. Once locked, Revenue Month no longer follows Timeline edits.
Opportunity Score
Score on each El Nova lead read from the Customer Summary PDF by vtg-lead-score and written to Opportunity Score (numeric_mm5w3j). The Leads board also has a separate Opp Score column (numeric_mm5wkd7d).
Sembly
Meeting recorder/notes service. Its webhook sends action items and notes to vtg-meeting-sync, which applies them to Projects #4 subitems and posts notes on the matching project.
Microsoft Graph
Microsoft's API for SharePoint and Microsoft 365. vtg-sp-folders uses it app-only (an Entra app registration with Sites.Selected and a write grant on each FY bid site) to build bid folders and copy addenda and SOVs.
Business-day due dates
Bids #3 subitem due dates counted back from Bid Due Date in business days, skipping weekends and US federal holidays only. Written into date3 by vtg-bid-task-dates for bids created after Sep 24 2026.
🏢 Accounts — #1
ID: 18176632844
2 automations · 0 workflows
IDTriggerActionNotes
615242921 When an item is created Send a webhook Fires vtg-account-logo Worker on Account creation to scrape + upload district logo
615244207 When column text_mkxpgyv6 (website URL) changes Send a webhook Re-triggers logo fetch when El Nova website URL is updated on an existing Account
SF sync webhook When Account created or updated Send webhook → vtg-sf-account-sync ⚠ NOT WIRED — checked Oct 1 2026. This automation could not be found. The Accounts #1 board’s only two webhooks were created Jul 28 and both feed the logo Worker, and vtg-sf-account-sync had zero invocations in the last seven days. Kept on the map because it was recorded as LIVE Sep 8 2026 and the Worker does do this work — upserting Account + Contact via Monday_Item_ID__c and writing the SF Account ID back to text_mm6s8adk — but only when something calls it, which today is backfill.mjs by hand.
👥 Contacts — #2
ID: 18176633260
0 automations · 0 workflows
No automations. Contact records are created and managed entirely by El Nova — no monday-native automation is needed.
⚡ El Nova Leads Board
ID: 18181651809
16 legacy + 1 workflow automations · 3 inactive
IDTriggerActionNotes
7920733007 When "Accept 470" button clicked Set Status column (color_mm599ptd) → Pending Intake First step of the accept chain — Pending Intake fires webhook 632506055 to vtg-bid-intake
608965294Inactive When Status → Accepted (color_mm599ptd) Send webhook Deactivated. Was the vtg-bid-intake trigger; replaced by 632506055 below. vtg-bid-intake now sets Status → Accepted itself on submit.
632506055 When Status → Pending Intake (color_mm599ptd index 6) Send webhook → vtg-bid-intake vtg-bid-intake writes the 📋 Intake Form link (link_mm6vnxwq) onto the lead; the rep opens the form from it
642139356El Nova Leads · create_item (webhook)POST /lead-created on vtg-bid-intake — addendum screenLive Sep 24 2026 — matches lead name (470#) against Bids #3 470__; on a single live-stage match attaches the addendum, stamps the addendum columns and posts a courtesy update. Never moves the bid stage. Behind ADDENDUM_DRY_RUN
645545831 / 645545840RFP Documents (file_mkw3ykdq) / Form 470 (file_mkw3w1z6) changes (webhook)POST /lead-files-changed on vtg-bid-intakeLive Oct 1 2026 — a new file on a lead whose 470 has one live bid is copied to that bid’s Addenda, the bid is flagged, owner + Sales Executive notified, lead returned to Accepted Leads
615218876 / 615223909 When "Accept 470" button (button_mkw37e4e) changes Send webhook (×2) El Nova integration webhooks registered via API (source: API, app 1573784) — El Nova listens for these to update its own system on accept
617748761 When file column (file_mkw7hy4z) changes Send webhook vtg-lead-score — reads the Opportunity Score out of the Customer Summary PDF and writes Opportunity Score (numeric_mm5w3j)
490861922 When "Accept 470" button clicked Move item to group (Accepted group) Austin's original El Nova automation — physically moves the lead item to the Accepted group on the board
490862005 When "Reject 470" button clicked Move item to Rejected group Routes rejected leads off the active list — rejected leads do NOT go to Accepted Monitor
493350968 / 493351900Inactive Form 470 / RFP Documents changes + item is in Accepted Leads Move item to New Leads + notify Sales Executive Deactivated Oct 1 2026 — sent accepted leads back to New Leads on an addendum, forcing a second intake. vtg-bid-intake /lead-files-changed handles these now.
493355183 / 493355373 Form 470 / RFP Documents changes + item is in the Rejected group Move item to New Leads + notify Sales Executive Still active — a rejected lead that gets an addendum comes back to New Leads: "New addendum for {District} - 470#: {name}"
566810401 / 566810403 When item created / When item name changes AI: extract "470 #" from item name → text_mm2f36c column monday AI automation — parses the 470# out of the lead item name and writes it to a dedicated text column for downstream useAI
ScopeStack webhook (Sep 8)ScopeStack document_status_changed (status=finished, type=sow)Download .docx → upload to Bids #3 file_mm6wm4hn or El Nova Leads file_mkw7hy4zvtg-scopestack-doc-sync · LIVE Sep 8 2026
🏆 Bids — #3
ID: 18176633000 · Subitem board: 18176633598
37 legacy + 2 workflows · 3 integrations
📋 Planned: Blueprints column to be added to Bids #3 for projects that originate directly on the board (not via El Nova) — will enable Generate SOW button to work without a Leads board blueprint selection.
IDTriggerActionNotes
482374702New item createdSet Bid Creation Date (deal_creation_date) to todayTimestamps every new bid automatically
482374703New item createdSet Bid Stage → Folder CreationAll new bids start at stage Folder Creation (index 15)
482374765New item createdCreate 23 subitems (full bid lifecycle task list)The backbone of the bid task system — creates all tasks from Folder Creation through Awaiting Results in one shot, each pre-tagged by stage and pre-dated from Bid Due Date
483152942New item createdMirror Bid Due Date to subitem "Bid Due Date Mirror" columnKeeps subitem task due date formula in sync from the parent bid due date
483296416New item createdRefresh Bid Name Formula column (formula_mkwrhcw)Forces the formula "District - 470#: XXXXXXXXX" to populate on creation
482374704Stage → Deal RegCreate linked item on Deal Reg board (18176632827)Auto-creates the Deal Reg record when stage changes; links back via connect_boards1 relation
482374714Stage → Deal RegMove item to Deal Reg groupGroup = physical location of the item in the board view
482374721Stage → Bid BuildingMove item to Bid Building group
482374719Stage → Bid CompilationMove item to Bid Compilation group
482374720Stage → Bid SubmittalMove item to Bid Submittal group
482374739Stage → Awaiting ResultsMove item to Awaiting Results group
482374746Stage → Post-SaleCreate 6 Post-Sale subitems + move to Post-Sale groupLOI, CW contract (dead task), FCDL/SPI tasks, PO, SOV update
482374740Stage → Post-MondayMove item to Post-Monday group
559103546Item enters Post-Monday groupCreate item on E-Rate Deals board (18406412794)The active Post-Monday handoff — replaces the inactive 482374713 (Projects #4) and 482374738 (CS/PM notification)
482374717Stage → Wins ArchivePost completion update + move to Wins Archive groupMessage: "This Bid has been completed and billed in full! Congrats! Bid Creation Date: {date} Bid Close Date: {date}"
482374723Stage → LostPost update + move to Lost group + rename itemMessage: "This Bid was lost. Please update all attached Boards, and fill in final amounts and results."
562741747Stage → Post-Sale (status index 12)Send webhook to vtg-cs-formOne of two vtg-cs-form webhook triggers
483153616Stage → Post-Sale (secondary trigger)Send webhook to vtg-cs-formRedundant webhook for vtg-cs-form reliability
482374706Subitem status → ARCHIVEArchive the subitemManual archive — hides completed/irrelevant tasks from the active subitem view
482374707Subitem status → You're Up!Notify assignee"You're Up! {task} is due {date} for {bid name}. You're not waiting on anyone."
482374711Subitem status → N/AClear assignee, due date, and Bid Stage SubitemEffectively removes the task from the active queue; used for inapplicable BEAR/SPI tasks
482374715Subitem due date set + Sales Rep = JakeAuto-assign Jake to subitemWatches deal_owner column — assigns Jake (92155649) to his subitems automatically
482374716Subitem due date set + Sales Rep = AlanAuto-assign Alan to subitemWatches deal_owner column — assigns Alan (92155651) to his subitems automatically
482374722Subitem due date = today (noon ET)Notify subitem assignee"Task due today: {task} is due {date} for {bid name}"
482374728 / 482374735 / 482374751Subitem due date = today (11am ET) + not completeSet parent status (Jake/Alan/Dylan Subitem Status) → Due TodayThree automations, one per person — highlights bids that need same-day attention on the parent item view
482374745 / 482374748 / 482374755Subitem status → Complete + assignee = Dylan/Alan/JakeClear parent Subitem Status column (remove Due Today)Clears the parent highlight once the person's task is done
482374724InactiveBid Due Date - 5 daysNotify assigned reps"Bid due in 5 days: {bid name} is due {date}. Delivery Method: {method}"
482374730InactiveSubitem due date + 3 days (overdue)Notify subitem assignee3-day overdue task reminder — currently off
482374713InactiveItem enters Post-Monday groupCreate item on Projects #4 + link via connect_boards6Replaced by 559103546 (E-Rate Deals creation). Left inactive as reference.
482374738InactiveStage → Post-MondayNotify CS/PM team"Hello CS and PM, this project now has a PO and is ready for processing." Replaced by E-Rate Deals flow.
7917794784 (workflow)When Bid Stage status changes to somethingCreate a subitemGeneral-purpose workflow used to add subitems on specific stage transitions beyond the initial 23-task creation
7917866595 (workflow)When subitem column changesChange parent item Bid Stage column to matchKeeps parent Bid Stage in sync when a subitem's Bid Stage Subitem column is manually changed
566854668 / 566856009 / 566856718 (integrations)Blueprint column → Wireless/Fiber Optic/BMICOverwrite item with matching item templateThree project-type templates applied when Blueprint is set on Bids #3 itemsApp
545905802 / 545905803 (AI)New item created / Item name changesAI: extract "470#:" from item name → text_mkqz3hwwmonday AI extraction automationAI
578063979 / 578063986 (AI)Item created (if Project Year empty) / text_mkqz3hww changesAI: categorize into Project Year dropdown (dropdown_mkqz1ay)Sets Project Year dropdown by AI-categorizing the 470# text columnAI
591750313Stage → Ready for Invoicing (lead_status index 3)Send webhook to vtg-billing-readyTriggers billing notification email to eratebilling@vtgus.com
628087115NS Sales Order # column (text_mm6hv20b) changesSend webhook to vtg-po-syncLive Aug 25 2026 — triggers PO sync back from NetSuite
Generate SOW button (Sep 8)Generate SOW button (button_mm70vvrb) clicked on Bids #3 itemSend webhook to vtg-scopestack-doc-sync /generate endpointTriggers programmatic SOW generation in ScopeStack; webhook auto-delivers the .docx back to Bids #3 SOW Document column (file_mm6wm4hn)
622380216 / 622381001Item created / any column changesSend webhook to vtg-monday-sf-sync (keyed connection)Salesforce Opportunity upsert · switched to the keyed connection Oct 1 2026
641680795 / 641680804Item created / Bid Stage (deal_stage) changesSend webhook to vtg-sp-foldersLive Sep 24 2026 — creates the SharePoint bid folder at Folder Creation, writes SharePoint Link, closes both Folder Creation subitems
645561102Addenda (file_mm7get0y) changesSend webhook to vtg-sp-folders /addendaLive Oct 1 2026 — copies addenda into the bid’s SharePoint folder root
645821765SOV PDF (file_mm749nna) changesSend webhook to vtg-sp-folders /sovLive Oct 1 2026 — copies each SOV version to Base Bid Docs/3 -SOV (60 s delay)
642315663 / 642315682 / 642315687Subitem created / subitem column changes / Bid Due Date changesSend webhook to vtg-bid-task-datesLive Sep 24 2026 — writes business-day due dates into subitem date3
👷 Projects — #4
ID: 18176626554
21 legacy + 11 workflows · incl. AI + app integrations
IDTriggerActionNotes
482368826New item createdSet Project Stage → New (index 6)All new Projects #4 items start at New stage automatically
482368825Stage → Kick OffMove to Kick Off group
482368827Stage → All Products ReceivedMove to All Products Received group
482368829Stage → Pre-Install Staging (index 7)Move to Construction Hold / Phased Install groupGroup is "Construction Hold or Phased install" — covers hold and staging scenarios
482368831Stage → Pre-Install Staging (index 11)Move to Equipment Only groupEquipment-only projects route to the Equipment Only group on pre-install staging
482368832Stage → Installing (index 8)Move to Installing group
482368830Stage → Closeout (index 9)Move to Closeout group
482368834Stage → Ready for Invoicing (index 3)Move to Ready for Invoicing group
482368833Stage → Closed (index 4)Move to Closed group
482368828ErrorStage → Waiting for ProductMove to Waiting for Product groupError: "missing_group" — target group no longer exists. Group was likely deleted or renamed.
591750313 (Projects webhook)Stage → Ready for InvoicingSend webhook to vtg-billing-readyFires billing notification email to eratebilling@vtgus.com via vtg-billing-ready Worker
628087115 (Projects PO webhook)NS Sales Order # column (text_mm6hv20b) changesSend webhook to vtg-po-syncLive Aug 25 2026 — fires vtg-po-sync when SO# is manually entered or backfilled
639640003 / 639640004Timeline (timerange_mm1q29se) / Project Stage changesSend webhook to vtg-revenue-monthKeeps Revenue Month equal to the Timeline end; stamps and locks it at Ready for Invoicing / Closed
545905802 / 545905803 (AI)New item created / Item name changesAI: extract "470#" from item name → text_mkqz3hwwAI extracts 470# for reporting and linkingAI
545919569 / 545919570ErrorNew item / name changeAI: extract Company → lead_company columnError: "The chosen column no longer exists." Column was deleted; automations broken.AI
578063979 / 578063986 (AI)Item created (if Project Year empty) / text changesAI: categorize into Project Year dropdownSets dropdown_mkqz1ay (Project Year) by AI categorization of the 470# textAI
566854668 / 566856009 / 566856718 (integrations)Blueprint column (color_mm2frt9j) → Wireless / Fiber Optic / BMICOverwrite item with matching item templateThree blueprint templates: "Wireless deployment - VectorFi - Wired", "Fiber Optic Cabling", "BMIC"App
7917221940 (workflow)Stage → Accept (index 6)Move item to Construction Hold / Phased Install group
7917971701 (workflow) InactiveSubitem status → Done (from anything)Move parent item to Ready for Invoicing groupAn older subitem-driven billing trigger — now superseded by vtg-materials-log stage advancement
7917999463 (workflow)Stage → Ready for InvoicingNotify Accounting team"This project is complete and ready to bill in full" — notifies the Accounting team (team ID 1424500) in monday.com
7918015674 (workflow)Blueprint column changes + contains BMICCreate subitem assigned to Engineer team"Insert the first row here" + "This might be a spot for the task" — a partially-configured placeholder; may need refinement
7918629648 (workflow)Stage → Equipment Only (index 11)Move to Equipment Only group
7918731761 (workflow)Blueprint column changes + Blueprint = Equipment Only (label 8)Move to Equipment Only groupRoutes equipment-only projects to the correct group when Blueprint is selected
7920172789 (workflow)Stage → Ready for InvoicingSet Actual Revenue Month (date_mm4tatyy) = todayStamps the revenue date for Forecast vs. Actual dashboard
7920172818 (workflow)Stage → ClosedSet Actual Revenue Month (date_mm4tatyy) = todayAlso stamps revenue date on Closed — covers projects that skip Ready for Invoicing
7920230690 (workflow)Stage → ClosedNotify Branden Sumerix + Dylan Lindhout"Performance Bond Complete — notify the bonding company that this project is complete."
7920569056 (workflow)Stage → Ready for InvoicingSet Ready for Invoicing Date (date_mm54qwps) = todayTimestamps the Ready for Invoicing date for billing SLA tracking
7922447604 (workflow)Stage → InstallingSet Materials Log link column (link_mm6mhdcx) = vtg-materials-log URL for this itemLive Aug 27 2026 — auto-populates the PM's one-click link to the materials log tool
backfill (Sep 3)One-timePopulate new 📊 SOV Builder column (link_mm6vbks) for all 156 existing bidsManual backfill completed Sep 3 2026; vtg-bid-intake now stamps both link_mm6vbks and link_mm591mdg on new bid creation going forward
📊 CRM Workspace Dashboards (Workspace 12853770)
E-Rate Pipeline Dashboard
CRM Workspace · Board 18419943586
Executive
The primary E-Rate revenue visibility tool. Shows the full pipeline from active bids through to billed projects — forecast vs. actual revenue by month, stage distribution across Bids #3, and project counts by status. Used by Jon and Greg to understand where revenue stands and what's pending in the pipeline at any given time.
Bids #3 (18176633000) — bid values, stage counts, deal owner breakdown
Projects #4 (18176626554) — Actual Revenue Month (date_mm4tatyy), Ready for Invoicing Date (date_mm54qwps)
E-Rate Revenue Forecast board (18419943586) — monthly forecast targets vs. actuals
⚠ Actual Revenue Month is auto-stamped by automations 7920172789 (Ready for Invoicing) and 7920172818 (Closed) — accuracy depends on those stages being set correctly
Bids #3 Views (Per-Person)
CRM Workspace · Board 18176633000
Sales / Bid Team
Not a separate dashboard — each team member has a dedicated Table View on Bids #3 filtered and column-ordered for their role: Alan's View, Jake's View, Dylan's View, Mark's View, plus a "My Kanban" and "My Timeline" view filtered to items assigned to the logged-in user. Each view hides irrelevant columns and surfaces what that person needs for their day-to-day bid work.
Bids #3 (18176633000) — all columns, role-filtered
Subitem board (18176633598) — task status, due dates per person
Bid Deadline View
CRM Workspace · Board 18176633000 · App: 18657380
Ops / Bid Team
A dedicated feature board view (Vibe app 18657380) on Bids #3 that surfaces bids sorted by deadline. Gives a quick at-a-glance view of what's due soonest — used during bid rush periods to prioritize workload across Dylan, Branden, Alan, and Jake.
Bids #3 (18176633000) — sorted by Bid Due Date DESC
E-Rate Historical Awards Board
CRM Workspace · Board 18424893495
Executive / Sales
Houses 1,107+ FRN records imported from nine years of USAC QuickBase exports (FY2017–FY2025), grouped by funding year. Used for win-rate analysis, territory planning, and pre-bid research — "have we won in this district before, and at what value?" Also serves as a historical reference for which 470s VTG has bid on and won over time.
USAC QuickBase export CSVs — imported via API import script
15 columns: District, FRN, Funding Year, Category, Award Amount, etc.
Projects #4 — Stage Group Views
CRM Workspace · Board 18176626554
PM / Jon
Projects #4 is organized into stage-based groups that function as a kanban board: New → Waiting for Product → All Products Received → Kick Off → Pre-Install Staging → Installing → Equipment Only → Construction Hold → Ready for Invoicing → Closed. Each group move is automated by stage changes. Jon uses this as his primary delivery management view — seeing what's installing, what's ready to bill, and what's waiting on product at a glance.
Projects #4 (18176626554) — all delivery stages, linked to Bids #3 via connect_boards6
Blueprint column drives item template overlays (Wireless/Fiber/BMIC)
⚠ "Waiting for Product" group automation (482368828) is in error state — group may have been renamed or deleted
Deal Reg Board
CRM Workspace · Board 18176632827
Branden / Deal Reg
Tracks deal registration records linked to Bids #3 items. A deal reg item is auto-created on Bids #3 when a bid moves to Deal Reg stage (automation 482374704). Branden uses this board to track registration numbers, manufacturer, status, and submission dates. Linked back to Bids #3 via the "🤝 Deal Reg's" board relation column.
Bids #3 (18176633000) — linked via connect_boards1
Auto-populated by automation 482374704 on Deal Reg stage
Bid Bonds Board
CRM Workspace · Board 18176632761
Dylan / Branden / Bonding
Tracks bid bond requirements for bids that require performance or bid bonds. A bond subitem is created on Bids #3 and a linked item is created on this board when the intake form indicates "bond required." vtg-bid-intake emails Alliant and CHC-Surety automatically. Bond status is tracked here and mirrored via the "🅱️ Bid Bonds" relation on Bids #3. When a project closes, automation 7920230690 notifies Branden and Dylan to release the bond.
Bids #3 (18176633000) — linked via board_relation0
vtg-bid-intake — creates bond email + subitem on intake form submit
Sep 25 2026 — request sets the bond subitem to Requested; Lost or Not Needed auto-cancels
Accepted Monitor Board
CRM Workspace · El Nova Leads (18181651809)
Ops / Jon
A parallel watchdog board created by El Nova when a rep clicks accept_470. Polls USAC automatically on a schedule to monitor whether the corresponding Form 470 receives funding. Purely informational — does not gate or block the Bids #3 flow. Used to catch situations where USAC denies or modifies funding on a bid already in progress. Rejected leads do not appear here.
El Nova system — creates item on accept_470 trigger
USAC API — polled on El Nova's schedule
📊 E-Rate Operating System Dashboards (Workspace 14860884)
E-Rate Deals Board
E-Rate OS Workspace · Board 18406412794
Finance / Jon
The financial deal-tracking layer for post-award E-Rate projects. Items are auto-created here when a Bids #3 item enters Post-Monday stage. Tracks: District, FRN, Contract Value, Funding Year, Category, Sales Owner, and Status (Pipeline → Submitted → Awarded → Booked). Status progression triggers E-Rate Projects creation (Pipeline→Awarded) and stamps Booking Date (→Booked). Currently has no defined owner for status updates — a documented gap.
Bids #3 (18176633000) — created by automation 559103546 on Post-Monday
E-Rate Projects (18406413755) — linked via Linked Deal relation
⚠ Gap: no defined owner or automation for status progression Pipeline → Submitted → Awarded → Booked
E-Rate Projects Board
E-Rate OS Workspace · Board 18406413755
Finance / Jon / PM
The financial and scheduling view of post-award E-Rate project execution. Mirrors data from Bids #3 (Account, Contact, Bid Value, 470#, SharePoint, Projects #4 link) and E-Rate Deals (District, Booking Date, Contract Value, Funding Year). Jon manages Execution Status, Billing Status, Planned Start Window, Risk Flag, PM/Project Owner, and timeline dates here. This board is the source of truth for when projects start and complete — complementing Projects #4 which tracks what is happening on the ground.
E-Rate Deals (18406412794) — created by automation 7917669964 when Status → Awarded
Bids #3 (18176633000) — mirrored via board_relation_mm1yt0xa
Projects #4 (18176626554) — mirrored via lookup_mm1ydhb5
📊 Standalone Dashboards & Tools (Cloudflare Pages)
VTG Inventory Dashboard
vtg-inventory.pages.dev
Ops / Warehouse
Company-wide NetSuite inventory dashboard. Fetches live from vtg-ns-mcp-sync /api/inventory/all and displays all NS locations: 41 Cabling Warehouse, 42 Secondary Warehouse, 4 Grand Rapids Office. Color-coded by location. Password protected (VTG2026 — Azure AD SSO planned). Features: search, location filter pills, sortable columns, light/dark mode, CSV export. Data refreshes every 15 min via vtg-ns-mcp-sync cron.
vtg-ns-mcp-sync /api/inventory/all · INVENTORY_CACHE KV (0233a14225194cbd81a49601f448963b)
GitHub: vtg-portal/vtg-inventory · Cloudflare Pages auto-deploy on push
⚠ After vtg-ns-mcp-sync redeploy: seed cache with curl .../api/inventory/all before dashboard will load
📊 VTG Portal — Tool & Doc Hub
VTG Staff Portal
vtg-portal.vectorfi-admin.workers.dev
All Staff
A Cloudflare Worker-hosted internal hub with four sections: Home (quick links), Tools (sales, finance, field, admin — links to all Workers and tools), Docs (markdown-backed documentation replacing OneNote — covers VES, integrations, troubleshooting, automation, E-Rate), and Admin (manage tool entries, doc pages). Config lives in GitHub: vtg-portal/vtg-portal (private repo), config/tools.json. Admin is currently password-gated; Azure AD SSO is planned.
GitHub vtg-portal/vtg-portal — tools.json + docs/ markdown files
All vtg-* Workers — linked from Tools section
Monthly Review Deck Builder
vtg-deck-builder Worker · KV: DECK_DATA
Executive / Division Leads
A Cloudflare Worker that serves the Monthly Review form. Each of the ten division leads enters their section; entries are stored in KV (DECK_DATA) and the browser builds the PowerPoint with PptxGenJS. The deployed copy (Sep 19 2026 snapshot) makes no monday.com calls — the figures are what each lead enters. Used for monthly leadership reviews.
Division leads’ form entries — KV DECK_DATA (one key per division)

Changelog

A record of all process changes, new Workers, and infrastructure updates to the VTG Lead → Invoice system.

Current: v2.14
Date Version Type Change
October 1, 2026
Oct 1 v2.14 UI Gap Analysis filters — chips at the top of Gap Analysis turn cards on and off by priority (High / Medium / Low), Paused, and Resolved / Done (which includes Live and Retired), and by section (Active gaps / Planned). Each chip shows its count, "Show all" resets, and the choice is remembered in your browser.
Oct 1 v2.13 Update Map checked against what is built — Every gap and Worker card compared with the current VTG Flows source, monday webhooks and automations, and live board data. Thirteen cards that showed planned or open work were already built; twelve Worker cards had wrong details. All corrected here, and seven deployed Workers that were missing are added.
Oct 1 v2.13 New vtg-sp-folders live since Sep 24 — Bid folders are created automatically at Folder Creation: Base Bid Docs copied with files, Lead files in the root, SharePoint Link filled, both Folder Creation subitems closed. 12 of 13 bids created Sep 24 – Oct 1 were done by the Worker; the 13th (a test bid with an invalid 470#) went Stuck as designed. Addenda and SOV copy added Oct 1.
Oct 1 v2.13 Gap Resolved Subitem reminders now fire — vtg-bid-task-dates live since Sep 24 — Due dates are written into date3 in business days, so the due-today notification, highlights and auto-assign automations finally have a date to act on.
Oct 1 v2.13 New NetSuite customer created from the CS Order form (Sep 28) · Remaining to Bill live · tax certificates done — New Client Setup creates or links the NetSuite customer through vtg-ns-so-backfill and writes the NS ID to Accounts #1. Invoiced to Date / Remaining to Bill fill every 4 hours (89 projects). 85 accounts carry their tax-exempt certificate. The Sep 29 entry saying vtg-cs-form does not create the NetSuite customer had checked the Sep 24 copy.
Oct 1 v2.13 Gap Resolved Addenda attach to the live bid (Oct 1) — vtg-bid-intake handles addendum files added to an existing lead with a live bid; reps no longer re-do the intake form. Dylan’s two Accepted → New Leads addendum automations were deactivated. Addendum detection runs live (dry run off).
Oct 1 v2.13 Process Change ConnectWise Sell / CPQ paused (Sep 29) — Six CPQ cards moved to Paused, and the diagram decision point is now a paused step. vtg-cs-form still calls vtg-monday-cpq on every CS Order submit.
Oct 1 v2.13 New Seven deployed Workers added to the map — vtg-revenue-month, vtg-lead-score, vtg-meeting-sync, vtg-logo-backfill, vtg-deck-builder, vtg-ns-mcp-sync-staging and vtg-ns-test — added to the Workers tab and, where they act, to the diagram, SOP, Data Flow, Automations and Glossary.
Oct 1 v2.13 Infrastructure vtg-ns-compare deleted — Deleted Oct 1 2026. Customer mapping is now the NetSuite Customer Internal ID on Accounts #1.
Oct 1 v2.13 Fix Corrections — vtg-po-sync writes Vendor PO #, not Customer PO #. vtg-sf-account-sync writes UID__c, not the Account ID. vtg-bid-intake is triggered by Status → Pending Intake (632506055); 608965294 is deactivated. The TD Synnex binding is not called — the duplicate Planned TD Synnex card is removed. vtg-ns-so-backfill card rewritten for v18. The Data Flow stage-map note is settled from the live code. The deck builder makes no monday calls.
Oct 1 v2.13 UI Diagram columns line up again — cells now stack their steps vertically, so every step sits under its own phase header instead of pushing later phases sideways.
Oct 1 v2.12 Infrastructure The UID is reference only — NetSuite Customer Internal ID is the match key — The UID (Salesforce UID__c auto-number) was adopted as the cross-system key and has been demoted. Salesforce duplicates accounts — 69 duplicates sent to Merlin for review — the value has not been stable, SF requirements keep moving, and it never matched NetSuite’s custentity_acs_unique_entity_identifier, which uses different numbering. Legacy rows carry blank or stale UIDs: 17 Projects #4 rows read "Cannot verify" as of Sep 28, and the fuzzy-name fallback is now off rather than papering over them. In its place the NS Customer Internal ID (text_mm7m8z67 on Accounts) is the matching key, and new NS customers created from the CS form carry externalId mon-<monday item id> — live since Sep 28. One dependency remains: vtg-ns-so-backfill’s auto-sync still links project → account by UID. The Data Flow note, the glossary entry and the order-push card were all updated to match.
Oct 1 v2.11 Resolved Both Salesforce Workers are now key-protected — vtg-monday-sf-sync (version dc33a840) and vtg-sf-account-sync (version e6d28b50). monday’s "send a webhook" automation sends no signature, so signature checking was never going to work; both Workers now require a shared key in the URL (?key=), checked before anything else, with 401 on anything unkeyed. They also narrowed what they accept: non-numeric item IDs are rejected, vtg-monday-sf-sync takes Bids #3 items only, vtg-sf-account-sync’s sync-by-ID takes Accounts #1 items only, and every route but /health is keyed. Both Bids #3 automations were switched to the keyed connection, and backfill.mjs now reads ACCOUNT_SYNC_KEY. Verified with a 401 on an unkeyed request and a live sync of Clinton Macomb Public Library.
Oct 1 v2.11 Infrastructure The old check failed twice over · secrets deleted — Worth recording because it explains why nothing caught it: the signature check on vtg-monday-sf-sync had two independent reasons it could never pass. The header never arrives, and the code read WEBHOOK_SECRET while the deployed secret was named MONDAY_WEBHOOK_SECRET. Fixing either one alone would have left it broken and looking fixed. On vtg-sf-account-sync the same pattern appeared again — /webhook checking an Authorization header monday never sends, while /sync/:itemId and /backfill had no check at all. The misnamed secret binding and the old WEBHOOK_SECRET have been deleted, and the binding name no longer appears on this map. It remains in this repo’s git history; the secret itself no longer exists.
Oct 1 v2.11 Gap The Account → Salesforce webhook cannot be found — The automations table has carried "SF sync webhook → vtg-sf-account-sync · LIVE Sep 8 2026" since it was built. Checked Oct 1: the Accounts #1 board has exactly two webhooks, both created Jul 28, and both feed the logo Worker. vtg-sf-account-sync recorded zero invocations in the preceding seven days. The row is kept and marked NOT WIRED rather than deleted — the Worker does the work it claims, but only when called, and today the only caller is backfill.mjs run by hand. SOP step 0.3 and the Account Sync detail panel were reworded to match; a new Low gap records the consequence, that a new or edited account sits in monday until someone runs the backfill. Low only because Salesforce integration work is paused.
Oct 1 v2.10 Infrastructure An addendum was making reps decline the lead — Found in the field at Kent ISD. When an addendum arrived, the automation sent the lead back to New Leads, so a rep had to complete a whole new intake form to re-accept a bid they were already working — and faced with that, reps declined those leads instead. The addendum screen exists to stop a second bid; this path was creating a second intake. Direction set: the Worker handles addendum files added to existing leads that already have a live bid, and Dylan’s two "Accepted Leads → New Leads" addendum automations are turned off. One of the few changes that touches Dylan’s automations rather than routing around them.
Oct 1 v2.10 Update Addenda to be copied into the bid’s SharePoint folder — Same treatment the RFP already gets, placed in the bid folder root next to the RFP and the 470 rather than a separate Addenda subfolder. Driven by a Bids #3 Addenda webhook. The route is /addenda on vtg-sp-folders and is key-less because the existing WEBHOOK_KEY could not be recovered; every other route keeps its key. Logged plainly because it is a second unauthenticated endpoint on this map.
Sep 30 v2.10 Resolved Salesforce CloseDate fixed — and the obvious fix would have broken it — Shipped 21 Sep, both paths verified in production. New date_mm7dfkx Actual Close Date column on Bids #3, stamped when the bid reaches Post-Sale; precedence Actual Close Date → Bid Due + 65 days → Creation + 65 (warned) → old fallback. One-way monday → Salesforce. The first suggestion was to use the existing Expected Award Date column — measurement killed it: 0 of 500 bids have it set, so the sync would have sent a null to a required Salesforce field, while 498 of 500 have Bid Due Date. Amount is unchanged and still takes a placeholder bid value as a real forecast number.
Sep 30 v2.10 Infrastructure Why the Salesforce endpoint can never authenticate — Established from the source rather than inferred. The Worker reads x-monday-signature, which monday does not send for a "send a webhook" automation, and verifySignature returns false on an empty signature — so the check can never pass and the secret is irrelevant. It was written against a header that never arrives. Fixing it means a scheme monday actually sends, or a shared secret in the URL. Separately, the write volume now has a cause: the "any column changes" webhook fires on subitems, so every subitem creation is another Salesforce write — 8 for a Post-Sale transition, ~22 for a bid creation. That is what the 414-run count was, not user edits. One-line early return fixes it.
Sep 30 v2.10 Update Two corrections: the SOW and SOV generators were never broken — Both were called broken during the walkthrough and both were working. Generate SOW simply takes ~3.5 minutes with no status column, which is indistinguishable from a failure; the SOV export had never been run on the bids being checked. The gap stands, but as a reporting gap. Likewise the two CS Order subitems are not an automation duplicate — vtg-cs-form creates the linked one and dedupes via KV, Dylan’s automation creates the plain checklist row. Nothing to raise there.
Sep 30 v2.10 Update The PO validator accepts its own placeholder — The hard block rejects N/A, TBD, all-x and all-zero, and a PO needs no particular format beyond being filled in. But the form’s own hint, PO-XXXX, normalises to poxxxx, which is not in the reject list — so typing the placeholder the form shows you passes the check meant to stop exactly that. One word closes it. Also: the Ionia walkthrough is finished and its records are deleted — bid 13089254247, test bids 13087066256 and 13089189680, and deal reg 13093685203 are all gone.
September 29, 2026
Sep 29 v2.9 New Data Flow tab added — Connectors carry real arrowheads, so the direction each record moves is readable at a glance rather than inferred from a caption. A system-level view of what actually runs: which system holds which record and what moves between them, for E-Rate and for Commercial, switchable. It shows only built and deployed behaviour — the three hand-keyed steps (NetSuite customer, sales order, invoice) are drawn as by-hand rather than omitted, and nothing planned appears on it, so it cannot drift from Gap Analysis by repeating it. Built for readers outside the team, which is why it sits second rather than behind the Changelog.
Sep 29 v2.9 Infrastructure vtg-cs-form does not create the NetSuite customer — Checked while building the Data Flow tab, because the new-client setup had been drawn elsewhere as live. Searched the deployed worker.js (Sep 24 copy, 130 KB): the only two occurrences of "NetSuite" in the whole file are the PO-number comment and its matching toast string. No SuiteTalk call, no customer create, no NS ID write-back, no custentity reference. So the NetSuite customer is still created by hand, the Planned entry for the monday client form stands, and the intake-vs-win question about when the NS customer gets created is moot until something builds it. Caveat: that copy predates Sep 25, and Cloudflare is the source of truth — if it shipped after Sep 24 this needs revisiting.
Sep 29 v2.9 Infrastructure Two accounts of the Salesforce stage map — unresolved — The Workers tab documents vtg-monday-sf-sync with a six-entry stage map (Folder Creation→1 … Awaiting Results→6), while the Sep 21 walkthrough recorded that Folder Creation, Deal Reg and Bid Compilation send no stage at all. Both statements are on this site and they cannot both be right — most likely the map exists in code but the send is conditional. Flagged on the Data Flow tab rather than silently picking one. Worth an hour with wrangler tail. Separately, the absence of any Post-Sale or Won entry in that map is what supports "Won is not sent".
September 28, 2026
Sep 28 v2.8 Infrastructure ⚠ The UID has not proved stable — reversal — The UID (Salesforce Account ID) was adopted as the cross-system source of truth on the understanding that the monday ↔ Salesforce sync was 100% reliable. It has not held: Salesforce duplicates contacts, the UID has not been stable, and Salesforce’s requirements keep changing. That leaves two problems where the map previously recorded one — legacy records with blank or stale UIDs, and newly-issued UIDs that cannot simply be trusted. The gap is raised to High and the glossary entry now carries the caveat. It also sharpens the case for the monday → NetSuite order push and the direct NS customer create: an identity minted where the record is created does not depend on a third system staying still.
Sep 28 v2.8 New Account creation order settled: monday → NetSuite → Salesforce — Account created in monday first, then the customer in NetSuite, then Salesforce, with the SF UID returned to both monday and NS. The NetSuite customer is created at won/order, not at lead. This reconciles the Sep 24 position (Salesforce out of the flow) with Bill’s new-client checklist automation: SF still gets the data, last, for reporting. Context for why the automation matters at all — sales reps do not want to create accounts in Salesforce and only do so when forced, on non-E-Rate work. Build notes: NetSuite API work runs under "VTG API Sync", an integration identity with no GUI login but full API access, whose keys an existing Worker already holds; and on the new-client form a requested credit limit over the threshold flags but does not block the NS create. SOP step 1.0 updated.
Sep 25 v2.8 New Bid bond workflow rebuilt — live — VTG’s surety is Alliant, and they confirmed system-generated requests are fine and that a lost-bid notice is enough to release a bond; the only real gap was delivery instructions. So the intake form now requires a delivery choice when the bond toggle is on: Electronic (Surety2000 / BidExpress / Other) or Physical, the default, with ship-to defaulting to the VTG office, editable, plus an instructions field. Bond emails go To CHC-Surety@alliant.com + bonds@vtgus.com, Cc Danny Rose, Nicholas Manning and the sales rep, all on one send. Bond Type is fixed at Surety bond — VTG uses surety bonds only. Needed-by defaults to 7 business days after submission, editable. Requesting sets the bid’s "Get bid bond - TOTAL = $" subitem to Requested; a bid set to Lost auto-cancels its bond, and a new Not Needed status sends the same cancellation. Pushed live Sep 25, pending Jon’s own live test.
Sep 25 v2.8 Update Intake contacts section replaces the single delivery field — Three role relations to Contacts #2 — board_relation_mm7gf0s2 End User, board_relation_mm7g1dbz Consultant, board_relation_mm7g72h8 eRate — plus text_mm7gb8eg Additional Recipients. Contacts are linked to Contacts #2, not duplicated as bid columns. Suggestions: consultant = best-scoring contact that looks like one, end user = best that does not, eRate = whoever filed the 470. "+ Add someone else" needs name and email, matches on email first to reuse a record, links it to the Account and types it Customer / Consultant so the scorer improves each bid — and a failed CRM write never fails the bid. Additional recipients are deliberately not written back. Bid delivery now takes multiple recipients as checkboxes across the three roles plus "a different address"; nothing is pre-ticked so the confirmation gate stays deliberate, and addresses de-duplicate since the consultant is often also the eRate contact. monday’s email column holds one address, so email_mm7gr1ce keeps the first recipient and text_mm7gt2na Bid Delivery Recipients holds the full list. A Billing contact field and the proposed Optional 1–5 fields were both dropped as excessive.
Sep 28 v2.8 Update Tax-exempt certificates to be pulled into monday · Design Desk bypassed — Customer tax-exempt certificates live in the SharePoint All Company Documentation library under Customers\<customer>\Accounting Documents; the library is synced but not downloaded (too large), so it has to be read through Graph. Logged as a Medium planned item — it back-fills what vtg-cs-form already captures at order time. Separately, the Design Desk dependency stays open but is being bypassed by routing orders monday → NetSuite directly.
September 25, 2026
Sep 25 v2.7 New ScopeStack customer summary now written by Claude, from monday — The team used to log into ScopeStack and write each project’s Customer Summary there. It now runs inside vtg-scopestack-doc-sync, which already held the ScopeStack API credentials. ScopeStack’s own generator was enabled first (Generate Executive Summary: Create on the Admin role) and produced poor output — it leaked "missing the JSON" text into the summary — so the writing is done by Claude via the Anthropic API, with a VTG organization key stored as ANTHROPIC_API_KEY on the Worker. It runs as part of the existing Generate SOW button; a separate "Write Summary" button was built and then removed, so there is one button, not two. One constraint worth remembering: ScopeStack’s SOW template prints Markdown symbols literally, so summary text written back must be plain text.
Sep 24 v2.7 New vtg-bid-task-dates approved — business-day subitem scheduling — The subitem plan counts back from Bid Due Date in calendar days with no weekend or holiday logic. New Worker converts the automation’s existing calendar-day offsets into equivalent business days (keeping the plan about the same length rather than reusing the numbers), skipping federal holidays only — no special Christmas–New Year handling. It works on subitems after creation so Dylan’s subitem-creation automation is untouched, and applies going forward only; existing bids are left alone. Delivery rules pinned: email bids can compile the day before sending; mailed bids go out 5 days before due, with Appendix C on the day of or the day after SOV/SOW. Mail transit is already in the offsets. If it proves out, the date3 "Task Due Date - Manual" column comes out entirely — which also closes the dead-reminder gap.
Sep 24 v2.7 Infrastructure Salesforce comes out of the flow · client form writes to NetSuite directly — Salesforce integration work is stopped until Salesforce settles its final product. It stays as the sales team’s pipeline reporting layer, not a link in the order-to-invoice chain, and nothing new gets built on it — the existing sync Workers keep running because that is how the UID is written back. In its place, the monday client form will create the new customer directly in NetSuite, carrying Cari’s required new-client fields (the same set Wendy is adding to the CSOP) so finance has what it needs at intake instead of chasing it at invoice time. Same principle as the planned monday → NS order push: create the record in NS when it exists rather than reconciling afterwards. SOP step 1.0 revised to match.
Sep 24 v2.7 Update "Remaining to invoice" wanted on Projects #4 — VTG progress-bills heavily on that board and nothing shows how much of a project is still uninvoiced. Capture invoiced amounts from NetSuite, subtract from Total Project Amount. Source-of-truth split is deliberate: monday.com owns the contract value (the sales proposal originates there and the team checks it there), NetSuite reports invoiced actuals against it. Scope is invoiced only — no collections, no AR, no credit-memo netting. Logged under Planned.
Sep 24 v2.7 Infrastructure Group-wide quote-to-cash consolidation in play — Bigger than this map but it will reshape what sits under it. Bill Loiacano ran a Quote-to-Cash discovery across the group (Comm Core, VTG logistics, Quotient, JJ’s), now moving from discovery into decision and execution, with Kevin F. wanting Jon, Bill and Radde on the group’s Q2C processes. Open feasibility question: drop Rev.io (Comm Core) in favour of NetSuite billing with monday for PM — can it be done and at what cost. The VoIP business stays and gets integrated rather than retired.
Sep 24 v2.7 Update Bid subitems should be created from intake selections, not pruned by hand — Every bid is created with the full subitem set and the team deletes what does not apply, on every bid, all season. The intake form already captures what decides it — delivery method, bond required, blueprint selection. Logged as a Medium gap; queued behind the date engine.
September 22–24, 2026
Sep 24 v2.6 New vtg-bid-intake — RFP addendum detection live — An addendum used to arrive on the Leads board looking like a brand-new opportunity and get worked as a second bid. New POST /lead-created endpoint, monday webhook 642139356 on Leads create_item, matches the lead name (the bare 470) against Bids #3 470__: one 470 never covers two separately-bid RFPs, so a repeat is an addendum. It attaches the document, stamps the new addendum columns and posts a courtesy update on the lead so nobody clicks Accept 470 — and never moves the bid’s stage. Guards: acts only on exactly one match in a live stage; zero, closed-stage and multiple-live matches log and do nothing. Dedupe strips monday’s <assetId>- prefix, without which the same certified 470 re-copies on every lead. Errors are swallowed so a new lead is never held up. Shipped behind ADDENDUM_DRY_RUN. Two API notes worth keeping: compare_value takes the CompareValue scalar, not [String!]; and only all-digit 470 values are matchable, which excludes the CBR4… / Non ERATE / No 470 bids.
Sep 24 v2.6 New Bid Delivery Contact confirmation on the intake form — The form pulls the contact email, asks whether that is who the bid should be delivered to, keeps it editable, and hard-blocks submit until it is confirmed — required whatever the delivery method, because that contact is also who bid questions go to. Three states: suggestion with Yes/No radios, consultant suggestion with a warning, no contact on file (radios gone, email required). contactCandidates() split out of pickContact() so the suggestion and the contact linked at submit use one scorer; candidate fetch is single-pass with no retries so a missing account record cannot hang the form. Validated in the browser and again in /submit. Confirmed address lands in the archived intake PDF. A free-text delivery-instructions field was considered and declined for this phase.
Sep 24 v2.6 Infrastructure Six new Bids #3 columns — file_mm7get0y Addenda (holds addendum 1, 2, 3 …), numeric_mm7gj7zz Addendum #, date_mm7gbfs7 Last Addendum Date, color_mm7ghh94 Addendum Status (Received - Unreviewed / Reviewed), email_mm7gr1ce Bid Delivery Email, date_mm7gj5zp Delivery Contact Confirmed.
Sep 23 v2.6 Update vtg-sp-folders design settled — Built as a Cloudflare Worker calling Microsoft Graph off a monday webhook, not Zapier/Make or a marketplace app. Folder name is the bid name with the colon removed (SharePoint rejects ":"). Standard subfolders come from the Base Bid Docs template (1-Cover Page … 9-Product Support Info) and are copied with their files, so each bid folder opens with VTG’s standard bid documents already in it. The Worker fills the SharePoint Link column, completes both Folder Creation subitems and uploads the Lead’s 470/RFP PDFs. Blocked on an Entra app registration + site grant from the M365 administrator; request email drafted.
Sep 22 v2.6 Infrastructure Pricing scope corrections · SOV Builder — Three facts worth pinning because they shape the discount-tier work: the top-level bidder/driver discount model applies only to Ruckus parts, not to every manufacturer; VTG does not sell Ruckus vSZD (virtual SmartZone Data Plane); and the TP-Link/Omada price list is now in hand — TP-Link is a carried line, so that half of the pending-catalogs gap is unblocked. Vertiv is still outstanding.
Sep 22 v2.6 Infrastructure Credential rotation flagged — Four credentials are hardcoded in vtg_sov_import_v4.py, across three copies of the file in the OneDrive-synced VTG Flows folder. Logged as a High gap: rotate, move to env vars or wrangler secret, delete the stale copies.
September 21, 2026
Sep 21 v2.5 Fix SOV Builder — a building could not be renamed — Renaming was implemented, as a double-click on the tab label, but nothing advertised it: no tooltip, no pencil, no affordance. The only tab control carrying a title was the harmless duplicate button; the × that deletes a building had none. Worse, the handler called window.prompt(), which browsers suppress in sandboxed and embedded contexts and which Chrome disables for the rest of a page's life once "prevent additional dialogs" is ticked — so for some users the double-click did nothing at all. It now reuses the in-page modal that Add building already used, prefilled and selected, with the mode and heading reset on cancel. Both tab buttons gained tooltips.
Sep 21 v2.5 Infrastructure vtg-sov-builder deploys worker-combined.js, not index.js — Recorded because three patch attempts changed nothing before this was noticed. wrangler.toml sets main = "worker-combined.js" in the folder root (~108 KB); index.js is a dead file from 14 Aug that nothing deploys, and two further stale copies of worker-combined.js sit under files\ (20 Aug) and Archive\files\ (14 Aug). Patch scripts for this worker must resolve the target from wrangler's main rather than guessing filenames. The first failure was initially misread as a line-ending problem, which cost four no-op deploys.
Sep 21 v2.5 Update Bid Building walked end to end on a real bid — Ionia Public Schools (470# 270000574, bid 13089254247) taken from Folder Creation through Bid Compilation with a live tail running. SharePoint folder linked, deal reg created by automation 482374704, and all three artifacts produced: SOW (asset 3261375108), SOV PDF (3261392198) and Proposal PDF (3261481236). Fourteen Bid Building subitems closed. Every finding below came out of that walk.
Sep 21 v2.5 Gap The subitem task schedule is computed and then ignored — formula8 "Task Due Date Formula" correctly derives each subitem's due date (FORMAT_DATE(SUBTRACT_DAYS({date},{numbers0}))), but date3 "Task Due Date - Manual" is empty on every subitem — and date3 is what seven active automations trigger on: the due-today notification, the three per-person row highlights, and the three auto-assign rules. monday formula columns cannot trigger automations, so the whole subitem reminder system is inert, which is almost certainly why the overdue reminder was switched off rather than fixed. Autoboost recipe 483152942 already writes a formula result into a real date column, so one more recipe of the same shape fixes it without editing anyone's automations. Caution: the three auto-assigns fire on that column changing, so a bulk backfill would trigger a wave of reassignments.
Sep 21 v2.5 Gap Salesforce receives almost nothing, fourteen times — One morning's walkthrough produced 14 updates to Opportunity 006aZ00000jC0OvQAK, every payload identical but for the timestamp. None of the work reached Salesforce: not the SOW, the SOV, the Proposal, the SharePoint folder, the deal reg, the 470 number, the account or the contact. Three separate problems sit behind that. skip: true only suppresses StageName — the Opportunity is still written on every column change at every stage. The stage map is incomplete, so Folder Creation, Deal Reg and Bid Compilation send no stage at all and Salesforce reads one or more steps behind monday. And CloseDate is populated from deal_creation_date, so every E-Rate Opportunity is created with a close date already in the past — Bids #3 has an unused date_mm2c6t1k "Expected Award Date" column that is the correct source.
Sep 21 v2.5 Gap vtg-monday-sf-sync accepts unsigned requests — Every invocation logs HMAC mismatch — sig received: <empty> and then processes the request anyway, so the public endpoint will write to a Salesforce Opportunity for anyone who knows the URL. The signature arriving empty has two plausible causes: monday's plain "send a webhook" action does not HMAC-sign its body, so the check may be for something that never arrives; or the secret is unreachable. The second is worth checking first — vtg-sf-account-sync carries a misnamed secret binding (deleted Oct 1 2026) that looks like a secret value pasted into the name field, leaving WEBHOOK_SECRET undefined and the comparison unable to succeed.
Sep 21 v2.5 Gap Generate SOW runs silently for three and a half minutes — Generate Proposal sets its status column to Working on it, produces the PDF and sets Done, the whole run taking nine seconds. Generate SOW has no status column at all: it goes quiet and a file appears some minutes later, which is indistinguishable from a failure and was in fact mistaken for one during this walkthrough. It needs a SOW Status column and the same pattern. Its filename also doubles the district name — Ionia-Public-Schools-Ionia-Public-Schools-470_-270000574-… — because the account name is prepended to a bid name that already starts with it. Separately, neither generator closes its own Create SOW / Create SOV subitem, so the artifact exists while the task still says it does not.
Sep 21 v2.5 Gap The SOV Builder link is not written at bid creation — link_mm6vbks is described on the board as auto-populated, but nothing in the current creation path writes it. Ionia arrived through vtg-bid-intake with its Customer Intake Form link set and no SOV Builder link; the ten older bids that have one most likely got it from a one-off backfill. Every new bid this season will arrive without it. The format is https://vtg-sov-builder.vectorfi-admin.workers.dev/?item=<itemId> — note ?item=, where vtg-cs-form uses ?bid=. The intake worker already writes the intake link at the same moment, so this is a couple of lines in a function that is already running.
Sep 21 v2.5 Infrastructure Board mechanics worth knowing before touching a bid — There is no group-move automation for Bid Stage → Folder Creation; every other stage has one, because the first stage was only ever reached at item creation. Sending a bid back to the start leaves stage and group disagreeing until someone drags it. Subitem status Create Item is the starting state for the five steps that produce an artifact, not a decoration. Setting a subitem's Status to N/A triggers automation 482374711, which clears its columns and deletes it — the intended way to strip Post-Sale subitems off a bid that was sent back. And monday's API will not return webhook target URLs, so a worker's name has to come from wrangler or the automation UI.
September 20, 2026
Sep 20 v2.4 Gap Resolved Customer PO # is now required on the CS Order form — Closes the Medium gap logged Sep 18. A hard block: no PO, no submission. Placeholders are refused too — the value is normalised to letters and digits, so N/A, n.a., TBD, pending, XXXX and 0000 all bounce, because a PO of "N/A" looks like a value and verifies nothing against NetSuite. Both required fields on the form now show an asterisk; previously nothing indicated that Target / Deadline Date was mandatory either.
Sep 20 v2.4 Fix vtg-bid-intake — every bid was being created with no Account and no Contact — The lookup declared its GraphQL variable as [ItemsQuery!] where monday expects [ItemsQueryRule!], so the query failed validation before it ever ran. An empty catch (_) {} swallowed the error, the function retried four times with 5-second sleeps and returned nulls, and the bid was created successfully with both relations blank. The tell was a consistent 17-second gap between form submit and the bid appearing — three sleeps of five seconds. Reproduced on two controlled runs, fixed, and verified in production on bid 13089254247.
Sep 20 v2.4 Update Contact selection rewritten and scored — Candidates now come from the Account's own Contacts relation rather than a board-wide name search, which had been returning the USAC billed_entity placeholder — a record named after the district, with no email and no person behind it. Duplicate emails collapse to the most recently updated record (El Nova creates a fresh contact per bid instead of updating the existing one, so 8% of accounts carry duplicates). Survivors are scored on email domain vs the Account website, Customer status, USAC technical type and job title, with consultants penalised heavily. Below the bar the field is left blank on purpose — a blank gets noticed, a confidently wrong contact does not.
Sep 20 v2.4 Fix Automatic district logos — 6 found in two months, now 242 of 331 — vtg-account-logo and vtg-logo-backfill shared a scraper that only read <img src>. Finalsite, ParentSquare and similar K-12 platforms emit no src at all in served HTML; the real URLs sit in data-image-sizes as percent-encoded JSON. Its Clearbit fallback had been dead since HubSpot shut the free Logo API on 8 Dec 2025, and its favicon guard didn't work — a favicon scored 14 and passed. The replacement reads lazy-load attributes, scores candidates by filename, alt text, CSS class and position, prefers a wordmark over an icon mark, and writes only at 70+. Measured read-only across all 331 addressable accounts before anything was written.
Sep 20 v2.4 New Completed Intake Form PDF on Bids #3 — The intake form now builds a PDF of everything submitted and attaches it to file_mm5bhcw7 on the new bid, using the same client-side jsPDF approach as vtg-cs-form. PDF generation can never block a submission; if it fails the bid is still created and the failure is logged. Note add_file_to_column appends rather than overwrites, so a future resubmit path would stack PDFs.
Sep 20 v2.4 Fix E-Rate Primary Contact dropdown and the blueprint mirror — The intake form's contact dropdown was a hardcoded ['Jake','Alan','Ruckus'] that had drifted from the monday column, so "John" could never be selected. It now reads the column's labels live and honours deactivated ones, meaning the list is managed in monday and cannot drift again. Separately, blueprint_name on Bids #3 was a mirror pointing at a Leads column that no longer exists (dropdown_mkw331zh); repointed to ScopeStack Blueprint(s). The Worker was never at fault there — it links the lead correctly.
Sep 20 v2.4 Infrastructure Silent failure treated as the real defect — Every bug above shared one cause: the failing path was the only one with no logging. The Account/Contact lookup, the logo scraper and the logo upload all swallowed their errors into empty catch blocks, which is why a 100%-reproducible bug survived months of production. Each now emits a tagged line — [contact-match], [intake-pdf], [logo-match] — naming what it chose, what it scored and why. vtg-account-logo already has observability with persisted logs enabled, so its output is visible in the Cloudflare dashboard, not only in a live tail.
September 18, 2026
Sep 18 v2.3 Infrastructure monday → NetSuite order push adopted as the direction — The monday ↔ NS record link is today reconstructed after the fact (UID-exact match with a fuzzy-name fallback in vtg-ns-so-backfill, read-back in vtg-po-sync). That is now formally a stopgap. The direction of travel is to create the order in NetSuite from monday at order time, so the NS record carries the monday/UID identity from creation and matching is accurate by construction. Added as a High item under Planned; the customer ID mapping blocker on the invoice flow is expected to fall out of it.
Sep 18 v2.3 Update Customer PO # to be required on the CS Order form — The form and the Projects #4 item it creates already carry a customer PO number, but it is optional. Plan: make it required and use it as the verification key against the NetSuite order, alongside UID matching. Logged as a Medium gap.
Sep 18 v2.3 Infrastructure UID confirmed as the cross-system source of truth · two new gaps logged — The UID (Salesforce Account ID, produced by the reliable monday ↔ Salesforce sync) is the standard going forward for every cross-system link; name matching is fallback only. Two consequences written onto the map: legacy monday records predate the standard and still need cleanup (Medium), and NetSuite data cleanup has no owner (Medium) — NS needs significant cleanup but is not a program Jon owns, so it needs an owner on the finance/NS side.
Sep 18 v2.3 Update Salesforce system-of-record rule added to the Commercial track — New step 1.0: Salesforce is the system of record for commercial (non-E-Rate) pipeline — "if it's not in Salesforce, it didn't happen." Routing rule documented: no E-Rate/FCC funding → Salesforce; E-Rate → monday.com; the non-E-Rate portion of a split-funded deal is tracked in Salesforce separately. vtg-sf-account-sync and vtg-monday-sf-sync are what keep reps from double-entering. Source: VTG Salesforce SOP v2.1 (Sep 9 2026).
September 17, 2026
Sep 17 v2.2 Update vtg-cs-form — tax exemption certificate capture — Section 1 gains a Tax Exempt Yes/No radio (defaults Yes) with certificate upload. New Tax Exempt Certificate file column on 🏢 Accounts #1 (file_mm79y1x5): an existing cert is auto-pulled and attached to the order and the email; a cert uploaded through the form replaces the Account copy (column cleared first, since add_file_to_column appends). Status and cert state land in the monday update body and the CSOP PDF. Blank-mode orders email the cert but write nothing to Accounts.
Sep 17 v2.2 Update vtg-cs-form — Licensing Order email prefill + bug fix — The Licensing Order checkbox handler read sm7 ("Create work order with the attached SOW") instead of sm9, so the email field could never be revealed. Fixed. New Licensing Email column on 📡 Controller Serials (email_mm799qya) prefills the field from a prior order once the box is checked; the address is only submitted when Licensing Order is actually selected. Both new columns are resolved by title and type, so a rename does not silently break the lookup.
Sep 17 v2.2 Infrastructure Process map accuracy audit — Every hardcoded column ID, status label and board ID on this map checked against the live monday boards and the deployed Worker source. Corrections: TD Synnex live pricing moved from Resolved back to an open High gap (binding declared, never called); SOV Builder trigger column corrected to link_mm6vbks; /admin/skus and the category filter bar removed from the SOV Builder card (neither exists in that Worker); TOKEN_CACHE removed from its KV list; CSOP recipients corrected to erateops@vectortechgroup.com + Sales@vtgus.com, both TO; Projects #4 stage list replaced with the board’s live labels; 8 Windows paths repaired where a literal \v had been eaten by escaping. Confirmed accurate: the UID stamp chain, all 6 PM subitem names, vtg-set-project-year’s label map, vtg-po-sync columns, both SOV KV IDs, and every board ID.
Sep 17 v2.2 Infrastructure E-Rate Deals → Projects handoff is not running — Live counts make gap #7 concrete: 📁 E-Rate Deals holds 102 items while E-Rate Projects holds 1. Automation 7917669964 only fires on Status → Awarded, and nobody sets it, so the downstream board is effectively empty. Also noted: five Workers on this map (vtg-portal, vtg-sow-builder, vtg-inventory, vtg-logo-backfill, vtg-sku-catalog) have no local source folder, so there is no redeploy path for them.
September 14–16, 2026
Sep 16 v2.1 Update vtg-materials-log v4 — NS SO writeback live — On submit, cabling lines PATCHed onto the NS Sales Order and an Item Fulfillment created. Drop-ship SOs skip fulfillment and leave a warehouse note. Re-push to NS button on locked page for retries. NS result (IF# or lines-added confirmation) stored in KV as materials_ns_result:{item_id} and posted to monday thread. NS role perms added: Transactions → Sales Order / Fulfill Orders / Item Fulfillment (Full).
Sep 16 v2.1 Infrastructure 621 missing NS inventory items bulk-written — vtg-ns-sku-writer.mjs wrote 621 items to NetSuite as InvtPart using template item C-101017BK (ID 23323). 96% SKU match rate achieved between vtg-sku-catalog and NS. 40 partial matches remain for review (10 need catalog SKU updates, 25 false matches correctly created, 5 need Mark's review). vtg-sku-compare.mjs and vtg-sku-partial-review.mjs used for analysis.
Sep 14 v2.0 Infrastructure Cloudflare Workers plan upgraded to Workers Paid — $5/month. Cron limit raised from 5 (free) to 1,000 workers. All existing cron jobs now within limits.
Sep 14 v2.0 Update vtg-ns-so-backfill v2 live — Rewritten with UID-exact matching as primary strategy: Projects #4 UID (text_mm76zvbz) → NS customer.custentity_acs_unique_entity_identifier → salesOrder.entity → tranId written to text_mm6hv20b. Fuzzy name as fallback. First sync wrote 43 SO numbers. Cron every 4h. HTML tool has Run Auto-Sync Now button, filter pills, score badges.
Sep 14 v2.0 Infrastructure Projects #4 UID column added — text_mm76zvbz created on Projects #4 board (18176626554). backfill-project-uid.mjs ran Sep 14 2026 — name-matched to Accounts board UID (text_mm6s8adk). 6 active E-Rate projects stamped manually. Remaining blanks: commercial/non-eRate (no Account in system) and closed projects.
Sep 14 v2.0 Fix vtg-cs-form: UID stamp on Projects #4 creation — /api/submit-pdf handler now reads Account UID (text_mm6s8adk from board_relation3 on Bid item) and writes to text_mm76zvbz on the new Projects #4 item at creation time. Going-forward fix — all new projects get UID stamped automatically. Deployed Sep 14 2026.
Sep 14 v2.0 Infrastructure vtg-proposal-builder v4.1 live — Bid due date y-position fixed (y=540, below district/470# line). SOV PDF column: file_mm749nna. Status column: color_mm74qsfe. Deployed at vtg-proposal-builder.vectorfi-admin.workers.dev.
Sep 14 v2.0 Infrastructure ScopeStack Template V5 fixes — Rate Adjustments section font corrected from Times New Roman to Calibri (36 occurrences). current_version.name merge field removed (was crashing generator). Blank page after Scope of Work is a ScopeStack limitation — not fixable.
Sep 14 v2.0 Infrastructure vtg-sov-builder PDF updates — Meta bar removed from PDF pages. Summary tab header "Location" → "Bid Item". Section headers full-width. Type column: IC for most sections, BMIC for BMIC section. SOV PDF uploads to file_mm749nna on Bids #3 (was wrong column).
September 13, 2026
Sep 13 v1.9 Infrastructure vtg-materials-log copper SKU catalog complete & in use — 951 copper SKUs (C- prefix) loaded from Mark's inventory list; catalog now 1,031 total (+ 80 fiber F- prefix); all SKUs merged into vtg-sku-catalog KV key. Gap closed.
Sep 13 v1.9 Fix vtg-monday-sf-sync patched — RecordTypeId hardcoded to Erate record type (012aZ00000BHkT7QAL); Cross_Sell_Opp__c set to "NO" on all records; stage logic finalized: SKIP stages (no SF upsert, fields-only update if record exists) = New Bid Folder Creation, Folder Creation, Deal Reg, Email, Bid Compilation, Bid Submittal, Bidding, Wins Archive; ACTIVE stages (full upsert incl. StageName) = Bid Building, Awaiting Results, Post-Sale, Post-Monday, Lost. Worker.js moved to VTG Flows\vtg-monday-sf-sync\.
Sep 13 v1.9 Infrastructure Salesforce Opportunity record types confirmed — Erate: 012aZ00000BHkT7QAL, Commercial: 012fo000000XSojAAG, RFP: 012fo000000XSqLAAW, VTG RFP: 012fo000000XSrxAAG. Cross_Sell_Opp__c picklist confirmed: --None--, NO, YES.
September 10, 2026
Sep 10 v1.8 Infrastructure SKU Catalog architecture revised — vtg-sku-catalog is now the single master key containing all vendors merged into one JSON array. Worker reads only this key. Separate vendor keys remain in KV as backups but are not read by loadSKUs(). Fixes disappearing-catalog bug where pushes to individual vendor keys weren't appearing in the SOV Builder.
Sep 10 v1.8 Infrastructure Ruckus catalog rebuilt from full Sep 2026 price list — 3,631 SKUs (692 wireless, 1,389 switches, 1,415 licensing, 89 transceivers, 46 accessories). All 4 Ruckus discount tiers now stored per SKU: Bidder VAR (RKS-0436), Driver VAR (RKS-0437), RSD VAR (RKS-0438), E-Rate Takeout (IDC017). Bidder VAR is the default; others selectable at bid time. Actual AP hardware units (R370, R670, R750, R770, T350, T670, T750, etc.) now in catalog with correct pricing.
Sep 10 v1.8 Infrastructure vtg-sku-catalog total: 5,042 SKUs — Ruckus 3,631 · VTG Cabling 1,031 · Fortinet 318 · N1C 62. Juniper/Mist excluded (single-customer, not worth catalog maintenance). Vertiv and TP-Link Omada pending price lists.
Sep 10 v1.8 Infrastructure ScopeStack eRate SOW Template V3 built — updated company branding (Vector Powered by VTG), FY2027 labor rates (Cabling $110, L1 $195, L2 $225, L3 $265, L4 Negotiated), five office locations in footer. New "Project Management — E-Rate" service (ID 471786) and blueprint (PM-ERATE, ID 6702) created in ScopeStack under eRate > Professional Services. PM blueprint applies to all installation bids; skip for equipment-only. vtg-scopestack-doc-sync template routing still hardcoded to V2 — needs update when V3 is uploaded.
September 8, 2026
Sep 8 v1.7 UI Slide-out detail panel — replaced bottom-of-page detail section with a slide-in drawer. Click any step card in the diagram to open the panel from the right. Close with ✕, Escape, or clicking the overlay.
Sep 8 v1.6 New Worker vtg-sf-account-sync — syncs monday.com Accounts (#1) and Contacts (#2) to Salesforce as Account and Contact objects using Monday_Item_ID__c as external ID. Writes SF Account ID back to UID column (text_mm6s8adk) on Accounts board. Backfill ran against all 791 existing accounts.
Sep 8 v1.6 New Worker vtg-scopestack-doc-sync — two-endpoint Worker. Endpoint 1: catches ScopeStack document_status_changed webhook, downloads .docx SOW, routes by template to Bids #3 SOW Document column (file_mm6wm4hn) or El Nova Leads. Endpoint 2: triggered by Generate SOW button (button_mm70vvrb) on Bids #3 to programmatically trigger SOW generation. First confirmed delivery: North Branch Area Schools, 470# 260005778.
Sep 8 v1.6 Infrastructure Fortinet catalog added to SKU_CATALOG KV — 318 SKUs (54 HW, 132 UTP bundles, 132 UTP licenses) covering FortiGate FG-30G through FG-900G at MSRP. Added via vtg-sov-builder /admin/skus.
Sep 8 v1.6 Infrastructure Live on vtg-process-map.pages.dev — process map deployed to Cloudflare Pages via GitHub (vtg-portal/vtg-process-map). Auto-redeploys within ~30 seconds of any push. URL is permanent and shareable.
September 4–5, 2026
Sep 4 v1.5 New Tool vsz-lldp-neighbors.py — local Python script that SSHes into Ruckus SmartZone, runs LLDP neighbor discovery across all APs in a zone, exports to timestamped CSV, optionally writes back to AP description. Added to vtg-portal as tool #23.
September 3, 2026
Sep 3 v1.4 Process Change Intake form redesigned — Sales Executive and ScopeStack Blueprint(s) are now entered inside the vtg-bid-intake form (after accept_470), not before. Blueprint selection in the form triggers ScopeStack proposal creation. Eliminates the pre-accept manual entry step.
Sep 3 v1.4 Bug Fix vtg-bid-intake patched — fixed Account/Contact lookup (replaced unreliable items_by_multiple_column_values with items_page + contains_text). Fixed SOV Builder link not being written on form submit. Bond section redesigned with Surety bond read-only. Retries bumped 3→4.
Sep 3 v1.4 New Worker vtg-tdsynnex — TD Synnex Partner API OAuth 2.0 integration. Exposes /api/lookup for live contracted pricing. Called internally by vtg-sov-builder via service binding. Falls back to SKU_CATALOG KV for non-TD Synnex items. TOKEN_CACHE KV with auto-refresh.
Sep 3 v1.4 Update vtg-sov-builder enhanced — [corrected v2.2: the TD Synnex live pricing, LIVE badge and category filter bar described here were planned but never shipped — see the TD Synnex gap] /admin/skus catalog admin UI. Sep 10 2026: SKU catalog rebuilt — 5,042 SKUs across Ruckus (3,631), VTG Cabling (1,031), Fortinet (318), N1C (62). All 4 Ruckus discount tiers (Bidder/Driver/RSD/Takeout VAR) stored per SKU. Full AP hardware catalog now loaded.
Sep 3 v1.4 Process Change Bids #3 column restructure — new 📊 SOV Builder column (link_mm6vbks) created; all 156 existing bids backfilled. Customer Intake Form column (link_mm591mdg) now dedicated to intake form links only. vtg-bid-intake stamps both columns on new bid creation.
August 25–30, 2026
Aug 30 v1.3 Doc Process map published — initial 7-tab HTML document covering E-Rate, Commercial, and E-Rate Op System tracks. Includes Flow Diagram, Written SOP, Gap Analysis, Workers, Glossary, Automations, and Dashboards tabs.
Aug 27 v1.2 Update
Sep 15 2026 vtg-ns-mcp-sync — inventory cache endpoints live — /api/inventory (location 41, feeds vtg-materials-log On Hand column) and /api/inventory/all (all locations, feeds vtg-inventory dashboard) added. INVENTORY_CACHE KV (ID: 0233a14225194cbd81a49601f448963b) shared between both consumers. Cron refreshes both keys every 15 min. NS VTG API Sync role permissions added: Lists → Items (Full), Lists → Locations (View), Reports → Inventory (View).
Sep 15 2026 vtg-inventory dashboard live — Company-wide NS inventory dashboard at vtg-inventory.pages.dev (Cloudflare Pages, GitHub repo vtg-portal/vtg-inventory). Password protected (VTG2026, Azure AD SSO planned). All NS locations: 41 Cabling Warehouse, 42 Secondary Warehouse, 4 Grand Rapids Office. Features: search, location filter pills, sortable columns, light/dark mode toggle, CSV export. Fetches live from vtg-ns-mcp-sync /api/inventory/all.
Sep 15 2026 vtg-materials-log v3 — NS Inventory On Hand column added to parts table; color-coded badges (green/yellow/red) from NS location 41 (Cabling Warehouse) via shared INVENTORY_CACHE KV; UID (text_mm76zvbz) and NS Sales Order # (text_mm6hv20b) added to project card; On Hand loading from KV — no direct NS API call on page load.
Aug 27 v1.2 New Worker vtg-revenue-month-sync — fires on Projects #4 Timeline column change, extracts end date, writes to Revenue Month (date_mm39fh8x). Skips Closed items and cleared timelines.
Aug 27 v1.2 New Worker vtg-msp-csop — Commercial/non-E-Rate CSOP form deployed. Bypasses Bids #3 and El Nova entirely. Creates Projects #4 item directly with task list subitems built from form fields.
Aug 27 v1.2 Infrastructure Cabling Install Scheduler board — new monday.com board (ID 18427983069) for 10-person crew scheduling. 4 stage groups, 33 jobs pre-loaded, 2 automations (tomorrow reminder + crew assignment notification).
Aug 25 v1.1 New Worker vtg-po-sync — syncs NetSuite PO numbers and approval status back to Projects #4. Webhook on NS SO# column change + cron every 4h. KV: PO_SYNC_KV.
Aug 25 v1.1 New Worker vtg-ns-so-backfill v2 — ongoing sync Worker (cron every 4h) for NetSuite Sales Order numbers into Projects #4. v2 uses UID-exact matching (text_mm76zvbz → NS custentity_acs_unique_entity_identifier) as primary strategy; fuzzy name fallback. First sync wrote 43 SO numbers on Sep 14 2026.
Aug 25 v1.1 Gap Resolved NS process documentation — vtg-ns-audit Node.js tool built. First-ever NetSuite process documentation for VTG via OAuth 2.0 M2M + SuiteQL. Generated self-contained HTML report tying NS data to each process step.
Prior to August 25, 2026
Aug 13 v1.0 New Worker vtg-monday-sf-sync — Bids #3 stage changes sync to Salesforce as Opportunity upserts via Monday_Item_ID__c external ID. First SF record: Shaker Heights City School District.
Aug 13 v1.0 Infrastructure vtg-ns-mcp-sync auth live — NetSuite production OAuth 2.0 M2M auth established. Six bidirectional sync flows coded. Blocked on customer ID mapping (vtg-ns-compare) and NS service item ID.
Ongoing v1.0 New Worker vtg-cs-form — CS Order Processing form generated and emailed to erateops@vectortechgroup.com when Bids #3 moves to Post-Sale. KV-based deduplication. monday subitem auto-created.
Ongoing v1.0 New Worker vtg-sov-builder — SOV quoting tool for sales. Multi-tab buildings, SKU catalog, section types, per-row labor, markup overrides, jsPDF generation, upload to Bids #3 Files column.
Ongoing v1.0 New Worker vtg-bid-intake — triggered by accept_470. Creates Bids #3 item, auto-links Account/Contact, serves intake form, handles bond creation. Core of the E-Rate lead intake flow.
Ongoing v1.0 New Worker vtg-materials-log — cabling materials accounting for Projects #4. PM submits fiber/copper parts on stage → Installing. Auto-advances to Ready for Invoicing and fires billing notification email.
Ongoing v1.0 New Worker vtg-account-logo — scrapes district website for logo, falls back to Clearbit, uploads to Accounts board logo column. Backfill ran against 786 existing accounts.
—
—
Click any step in the diagram to see details.