Skip to content

Dealflow & Member Onboarding Microservice

The Dealflow Microservice (dealflow/) manages lead intake questionnaires, commercial offer generation, dynamic presentation pages, and member accession declarations for Polish energy cooperatives.


1. Directory Structure

dealflow/
├── api/
│ ├── create_offer.php # REST API: Generate new published offer
│ ├── form-writer.php # Handles raw inquiry form submissions
│ ├── save_dealflow.php # Core API: Ingest deal & generate embed iframe
│ └── save_response.php # Logs customer interactive responses
├── backend/
│ ├── delete_json.php # Administrative cleanup tool
│ └── delete_log.txt # Record deletion audit log
├── cookie-banner.php # Reusable GDPR / RODO compliance banner
├── data/ # Persistent JSON records (deals, offers, tokens)
├── inquiry-success.php # Lead submission confirmation view
├── inquiry.php # Client lead intake questionnaire
├── offer.php # Dual-mode offer presentation & onboarding form
└── test_generator.php # Developer mock payload generator

2. Dual Operation Modes in offer.php

The primary presentation controller dealflow/offer.php supports two distinct execution paths detected via query parameters:

flowchart TD
    UserReq["User navigates to offer.php"] --> Detect{"Check Query Parameters"}
    
    Detect -->|"?id=offer_123"| OfferMode["Standard Offer Presentation Mode"]
    OfferMode --> LoadOffer["Load dealflow/data/{id}.json"]
    LoadOffer --> RenderOfferUI["Render Energy Sizing, Tariffs & Costs"]
    RenderOfferUI --> ClientAccept["Client Reviews / Approves Deal"]

    Detect -->|"?token=abc123... (>= 32 hex)"| TokenMode["Member Onboarding Declaration Mode"]
    TokenMode --> LoadToken["Load dealflow/data/{token}.json"]
    LoadToken --> CheckTTL{"expires_at < time()?"}
    CheckTTL -->|Expired| ShowExpired["Display 'Link expired (valid 72h)'"]
    CheckTTL -->|Valid| RenderForm["Render Official Accession Form"]
    RenderForm --> SubmitSupabase["POST to Supabase Edge Function
(submit-member-declaration)"]

A. Offer Mode (?id=XXX)

  • Displays customized energy generation calculations, estimated savings, equipment specifications (PV capacity, inverter type, battery storage), and investment financing options.
  • The view can be viewed directly by clients in browser or embedded inside partner websites using the generated iframe.

B. Member Onboarding Declaration Mode (?token=XXX)

  • When a cooperative invites a member to sign the formal accession declaration, a 32-character hexadecimal token is generated.
  • The form renders the statutory Polish cooperative membership fields (PESEL/NIP, address, energy meter point PPE, installed capacity).
  • Upon submission, the form securely posts directly to the Supabase Edge Function:
    const submitUrl = `${supabaseUrl}/functions/v1/submit-member-declaration`;
    fetch(submitUrl, {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${supabaseAnonKey}`
    },
    body: JSON.stringify(formData)
    });

3. Core API Endpoints

1. POST /api/create_offer.php

Generates a published offer from an incoming JSON payload (typically dispatched from the Planovi Flutter App or CRM).

Request Headers:

POST /api/create_offer.php HTTP/1.1
Host: dev-dealflow.planovi.app
Content-Type: application/json
X-Secret-Key: <DEALFLOW_API_SECRET>

Sample Request Body:

{
"company_id": "c7a86890-4107-4e3a-b856-347b7123abcd",
"user_id": "u1b94812-3211-47fa-a389-9182abcdef01",
"customer_name": "Krzysztof Nowak",
"customer_phone": "+48 501 234 567",
"customer_email": "k.nowak@example.pl",
"pv_capacity_kwp": 9.8,
"battery_capacity_kwh": 10.0,
"estimated_annual_savings_pln": 6400.00,
"pricing": {
"total_gross_pln": 48500.00,
"subsidy_pln": 16000.00,
"net_investment_pln": 32500.00
}
}

Sample Response (201 Created):

{
"status": "success",
"offer_id": "offer_66ebc1234_ab12",
"url": "https://dev-dealflow.planovi.app/offer.php?id=offer_66ebc1234_ab12"
}

2. POST /api/save_dealflow.php

Ingests a deal configuration, saves the persistent state, and calculates an embeddable HTML <iframe> snippet for CRM portals:

Sample Response:

{
"status": "success",
"deal_id": "deal_1771006118990",
"public_url": "https://dev-dealflow.planovi.app/inquiry.php?deal=deal_1771006118990",
"embed_code": "<iframe src=\"https://dev-dealflow.planovi.app/inquiry.php?deal=deal_1771006118990\" width=\"100%\" height=\"800px\" frameborder=\"0\"></iframe>"
}

All client-facing Dealflow screens include cookie-banner.php, providing Polish and European RODO/GDPR compliance:

  • Stores user consent in localStorage under planovi_cookie_consent.
  • Provides consent toggles for Functional, Analytical, and Marketing cookies.