feat-insert-service (#5)

Reviewed-on: http://catelliub.zapto.org:3000/brontomark/flux/pulls/5
Co-authored-by: mark-cachy <marco@catelli.it>
Co-committed-by: mark-cachy <marco@catelli.it>
This commit is contained in:
2026-04-20 16:52:20 +02:00
committed by brontomark
parent 667bbf6404
commit c3d4f3fac7
63 changed files with 4715 additions and 1371 deletions

View File

@@ -0,0 +1,98 @@
import 'dart:typed_data';
import 'package:equatable/equatable.dart';
class ServiceFileModel extends Equatable {
final String? id;
final DateTime? createdAt;
final String name;
final String extension;
final String url;
final String serviceId;
final int fileSize;
final Uint8List? localBytes;
const ServiceFileModel({
this.id,
this.createdAt,
required this.name,
required this.extension,
required this.url,
required this.serviceId,
required this.fileSize,
this.localBytes,
});
// Trasforma i byte in qualcosa di leggibile (KB, MB, GB)
String get sizeFormatted {
if (fileSize <= 0) return "0 B";
const suffixes = ["B", "KB", "MB", "GB", "TB"];
var i = (fileSize.toString().length - 1) ~/ 3;
if (i >= suffixes.length) i = suffixes.length - 1;
double num = fileSize / (1 << (i * 10));
return "${num.toStringAsFixed(i == 0 ? 0 : 1)} ${suffixes[i]}";
}
bool get isPdf => extension.toLowerCase().replaceAll('.', '') == 'pdf';
ServiceFileModel copyWith({
String? id,
DateTime? createdAt,
String? name,
String? extension,
String? url,
String? serviceId,
int? fileSize,
Uint8List? localBytes,
}) {
return ServiceFileModel(
id: id ?? this.id,
createdAt: createdAt ?? this.createdAt,
name: name ?? this.name,
extension: extension ?? this.extension,
url: url ?? this.url,
serviceId: serviceId ?? this.serviceId,
fileSize: fileSize ?? this.fileSize,
localBytes: localBytes ?? this.localBytes,
);
}
factory ServiceFileModel.fromMap(Map<String, dynamic> map) {
return ServiceFileModel(
id: map['id'] as String,
createdAt: map['created_at'] != null
? DateTime.parse(map['created_at'])
: null,
name: map['name'] ?? '',
extension: map['extension'] ?? '',
url: map['url'] ?? '',
serviceId: map['service_id']?.toString() ?? '',
fileSize: map['file_size'] is int
? map['file_size']
: int.tryParse(map['file_size']?.toString() ?? '0') ?? 0,
);
}
Map<String, dynamic> toMap() {
return {
if (id != null) 'id': id,
'name': name,
'extension': extension,
'url': url,
'service_id': serviceId,
'file_size': fileSize,
};
}
@override
List<Object?> get props => [
id,
createdAt,
name,
extension,
url,
serviceId,
fileSize,
localBytes,
];
}

View File

@@ -1,7 +1,9 @@
import 'package:equatable/equatable.dart';
import 'package:flux/core/utils/string_extensions.dart';
import 'package:flux/features/services/models/energy_service_model.dart';
import 'package:flux/features/services/models/entertainment_service_model.dart';
import 'package:flux/features/services/models/fin_service_model.dart';
import 'package:flux/features/services/models/service_file_model.dart'; // <-- Aggiunto Import
class ServiceModel extends Equatable {
final String? id;
@@ -14,6 +16,7 @@ class ServiceModel extends Equatable {
final String note;
final bool resultOk;
final String? customerDisplayName;
final String companyId;
// Telefonia
final int al;
@@ -27,6 +30,9 @@ class ServiceModel extends Equatable {
final List<FinServiceModel> finServices;
final List<EntertainmentServiceModel> entertainmentServices;
// ALLEGATI (Aggiunto)
final List<ServiceFileModel> files;
const ServiceModel({
this.id,
this.createdAt,
@@ -45,7 +51,9 @@ class ServiceModel extends Equatable {
this.energyServices = const [],
this.finServices = const [],
this.entertainmentServices = const [],
this.files = const [], // <-- Aggiunto default vuoto
this.customerDisplayName,
required this.companyId,
});
ServiceModel copyWith({
@@ -66,7 +74,9 @@ class ServiceModel extends Equatable {
List<EnergyServiceModel>? energyServices,
List<FinServiceModel>? finServices,
List<EntertainmentServiceModel>? entertainmentServices,
List<ServiceFileModel>? files, // <-- Aggiunto
String? customerDisplayName,
String? companyId,
}) {
return ServiceModel(
id: id ?? this.id,
@@ -87,7 +97,9 @@ class ServiceModel extends Equatable {
finServices: finServices ?? this.finServices,
entertainmentServices:
entertainmentServices ?? this.entertainmentServices,
files: files ?? this.files, // <-- Aggiunto
customerDisplayName: customerDisplayName ?? this.customerDisplayName,
companyId: companyId ?? this.companyId,
);
}
@@ -110,17 +122,21 @@ class ServiceModel extends Equatable {
energyServices,
finServices,
entertainmentServices,
files, // <-- Aggiunto
customerDisplayName,
companyId,
];
factory ServiceModel.fromMap(Map<String, dynamic> map) {
return ServiceModel(
id: map['id'],
createdAt: DateTime.parse(map['created_at']),
storeId: map['store_id'],
employeeId: map['employee_id'],
customerId: map['customer_id'],
number: map['number'] ?? '',
id: map['id'].toString(),
createdAt: map['created_at'] != null
? DateTime.parse(map['created_at'])
: DateTime.now(),
storeId: map['store_id'] ?? '',
employeeId: map['employee_id']?.toString(),
customerId: map['customer_id']?.toString(),
number: map['number']?.toString() ?? '',
isBozza: map['bozza'] ?? true,
note: map['note'] ?? '',
resultOk: map['result_ok'] ?? true,
@@ -130,7 +146,7 @@ class ServiceModel extends Equatable {
unica: map['unica'] ?? 0,
telepass: map['telepass'] ?? 0,
// Mappaggio delle liste collegate (se incluse nella query)
// Estrazione sicura liste collegate
energyServices:
(map['energy_service'] as List?)
?.map((x) => EnergyServiceModel.fromMap(x))
@@ -146,9 +162,19 @@ class ServiceModel extends Equatable {
?.map((x) => EntertainmentServiceModel.fromMap(x))
.toList() ??
const [],
// I FILE! (Assicurati che la foreign key su Supabase usi esattamente questo nome)
files:
(map['service_file'] as List?)
?.map((x) => ServiceFileModel.fromMap(x))
.toList() ??
const [],
// Display name del cliente con fallback
customerDisplayName: map['customer'] != null
? "${map['customer']['name']} ${map['customer']['surname']}"
: "Cliente sconosciuto",
? "${map['customer']['nome'] ?? ''}".myFormat()
: "Cliente non assegnato",
companyId: map['company_id'] as String,
);
}
@@ -167,6 +193,7 @@ class ServiceModel extends Equatable {
'nip': nip,
'unica': unica,
'telepass': telepass,
'company_id': companyId,
// Le liste non le mettiamo qui perché vanno in tabelle diverse!
};
}