@SpringBootApplication and the production entry point. Defines the Lambda bean Function<SQSEvent,String> loadInvoices(): parses each SQS record body into a Tenant (Gson) and delegates to JbDataLoadService.loadInvoices.
controller/InvoiceController
@RestController, POST /api/invoices/load. HTTP mirror of the Lambda bean for local/dev invocation — accepts an SQSEvent-shaped JSON body.
Start with InvoiceService — it is where nearly every change to this module lands.
Class
Responsibility
service/JbDataLoadService
Thin orchestrator. Calls InvoiceService.loadInvoices(tenant), then persists the audit: updates tblTransmissionDetails for the tenant and inserts a tblTransmissionDetailsHistory row including the captured run log.
service/InvoiceService
The core (~1,300 lines). Everything ServiceTitan: paged invoice extraction and mapping to entities, contact enrichment (batched, 250 location ids per call), installed-equipment pulls, and the outbound callServiceTitan(...) push (agreements → location tags/custom fields/notes + equipment warranty dates; claims → job PATCHes). Also applies the inbound transforms (name splitting, truncation, price summation, missingEquipment / isSeaCoast flags).
service/TokenService
ServiceTitan OAuth2 client-credentials flow. Builds the token request against ST_AUTH_URL, adds the ST-App-key header from ST_APP_KEY, and produces authenticated headers for all subsequent calls.
Builds the real (Lambda) datasource in code: MySQL URL from DATABASE_ENDPOINT/DATABASE_PORT, username from the Secrets Manager secret (SECRET_NAME), password from a generated RDS IAM auth token. Also configures the JPA entity manager (Hibernate, MySQL dialect, entity scan of this package).
config/PersistenceConfig
JPA/transaction wiring companion to JpaConfiguration.
config/RestConfig
RestTemplate bean using the Apache HttpClient 5 request factory.
Raw JdbcTemplate queries that don’t fit JPA: batch phone/email UPDATEs, location/agreement id lookups for equipment pulls, and the outbound read queries (getAgreementDetails — join of tblAgreement+tblAgreementEquipments+tblProducts filtered to agreementStatus='PAID' AND isSentToST=0; getClaimsDetails — isReadyForST=1 AND isSentToST=0; custom tag/field lookups from tblTenantCustomTags/tblTenantCustomFields).