isaaccladandCursor 6e66f7c584
Deploy Ladill Queue / deploy (push) Successful in 53s
Scope Queue team members and add mailbox invite picker.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 21:59:51 +00:00
2026-07-07 23:13:59 +00:00

Ladill CRM

The Ladill sales CRM at crm.ladill.com — a full SSO web app for managing contacts, leads, deals, activities and productsand 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 <CRM_API_KEY_*> (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=<sub>&search=
POST   /api/customers            {owner,name,email,phone,company,...}
... (show/update/destroy)

GET    /api/leads?owner=<sub>&status=
POST   /api/leads                {owner,name,status,estimated_value_minor,...}
POST   /api/leads/{id}/convert   {owner}        -> creates/links a customer

GET    /api/products?owner=<sub>&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

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.

S
Description
No description provided
Readme
1.7 MiB
Languages
PHP 67.6%
Blade 26.9%
JavaScript 2.2%
CSS 1.7%
Shell 1.6%