Skip to content

Code Reference — jbw-sam

High-level, per-Lambda guide. All paths relative to st-integration/jbw-sam/. Function names deploy as ${Environment}_<logicalId> (e.g. prod_jbwalldealerlist).

Every Node function carries its own copy of util/index.js (canonical copy at src/util/index.js) exporting:

  • sendResponse(statusCode, body) — CORS JSON response wrapper
  • validateInput(...) — request validation
  • mysqlConnection() — mysql2 connection through RDS Proxy using an IAM auth token (AWS.RDS.Signer, mysql_clear_password plugin, ssl.rejectUnauthorized=false)
  • some functions also use mySqlCon — promise-based, transaction-capable variant

Most handlers are thin: validate input → run SQL against the jbwst schema → sendResponse. SQL is largely string-interpolated (see caveats in the module doc).

Complete method + path → function map from template.yaml:

MethodPathFunctionNotes
GET/dealerjbwalldealerlistdealer search/list (?key=&type=)
PATCH/dealer/{id}jbwdealerstatusregisterupdatedealer status update
GET/dealer/{id}/verifyjbwdealerverificationdealer existence check
GET/dealer/{id}/onboardjbwonboarddetailsonboarding record
GET/dealer/{id}/cardsdatajbwdealerdetailscardsdatadealer dashboard KPIs
GET/dealer/{id}/gettenantinfogetTenantInforeads Active tenants (tblTenant+tblTransmissionDetails) and enqueues one SQS message per tenant to JBWSQSURL — the trigger hand-off to the extraction Lambda
GET/dealer/{id}/transmissiondetailsjbwtransmissiondetailsbydealerlatest sync audit
GET/dealer/{id}/transmissiondetailshistoryjbwtransmissiondetailshistorybydealersync audit history
GET/dealer/nononboardedlistjbwnononboardeddealerlistdealers not yet onboarded
GET/dealer/latestonboardeddealersjbwgetfivelatestdealeronboardlistadmin dashboard widget
POST/newdealeronboardjbwnewonboardingpersists onboarding, then invokes jbwagreementsdatamatch for the initial sync
GET/dealeronboardjbwdealeronboardedlistonboarded dealer list
POST/dealerregister/addjbwdealerregistercreateregistration record
GET/dealerregisterjbwdealerregistrationlistregistration list
GET/dealerregister/{id}/dealerverifyjbwdealerregistrationverify(timeout 900 s)
PUT/dealerregister/userstatusjbwuseractivestatusCognito enable/disable + SES; invokes jbwdealerregistrationsetactivestatus
PATCH/dealerregister/{id}/updatereleasenotestatusjbwupdatereleasenotesstatusrelease-notes seen flag
POST/signupjbwusersignupCognito signup; invokes jbwdealerregistercreate + jbwemailservice
POST/changepasswordjbwchangePasswordCognito + SES
POST/resetpasswordjbwuserresetpasswordCognito + SES; invokes jbwdealerregistrationuserverify
GET/tenant/{tenantid}jbwtenantidverificationtenant check
PATCH/tenant/{tenantid}jbwtenantclientidupdateupdate ST creds for tenant
GET/tenant/dealer/{dealerid}jbwtenantslistbydealertenants per dealer
POST/jbwservicetitanJBWClientServiceTitanVerificationverifies ST OAuth creds; optionally checks required tag-types, job custom fields, location custom fields exist (see below)
GET/workiz/accountverifyjbwworkizaccountverifyverifies Workiz account via job/all/
GET/agreements/dealer/{dealerid}jbwdealeragreementlistagreement grid
GET/agreements/{id}/equipmentsjbwagreementequipmentsbyagreementidequipment rows
POST/agreements/{id}/equipmentsjbwagreementequipmentaddadd equipment
PATCH/agreements/{id}/equipmentsjbwdeleteagreementbyid⚠ route collides with add/get; part of the mis-indented template block
PUT/agreements/{id}/equipmentsyncjbwservicetitansagreementspullcreates the agreement in JBW: builds payload from tblAgreement/tblAgreementEquipments/tblBusinessUnit (max 5 equipments), POSTs to JBW_AGREEMENTS_URL, writes back jbwAgreementId/pdfUrl/warranty dates/status SAVED; handles renewals
GET/agreements/{id}/agreementdetailsjbwagreementwithequipmentsdetailsagreement + equipment detail
POST/agreements/{id}/duplicateagreementjbwcreateduplicateagreementwithequipmentsclone agreement
GET/agreements/dealer/{dealerid}/invoicesearchjbwinvoicejobsearchST invoice lookup (accounting/v2 + installed-equipment)
POST/agreements/dealer/{dealerid}/newinvoiceagreementjbwcreateagreementfrominvoiceagreement from invoice
GET/agreements/dealer/{dealerid}/stequipmentsjbwgetstequipmentsfortenantST installed-equipment by location ids
GET/jbwagreements/agreement/{jbwagreementId}jbwagreementdetailswithjbwagreementidlookup by JBW agreement id
GET/agreementsync/{id}jbwagreementsyncdatalistmatch-grid data (paged, tab-typed)
GET/agreementsync/{id}/spcalljbwstdatasyncspcallsync trigger: per tenant of the dealer, invokes jbwagreementsdatamatch (RequestResponse)
PUT/agreementsync/approvejbwagreementapproveprocessapprove matched agreements
PUT/agreementsync/{id}/locationjbwagreementmatchingdatalocationupdatemanual location match
GET/claims/{dealerId}jbwclaimslistclaims grid
PATCH/claims/stupdatejbwclaimsstupdateJBW → DB claim sync: fetches JB360ClaimStatus SQL view from the JBW public API (single/bulk/last-day modes), matches to tblClaims, updates status and sets isReadyForST=1, isSentToST=0 for the ST push done by extraction
PATCH/claims/reject/{claimid}jbwclaimsrejectclaimstatusreject claim
PATCH/claims/claimidupdate/{id}jbwclaimsclaimidupdateattach JBW claim id
GET/invoices/invoicedetails/{invoiceid}jbwinvoicedetailsbyinvoiceidinvoice detail
GET/tblproducts/searchjbwtblproductssearchproduct SKU search
GET/stlocations/search/{dealerid}jbwstlocationsearchstaged ST location search
GET/customdatajbwgetcustomdatareference data
GET/admindashboard/cardsdatajbwadmindashboardcardsdataadmin KPIs
GET/emailnotificationsjbwemailnotificationlistnotification inbox
PATCH/emailnotifications/{id}jbwemailnotificationviewedupdatemark viewed
FunctionRole
jbwagreementsdatamatchThe core sync engine (timeout 300 s). Per dealer: pulls JBW agreements (GET public-api.jbwarranties.com/v1/dealers/{id}/agreements, paged 500) into tblJBWAgreementData; pulls ST locations (crm/v2, pageSize 5000) into tblSTLocationData or Workiz job-locations into tblWorkizLocationData; then CALL jbw_st_dataSync(dealerId, crmSystem) to match locations ↔ agreements. Invoked by jbwstdatasyncspcall and jbwnewonboarding.
jbwagreementslocationsstupload(timeout 900 s) Writes JBW agreement references back into ServiceTitan: PATCH crm/v2 locations/{id} + POST locations/{id}/notes.
jbwequipmentsyncstoredpro, jbwpendingclaimstoredproc(timeout 900 s) Stored-procedure runners.
jbwpendingagreementsnotification, jbwdealerpendingagreementsclaimsnotification, jbwemailserviceSES notification emails (pending agreements/claims; general email service). ⚠ the claims-notification function references a misnamed function (...claimlist vs dir ...claimslist).
jbwworkizjobsdatafetch / jbwworkizjobsdatasavePull completed Workiz jobs (job/all/?status=done) and persist them.
jbwdealerregistrationsetactivestatus, jbwdealerregistrationuserverifyCognito/registration helpers invoked by the auth-flow functions.

~30 source dirs under src/ are not wired into template.yaml — deployed or invoked manually (console), or WIP. The important ones:

DirRole
cognitoclienttokenauthorizer/API Gateway Lambda authorizer — verifies Cognito JWTs (jsonwebtoken + jwks-rsa), stage→pool map, requires scope https://jb360api.jbwarranties.com/apivendor, returns IAM Allow/Deny.
jbwapiauthorizerupdate/ (ESM)Post-deploy utility that walks all API Gateway methods and attaches the Cognito authorizer (OPTIONS → NONE). Must be run after every API redeploy.
jbwdatapullfromJB/ (Python 3.12)Reverse sync JBW → DB: fetches recently modified agreements from a JBW API and updates tblAgreement status/dates/comments by jbwAgreementId (handles cancelled/deleted). Vendored pymssql/pymysql deps; RDS IAM auth.
jbwagreementreferenceremovalfromst/Removes JBW references (notes, custom fields, equipment data) from ServiceTitan locations.
jbwremoveduplicatelocationnotesfromst/Dedupes agreement-link notes on ST locations.
jbwcreatepotentialclaim/Inserts a tblClaims row with status “Potential Claim Created”.
jbwautoprocessagreementsstatus/Toggles tblTenant.autoProcessAgreements.
jbwdbconnection/Standalone MSSQL connectivity test (not part of the app).

Others (same DB-CRUD pattern): jbwagreementdismiss, jbwagreementsearch, jbwagreementslocationsfetch, jbwagreementsyncfileupload, jbwagreementsyncuploadcsvdata, jbwclaimsadmintoolsupdate, jbwclaimsdownloadadmintools, jbwclaimsearch, jbwcreateupdateemailtemplate, jbwdealeradmintoolsupdate, jbwgetagreementdetailsbyjbwagreementid, jbwgetequipmenttypes, jbwgetstinstalledequipments, jbwinvoiceitemskuupdate, jbwinvoicelookup, jbwinvoicesummarylist, jbwsendagreementemail, jbwstlocationdatawithagreement, jbwupdateagreementcontactinfo, jbwupdateagreementsynclocation, jbwusersignupemail.

  • JBWClientServiceTitanVerification — body {clientId, secretId, tenantId, tagsList, jobId, fieldsList}. Gets an ST OAuth token; with jobId it additionally checks tenant tag-types (settings/v2), job custom fields (jpm/v2/jobs?number=), and location custom fields (crm/v2/locations/{id}) and reports which required tags/fields are missing.
  • getTenantInfo — the bridge to extraction: each SQS message carries tenantId, dealerId, ST clientId/clientSecret, batchId, syncStartDate. Has an EventBridge Scheduler IAM policy, so it can be (and likely is) invoked on a schedule.
  • jbwclaimsstupdate — matches JBW claims to local rows by jbwClaimId, or by job number + dealer + agreement (FIND_IN_SET) as fallback.

Tables: tblTenant, tblDealerOnboard, tblDealerRegister, tblTransmissionDetails(+History), tblAgreement, tblAgreementEquipments, tblJBWAgreementData, tblSTLocationData, tblWorkizLocationData, tblWorkizAccounts, tblClaims, tblBusinessUnit, tblProducts, tblInvoice, tblInvoiceItem. Views: vwOnboardedDealers, plus JBW-side JB360ClaimStatus (remote, via public API). Stored procedures: jbw_st_dataSync and 9 others — documented from the live DB in aws/database.md. (Code references to a jbw_workiz_dataSync notwithstanding, the live prod DB has no such procedure — Workiz is a _platform='Workiz' branch inside jbw_st_dataSync.)