feat: add clients nomenclator, order edit/delete/devalidate, invoice types, dashboard redesign

- New clients table with PF/PJ support, fiscal data (CUI, IBAN, eFactura fields)
- Full CRUD API for clients with search, sync integration
- Order lifecycle: edit header (DRAFT), devalidate (VALIDAT→DRAFT), delete order/invoice
- Invoice types: FACTURA (B2B) vs BON_FISCAL (B2C) with different nr formats
- OrderCreateView redesigned as multi-step flow (client→vehicle→details)
- Autocomplete from catalog_norme/catalog_preturi in OrderLineForm
- Dashboard now combines stats + full orders table with filter tabs and search
- ClientPicker and VehiclePicker with inline creation capability
- Frontend schema aligned with backend (missing columns causing sync errors)
- Mobile responsive fixes for OrderDetailView buttons

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-14 00:36:40 +02:00
parent 3e449d0b0b
commit 9db4e746e3
34 changed files with 2221 additions and 211 deletions

View File

@@ -42,14 +42,26 @@ export const useVehiclesStore = defineStore('vehicles', () => {
return rows[0] || null
}
async function getByClient(clientId) {
return execSQL(
`SELECT v.*, m.denumire as marca_denumire, mo.denumire as model_denumire
FROM vehicles v
LEFT JOIN catalog_marci m ON v.marca_id = m.id
LEFT JOIN catalog_modele mo ON v.model_id = mo.id
WHERE v.client_id = ? AND v.tenant_id = ?
ORDER BY v.nr_inmatriculare`,
[clientId, auth.tenantId]
)
}
async function create(data) {
const id = crypto.randomUUID()
const now = new Date().toISOString()
await execSQL(
`INSERT INTO vehicles (id, tenant_id, client_nume, client_telefon, client_email, client_cod_fiscal, client_adresa, nr_inmatriculare, marca_id, model_id, an_fabricatie, serie_sasiu, tip_motor_id, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
[id, auth.tenantId, data.client_nume || '', data.client_telefon || '',
`INSERT INTO vehicles (id, tenant_id, client_id, client_nume, client_telefon, client_email, client_cod_fiscal, client_adresa, nr_inmatriculare, marca_id, model_id, an_fabricatie, serie_sasiu, tip_motor_id, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
[id, auth.tenantId, data.client_id || null, data.client_nume || '', data.client_telefon || '',
data.client_email || '', data.client_cod_fiscal || '', data.client_adresa || '',
data.nr_inmatriculare || '', data.marca_id || null, data.model_id || null,
data.an_fabricatie || null, data.serie_sasiu || '', data.tip_motor_id || null, now, now]
@@ -72,9 +84,24 @@ export const useVehiclesStore = defineStore('vehicles', () => {
await syncEngine.addToQueue('vehicles', id, 'UPDATE', data)
}
async function search(query) {
if (!query || query.length < 2) return []
async function search(query, clientId = null) {
if (!query || query.length < 2) {
// If no query but clientId, return client vehicles
if (clientId) return getByClient(clientId)
return []
}
const like = `%${query}%`
if (clientId) {
return execSQL(
`SELECT v.*, m.denumire as marca_denumire, mo.denumire as model_denumire
FROM vehicles v
LEFT JOIN catalog_marci m ON v.marca_id = m.id
LEFT JOIN catalog_modele mo ON v.model_id = mo.id
WHERE v.tenant_id = ? AND v.client_id = ? AND (v.nr_inmatriculare LIKE ? OR v.client_nume LIKE ?)
ORDER BY v.nr_inmatriculare LIMIT 10`,
[auth.tenantId, clientId, like, like]
)
}
return execSQL(
`SELECT v.*, m.denumire as marca_denumire, mo.denumire as model_denumire
FROM vehicles v
@@ -100,5 +127,5 @@ export const useVehiclesStore = defineStore('vehicles', () => {
)
}
return { getAll, getById, create, update, search, getMarci, getModele }
return { getAll, getById, getByClient, create, update, search, getMarci, getModele }
})