fix macos pdf
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||||
import 'package:flux/features/documents/data/tickets_shipment_repository.dart';
|
import 'package:flux/features/tickets/data/tickets_shipment_repository.dart';
|
||||||
import 'package:flux/features/documents/models/shipment_document_model.dart';
|
import 'package:flux/features/tickets/models/shipment_document_model.dart';
|
||||||
import 'package:flux/features/master_data/providers/models/provider_location_model.dart';
|
import 'package:flux/features/master_data/providers/models/provider_location_model.dart';
|
||||||
import 'package:flux/features/master_data/providers/models/provider_model.dart';
|
import 'package:flux/features/master_data/providers/models/provider_model.dart';
|
||||||
import 'package:flux/features/settings/document_sequence/data/document_sequence_repository.dart';
|
import 'package:flux/features/settings/document_sequence/data/document_sequence_repository.dart';
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||||
|
import 'package:flux/features/settings/document_sequence/data/document_sequence_repository.dart';
|
||||||
|
import 'package:flux/features/settings/document_sequence/models/document_sequence_model.dart';
|
||||||
import 'package:flux/features/tickets/models/ticket_model.dart';
|
import 'package:flux/features/tickets/models/ticket_model.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
|
|
||||||
class TicketRepository {
|
class TicketRepository {
|
||||||
final SupabaseClient _supabase = GetIt.I.get<SupabaseClient>();
|
final SupabaseClient _supabase = GetIt.I.get<SupabaseClient>();
|
||||||
|
final DocumentSequenceRepository _documentSequenceRepository = GetIt.I
|
||||||
|
.get<DocumentSequenceRepository>();
|
||||||
|
|
||||||
TicketRepository();
|
TicketRepository();
|
||||||
|
|
||||||
@@ -192,29 +196,29 @@ class TicketRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> generateTicketReference(String companyId) async {
|
// Future<String> generateTicketReference(String companyId) async {
|
||||||
final response = await Supabase.instance.client.rpc(
|
// final response = await Supabase.instance.client.rpc(
|
||||||
'get_next_document_number',
|
// 'get_next_document_number',
|
||||||
params: {'p_company_id': companyId, 'p_doc_type': 'ticket'},
|
// params: {'p_company_id': companyId, 'p_doc_type': 'ticket'},
|
||||||
);
|
// );
|
||||||
|
|
||||||
// Estraiamo i dati dal JSON
|
// // Estraiamo i dati dal JSON
|
||||||
final int nextValue = response['next_value'];
|
// final int nextValue = response['next_value'];
|
||||||
final String prefix = response['prefix'] ?? '';
|
// final String prefix = response['prefix'] ?? '';
|
||||||
|
|
||||||
final year = DateTime.now().year; // 2026
|
// final year = DateTime.now().year; // 2026
|
||||||
|
|
||||||
// Formattazione con zeri iniziali (es. 000125)
|
// // Formattazione con zeri iniziali (es. 000125)
|
||||||
final paddedNumber = nextValue.toString().padLeft(6, '0');
|
// final paddedNumber = nextValue.toString().padLeft(6, '0');
|
||||||
|
|
||||||
// Costruiamo la stringa. Se c'è un prefisso mette "TCK-2026-000125",
|
// // Costruiamo la stringa. Se c'è un prefisso mette "TCK-2026-000125",
|
||||||
// altrimenti solo "2026-000125"
|
// // altrimenti solo "2026-000125"
|
||||||
if (prefix.isNotEmpty) {
|
// if (prefix.isNotEmpty) {
|
||||||
return '$prefix-$year-$paddedNumber';
|
// return '$prefix-$year-$paddedNumber';
|
||||||
} else {
|
// } else {
|
||||||
return '$year-$paddedNumber';
|
// return '$year-$paddedNumber';
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Salva il ticket
|
/// Salva il ticket
|
||||||
Future<TicketModel> insertTicket(TicketModel ticket) async {
|
Future<TicketModel> insertTicket(TicketModel ticket) async {
|
||||||
@@ -223,7 +227,9 @@ class TicketRepository {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final ticketToSave = ticket.copyWith(
|
final ticketToSave = ticket.copyWith(
|
||||||
referenceId: await generateTicketReference(ticket.companyId),
|
referenceId: await _documentSequenceRepository.getNextDocumentNumber(
|
||||||
|
DocumentType.ticket.name,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
final response = await _supabase
|
final response = await _supabase
|
||||||
.from(_tableName)
|
.from(_tableName)
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
import 'package:flux/features/tickets/models/shipment_document_model.dart';
|
||||||
import 'package:flux/features/documents/models/shipment_document_model.dart';
|
|
||||||
import 'package:flux/features/master_data/providers/models/provider_model.dart';
|
import 'package:flux/features/master_data/providers/models/provider_model.dart';
|
||||||
import 'package:flux/features/master_data/providers/models/provider_role.dart';
|
import 'package:flux/features/master_data/providers/models/provider_role.dart';
|
||||||
import 'package:flux/features/settings/document_sequence/models/document_sequence_model.dart';
|
|
||||||
import 'package:flux/features/tickets/models/ticket_model.dart';
|
import 'package:flux/features/tickets/models/ticket_model.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
|
|
||||||
class TicketsShipmentRepository {
|
class TicketsShipmentRepository {
|
||||||
final _supabase = GetIt.I.get<SupabaseClient>();
|
final _supabase = GetIt.I.get<SupabaseClient>();
|
||||||
final _companyId = GetIt.I.get<SessionCubit>().state.company!.id!;
|
|
||||||
|
|
||||||
Future<List<ProviderModel>> fetchRepairCenters() async {
|
Future<List<ProviderModel>> fetchRepairCenters() async {
|
||||||
try {
|
try {
|
||||||
@@ -213,8 +213,12 @@ class _TicketFormScreenState extends State<TicketFormScreen> {
|
|||||||
.generateTicketReceipt(ticket);
|
.generateTicketReceipt(ticket);
|
||||||
final bytes = await doc.save();
|
final bytes = await doc.save();
|
||||||
final fileName = 'Ricevuta_${ticket.referenceId}.pdf';
|
final fileName = 'Ricevuta_${ticket.referenceId}.pdf';
|
||||||
|
await Printing.layoutPdf(
|
||||||
|
onLayout: (format) async => bytes,
|
||||||
|
name: fileName,
|
||||||
|
);
|
||||||
|
|
||||||
if (kIsWeb || Platform.isMacOS) {
|
/* if (kIsWeb || Platform.isMacOS) {
|
||||||
// Forza il download/salvataggio senza passare per il print spooler
|
// Forza il download/salvataggio senza passare per il print spooler
|
||||||
await Printing.sharePdf(
|
await Printing.sharePdf(
|
||||||
bytes: bytes,
|
bytes: bytes,
|
||||||
@@ -222,11 +226,8 @@ class _TicketFormScreenState extends State<TicketFormScreen> {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Su Android/iOS continuiamo a usare la stampa diretta che funziona
|
// Su Android/iOS continuiamo a usare la stampa diretta che funziona
|
||||||
await Printing.layoutPdf(
|
|
||||||
onLayout: (format) async => bytes,
|
} */
|
||||||
name: fileName,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (company.labelFormat != LabelFormat.none)
|
if (company.labelFormat != LabelFormat.none)
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import 'package:flutter/foundation.dart' show kIsWeb, defaultTargetPlatform;
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flux/core/blocs/session/session_cubit.dart';
|
import 'package:flux/core/blocs/session/session_cubit.dart';
|
||||||
import 'package:flux/features/documents/models/shipment_document_model.dart';
|
import 'package:flux/features/tickets/models/shipment_document_model.dart';
|
||||||
import 'package:flux/features/master_data/providers/models/provider_location_model.dart';
|
import 'package:flux/features/master_data/providers/models/provider_location_model.dart';
|
||||||
import 'package:flux/features/master_data/providers/models/provider_model.dart';
|
import 'package:flux/features/master_data/providers/models/provider_model.dart';
|
||||||
import 'package:flux/features/tickets/blocs/ticket_list_cubit.dart';
|
import 'package:flux/features/tickets/blocs/ticket_list_cubit.dart';
|
||||||
@@ -148,24 +147,10 @@ class TicketList extends StatelessWidget {
|
|||||||
document: result.document,
|
document: result.document,
|
||||||
tickets: state.selectedTickets.toList(),
|
tickets: state.selectedTickets.toList(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// 4. LANCIAMO LA STAMPA (Anteprima nativa / Browser)
|
|
||||||
// Check sicuro: se NON siamo sul web E la piattaforma nativa è macOS
|
|
||||||
if (!kIsWeb &&
|
|
||||||
defaultTargetPlatform == TargetPlatform.macOS) {
|
|
||||||
// Scialuppa di salvataggio per il Mac
|
|
||||||
await Printing.sharePdf(
|
|
||||||
bytes: pdfBytes,
|
|
||||||
filename: 'ddt_${result.document.docNumber}.pdf',
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Per Web, Windows, Linux, Android e iOS... diamo spettacolo!
|
|
||||||
await Printing.layoutPdf(
|
await Printing.layoutPdf(
|
||||||
onLayout: (PdfPageFormat format) async =>
|
onLayout: (PdfPageFormat format) async => pdfBytes,
|
||||||
pdfBytes,
|
|
||||||
name: 'ddt_${result.document.docNumber}.pdf',
|
name: 'ddt_${result.document.docNumber}.pdf',
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Pulizia finale: Deselezioniamo tutti i ticket e ricarichiamo la lista
|
// 5. Pulizia finale: Deselezioniamo tutti i ticket e ricarichiamo la lista
|
||||||
ticketListCubit.clearSelection();
|
ticketListCubit.clearSelection();
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ class _TicketShippingModalState extends State<TicketShippingModal> {
|
|||||||
TicketShippingState state,
|
TicketShippingState state,
|
||||||
) {
|
) {
|
||||||
return DropdownButtonFormField<String>(
|
return DropdownButtonFormField<String>(
|
||||||
value: state.document.providerId.isEmpty
|
initialValue: state.document.providerId.isEmpty
|
||||||
? null
|
? null
|
||||||
: state.document.providerId,
|
: state.document.providerId,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
@@ -207,7 +207,7 @@ class _TicketShippingModalState extends State<TicketShippingModal> {
|
|||||||
TicketShippingState state,
|
TicketShippingState state,
|
||||||
) {
|
) {
|
||||||
return DropdownButtonFormField<String>(
|
return DropdownButtonFormField<String>(
|
||||||
value: state.document.destinationLocationId.isEmpty
|
initialValue: state.document.destinationLocationId.isEmpty
|
||||||
? null
|
? null
|
||||||
: state.document.destinationLocationId,
|
: state.document.destinationLocationId,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
@@ -280,6 +280,7 @@ class _TicketShippingModalState extends State<TicketShippingModal> {
|
|||||||
),
|
),
|
||||||
trailing: const Icon(Icons.calendar_month),
|
trailing: const Icon(Icons.calendar_month),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
final ticketShippingCubit = context.read<TicketShippingCubit>();
|
||||||
final newDate = await showDatePicker(
|
final newDate = await showDatePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialDate: date,
|
initialDate: date,
|
||||||
@@ -287,7 +288,7 @@ class _TicketShippingModalState extends State<TicketShippingModal> {
|
|||||||
lastDate: DateTime.now().add(const Duration(days: 365)),
|
lastDate: DateTime.now().add(const Duration(days: 365)),
|
||||||
);
|
);
|
||||||
if (newDate != null) {
|
if (newDate != null) {
|
||||||
context.read<TicketShippingCubit>().updateDocument(docDate: newDate);
|
ticketShippingCubit.updateDocument(docDate: newDate);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:flux/features/company/models/company_model.dart';
|
import 'package:flux/features/company/models/company_model.dart';
|
||||||
import 'package:flux/features/documents/models/shipment_document_model.dart';
|
import 'package:flux/features/tickets/models/shipment_document_model.dart';
|
||||||
import 'package:flux/features/master_data/providers/models/provider_location_model.dart';
|
import 'package:flux/features/master_data/providers/models/provider_location_model.dart';
|
||||||
import 'package:flux/features/master_data/providers/models/provider_model.dart';
|
import 'package:flux/features/master_data/providers/models/provider_model.dart';
|
||||||
import 'package:flux/features/tickets/models/ticket_model.dart';
|
import 'package:flux/features/tickets/models/ticket_model.dart';
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import 'package:flutter_dotenv/flutter_dotenv.dart';
|
|||||||
import 'package:flux/features/attachments/data/attachments_repository.dart';
|
import 'package:flux/features/attachments/data/attachments_repository.dart';
|
||||||
import 'package:flux/features/auth/bloc/auth_cubit.dart';
|
import 'package:flux/features/auth/bloc/auth_cubit.dart';
|
||||||
import 'package:flux/features/company/data/company_repository.dart';
|
import 'package:flux/features/company/data/company_repository.dart';
|
||||||
import 'package:flux/features/documents/data/tickets_shipment_repository.dart';
|
import 'package:flux/features/tickets/data/tickets_shipment_repository.dart';
|
||||||
import 'package:flux/features/master_data/providers/blocs/provider_list_cubit.dart';
|
import 'package:flux/features/master_data/providers/blocs/provider_list_cubit.dart';
|
||||||
import 'package:flux/features/operations/blocs/operation_list_cubit.dart';
|
import 'package:flux/features/operations/blocs/operation_list_cubit.dart';
|
||||||
import 'package:flux/features/operations/data/operations_repository.dart';
|
import 'package:flux/features/operations/data/operations_repository.dart';
|
||||||
|
|||||||
@@ -30,5 +30,7 @@
|
|||||||
<string>NSApplication</string>
|
<string>NSApplication</string>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>FLUX ha bisogno della fotocamera per scansionare i QR Code e acquisire documenti.</string>
|
<string>FLUX ha bisogno della fotocamera per scansionare i QR Code e acquisire documenti.</string>
|
||||||
|
<key>FLTEnableMergedPlatformUIThread</key>
|
||||||
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
Reference in New Issue
Block a user