# Ladill CRM The Ladill **sales CRM** at `crm.ladill.com` — a full SSO web app for managing **contacts, leads, deals, activities and products** — *and* the shared Customers/Leads/Products service consumed over HTTP by Ladill Invoice, Merchant, Mini and future apps, so contact + catalog data is owned in one place and reused everywhere. Every record is scoped to one platform account via `owner_ref` (the user's `public_id` / OIDC `sub`). ## App (web UI — Sign in with Ladill) Authenticates against `auth.ladill.com` (OIDC Authorization Code + PKCE; see `Auth\SsoLoginController`). Local session is subordinate to the platform session (`platform.session` middleware) and joins Single Logout via `/sso/logout-frontchannel`. - **Dashboard** — KPIs (contacts, open leads, open deals, pipeline value), tasks due, recent activity. - **Contacts** — the contact book, with a per-contact **timeline** (notes, tasks, logged calls/meetings, sent email + SMS) and cross-product events (invoices, payments, orders) pushed from sibling apps. - **Leads** — list + **kanban board** (`new → contacted → qualified`), convert to a contact. - **Deals** — drag-free **pipeline** kanban across configurable stages (`config/crm.pipeline_stages`), won/lost tracking. - **Activities** — notes, tasks (with due dates / completion), calls, meetings. - **Products & services** — reusable catalog items. - **Comms** — email contacts (via the app mailer / Ladill Bird SMTP) and SMS (Termii); each send is logged on the timeline. - **Reports** — pipeline by stage, win rate, won value over time, leads by status, activity mix. ## Service API (first-party, service-key auth) Authenticate with a per-consumer service key: `Authorization: Bearer ` (see `config/crm.php`, `App\Http\Middleware\AuthenticateService`, alias `auth.service:crm`). Every request must pass `owner` (query or body) to scope data to the end user. ``` GET /api/customers?owner=&search= POST /api/customers {owner,name,email,phone,company,...} ... (show/update/destroy) GET /api/leads?owner=&status= POST /api/leads {owner,name,status,estimated_value_minor,...} POST /api/leads/{id}/convert {owner} -> creates/links a customer GET /api/products?owner=&type=&active= POST /api/products {owner,name,type,unit_price_minor,currency,tax_rate} POST /api/timeline {owner,event,title,external_id,amount_minor, currency,url,customer_id|customer_email,...} ``` `POST /api/timeline` is how sibling products push "what happened" events onto a contact's timeline (`invoice.sent`, `payment.received`, `order.paid`). The `source` is derived from the service key (never client-supplied) and the write is idempotent per `(owner, source, external_id, event)`. Reference consumer: `ladill-invoice` `App\Services\Crm\CrmClient::pushTimeline()`. No key → 401; missing `owner` → 422; cross-owner access → 404. ## Local dev ```bash composer install cp .env.example .env && php artisan key:generate # sqlite for local: set DB_CONNECTION=sqlite and `touch database/database.sqlite` php artisan migrate npm install && npm run build # or `npm run dev` php artisan serve php artisan test ``` See `DEPLOY.md` for production cutover.