j
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||
import 'package:flux/features/operations/data/operations_repository.dart';
|
||||
import 'package:flux/features/operations/models/operation_model.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
part 'operation_form_state.dart';
|
||||
|
||||
class OperationFormCubit extends Cubit<OperationFormState> {
|
||||
final OperationsRepository _repository = GetIt.I<OperationsRepository>();
|
||||
final SessionCubit _sessionCubit = GetIt.I<SessionCubit>();
|
||||
final Uuid _uuid = const Uuid();
|
||||
|
||||
OperationFormCubit()
|
||||
: super(
|
||||
OperationFormState(
|
||||
// Inizializziamo con un modello vuoto di sicurezza
|
||||
operation: OperationModel(
|
||||
storeId: '',
|
||||
companyId: '',
|
||||
reference: '',
|
||||
status: OperationStatus.draft,
|
||||
createdAt: DateTime.now(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Future<void> initForm({
|
||||
OperationModel? existingOperation,
|
||||
String? operationId,
|
||||
}) async {
|
||||
emit(state.copyWith(status: OperationFormStatus.loading));
|
||||
|
||||
try {
|
||||
if (existingOperation != null) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
operation: existingOperation,
|
||||
status: OperationFormStatus.ready,
|
||||
),
|
||||
);
|
||||
} else if (operationId != null) {
|
||||
// Avendo separato i cubit, se ci passano solo l'ID lo scarichiamo dal DB
|
||||
final operation = await _repository.fetchOperationById(operationId);
|
||||
emit(
|
||||
state.copyWith(
|
||||
operation: operation,
|
||||
status: OperationFormStatus.ready,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// NUOVA PRATICA: Creiamo un nuovo Batch UUID
|
||||
emit(
|
||||
state.copyWith(
|
||||
operation: OperationModel(
|
||||
storeId: _sessionCubit.state.currentStore?.id ?? '',
|
||||
reference: '',
|
||||
createdAt: DateTime.now(),
|
||||
companyId: _sessionCubit.state.company!.id!,
|
||||
status: OperationStatus.draft,
|
||||
batchUuid: _uuid.v4(),
|
||||
),
|
||||
status: OperationFormStatus.ready,
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationFormStatus.failure,
|
||||
errorMessage: "Errore inizializzazione form: $e",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// --- LOGICA BATCH ---
|
||||
|
||||
void _prepareNextOperationInBatch() {
|
||||
final current = state.operation;
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationFormStatus.ready, // Torna ready per il nuovo form
|
||||
operation: OperationModel(
|
||||
companyId: current.companyId,
|
||||
storeId: current.storeId,
|
||||
storeDisplayName: current.storeDisplayName,
|
||||
batchUuid: current.batchUuid, // MANTIENE IL COLLEGAMENTO
|
||||
customerId: current.customerId, // MANTIENE IL CLIENTE
|
||||
customerDisplayName: current.customerDisplayName,
|
||||
status: OperationStatus.draft,
|
||||
createdAt: DateTime.now(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// --- SALVATAGGIO ---
|
||||
|
||||
Future<void> saveOperation({
|
||||
required OperationStatus targetStatus,
|
||||
required bool keepAdding,
|
||||
}) async {
|
||||
emit(
|
||||
state.copyWith(status: OperationFormStatus.saving, errorMessage: null),
|
||||
);
|
||||
|
||||
try {
|
||||
final operationToSave = state.operation.copyWith(status: targetStatus);
|
||||
final savedOperation = await _repository.saveFullOperation(
|
||||
operation: operationToSave,
|
||||
);
|
||||
|
||||
if (keepAdding) {
|
||||
// Salviamo nella "memoria" del batch le pratiche create finora
|
||||
final updatedBatchList = List<OperationModel>.from(
|
||||
state.savedBatchOperations,
|
||||
)..add(savedOperation);
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationFormStatus.successAndAddAnother,
|
||||
savedBatchOperations: updatedBatchList,
|
||||
),
|
||||
);
|
||||
|
||||
// Pulisce i campi per la prossima operazione
|
||||
_prepareNextOperationInBatch();
|
||||
} else {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationFormStatus.success,
|
||||
operation: savedOperation, // Aggiorniamo con l'ID restituito dal DB
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationFormStatus.failure,
|
||||
errorMessage: e.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> saveOperationDraft() async {
|
||||
try {
|
||||
final operationToSave = state.operation;
|
||||
if (operationToSave.customerId == null ||
|
||||
operationToSave.customerId!.isEmpty) {
|
||||
throw Exception('Seleziona un cliente prima di poter usare il QR');
|
||||
}
|
||||
final savedOperation = await _repository.saveFullOperation(
|
||||
operation: operationToSave,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
operation: savedOperation,
|
||||
status: OperationFormStatus.ready,
|
||||
),
|
||||
);
|
||||
return savedOperation.id;
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationFormStatus.failure,
|
||||
errorMessage: e.toString(),
|
||||
),
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// --- GESTIONE DEI CAMPI IN TEMPO REALE ---
|
||||
|
||||
void updateFields({
|
||||
String? customerId,
|
||||
String? customerDisplayName,
|
||||
String? reference,
|
||||
String? note,
|
||||
String? type,
|
||||
String? providerId,
|
||||
String? providerDisplayName,
|
||||
String? subtype,
|
||||
String? description,
|
||||
DateTime? expirationDate,
|
||||
int? quantity,
|
||||
String? modelId,
|
||||
String? modelDisplayName,
|
||||
String? staffId,
|
||||
String? staffDisplayName,
|
||||
OperationStatus? status,
|
||||
|
||||
bool clearProvider = false,
|
||||
bool clearType = false,
|
||||
bool clearSubtype = false,
|
||||
bool clearDescription = false,
|
||||
bool clearExpiration = false,
|
||||
bool clearQuantity = false,
|
||||
bool clearModel = false,
|
||||
}) {
|
||||
final current = state.operation;
|
||||
|
||||
int? newQuantity;
|
||||
if (clearQuantity) newQuantity = 1;
|
||||
if (quantity != null && quantity <= 0) newQuantity = 0;
|
||||
if (quantity != null && quantity > 0) newQuantity = quantity;
|
||||
|
||||
final updated = current.copyWith(
|
||||
customerId:
|
||||
customerId ??
|
||||
current.customerId, // Se non passo customerId, tengo il vecchio
|
||||
customerDisplayName: customerDisplayName ?? current.customerDisplayName,
|
||||
reference: reference ?? current.reference,
|
||||
note: note ?? current.note,
|
||||
providerId: clearProvider ? null : (providerId ?? current.providerId),
|
||||
providerDisplayName: clearProvider
|
||||
? null
|
||||
: (providerDisplayName ?? current.providerDisplayName),
|
||||
quantity: newQuantity ?? current.quantity,
|
||||
type: clearType ? null : (type ?? current.type),
|
||||
description: clearDescription
|
||||
? null
|
||||
: (description ?? current.description),
|
||||
subtype: clearSubtype ? null : (subtype ?? current.subtype),
|
||||
expirationDate: clearExpiration
|
||||
? null
|
||||
: (expirationDate ?? current.expirationDate),
|
||||
modelId: clearModel ? null : (modelId ?? current.modelId),
|
||||
modelDisplayName: clearModel
|
||||
? null
|
||||
: (modelDisplayName ?? current.modelDisplayName),
|
||||
staffId: staffId ?? current.staffId,
|
||||
staffDisplayName: staffDisplayName ?? current.staffDisplayName,
|
||||
status: status ?? current.status,
|
||||
);
|
||||
|
||||
emit(state.copyWith(operation: updated));
|
||||
}
|
||||
|
||||
// --- UTILS ---
|
||||
|
||||
void setTypeWithSmartDefault(String type) {
|
||||
DateTime? defaultDate;
|
||||
final now = DateTime.now();
|
||||
|
||||
if (type == 'Energy') {
|
||||
defaultDate = DateTime(now.year, now.month + 24, now.day);
|
||||
}
|
||||
if (type == 'Fin') {
|
||||
defaultDate = DateTime(now.year, now.month + 30, now.day);
|
||||
}
|
||||
if (type == 'Entertainment') {
|
||||
defaultDate = DateTime(now.year, now.month + 12, now.day);
|
||||
}
|
||||
|
||||
updateFields(
|
||||
type: type,
|
||||
expirationDate: defaultDate,
|
||||
clearProvider: true,
|
||||
clearSubtype: true,
|
||||
clearModel: true,
|
||||
clearQuantity: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,48 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flux/features/operations/models/operation_model.dart';
|
||||
part of 'operation_form_cubit.dart';
|
||||
|
||||
enum OperationFormStatus {
|
||||
initial,
|
||||
ready,
|
||||
loading,
|
||||
ready,
|
||||
saving,
|
||||
success,
|
||||
successAndAddAnother,
|
||||
successAndAddAnother, // Nuovo stato in stile Ticket!
|
||||
failure,
|
||||
}
|
||||
|
||||
class OperationFormState extends Equatable {
|
||||
final OperationModel operation;
|
||||
final OperationFormStatus status;
|
||||
final OperationModel operation;
|
||||
final String? errorMessage;
|
||||
// Teniamo traccia delle operazioni salvate in questa sessione (per UI riepilogo)
|
||||
final List<OperationModel> savedBatchOperations;
|
||||
|
||||
const OperationFormState({
|
||||
required this.operation,
|
||||
this.status = OperationFormStatus.initial,
|
||||
required this.operation,
|
||||
this.errorMessage,
|
||||
this.savedBatchOperations = const [],
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [operation, status, errorMessage];
|
||||
|
||||
OperationFormState copyWith({
|
||||
OperationModel? operation,
|
||||
OperationFormStatus? status,
|
||||
OperationModel? operation,
|
||||
String? errorMessage,
|
||||
List<OperationModel>? savedBatchOperations,
|
||||
}) {
|
||||
return OperationFormState(
|
||||
operation: operation ?? this.operation,
|
||||
status: status ?? this.status,
|
||||
operation: operation ?? this.operation,
|
||||
errorMessage: errorMessage,
|
||||
savedBatchOperations: savedBatchOperations ?? this.savedBatchOperations,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
status,
|
||||
operation,
|
||||
errorMessage,
|
||||
savedBatchOperations,
|
||||
];
|
||||
}
|
||||
|
||||
81
lib/features/operations/blocs/operation_list_cubit.dart
Normal file
81
lib/features/operations/blocs/operation_list_cubit.dart
Normal file
@@ -0,0 +1,81 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||
import 'package:flux/features/operations/data/operations_repository.dart';
|
||||
import 'package:flux/features/operations/models/operation_model.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
part 'operation_list_state.dart';
|
||||
|
||||
class OperationListCubit extends Cubit<OperationListState> {
|
||||
final OperationsRepository _repository = GetIt.I<OperationsRepository>();
|
||||
final SessionCubit _sessionCubit = GetIt.I<SessionCubit>();
|
||||
|
||||
OperationListCubit() : super(const OperationListState());
|
||||
|
||||
Future<void> loadOperations({bool refresh = false}) async {
|
||||
if (state.status == OperationListStatus.loading) return;
|
||||
if (!refresh && state.hasReachedMax) return;
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationListStatus.loading,
|
||||
errorMessage: null,
|
||||
operations: refresh ? [] : state.operations,
|
||||
hasReachedMax: refresh ? false : state.hasReachedMax,
|
||||
),
|
||||
);
|
||||
|
||||
try {
|
||||
final currentOffset = refresh ? 0 : state.operations.length;
|
||||
final companyId = _sessionCubit.state.company?.id;
|
||||
|
||||
if (companyId == null) {
|
||||
throw Exception("Company ID non trovato nella sessione");
|
||||
}
|
||||
|
||||
final newOperations = await _repository.fetchOperations(
|
||||
companyId: companyId,
|
||||
offset: currentOffset,
|
||||
limit: 50,
|
||||
searchTerm: state.query,
|
||||
dateRange: state.dateRange,
|
||||
);
|
||||
|
||||
final bool reachedMax = newOperations.length < 50;
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationListStatus.success,
|
||||
operations: refresh
|
||||
? newOperations
|
||||
: [...state.operations, ...newOperations],
|
||||
hasReachedMax: reachedMax,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationListStatus.failure,
|
||||
errorMessage: "Errore nel caricamento operazioni: $e",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void updateFilters({String? query, DateTimeRange? range}) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
query: query ?? state.query,
|
||||
dateRange: range ?? state.dateRange,
|
||||
),
|
||||
);
|
||||
loadOperations(refresh: true);
|
||||
}
|
||||
|
||||
void clearFilters() {
|
||||
emit(const OperationListState()); // Resetta tutto allo stato iniziale
|
||||
loadOperations(refresh: true);
|
||||
}
|
||||
}
|
||||
49
lib/features/operations/blocs/operation_list_state.dart
Normal file
49
lib/features/operations/blocs/operation_list_state.dart
Normal file
@@ -0,0 +1,49 @@
|
||||
part of 'operation_list_cubit.dart';
|
||||
|
||||
enum OperationListStatus { initial, loading, success, failure }
|
||||
|
||||
class OperationListState extends Equatable {
|
||||
final OperationListStatus status;
|
||||
final List<OperationModel> operations;
|
||||
final bool hasReachedMax;
|
||||
final String? errorMessage;
|
||||
final String query;
|
||||
final DateTimeRange? dateRange;
|
||||
|
||||
const OperationListState({
|
||||
this.status = OperationListStatus.initial,
|
||||
this.operations = const [],
|
||||
this.hasReachedMax = false,
|
||||
this.errorMessage,
|
||||
this.query = '',
|
||||
this.dateRange,
|
||||
});
|
||||
|
||||
OperationListState copyWith({
|
||||
OperationListStatus? status,
|
||||
List<OperationModel>? operations,
|
||||
bool? hasReachedMax,
|
||||
String? errorMessage,
|
||||
String? query,
|
||||
DateTimeRange? dateRange,
|
||||
}) {
|
||||
return OperationListState(
|
||||
status: status ?? this.status,
|
||||
operations: operations ?? this.operations,
|
||||
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
|
||||
errorMessage: errorMessage,
|
||||
query: query ?? this.query,
|
||||
dateRange: dateRange ?? this.dateRange,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
status,
|
||||
operations,
|
||||
hasReachedMax,
|
||||
errorMessage,
|
||||
query,
|
||||
dateRange,
|
||||
];
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||
import 'package:flux/features/operations/data/operations_repository.dart';
|
||||
import 'package:flux/features/operations/models/operation_model.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
part 'operations_state.dart';
|
||||
|
||||
class OperationsCubit extends Cubit<OperationsState> {
|
||||
final OperationsRepository _repository = GetIt.I<OperationsRepository>();
|
||||
final SessionCubit _sessionCubit = GetIt.I<SessionCubit>();
|
||||
final Uuid _uuid = const Uuid(); // Generatore di UUID per il batch
|
||||
|
||||
OperationsCubit()
|
||||
: super(const OperationsState(status: OperationsStatus.initial));
|
||||
|
||||
// --- CARICAMENTO E PAGINAZIONE ---
|
||||
|
||||
Future<void> loadOperations({bool refresh = false}) async {
|
||||
if (state.status == OperationsStatus.loading) return;
|
||||
if (!refresh && state.hasReachedMax) return;
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationsStatus.loading,
|
||||
errorMessage: null,
|
||||
allOperations: refresh ? [] : state.allOperations,
|
||||
hasReachedMax: refresh ? false : state.hasReachedMax,
|
||||
),
|
||||
);
|
||||
|
||||
try {
|
||||
final currentOffset = refresh ? 0 : state.allOperations.length;
|
||||
final companyId = _sessionCubit.state.company?.id;
|
||||
|
||||
if (companyId == null) {
|
||||
throw Exception("Company ID non trovato nella sessione");
|
||||
}
|
||||
|
||||
final newOperations = await _repository.fetchOperations(
|
||||
companyId: companyId,
|
||||
offset: currentOffset,
|
||||
limit: 50,
|
||||
searchTerm: state.query,
|
||||
dateRange: state.dateRange,
|
||||
);
|
||||
|
||||
final bool reachedMax = newOperations.length < 50;
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationsStatus.ready,
|
||||
allOperations: refresh
|
||||
? newOperations
|
||||
: [...state.allOperations, ...newOperations],
|
||||
hasReachedMax: reachedMax,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationsStatus.failure,
|
||||
errorMessage: "Errore nel caricamento operazioni: $e",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// --- GESTIONE FILTRI ---
|
||||
|
||||
void updateFilters({String? query, DateTimeRange? range}) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
query: query ?? state.query,
|
||||
dateRange: range ?? state.dateRange,
|
||||
),
|
||||
);
|
||||
loadOperations(refresh: true);
|
||||
}
|
||||
|
||||
void clearFilters() {
|
||||
emit(state.copyWith(query: '', dateRange: null));
|
||||
loadOperations(refresh: true);
|
||||
}
|
||||
|
||||
void initOperationForm({
|
||||
OperationModel? existingOperation,
|
||||
String? operationId,
|
||||
String? staffId,
|
||||
String? staffDisplayName,
|
||||
}) async {
|
||||
if (existingOperation != null) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
currentOperation: existingOperation,
|
||||
status: OperationsStatus.ready,
|
||||
),
|
||||
);
|
||||
} else if (operationId != null) {
|
||||
OperationModel? operationModel = state.allOperations.firstWhereOrNull(
|
||||
(s) => s.id == operationId,
|
||||
);
|
||||
operationModel ??= await _repository.fetchOperationById(operationId);
|
||||
emit(
|
||||
state.copyWith(
|
||||
currentOperation: operationModel,
|
||||
status: OperationsStatus.ready,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// NUOVA PRATICA: Creiamo un nuovo Batch UUID
|
||||
emit(
|
||||
state.copyWith(
|
||||
currentOperation: OperationModel(
|
||||
storeId: _sessionCubit.state.currentStore?.id ?? '',
|
||||
reference: '',
|
||||
createdAt: DateTime.now(),
|
||||
companyId: _sessionCubit.state.company!.id!,
|
||||
status: OperationStatus.draft,
|
||||
batchUuid: _uuid.v4(), // <-- GENERIAMO IL BATCH UNIVOCO
|
||||
),
|
||||
status: OperationsStatus.ready,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// MAGIA PURA: Prepara il form per inserire un altro servizio nella stessa pratica.
|
||||
/// Mantiene il Cliente, il Batch e lo Store, ma svuota il resto.
|
||||
void prepareNextOperationInBatch() {
|
||||
if (state.currentOperation == null) return;
|
||||
|
||||
final current = state.currentOperation!;
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationsStatus.ready,
|
||||
currentOperation: OperationModel(
|
||||
companyId: current.companyId,
|
||||
storeId: current.storeId,
|
||||
storeDisplayName: current.storeDisplayName,
|
||||
batchUuid: current.batchUuid, // <-- MANTIENE IL COLLEGAMENTO
|
||||
customerId: current.customerId, // <-- MANTIENE IL CLIENTE
|
||||
customerDisplayName: current.customerDisplayName,
|
||||
status: OperationStatus.draft,
|
||||
createdAt: DateTime.now(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// --- PERSISTENZA ---
|
||||
|
||||
Future<void> saveCurrentOperation({
|
||||
required OperationStatus targetStatus,
|
||||
bool shouldPop = true,
|
||||
}) async {
|
||||
if (state.currentOperation == null) return;
|
||||
|
||||
emit(state.copyWith(status: OperationsStatus.saving, errorMessage: null));
|
||||
try {
|
||||
final operationToSave = state.currentOperation!.copyWith(
|
||||
status: targetStatus,
|
||||
);
|
||||
|
||||
final updatedOperation = await _repository.saveFullOperation(
|
||||
operation: operationToSave,
|
||||
);
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
// Se non facciamo Pop (es. l'utente vuole aggiungere un altro servizio), non killiamo l'operazione corrente
|
||||
status: shouldPop
|
||||
? OperationsStatus.saved
|
||||
: OperationsStatus.savedNoPop,
|
||||
currentOperation: shouldPop ? null : updatedOperation,
|
||||
),
|
||||
);
|
||||
|
||||
// Ricarica in background per la dashboard
|
||||
loadOperations(refresh: true);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: OperationsStatus.failure,
|
||||
errorMessage: e.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// --- RECUPERO OPERAZIONI DELLO STESSO BATCH (Per UI di riepilogo) ---
|
||||
|
||||
/// Puoi usare questa funzione se nella UI vuoi mostrare "Hai inserito 3 servizi in questa pratica"
|
||||
List<OperationModel> getOperationsInCurrentBatch() {
|
||||
if (state.currentOperation == null) return [];
|
||||
final currentBatch = state.currentOperation!.batchUuid;
|
||||
|
||||
// Filtriamo dalla lista caricata (o potresti fare una query diretta a Supabase se preferisci)
|
||||
return state.allOperations
|
||||
.where(
|
||||
(op) =>
|
||||
op.batchUuid == currentBatch &&
|
||||
op.id != state.currentOperation!.id,
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
// --- GESTIONE DELLO STATO DEL FORM IN TEMPO REALE ---
|
||||
void updateOperationFields({
|
||||
String? customerId,
|
||||
String? customerDisplayName,
|
||||
String? type,
|
||||
String? providerId,
|
||||
String? providerDisplayName,
|
||||
String? subtype,
|
||||
String? description,
|
||||
DateTime? expirationDate,
|
||||
int? quantity,
|
||||
String? modelId,
|
||||
String? modelDisplayName,
|
||||
String? staffId,
|
||||
String? staffDisplayName,
|
||||
// Aggiungiamo questi flag per forzare la pulizia dei campi quando cambi tipo
|
||||
bool clearProvider = false,
|
||||
bool clearType = false,
|
||||
bool clearSubtype = false,
|
||||
bool clearDescription = false,
|
||||
bool clearExpiration = false,
|
||||
bool clearQuantity = false,
|
||||
bool clearModel = false,
|
||||
}) {
|
||||
if (state.currentOperation == null) return;
|
||||
|
||||
final current = state.currentOperation!;
|
||||
|
||||
// Creiamo il modello aggiornato
|
||||
// ATTENZIONE: adatta questa logica in base a come è scritto il tuo copyWith!
|
||||
int? newQuantity;
|
||||
if (clearQuantity) {
|
||||
newQuantity = 1;
|
||||
}
|
||||
if (quantity != null && quantity <= 0) {
|
||||
newQuantity = 0;
|
||||
}
|
||||
if (quantity != null && quantity > 0) {
|
||||
newQuantity = quantity;
|
||||
}
|
||||
final updated = current.copyWith(
|
||||
customerId: customerId,
|
||||
customerDisplayName: customerDisplayName,
|
||||
|
||||
// Se clearProvider è true, forziamo una stringa vuota (o null se il tuo modello lo supporta)
|
||||
providerId: clearProvider ? null : (providerId ?? current.providerId),
|
||||
providerDisplayName: clearProvider
|
||||
? null
|
||||
: (providerDisplayName ?? current.providerDisplayName),
|
||||
quantity: newQuantity,
|
||||
type: clearType ? null : (type ?? current.type),
|
||||
description: clearDescription
|
||||
? null
|
||||
: (description ?? current.description),
|
||||
subtype: clearSubtype ? null : (subtype ?? current.subtype),
|
||||
expirationDate: clearExpiration
|
||||
? null
|
||||
: (expirationDate ?? current.expirationDate),
|
||||
modelId: clearModel ? null : (modelId ?? current.modelId),
|
||||
modelDisplayName: clearModel
|
||||
? null
|
||||
: (modelDisplayName ?? current.modelDisplayName),
|
||||
staffId: staffId ?? current.staffId,
|
||||
staffDisplayName: staffDisplayName ?? current.staffDisplayName,
|
||||
);
|
||||
|
||||
emit(state.copyWith(currentOperation: updated));
|
||||
}
|
||||
|
||||
// Metodo di utilità per calcolare la data X mesi da oggi
|
||||
DateTime _calculateMonths(int months) {
|
||||
final now = DateTime.now();
|
||||
return DateTime(now.year, now.month + months, now.day);
|
||||
}
|
||||
|
||||
// Quando l'utente seleziona un tipo, impostiamo il default
|
||||
void setTypeWithSmartDefault(String type) {
|
||||
DateTime? defaultDate;
|
||||
|
||||
if (type == 'Energy') defaultDate = _calculateMonths(24);
|
||||
if (type == 'Fin') defaultDate = _calculateMonths(30);
|
||||
if (type == 'Entertainment') defaultDate = _calculateMonths(12);
|
||||
|
||||
updateOperationFields(
|
||||
type: type,
|
||||
expirationDate: defaultDate,
|
||||
clearProvider: true,
|
||||
clearSubtype: true,
|
||||
clearModel: true,
|
||||
clearQuantity: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
part of 'operations_cubit.dart';
|
||||
|
||||
enum OperationsStatus {
|
||||
initial,
|
||||
loading,
|
||||
ready,
|
||||
saving,
|
||||
saved,
|
||||
savedNoPop,
|
||||
success,
|
||||
failure,
|
||||
}
|
||||
|
||||
class OperationsState extends Equatable {
|
||||
final OperationsStatus status;
|
||||
final List<OperationModel> allOperations;
|
||||
final OperationModel? currentOperation; // La bozza che stiamo editando
|
||||
final String? errorMessage;
|
||||
final String query;
|
||||
final DateTimeRange? dateRange;
|
||||
final bool hasReachedMax;
|
||||
final bool isSavingDraft;
|
||||
|
||||
const OperationsState({
|
||||
required this.status,
|
||||
this.allOperations = const [],
|
||||
this.currentOperation,
|
||||
this.errorMessage,
|
||||
this.query = '',
|
||||
this.dateRange,
|
||||
this.hasReachedMax = false,
|
||||
this.isSavingDraft = false,
|
||||
});
|
||||
|
||||
OperationsState copyWith({
|
||||
OperationsStatus? status,
|
||||
List<OperationModel>? allOperations,
|
||||
OperationModel? currentOperation,
|
||||
String? errorMessage,
|
||||
String? query,
|
||||
DateTimeRange? dateRange,
|
||||
bool? hasReachedMax,
|
||||
bool? isSavingDraft,
|
||||
}) {
|
||||
return OperationsState(
|
||||
status: status ?? this.status,
|
||||
allOperations: allOperations ?? this.allOperations,
|
||||
currentOperation: currentOperation ?? this.currentOperation,
|
||||
errorMessage: errorMessage,
|
||||
query: query ?? this.query,
|
||||
dateRange: dateRange ?? this.dateRange,
|
||||
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
|
||||
isSavingDraft: isSavingDraft ?? this.isSavingDraft,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
status,
|
||||
allOperations,
|
||||
currentOperation,
|
||||
errorMessage,
|
||||
query,
|
||||
dateRange,
|
||||
hasReachedMax,
|
||||
isSavingDraft,
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user