feat: add export service
This commit is contained in:
@@ -3,6 +3,7 @@ import 'package:provider/provider.dart';
|
||||
|
||||
import '../database/app_database.dart';
|
||||
import '../services/default_product_seeder.dart';
|
||||
import '../services/export_service.dart';
|
||||
import '../viewmodels/bar_screen_view_model.dart';
|
||||
import '../viewmodels/product_list_view_model.dart';
|
||||
|
||||
@@ -28,6 +29,8 @@ class _AppBootstrapState extends State<AppBootstrap> {
|
||||
|
||||
context.read<ProductListViewModel>().ensureLoaded();
|
||||
context.read<BarScreenViewModel>().ensureLoaded();
|
||||
|
||||
DefaultExportService(database: database).uploadToServer();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../database/app_database.dart';
|
||||
import '../utils/app_config.dart';
|
||||
|
||||
abstract class ExportService {
|
||||
Future<void> uploadToServer();
|
||||
}
|
||||
|
||||
class DefaultExportService implements ExportService {
|
||||
final AppDatabase database;
|
||||
|
||||
DefaultExportService({required this.database});
|
||||
|
||||
@override
|
||||
Future<void> uploadToServer() async {
|
||||
try {
|
||||
final closedTabs = await _getAllClosedTabs();
|
||||
final exportData = _buildExportPayload(closedTabs);
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse(kExportServerUrl),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: jsonEncode(exportData),
|
||||
);
|
||||
|
||||
if (response.statusCode != 200 && response.statusCode != 201) {
|
||||
// Silently fail - this is a non-critical background operation
|
||||
}
|
||||
} catch (_) {
|
||||
// Silently fail - this is a non-critical background operation
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<_ClosedTabExport>> _getAllClosedTabs() async {
|
||||
final tabQuery = database.select(database.closedTabs)
|
||||
..orderBy([(tab) => OrderingTerm.desc(tab.closedAt)]);
|
||||
|
||||
final tabRows = await tabQuery.get();
|
||||
|
||||
final result = <_ClosedTabExport>[];
|
||||
|
||||
for (final tabRow in tabRows) {
|
||||
final itemsQuery = database.select(database.closedTabItems)
|
||||
..where((item) => item.closedTabId.equals(tabRow.id));
|
||||
|
||||
final itemRows = await itemsQuery.get();
|
||||
|
||||
result.add(_ClosedTabExport(
|
||||
id: tabRow.id,
|
||||
originalTabId: tabRow.originalTabId,
|
||||
customerName: tabRow.customerName,
|
||||
closedAt: tabRow.closedAt.toIso8601String(),
|
||||
paymentMethod: tabRow.paymentMethod,
|
||||
items: itemRows.map((row) => _ClosedTabItemExport(
|
||||
productId: row.productId,
|
||||
productName: row.productName,
|
||||
quantity: row.quantity,
|
||||
unitPriceInCents: row.unitPriceInCents,
|
||||
)).toList(),
|
||||
));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<String, dynamic> _buildExportPayload(List<_ClosedTabExport> tabs) {
|
||||
return {
|
||||
'exportedAt': DateTime.now().toIso8601String(),
|
||||
'appVersion': '1.0.7',
|
||||
'closedTabs': tabs.map((tab) => {
|
||||
'id': tab.id,
|
||||
'originalTabId': tab.originalTabId,
|
||||
'customerName': tab.customerName,
|
||||
'closedAt': tab.closedAt,
|
||||
'paymentMethod': tab.paymentMethod,
|
||||
'items': tab.items.map((item) => {
|
||||
'productId': item.productId,
|
||||
'productName': item.productName,
|
||||
'quantity': item.quantity,
|
||||
'unitPriceInCents': item.unitPriceInCents,
|
||||
'lineTotalInCents': item.quantity * item.unitPriceInCents,
|
||||
}).toList(),
|
||||
'itemCount': tab.items.fold(0, (sum, item) => sum + item.quantity),
|
||||
'totalInCents': tab.items.fold(0, (sum, item) => sum + item.quantity * item.unitPriceInCents),
|
||||
}).toList(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class _ClosedTabItemExport {
|
||||
final String productId;
|
||||
final String productName;
|
||||
final int quantity;
|
||||
final int unitPriceInCents;
|
||||
|
||||
_ClosedTabItemExport({
|
||||
required this.productId,
|
||||
required this.productName,
|
||||
required this.quantity,
|
||||
required this.unitPriceInCents,
|
||||
});
|
||||
}
|
||||
|
||||
class _ClosedTabExport {
|
||||
final String id;
|
||||
final String originalTabId;
|
||||
final String customerName;
|
||||
final String closedAt;
|
||||
final String paymentMethod;
|
||||
final List<_ClosedTabItemExport> items;
|
||||
|
||||
_ClosedTabExport({
|
||||
required this.id,
|
||||
required this.originalTabId,
|
||||
required this.customerName,
|
||||
required this.closedAt,
|
||||
required this.paymentMethod,
|
||||
required this.items,
|
||||
});
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
const kUpdateServerUrl = 'https://updater.brammie15.dev';
|
||||
const kUpdateServerUrl = 'https://updater.brammie15.dev';
|
||||
const kExportServerUrl = 'https://your-server.com/api/backup';
|
||||
Reference in New Issue
Block a user