asd
This commit is contained in:
@@ -4,40 +4,40 @@ import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||
import 'package:flux/core/utils/extensions.dart';
|
||||
import 'package:flux/features/customers/data/customer_repository.dart';
|
||||
import 'package:flux/features/customers/models/customer_file_model.dart';
|
||||
import 'package:flux/features/operations/models/service_file_model.dart';
|
||||
import 'package:flux/features/operations/models/operation_file_model.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import '../models/service_model.dart';
|
||||
import '../models/operation_model.dart';
|
||||
|
||||
class ServicesRepository {
|
||||
class OperationsRepository {
|
||||
final _supabase = Supabase.instance.client;
|
||||
final companyId = GetIt.I.get<SessionCubit>().state.company!.id;
|
||||
final CustomerRepository _customerRepository = GetIt.I<CustomerRepository>();
|
||||
|
||||
// --- RECUPERO SINGOLO SERVIZIO CON JOIN COMPLETO ---
|
||||
Future<ServiceModel> fetchServiceById(String id) async {
|
||||
Future<OperationModel> fetchOperationById(String id) async {
|
||||
try {
|
||||
final response = await _supabase
|
||||
.from('operation')
|
||||
.select('''
|
||||
*,
|
||||
customer(nome),
|
||||
energy_service(*),
|
||||
fin_service(*),
|
||||
entertainment_service(*),
|
||||
service_file(*)
|
||||
energy_operation(*),
|
||||
fin_operation(*),
|
||||
entertainment_operation(*),
|
||||
operation_file(*)
|
||||
''')
|
||||
.eq('id', id)
|
||||
.single();
|
||||
|
||||
return ServiceModel.fromMap(response);
|
||||
return OperationModel.fromMap(response);
|
||||
} catch (e) {
|
||||
throw Exception('Errore nel caricamento del servizio: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// --- RECUPERO PAGINATO CON FILTRI E JOIN ---
|
||||
Future<List<ServiceModel>> fetchServices({
|
||||
Future<List<OperationModel>> fetchOperations({
|
||||
required String companyId,
|
||||
required int offset,
|
||||
int limit = 50,
|
||||
@@ -51,10 +51,10 @@ class ServicesRepository {
|
||||
.select('''
|
||||
*,
|
||||
customer(nome),
|
||||
energy_service(*),
|
||||
fin_service(*),
|
||||
entertainment_service(*),
|
||||
service_file(*)
|
||||
energy_operation(*),
|
||||
fin_operation(*),
|
||||
entertainment_operation(*),
|
||||
operation_file(*)
|
||||
''')
|
||||
.eq('company_id', companyId);
|
||||
|
||||
@@ -77,14 +77,14 @@ class ServicesRepository {
|
||||
.range(offset, offset + limit - 1);
|
||||
|
||||
return (response as List)
|
||||
.map((map) => ServiceModel.fromMap(map))
|
||||
.map((map) => OperationModel.fromMap(map))
|
||||
.toList();
|
||||
} catch (e) {
|
||||
throw Exception('Errore nel caricamento servizi: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Stream<List<ServiceModel>> getLastStoreServicesStream({
|
||||
Stream<List<OperationModel>> getLastStoreOperationsStream({
|
||||
required String storeId,
|
||||
required int limit,
|
||||
}) {
|
||||
@@ -96,32 +96,32 @@ class ServicesRepository {
|
||||
.limit(limit)
|
||||
.map(
|
||||
(listOfMaps) =>
|
||||
listOfMaps.map((map) => ServiceModel.fromMap(map)).toList(),
|
||||
listOfMaps.map((map) => OperationModel.fromMap(map)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
// --- SALVATAGGIO COMPLETO (PRIMA PADRE, POI FIGLI) ---
|
||||
Future<ServiceModel> saveFullService(ServiceModel operation) async {
|
||||
Future<OperationModel> saveFullOperation(OperationModel operation) async {
|
||||
try {
|
||||
// 1. Upsert del record principale
|
||||
final serviceData = await _supabase
|
||||
final operationData = await _supabase
|
||||
.from('operation')
|
||||
.upsert(operation.toMap())
|
||||
.select()
|
||||
.single();
|
||||
|
||||
final String newId = serviceData['id'];
|
||||
final String newId = operationData['id'];
|
||||
|
||||
// 2. MODIFICA: Pulizia atomica dei figli
|
||||
// Se stiamo modificando (id != null), resettiamo le tabelle collegate
|
||||
if (operation.id != null) {
|
||||
await Future.wait([
|
||||
_supabase.from('energy_service').delete().eq('service_id', newId),
|
||||
_supabase.from('fin_service').delete().eq('service_id', newId),
|
||||
_supabase.from('energy_operation').delete().eq('operation_id', newId),
|
||||
_supabase.from('fin_operation').delete().eq('operation_id', newId),
|
||||
_supabase
|
||||
.from('entertainment_service')
|
||||
.from('entertainment_operation')
|
||||
.delete()
|
||||
.eq('service_id', newId),
|
||||
.eq('operation_id', newId),
|
||||
// Aggiungi qui eventuali altre tabelle pivot o file
|
||||
]);
|
||||
}
|
||||
@@ -129,37 +129,37 @@ class ServicesRepository {
|
||||
// 3. Inserimento dei moduli in parallelo per velocità
|
||||
final List<Future> insertTasks = [];
|
||||
|
||||
if (operation.energyServices.isNotEmpty) {
|
||||
if (operation.energyOperations.isNotEmpty) {
|
||||
insertTasks.add(
|
||||
_supabase
|
||||
.from('energy_service')
|
||||
.from('energy_operation')
|
||||
.insert(
|
||||
operation.energyServices
|
||||
.map((item) => item.copyWith(serviceId: newId).toMap())
|
||||
operation.energyOperations
|
||||
.map((item) => item.copyWith(operationId: newId).toMap())
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (operation.finServices.isNotEmpty) {
|
||||
if (operation.finOperations.isNotEmpty) {
|
||||
insertTasks.add(
|
||||
_supabase
|
||||
.from('fin_service')
|
||||
.from('fin_operation')
|
||||
.insert(
|
||||
operation.finServices
|
||||
.map((item) => item.copyWith(serviceId: newId).toMap())
|
||||
operation.finOperations
|
||||
.map((item) => item.copyWith(operationId: newId).toMap())
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (operation.entertainmentServices.isNotEmpty) {
|
||||
if (operation.entertainmentOperations.isNotEmpty) {
|
||||
insertTasks.add(
|
||||
_supabase
|
||||
.from('entertainment_service')
|
||||
.from('entertainment_operation')
|
||||
.insert(
|
||||
operation.entertainmentServices
|
||||
.map((item) => item.copyWith(serviceId: newId).toMap())
|
||||
operation.entertainmentOperations
|
||||
.map((item) => item.copyWith(operationId: newId).toMap())
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
@@ -186,7 +186,7 @@ class ServicesRepository {
|
||||
: 'image/${file.extension}';
|
||||
|
||||
final fileToSave = file.copyWith(
|
||||
serviceId: newId,
|
||||
operationId: newId,
|
||||
storagePath: storagePath,
|
||||
);
|
||||
|
||||
@@ -202,7 +202,7 @@ class ServicesRepository {
|
||||
);
|
||||
|
||||
// B. Inserimento riga nel DB relazionale
|
||||
await _supabase.from('service_file').insert(fileToSave.toMap());
|
||||
await _supabase.from('operation_file').insert(fileToSave.toMap());
|
||||
}
|
||||
|
||||
uploadTasks.add(uploadAndLink());
|
||||
@@ -214,20 +214,20 @@ class ServicesRepository {
|
||||
|
||||
// 5. GRAN FINALE: RECUPERO DEL MODELLO COMPLETO E AGGIORNATO
|
||||
// Interroghiamo Supabase per farci restituire la pratica con TUTTI gli ID generati
|
||||
// (inclusi quelli della tabella service_file appena inseriti)
|
||||
final updatedServiceData = await _supabase
|
||||
// (inclusi quelli della tabella operation_file appena inseriti)
|
||||
final updatedOperationData = await _supabase
|
||||
.from('operation')
|
||||
.select('''
|
||||
*,
|
||||
energy_service(*),
|
||||
fin_service(*),
|
||||
entertainment_service(*),
|
||||
service_file(*)
|
||||
energy_operation(*),
|
||||
fin_operation(*),
|
||||
entertainment_operation(*),
|
||||
operation_file(*)
|
||||
''')
|
||||
.eq('id', newId)
|
||||
.single();
|
||||
|
||||
return ServiceModel.fromMap(updatedServiceData);
|
||||
return OperationModel.fromMap(updatedOperationData);
|
||||
} catch (e) {
|
||||
// Qui potresti aggiungere una logica di "rollback manuale" se necessario
|
||||
throw Exception('Errore durante il salvataggio corazzato: $e');
|
||||
@@ -235,7 +235,7 @@ class ServicesRepository {
|
||||
}
|
||||
|
||||
// --- ELIMINAZIONE ---
|
||||
Future<void> deleteService(String id) async {
|
||||
Future<void> deleteOperation(String id) async {
|
||||
try {
|
||||
await _supabase.from('operation').delete().eq('id', id);
|
||||
} catch (e) {
|
||||
@@ -249,7 +249,7 @@ class ServicesRepository {
|
||||
// Cerchiamo i tipi più frequenti associati ai servizi di questa company
|
||||
// Nota: dobbiamo passare attraverso la tabella 'operation' per filtrare per company_id
|
||||
final response = await _supabase
|
||||
.from('entertainment_service')
|
||||
.from('entertainment_operation')
|
||||
.select('type, operation!inner(store!inner(company_id))')
|
||||
.eq('operation.store.company_id', companyId)
|
||||
.limit(100); // Prendiamo un campione
|
||||
@@ -276,20 +276,20 @@ class ServicesRepository {
|
||||
}
|
||||
|
||||
/// Ascolta in tempo reale i file caricati per una pratica
|
||||
Stream<List<ServiceFileModel>> getServiceFilesStream(String serviceId) {
|
||||
Stream<List<OperationFileModel>> getOperationFilesStream(String operationId) {
|
||||
return _supabase
|
||||
.from('service_file')
|
||||
.from('operation_file')
|
||||
.stream(primaryKey: ['id'])
|
||||
.eq('service_id', serviceId)
|
||||
.eq('operation_id', operationId)
|
||||
.order('created_at', ascending: false)
|
||||
.map(
|
||||
(listOfMaps) =>
|
||||
listOfMaps.map((map) => ServiceFileModel.fromMap(map)).toList(),
|
||||
listOfMaps.map((map) => OperationFileModel.fromMap(map)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<ServiceFileModel> uploadAndRegisterServiceFile({
|
||||
required String serviceId,
|
||||
Future<OperationFileModel> uploadAndRegisterOperationFile({
|
||||
required String operationId,
|
||||
required PlatformFile pickedFile,
|
||||
}) async {
|
||||
final cleanFileName = pickedFile.name.replaceAll(
|
||||
@@ -297,10 +297,10 @@ class ServicesRepository {
|
||||
'_',
|
||||
);
|
||||
final storagePath =
|
||||
'$companyId/operations/$serviceId/${DateTime.now().millisecondsSinceEpoch}_$cleanFileName';
|
||||
'$companyId/operations/$operationId/${DateTime.now().millisecondsSinceEpoch}_$cleanFileName';
|
||||
final int fileSize = pickedFile.size;
|
||||
final fileToSave = ServiceFileModel(
|
||||
serviceId: serviceId,
|
||||
final fileToSave = OperationFileModel(
|
||||
operationId: operationId,
|
||||
name: cleanFileName.fileNameWithoutExtension(),
|
||||
extension: cleanFileName.fileExtension(),
|
||||
storagePath: storagePath,
|
||||
@@ -327,19 +327,19 @@ class ServicesRepository {
|
||||
}
|
||||
|
||||
final response = await _supabase
|
||||
.from('service_file')
|
||||
.from('operation_file')
|
||||
.insert(fileToSave.toMap())
|
||||
.select()
|
||||
.single();
|
||||
|
||||
return ServiceFileModel.fromMap(response);
|
||||
return OperationFileModel.fromMap(response);
|
||||
} catch (e) {
|
||||
throw 'Errore durante l\'upload: $e';
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> copyFileToCustomer({
|
||||
required ServiceFileModel file,
|
||||
required OperationFileModel file,
|
||||
required String customerId,
|
||||
}) async {
|
||||
CustomerFileModel fileToCopy = CustomerFileModel(
|
||||
@@ -352,14 +352,17 @@ class ServicesRepository {
|
||||
await _customerRepository.saveFileReference(fileToCopy);
|
||||
}
|
||||
|
||||
Future<void> deleteServiceFiles(List<ServiceFileModel> files) async {
|
||||
Future<void> deleteOperationFiles(List<OperationFileModel> files) async {
|
||||
if (files.isEmpty) return;
|
||||
// 1. Prepariamo le liste di ID e di Percorsi
|
||||
final List<String> idsToDelete = files.map((f) => f.id!).toList();
|
||||
final List<String> storagePaths = files.map((f) => f.storagePath).toList();
|
||||
|
||||
try {
|
||||
await _supabase.from('service_file').delete().inFilter('id', idsToDelete);
|
||||
await _supabase
|
||||
.from('operation_file')
|
||||
.delete()
|
||||
.inFilter('id', idsToDelete);
|
||||
|
||||
await _supabase.storage.from('documents').remove(storagePaths);
|
||||
|
||||
Reference in New Issue
Block a user