reworked operation (#12)
Reviewed-on: #12 Co-authored-by: Mark M2 Macbook <marco@catelli.it> Co-committed-by: Mark M2 Macbook <marco@catelli.it>
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||
import 'package:flux/core/utils/string_extensions.dart';
|
||||
import 'package:flux/features/customers/models/customer_file_model.dart';
|
||||
import 'package:flux/core/utils/extensions.dart';
|
||||
import 'package:flux/features/attachments/models/attachment_model.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import '../models/customer_model.dart';
|
||||
@@ -21,7 +20,7 @@ class CustomerRepository {
|
||||
.single();
|
||||
return CustomerModel.fromMap(response);
|
||||
} catch (e) {
|
||||
throw 'Errore durante il salvataggio del cliente: $e';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +34,7 @@ class CustomerRepository {
|
||||
.single();
|
||||
return CustomerModel.fromMap(response);
|
||||
} catch (e) {
|
||||
throw 'Errore durante la modifica del cliente: $e';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,15 +45,15 @@ class CustomerRepository {
|
||||
.from('customer')
|
||||
.select('''
|
||||
*,
|
||||
customer_file(*)
|
||||
attachment(*)
|
||||
''')
|
||||
.eq('company_id', companyId)
|
||||
.eq('is_active', true)
|
||||
.order('nome');
|
||||
.order('name');
|
||||
|
||||
return (response as List).map((c) => CustomerModel.fromMap(c)).toList();
|
||||
} catch (e) {
|
||||
throw 'Errore nel recupero clienti';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +67,7 @@ class CustomerRepository {
|
||||
.from('customer')
|
||||
.select()
|
||||
.eq('company_id', companyId)
|
||||
.or('nome.ilike.%$query%,telefono.ilike.%$query%')
|
||||
.or('name.ilike.%$query%,phone_number.ilike.%$query%')
|
||||
.limit(10);
|
||||
|
||||
return (response as List).map((c) => CustomerModel.fromMap(c)).toList();
|
||||
@@ -78,36 +77,34 @@ class CustomerRepository {
|
||||
}
|
||||
|
||||
/// Ascolta in tempo reale i file caricati per un cliente
|
||||
Stream<List<CustomerFileModel>> getCustomerFilesStream(String customerId) {
|
||||
Stream<List<AttachmentModel>> getCustomerFilesStream(String customerId) {
|
||||
return _supabase
|
||||
.from('customer_file')
|
||||
.from('attachment')
|
||||
.stream(primaryKey: ['id'])
|
||||
.eq('customer_id', customerId)
|
||||
.order('created_at', ascending: false)
|
||||
.map(
|
||||
(listOfMaps) =>
|
||||
listOfMaps.map((map) => CustomerFileModel.fromMap(map)).toList(),
|
||||
listOfMaps.map((map) => AttachmentModel.fromMap(map)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Recupera i file di un cliente specifico
|
||||
Future<List<CustomerFileModel>> getCustomerFiles(String customerId) async {
|
||||
Future<List<AttachmentModel>> getCustomerFiles(String customerId) async {
|
||||
try {
|
||||
final response = await _supabase
|
||||
.from('customer_file')
|
||||
.from('attachment')
|
||||
.select()
|
||||
.eq('customer_id', customerId);
|
||||
|
||||
return (response as List)
|
||||
.map((f) => CustomerFileModel.fromMap(f))
|
||||
.toList();
|
||||
return (response as List).map((f) => AttachmentModel.fromMap(f)).toList();
|
||||
} catch (e) {
|
||||
throw 'Errore recupero file: $e';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
|
||||
/// Carica un file e salva il riferimento nel database
|
||||
Future<CustomerFileModel> uploadAndRegisterFile({
|
||||
Future<AttachmentModel> uploadAndRegisterFile({
|
||||
required String customerId,
|
||||
required PlatformFile pickedFile,
|
||||
}) async {
|
||||
@@ -118,7 +115,8 @@ class CustomerRepository {
|
||||
final storagePath =
|
||||
'$companyId/customers/${DateTime.now().millisecondsSinceEpoch}_$cleanFileName';
|
||||
final int fileSize = pickedFile.size;
|
||||
final fileToSave = CustomerFileModel(
|
||||
final fileToSave = AttachmentModel(
|
||||
companyId: companyId,
|
||||
customerId: customerId,
|
||||
name: cleanFileName.fileNameWithoutExtension(),
|
||||
extension: cleanFileName.fileExtension(),
|
||||
@@ -131,7 +129,7 @@ class CustomerRepository {
|
||||
try {
|
||||
// Usiamo bytes invece del path per massima compatibilità
|
||||
if (pickedFile.bytes == null && pickedFile.path == null) {
|
||||
throw 'Impossibile leggere il contenuto del file';
|
||||
throw 'File read error';
|
||||
}
|
||||
|
||||
// Se siamo su desktop/mobile abbiamo il path, su web abbiamo i bytes
|
||||
@@ -146,54 +144,51 @@ class CustomerRepository {
|
||||
}
|
||||
|
||||
final response = await _supabase
|
||||
.from('customer_file')
|
||||
.from('attachment')
|
||||
.insert(fileToSave.toMap())
|
||||
.select()
|
||||
.single();
|
||||
|
||||
return CustomerFileModel.fromMap(response);
|
||||
return AttachmentModel.fromMap(response);
|
||||
} catch (e) {
|
||||
throw 'Errore durante l\'upload: $e';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> saveFileReference(CustomerFileModel file) async {
|
||||
await _supabase.from('customer_file').upsert(file.toMap());
|
||||
Future<void> saveFileReference(AttachmentModel file) async {
|
||||
await _supabase.from('attachment').upsert(file.toMap());
|
||||
}
|
||||
|
||||
/// Aggiorna la lista degli URL nel database
|
||||
Future<void> updateCustomerDocuments(int id, List<String> urls) async {
|
||||
await _supabase
|
||||
.from('customer')
|
||||
.update({'document_urls': urls})
|
||||
.eq('id', id);
|
||||
}
|
||||
|
||||
Future<void> deleteDocuments(List<CustomerFileModel> files) async {
|
||||
Future<void> deleteDocuments(List<AttachmentModel> 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();
|
||||
|
||||
final List<String> idsToDelete = [];
|
||||
final List<String> storagePathsToDelete = [];
|
||||
final List<String> idsToEdit = [];
|
||||
for (var file in files) {
|
||||
if (file.operationId == null) {
|
||||
idsToDelete.add(file.id!);
|
||||
storagePathsToDelete.add(file.storagePath!);
|
||||
} else {
|
||||
idsToEdit.add(file.id!);
|
||||
}
|
||||
}
|
||||
try {
|
||||
// 2. Cancellazione MASSIVA dal DB (una sola chiamata invece di un ciclo!)
|
||||
// .in_ dice: "cancella tutti i record il cui ID è contenuto in questa lista"
|
||||
await _supabase
|
||||
.from('customer_file')
|
||||
.delete()
|
||||
.inFilter('id', idsToDelete);
|
||||
|
||||
// 3. Cancellazione MASSIVA dallo Storage
|
||||
await _supabase.storage.from('documents').remove(storagePaths);
|
||||
|
||||
debugPrint("Eliminati con successo ${files.length} file.");
|
||||
if (idsToDelete.isNotEmpty) {
|
||||
await _supabase.from('attachment').delete().inFilter('id', idsToDelete);
|
||||
// 3. Cancellazione MASSIVA dallo Storage
|
||||
await _supabase.storage.from('documents').remove(storagePathsToDelete);
|
||||
}
|
||||
if (idsToEdit.isNotEmpty) {
|
||||
await _supabase
|
||||
.from('attachment')
|
||||
.update({'customer_id': null})
|
||||
.inFilter('id', idsToEdit);
|
||||
}
|
||||
} on PostgrestException catch (e) {
|
||||
debugPrint("Errore DB: ${e.message}");
|
||||
throw 'Errore database: ${e.message}';
|
||||
throw e.message;
|
||||
} catch (e) {
|
||||
debugPrint("Errore generico: $e");
|
||||
throw 'Errore durante l\'eliminazione dei file: $e';
|
||||
throw '$e';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user