third commit

This commit is contained in:
2026-07-31 17:06:52 +05:30
parent d9886880cc
commit 9891a69a5f
32 changed files with 2083 additions and 557 deletions

View File

@@ -1,5 +1,3 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:path/path.dart' as p;
import 'package:sqflite/sqflite.dart';
@@ -16,7 +14,7 @@ class AppDatabase {
static final AppDatabase instance = AppDatabase._();
static const String _fileName = 'nearle_pos.db';
static const int _version = 1;
static const int _version = 3;
Database? _db;
@@ -37,7 +35,21 @@ class AppDatabase {
Future<void> open({String? overridePath}) async {
if (_db != null) return;
if (!kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS)) {
if (kIsWeb) {
// sqflite has no web implementation. Fail loudly here rather than
// letting databaseFactory throw something unreadable further down.
throw UnsupportedError(
'Nearle POS stores bills in SQLite, which has no web implementation. '
'Run the app on macOS, Windows, Linux or an Android tablet.',
);
}
const desktop = {
TargetPlatform.windows,
TargetPlatform.linux,
TargetPlatform.macOS,
};
if (desktop.contains(defaultTargetPlatform)) {
sqfliteFfiInit();
databaseFactory = databaseFactoryFfi;
}
@@ -52,7 +64,12 @@ class AppDatabase {
onConfigure: (db) => db.execute('PRAGMA foreign_keys = ON'),
onCreate: (db, version) async => _createSchema(db),
onUpgrade: (db, from, to) async {
// Single version so far; migrations land here as the schema grows.
if (from < 2) await db.execute(_createDayArchive);
if (from < 3) {
await db.execute(
'ALTER TABLE ${Tables.products} ADD COLUMN hsn_code TEXT',
);
}
},
),
);
@@ -84,6 +101,7 @@ class AppDatabase {
for (final t in const [
Tables.orderItems,
Tables.orders,
Tables.dayArchive,
Tables.products,
Tables.customers,
Tables.parkedBills,
@@ -111,6 +129,7 @@ class AppDatabase {
image_url TEXT,
unit TEXT NOT NULL DEFAULT 'piece',
gst_rate REAL NOT NULL DEFAULT 0.18,
hsn_code TEXT,
brand TEXT,
is_active INTEGER NOT NULL DEFAULT 1,
updated_at INTEGER NOT NULL
@@ -232,6 +251,9 @@ class AppDatabase {
)
''');
// ------------------------------------------------------------- archive
await db.execute(_createDayArchive);
// ----------------------------------------------------------------- meta
await db.execute('''
CREATE TABLE ${Tables.meta} (
@@ -242,9 +264,34 @@ class AppDatabase {
}
}
/// Running totals per business day.
///
/// Synced orders are deleted from the terminal, so their figures are folded in
/// here first — otherwise "Bills Today" would collapse to zero the moment a
/// mid-shift sync ran.
const String _createDayArchive = '''
CREATE TABLE day_archive (
business_date TEXT PRIMARY KEY,
bill_count INTEGER NOT NULL DEFAULT 0,
item_count REAL NOT NULL DEFAULT 0,
gross_sales REAL NOT NULL DEFAULT 0,
tax_collected REAL NOT NULL DEFAULT 0,
discount_given REAL NOT NULL DEFAULT 0,
round_off REAL NOT NULL DEFAULT 0,
points_issued INTEGER NOT NULL DEFAULT 0,
points_redeemed INTEGER NOT NULL DEFAULT 0,
payments_json TEXT NOT NULL DEFAULT '{}',
first_bill_at INTEGER,
last_bill_at INTEGER,
synced_bills INTEGER NOT NULL DEFAULT 0
)
''';
class Tables {
const Tables._();
static const String dayArchive = 'day_archive';
static const String products = 'products';
static const String customers = 'customers';
static const String orders = 'orders';
@@ -260,4 +307,11 @@ class MetaKeys {
static const String lastImportAt = 'last_import_at';
static const String catalogueRevision = 'catalogue_revision';
static const String invoiceSequence = 'invoice_sequence';
/// Printer chosen in Settings. Stored as the printer's `url`, which is what
/// `Printing.directPrintPdf` needs to target it without a dialog.
static const String printerUrl = 'printer_url';
static const String printerName = 'printer_name';
static const String autoPrint = 'auto_print';
static const String openDrawer = 'open_cash_drawer';
}