Skip to main content

Planning Document: Lead Marketing Module & "Save as Quote" Feature

1. Background & Objective

The "Lead Marketing" module currently manages prospective customer inquiries primarily through raw text messages. However, there is a gap in the workflow when sales representatives need to create a detailed quote (with specific bin sizes, waste types, locations, and extra fees) for these prospects. Currently, doing so forces the creation of a live order or contract, polluting the master customers and orders tables with prospects who haven't committed to a deal.

The objective of this implementation plan:

  1. Inquiry Intake Sandbox: Raw queries from public website contact blocks or Twilio SMS hooks populate a flat, isolated structure. No relational dependencies or system accounts are initialized at this point. Purchase intent remains unquantified.
  2. Lead Marketing CRUD: When an administrator validates that an inquiry represents a qualified pipeline candidate, the record is promoted to the core CRM pipeline context. Formalize and upgrade the Lead Marketing module's CRUD operations to handle rich prospect data, including comments and status tracking.
  3. Unified Look-Up Interface: When creating an Ad-hoc Order or dynamic Contract, the administrative customer autocomplete field executes a unionized look-up, querying both stable corporate customer rows and unapproved lead rows simultaneously, differentiating them cleanly via distinct UI flagging utilities.
  4. Conditional Execution Engine: Selecting a prospect flagged as a Lead and hitting a submission boundary triggers divergent computational paths based on the requested transaction type:
  • Save as Quote: Bypasses accounting services. Serializes the current Vue form data configuration into an isolated blob and writes it into the lead column snapshot record.
  • Place Order / Save: Executes an immediate, atomic promotion block. Provisoning legal structural entities first before routing transaction objects into live scheduling stacks and Xero accounting pipelines.

2. Core Architecture Rules

To maintain strict database hygiene and operational integrity, the following architectural boundaries must be enforced: The "Sandbox" Concept (No Pollution): Clicking "Save as Quote" MUST NOT create records in the orders, customers, addresses, or billing_contacts tables. It only interacts with the leads table. Validation Bypass: Financial and operational validations (Stripe, GoCardless, Credit Limits) must be bypassed when saving a quote from the Order or Contract forms. JSON Payload Storage: The entire Vue.js form state (customer details + cart items) from the Order/Contract screens will be serialized into a JSON string and stored in a new quote_payload column inside the leads table. Multi-Quote Handling: A single prospect (identified by email/phone) can have multiple quotes over time. Saving a new quote creates a new lead record to preserve history. Conversion Flow: Only when a Quote is explicitly "Converted" by the admin via the Lead Details page will the system re-inject the JSON payload back into the Order/Contract form to be processed as a legitimate transaction. Soft Deletes: Lead deletion must use Soft Deletes to preserve historical comment integrity.

3. Form Submission & State Mutation Matrix

When processing operations inside order or contract creation forms, the application evaluates the active metadata context to split processing boundaries according to this transactional rule map:

Active Selection TypeUser Submission TriggerRelational Operational ActionsCRM Pipeline Status Shift
customerPlace Order / SaveSaves standard live order object elements.N/A (No pipeline tracking row)
customerSave as QuoteGenerates an order with an internal status = 'quote' flag representation.N/A
leadsPlace Order / SaveAtomic Auto-Approval: Safe insertion running inside database transaction blocks. Instantiates 1 customer, 1 address, and 1 billing_contact row first, then attaches the newly generated keys to complete live order write operations.Updates status to converted. Marks prospect row approved.
leadsSave as QuoteBypasses operational entity tables. Serializes form data arrays into an isolated string blob and stores it inside the Lead column context.Updates status to quote sent. Preserves quotation state.

4. Database Modifications

To back this multi-tiered architecture without regression anomalies, the relational schema models are modified as follows:

Table TargetedField Column TargetData Struct TypeNull ConstraintArchitectural Function & Use Case
inquiriesidBIGINT (AutoInc)NOT NULL (PK)Primary isolation filter row key for web intake.
inquiriesname, email, phoneVARCHAR structuresNullable parametersLoose capture text inputs sent from external site fields.
inquiriesmessageTEXTNOT NULLRaw question block entered by the anonymous user.
inquiriesstatusENUMNOT NULLTriage state tracking: 'pending', 'converted', 'junk'.
lead_marketinginquiry_idBIGINTNullable (FK)Lineage tracing key binding lead to parent origin inquiry data row.
lead_marketingquote_payloadLONGTEXT / JSONNullableSandbox data bucket storing serialized vue form cart item details.
lead_marketingquote_totalLDECIMAL(10,2)NullableAggregated financial total used for dashboard metric tracking.
lead_marketingsourceVARCHAR(50)NullableIdentifies origin: e.g., 'website_form', 'twilio_sms', 'admin_cart_order', 'admin_cart_contract'.

6. Acceptance Criteria & Test Cases

TC-LEAD-01 (Standard Creation): An admin or webhook can successfully create a basic lead. TC-LEAD-02 (Soft Delete): Deleting a lead removes it from the UI but retains the record and associated comments in the database (deleted_at is populated). TC-QTE-01 (Strict Isolation): When an admin creates a complex order and clicks "Save as Quote", verify that NO new rows are added to customers, addresses, or orders tables. TC-QTE-02 (Payload Integrity): Verify that the quote_payload in the database contains valid JSON reflecting the exact bin, waste type, schedule, and pricing selected. TC-QTE-03 (Multi-Quote): Generating a second quote for an existing prospect email creates a new, distinct Lead record to preserve the history of both quotes. TC-QTE-04 (Conversion Pre-fill): When an admin clicks "Convert to Order" on a lead, the target creation page loads with all customer details and cart items accurately pre-filled from the saved quote. TC-FUNNEL-01 (Inquiry-to-Lead Progressive Promotion): Post a raw dataset query to the public endpoint channel. Promote the status flag through the CRM dashboard. Verify that a parent row allocation occurs within lead_marketing without creating partial objects inside master client tables. TC-FUNNEL-02 (Unified Component Dropdown Cues): Input character search tags in the Admin booking interface. Confirm that customer accounts render standard text layout elements, whereas prospect lead results display a clear, prepend visual alert notification tag. TC-FUNNEL-03 (Sandbox Price Quote Isolation): Select an unapproved pipeline prospect label inside the contract creation layout interface and trigger the secondary "Save as Quote" workflow run. Verify that zero relational updates hit master financial datasets, and check that the entire cart data structure drops cleanly as an immutable serialized array within the sandbox database storage row.