06696727dd670f267d8e8d766d9112f8c26c3ac9
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
06696727dd |
Faza 6: Activity log + Kanban + Payroll + cleanup
══════ Activity log (Spatie) ══════ - spatie/laravel-activitylog v5 instalat - Migration cu company_id pentru tenant scoping - Trait Auditable (App\Models\Concerns\Auditable): - LogOptions cu logFillable + logOnlyDirty + dontSubmitEmptyLogs - tapActivity auto-fill company_id + causer - Descrieri RO (creat/modificat/șters/restaurat) - Aplicat pe: Client, Vehicle, Lead, Deal, WorkOrder, Payment, Expense - ActivityResource (group Admin → Jurnal activitate) - Listă read-only, scope pe tenant, filtre by description/today ══════ Kanban Work Orders ══════ - Custom Filament page la /app/kanban (group Service) - 6 coloane (new → diagnosis → agreement → in_work → awaiting_parts → ready) - Drag-drop nativ HTML5 cu wire:click moveCard() - Cards arată: număr fișă, client, auto, plate, master, total - Link 'Deschide' direct la editare WO ══════ Payroll (Salarii) ══════ Schema: - employee_profiles: user_id, position, base_salary, works_pct, parts_pct - payroll_runs: period (YYYY-MM), base, works_revenue/pct, parts_margin/pct, bonus, fines, advance, total auto-calculat - payroll_adjustments: bonus/fine/advance per period PayrollCalculator service: - compute($userId, $period) — calculează auto: - Manopere finalizate de mecanic în luna respectivă (sum total) - Marja pieselor montate de el (sell-buy * qty) - Bonus + fines + advance from adjustments - Total = base + works% + parts% + bonus - fines - advance Resources Filament (group Finanțe): - EmployeeProfileResource: profil cu % comisioane - PayrollRunResource: salarii cu action 'Calculează luna curentă' (toți userii) + per-row 'Recalculează'; Sum summary pe total - PayrollAdjustmentResource: gestionare bonus/penalizări/avansuri ══════ Cleanup ══════ - Șterse toate /__debug, /__seed, /__try-login, /__force-login, /__whoami, /__coolify-check (security) - Routes/web.php conține doar / redirect, /manifest.json, /sw.js Total Filament tenant routes: 92. |
||
|
|
8d82af2f54 |
Faza 3.5+3.6+4+5: Marketing, Reports, Provisioning, PWA
═══ Faza 3.5: Marketing ═══
Schema: msg_templates, marketing_channels, calls
Modele cu logică:
- MessageTemplate::render($context) — substituie {key} tokens
- MarketingChannel: roi/conversion_rate/cost_per_lead computed attrs
- Call: duration_formatted helper
Resources Filament (group Marketing):
- MessageTemplateResource: 5 canale (telegram/whatsapp/viber/sms/email)
- MarketingChannelResource: budget vs revenue cu ROI live calculat
- CallResource: in/out/missed cu filtre azi/missed
═══ Faza 3.6: Analytics ═══
Custom Filament Page Reports cu 6 rapoarte tab-uite:
- Finanțe: încasări/cheltuieli/profit/datorii + breakdown pe metodă/categorie
- Încărcare: fișe deschise/închise + breakdown pe status
- Mecanici: ore lucrate, manopere, venit per mecanic
- Manopere top: cele mai frecvente cu nr/ore/venit
- Piese: top vândute + low-stock
- Clienți: noi în perioadă + lead-uri pe sursă
Selector perioadă: azi / săptămâna / luna / luna trecută / anul
═══ Faza 4: Central provisioning ═══
- CoolifyClient service (Coolify v4 REST API wrapper)
- CompanyProvisioner: creează Company + admin user + roles + adaugă
subdomeniul în Coolify FQDN + trigger redeploy automat
- CreateCompany page override → folosește provisioner, returnează
notificare cu credentialele admin
- Form CompanyResource extins cu admin_name/email/password (vizibil doar create)
- Action 'Suspendă' / 'Activează' pe table cu confirmation
Env vars necesare în Coolify pentru provisioning auto:
COOLIFY_API_URL=http://65.21.20.141:8000
COOLIFY_API_TOKEN=<token>
COOLIFY_APP_UUID=g13hlrpd5g44zxl5af3ktio2
═══ Faza 5: PWA + branding ═══
- Route /manifest.json dinamic per tenant (nume, theme color, icons)
- Route /sw.js — service worker minimal (cache shell + static)
- TenantPanelProvider renderHook HEAD_END — link manifest + theme-color
+ apple-mobile-web-app meta
- TenantPanelProvider renderHook BODY_END — registrare service worker
Seed extins:
- 5 template-uri mesaje (programare/auto-gata/reminder/ITP/felicitare)
- 5 canale marketing (Google Ads/FB/IG/Telegram/Recomandări)
- 2 apeluri demo
Total Filament tenant routes: 81.
|
||
|
|
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. |
||
|
|
7264dccffa |
Faza 3.3: Depozit — Furnizori + Catalog piese + Achiziții
Schema: - suppliers: name, contact, phone/email/website, pay_terms, delivery_days, rating (1-5), discount_pct, categories (JSON), is_active, notes - parts: name, article (UNIQUE per tenant), brand, category, qty/unit/min_qty, buy_price/sell_price, location (rack/bin), barcode, preferred_supplier_id, is_active. Index pe (company_id, category) și (company_id, is_active). - purchases: număr unique per tenant + an, supplier_id, status workflow (draft/ordered/received/cancelled), order/expected/received/paid_at, total - purchase_items: name, article, qty, unit, buy_price, total auto, received bool; link opțional la part_id - wo_parts + part_id: linkare opțională la catalog (alter migration) Modele cu logică: - Part::adjustStock($delta) — modifică qty cu validare ≥ 0 - Part::isLow() / isOut() helpers - Purchase::markReceived() — atomic: marchează items ca received + creste qty pe pieces din catalog (DB::transaction) - WorkOrderPart::updating event — la trecerea status='installed' decrementează stoc auto. La revenire (ex: storno) incrementează la loc. - PurchaseItem::saving — total = qty * buy_price; recalc parent total Filament resources (group Depozit): - SupplierResource: form 3 secțiuni, rating ★★★★★, TagsInput pentru categorii - PartResource: form 4 secțiuni, badge nav cu nr. piese sub stoc minim, filtre low_stock + out_of_stock, coloană qty colorată după stoc - PurchaseResource: form antet + RelationManager Items. Action 'Recepționează' care apelează markReceived() — un click = stoc actualizat WorkOrder PartsRelationManager updated: - Selector din catalog (Part::active) cu stoc afișat - Auto-fill name/article/brand/unit/buy_price/sell_price din piesa selectată - Helper text: la status='installed' se scade din stoc Widget low-stock: - TableWidget pe dashboard tenant, listează piesele cu qty <= min_qty - Span full, sortat după qty (cele mai critice sus) Seed: - 2 furnizori (AutoParts Moldova SRL ★5, Inter Cars Moldova ★4) - 5 piese demo: Ulei Shell, Filtru Mann, Plăcuțe Brembo, Antigel (qty=0!), Bujii NGK - 1 achiziție recepționată (P-26-0001) cu 2 articole linked la catalog Total Filament tenant routes: 63 (de la 31). |
||
|
|
51a0bab39e |
Faza 3.2: Service modules — Norme-ore, Tehnicieni, Fișe lucru
Schema:
- users + specialization, color, hourly_rate (pentru maistri)
- labors: catalog manopere standard cu category/ore/preț (RO+RU)
- work_orders: nr unique per tenant, status workflow (9 stări),
pay_status (3 stări), client/vehicle/master/deal/appointment refs,
complaint/diagnosis/recommendations, total auto-calculat
- wo_works: manopere per fișă, recalc auto la save/delete
- wo_parts: piese per fișă (free-text deocamdată), discount/total auto
Filament resources (group Service):
- LaborResource: CRUD + grupare pe categorie + filter active
- WorkOrderResource: form complex în 4 secțiuni (antet, diagnostic, plată)
+ 2 RelationManagers (Works, Parts)
- MasterResource: vedere User filtrată role=mechanic, edit specializare/
culoare calendar/tarif oră
Conversie auto: la adaugare manoperă din catalog Labor,
form populează numele + ore + preț/oră derivat (price/hours).
Number generator pentru WO: format WO-{YY}-{NNNN} per tenant per an,
calculat în CreateWorkOrder via WorkOrder::generateNumber().
Seed extins:
- 3 mecanici (Vasile/Andrei/Nicolae) cu culori + specializări
- 10 manopere standard din prototipul AutoCRM.html
- 1 fișă demo (BMW X5 plăcuțe Brembo) cu 1 manoperă + 1 piesă, total auto
|
||
|
|
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 |
||
|
|
4b1635d045 |
Faza 2: multi-tenancy + Filament dual panels + seed PSauto
Schema centrală: - companies (slug unique, status, plan_id, settings JSON, trial/active dates) - super_admins (operator platform) - plans (free/basic/pro) Schema tenant (toate cu company_id NOT NULL): - users (UNIQUE company_id+email) - clients - vehicles Tenancy core: - App\Tenancy\TenantManager singleton - App\Models\Concerns\BelongsToTenant trait + TenantScope - ResolveTenant middleware (slug → Company, 404 pentru rezervate/missing) - CheckTenantStatus middleware (suspended/expired/archived) - Fail-safe: TenantScope returns 0 rows când tenant nu e rezolvat Auth guards: - 'central' guard cu super_admins provider (panou platform) - 'web' guard cu users provider (per-tenant) Filament panels: - CentralPanelProvider la service.mir.md/admin - TenantPanelProvider la <slug>.service.mir.md/app - CompanyResource (central): CRUD companii cu status badge + filtre - ClientResource (tenant): CRUD clienți cu status, sursă, sold - VehicleResource (tenant): CRUD mașini cu marcă/model/VIN Seed: - 3 plans (free/basic/pro) - super-admin: vasyka.moraru@gmail.com / admin123 - demo company 'psauto' cu admin user admin@psauto.md / admin123 - 3 clienți + 3 mașini preluate din AutoCRM.html Bootstrap: - TrustProxies (Cloudflare→Traefik HTTPS detection) - forceScheme/forceRootUrl când APP_URL e HTTPS - Helper global tenant() în app/helpers.php (autoload via composer) - RUN_SEED env var în entrypoint pentru db:seed condiționat |