Commit Graph

6 Commits

Author SHA1 Message Date
Vasyka 976c0f03e3 AI Assistant — multi-provider chat (Claude / GPT / Gemini)
Schema:
- ai_chats: company_id, user_id, title, provider; index pe activitate
- ai_messages: role (system/user/assistant), content, meta JSON (tokens, latency, model)

Service AiAssistantService (multi-provider):
- ask($chat, $message): persistă mesajul user, build system prompt cu context
  tenant (statistici clienți/mașini/cereri/datorii), apelează API-ul providerului,
  persistă răspunsul cu meta (tokens, latency)
- callClaude: api.anthropic.com/v1/messages cu claude-sonnet-4-5
- callOpenAI: api.openai.com/v1/chat/completions cu gpt-4o-mini
- callGemini: generativelanguage.googleapis.com cu gemini-1.5-flash
- Try/catch pe toate; eroare devine mesaj asistent fără să crape

System prompt include:
- Numele și orașul companiei
- Statistici curente (clienți, mașini, cereri noi, fișe active, datorii)
- Limita stricta: NU inventează date

Custom Filament Page /app/ai-assistant (group Analiză):
- Sidebar stâng: listă conversații (last 20), buton 'Nouă' + delete cu confirm
- Main: bubble chat (user dreapta albastru, asistent stânga gri)
- Meta jos pe răspuns: provider · latency · tokens
- Empty state friendly cu instrucțiuni configurare
- Loading indicator (3 dots animate) când AI răspunde
- Auto-scroll la mesaj nou
- Enter trimite, Shift+Enter newline
- Auto-titlu chat din primul mesaj user (60 chars)

Settings page extins cu secțiune 'Asistent AI':
- Provider implicit (claude/gpt/gemini)
- 3 chei API (password fields, revealable)
- Key-urile salvate în companies.settings.ai (per tenant, izolat)
2026-05-07 14:50:56 +00:00
Vasyka 09fd0bada2 Faza 2 (din continuare): Email notifications
4 Mailables auto-trigger pe model events:
- WorkOrderReadyMail: la WO.status → 'ready', către client.email
  • Atașat PDF fișa lucru (via WorkOrderPdfService)
  • Total/achitat/rest, recomandări (warning box)
- PaymentReceivedMail: la Payment::created, confirmare cu sumă/metodă/ref
- AppointmentConfirmedMail: la Appointment::created status='scheduled'
- ServiceReminderMail: dispatch manual (vehicle, type=itp/oil/general, note)

Layout email branded (resources/views/emails/layout.blade.php):
- Header cu logo tenant + theme_color border-bottom
- Footer cu telefon/email/disclaimer
- Stiluri inline (compatibil tot mail client)

Settings page extins cu 4 toggle:
- 'Mașina e gata de ridicat'
- 'Confirmare plată primită'
- 'Programare confirmată'
- 'Reminder ITP / revizie'
Salvate în companies.settings.notify (JSON), default true.

NotificationDispatcher service centralizat:
- Verifică isEnabled() pe settings.notify[$key]
- Skip dacă client n-are email
- Try/catch + Log::warning pe eșec (nu crapă request-ul)

Mailables folosesc UsesTenantBranding trait pentru context unitar.
Test prin Mailpit: https://mailpit.service.mir.md (capturează toate).
2026-05-07 13:20:19 +00:00
Vasyka f1d196f018 Faza 7: White-label per tenant — logo + theme color dinamic
- spatie/laravel-medialibrary instalat (migration media table)
- filament/spatie-laravel-media-library-plugin
- Company implements HasMedia + InteractsWithMedia
  - collections: 'logo' + 'favicon' (singleFile)
  - getLogoUrl() / getFaviconUrl() helpers
- Settings page extins: secțiune Logo & favicon cu FileUpload
  - On save: clear collection + addMedia from temp upload + cleanup tmp file
- TenantPanelProvider render hooks:
  - HEAD_END: theme-color meta + favicon + CSS vars override
    (--primary-50 → --primary-950 generate din hex theme_color)
  - SIDEBAR_LOGO_BEFORE: afișare logo upload-uit, max-height 56px

Cum funcționează:
- Tenant uploadează logo în Settings
- La fiecare request, render hook injectează <style> cu CSS vars custom
- Filament respectă --primary-* → toate butoanele/badge-urile primesc culoarea brand
- Logo apare deasupra meniului (sidebar)
2026-05-07 12:51:19 +00:00
Vasyka f0f9fdd555 Faza 3.4: Finanțe — Plăți + Cheltuieli + Cashflow
Schema:
- payments: client_id, work_order_id, user_id (operator), paid_at, amount,
  method (cash/card/transfer/mobile), reference, notes
- expenses: supplier_id, purchase_id, paid_at, category (salary/purchase/rent/
  utilities/advance/tax/fuel/tools/marketing/other), name, amount, method, ref

Logică auto:
- Payment::saved/deleted recalculează automat work_order.pay_status
  (unpaid → partial → paid) based on suma totală vs work_order.total
- WO model are noi metode: payments(), paidAmount(), balanceDue()

Filament resources (group Finanțe):
- PaymentResource: form cu legare opțională la WO + client; tabel cu
  Sum summary, filtre azi/luna_curentă/method
- ExpenseResource: 10 categorii preset, badge categ, total summary,
  filtru luna curentă
- PaymentsRelationManager pe WO: "Plăți" tab cu auto-fill client_id +
  user_id la creare

Widget FinanceOverview:
- Încasări (luna), Cheltuieli (luna), Profit (luna), Datorii clienți
- color coded: profit verde sau roșu, datorii galben/verde

Settings page fix (Filament v5):
- mount() folosește acum $this->form->fill([...]) în loc de $this->data direct
- Filament v5 cere fill explicit pentru a inițializa state-ul schemei

Seed:
- 1 plată parțială pe fișa BMW (200 din 750)
- 6 cheltuieli demo: 3 salarii, chirie, electricitate, achiziție piese

Total Filament tenant routes: 69.
2026-05-06 22:55:50 +00:00
Vasyka 721c57ff97 Filament v5: Forms\Components\Section → Schemas\Components\Section, Forms\Get → Schemas\Components\Utilities\Get
Layout components (Section, Grid, Tabs, etc.) au fost mutate din
Filament\Forms\Components în Filament\Schemas\Components.
Forms\Components păstrează doar field-urile (TextInput, Select, etc.).

Forms\Get s-a mutat în Schemas\Components\Utilities\Get.
2026-05-06 18:07:10 +00:00
Vasyka c9cb3560ef Faza 3.1: CRM core — Leads, Deals, Appointments, Settings, Widgets, Users
Spatie Permission cu teams (team_foreign_key=company_id, teams=true):
- migrations create_permission_tables (model_has_roles cu company_id scope)
- HasRoles trait pe User
- ResolveTenant middleware setează permissions team_id la tenant.id
- Seed: 7 roluri default per tenant (admin/manager/receptionist/mechanic/parts_manager/accountant/marketer)

Module noi:
- Leads (cereri): name, phone, car/model, source, UTM, status, budget, assigned_to,
  acțiune "Convertește" → creează automat Client + Deal
- Deals (pipeline): client/vehicle, stage (8 stage-uri), price, source, lost_reason
- Posts + Appointments: post_id (boxă), master_id, date+time_start+time_end, status, color
- UserResource (tenant): CRUD users cu role/status/locale; canViewAny doar pentru admin

Custom Filament page "Setări" (tenant):
- Brand & contact (display_name, city, phone, email)
- Localizare (limba RO/RU/EN, currency, theme color picker)
- Servicii & tarif (labor_rate)
- Liste configurabile (services, cars) — păstrate în companies.settings JSON

Widgets dashboard:
- Tenant: StatsOverview (Clienți, Mașini, Cereri noi, Deal-uri active, Programări azi)
- Central: PlatformStats (Companii total/active/trial, Expiră în 7 zile)

Seed extins demo PSauto:
- 3 posturi (Pod 1/2/3 cu culori)
- 2 lead-uri demo (Alex Grosu Telegram, Irina Cojocaru WhatsApp)
- 3 deal-uri demo (BMW done, Audi in_work, Porsche agree)
- 2 programări (azi + mâine)

Filament v5 fixes:
- $navigationGroup type → string|UnitEnum|null (parent stricter signature)
- Toate resources noi au tipurile corecte
2026-05-06 17:36:32 +00:00