This commit is contained in:
Phuoc Nguyen
2025-10-10 16:38:07 +07:00
parent e5b247d622
commit b94c158004
177 changed files with 25080 additions and 152 deletions

637
docs/DATABASE_SCHEMA.md Normal file
View File

@@ -0,0 +1,637 @@
# Hive CE Database Schema Documentation
## Overview
This document describes the complete Hive CE database schema for the Retail POS application. The database uses Hive CE (Community Edition) for offline-first local storage with type-safe adapters.
---
## Database Structure
### Hive Boxes
The application uses 5 main Hive boxes:
| Box Name | Type | Purpose |
|----------|------|---------|
| `products` | `Box<ProductModel>` | Store all product data |
| `categories` | `Box<CategoryModel>` | Store all category data |
| `cart` | `Box<CartItemModel>` | Store current cart items |
| `transactions` | `Box<TransactionModel>` | Store completed transactions |
| `settings` | `Box<AppSettingsModel>` | Store app settings |
### Type ID Assignments (0-223)
| Model | Type ID | Description |
|-------|---------|-------------|
| `ProductModel` | 0 | Product entity |
| `CategoryModel` | 1 | Category entity |
| `CartItemModel` | 2 | Shopping cart item |
| `TransactionModel` | 3 | Completed transaction |
| `AppSettingsModel` | 4 | Application settings |
---
## Model Schemas
### 1. ProductModel (typeId: 0)
**File**: `lib/features/products/data/models/product_model.dart`
#### Fields
| Field | Type | HiveField | Description | Required |
|-------|------|-----------|-------------|----------|
| `id` | String | 0 | Unique product identifier (UUID) | Yes |
| `name` | String | 1 | Product name | Yes |
| `description` | String | 2 | Product description | Yes |
| `price` | double | 3 | Product price (USD) | Yes |
| `imageUrl` | String? | 4 | Product image URL | No |
| `categoryId` | String | 5 | Associated category ID | Yes |
| `stockQuantity` | int | 6 | Current stock quantity | Yes |
| `isAvailable` | bool | 7 | Availability status | Yes |
| `createdAt` | DateTime | 8 | Creation timestamp | Yes |
| `updatedAt` | DateTime | 9 | Last update timestamp | Yes |
#### Methods
- `copyWith()` - Create a copy with updated fields
- `toJson()` - Convert to JSON map
- `fromJson()` - Create from JSON map
- `toString()` - String representation
- Equality operators (==, hashCode)
#### Example
```dart
ProductModel(
id: 'prod_123',
name: 'Wireless Headphones',
description: 'Premium noise-cancelling wireless headphones',
price: 299.99,
imageUrl: 'https://example.com/image.jpg',
categoryId: 'cat_electronics',
stockQuantity: 25,
isAvailable: true,
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
)
```
---
### 2. CategoryModel (typeId: 1)
**File**: `lib/features/categories/data/models/category_model.dart`
#### Fields
| Field | Type | HiveField | Description | Required |
|-------|------|-----------|-------------|----------|
| `id` | String | 0 | Unique category identifier | Yes |
| `name` | String | 1 | Category name | Yes |
| `description` | String? | 2 | Category description | No |
| `iconPath` | String? | 3 | Icon path or Material icon name | No |
| `color` | String? | 4 | Hex color string (e.g., '#2196F3') | No |
| `productCount` | int | 5 | Number of products in category | Yes |
| `createdAt` | DateTime | 6 | Creation timestamp | Yes |
#### Methods
- `copyWith()` - Create a copy with updated fields
- `toJson()` - Convert to JSON map
- `fromJson()` - Create from JSON map
- `toString()` - String representation
- Equality operators (==, hashCode)
#### Example
```dart
CategoryModel(
id: 'cat_electronics',
name: 'Electronics',
description: 'Electronic devices and accessories',
iconPath: 'devices',
color: '#2196F3',
productCount: 15,
createdAt: DateTime.now(),
)
```
---
### 3. CartItemModel (typeId: 2)
**File**: `lib/features/home/data/models/cart_item_model.dart`
#### Fields
| Field | Type | HiveField | Description | Required |
|-------|------|-----------|-------------|----------|
| `productId` | String | 0 | Product identifier | Yes |
| `productName` | String | 1 | Product name (cached) | Yes |
| `price` | double | 2 | Price at time of adding | Yes |
| `quantity` | int | 3 | Quantity of items | Yes |
| `imageUrl` | String? | 4 | Product image URL (cached) | No |
| `addedAt` | DateTime | 5 | Timestamp when added | Yes |
#### Computed Properties
- `lineTotal` - Calculated as `price * quantity`
#### Methods
- `copyWith()` - Create a copy with updated fields
- `toJson()` - Convert to JSON map
- `fromJson()` - Create from JSON map
- `toString()` - String representation
- Equality operators (==, hashCode)
#### Example
```dart
CartItemModel(
productId: 'prod_123',
productName: 'Wireless Headphones',
price: 299.99,
quantity: 2,
imageUrl: 'https://example.com/image.jpg',
addedAt: DateTime.now(),
)
// lineTotal = 599.98
```
---
### 4. TransactionModel (typeId: 3)
**File**: `lib/features/home/data/models/transaction_model.dart`
#### Fields
| Field | Type | HiveField | Description | Required |
|-------|------|-----------|-------------|----------|
| `id` | String | 0 | Unique transaction identifier | Yes |
| `items` | List<CartItemModel> | 1 | List of cart items | Yes |
| `subtotal` | double | 2 | Subtotal (before tax/discount) | Yes |
| `tax` | double | 3 | Tax amount | Yes |
| `discount` | double | 4 | Discount amount | Yes |
| `total` | double | 5 | Total amount | Yes |
| `completedAt` | DateTime | 6 | Transaction completion time | Yes |
| `paymentMethod` | String | 7 | Payment method used | Yes |
#### Computed Properties
- `totalItems` - Total number of items in transaction
#### Methods
- `copyWith()` - Create a copy with updated fields
- `toJson()` - Convert to JSON map
- `fromJson()` - Create from JSON map
- `toString()` - String representation
- Equality operators (==, hashCode)
#### Example
```dart
TransactionModel(
id: 'txn_123',
items: [cartItem1, cartItem2],
subtotal: 599.98,
tax: 60.00,
discount: 0.00,
total: 659.98,
completedAt: DateTime.now(),
paymentMethod: 'cash',
)
```
---
### 5. AppSettingsModel (typeId: 4)
**File**: `lib/features/settings/data/models/app_settings_model.dart`
#### Fields
| Field | Type | HiveField | Description | Required |
|-------|------|-----------|-------------|----------|
| `themeModeString` | String | 0 | Theme mode ('light', 'dark', 'system') | Yes |
| `language` | String | 1 | Language code (e.g., 'en', 'es') | Yes |
| `currency` | String | 2 | Currency code (e.g., 'USD', 'EUR') | Yes |
| `taxRate` | double | 3 | Tax rate as decimal (e.g., 0.10 = 10%) | Yes |
| `storeName` | String | 4 | Store name | Yes |
| `enableSync` | bool | 5 | Enable automatic sync | Yes |
| `lastSyncAt` | DateTime? | 6 | Last sync timestamp | No |
#### Computed Properties
- `themeMode` - Returns `ThemeMode` enum from string
#### Factory Constructors
- `fromThemeMode()` - Create from ThemeMode enum
- `defaultSettings()` - Create with default values
#### Methods
- `copyWith()` - Create a copy with updated fields
- `toJson()` - Convert to JSON map
- `fromJson()` - Create from JSON map
- `toString()` - String representation
#### Example
```dart
AppSettingsModel(
themeModeString: 'system',
language: 'en',
currency: 'USD',
taxRate: 0.08,
storeName: 'My Retail Store',
enableSync: true,
lastSyncAt: DateTime.now(),
)
```
---
## Data Sources
### ProductLocalDataSource
**File**: `lib/features/products/data/datasources/product_local_datasource_hive.dart`
#### Methods
- `getAllProducts()` - Get all products
- `getProductById(id)` - Get product by ID
- `getProductsByCategory(categoryId)` - Get products by category
- `saveProducts(products)` - Bulk save products
- `saveProduct(product)` - Save single product
- `updateProduct(product)` - Update product
- `deleteProduct(id)` - Delete product
- `deleteAllProducts()` - Clear all products
- `productExists(id)` - Check if product exists
- `getAvailableProducts()` - Get available products only
- `getLowStockProducts(threshold)` - Get low stock products
- `searchProducts(query)` - Search products by name/description
### CategoryLocalDataSource
**File**: `lib/features/categories/data/datasources/category_local_datasource_hive.dart`
#### Methods
- `getAllCategories()` - Get all categories
- `getCategoryById(id)` - Get category by ID
- `saveCategories(categories)` - Bulk save categories
- `saveCategory(category)` - Save single category
- `updateCategory(category)` - Update category
- `deleteCategory(id)` - Delete category
- `deleteAllCategories()` - Clear all categories
- `categoryExists(id)` - Check if category exists
- `updateProductCount(categoryId, count)` - Update product count
### CartLocalDataSource
**File**: `lib/features/home/data/datasources/cart_local_datasource.dart`
#### Cart Methods
- `getCartItems()` - Get all cart items
- `getCartItem(productId)` - Get specific cart item
- `addToCart(item)` - Add item to cart
- `updateCartItem(item)` - Update cart item
- `removeFromCart(productId)` - Remove from cart
- `clearCart()` - Clear entire cart
- `isInCart(productId)` - Check if item is in cart
- `getCartTotal()` - Calculate cart total
- `getCartItemCount()` - Get total item count
#### Transaction Methods
- `saveTransaction(transaction)` - Save completed transaction
- `getAllTransactions()` - Get all transactions
- `getTransaction(id)` - Get transaction by ID
- `getTransactionsByDateRange(start, end)` - Get transactions by date
- `getTodayTransactions()` - Get today's transactions
- `getTotalSales(start, end)` - Calculate total sales
- `getTodaySales()` - Calculate today's sales
- `deleteTransaction(id)` - Delete transaction
- `clearAllTransactions()` - Clear all transactions
- `getTransactionCount()` - Get transaction count
### SettingsLocalDataSource
**File**: `lib/features/settings/data/datasources/settings_local_datasource_hive.dart`
#### Methods
- `getSettings()` - Get current settings
- `saveSettings(settings)` - Save settings
- `updateThemeMode(mode)` - Update theme mode
- `updateLanguage(language)` - Update language
- `updateLastSyncTime(time)` - Update last sync time
- `updateCurrency(currency)` - Update currency
- `updateTaxRate(taxRate)` - Update tax rate
- `updateStoreName(storeName)` - Update store name
- `toggleSync(enable)` - Toggle sync on/off
- `resetSettings()` - Reset to defaults
---
## Database Initialization
### HiveDatabase
**File**: `lib/core/database/hive_database.dart`
Singleton class managing all Hive boxes and operations.
#### Methods
- `init()` - Initialize Hive and open all boxes
- `getBox<T>(boxName)` - Get a specific box
- `clearAllData()` - Clear all data (except settings)
- `clearCart()` - Clear cart only
- `compactAll()` - Compact all boxes (optimize storage)
- `closeAll()` - Close all boxes
- `deleteAll()` - Delete all boxes (complete reset)
- `getStatistics()` - Get database statistics
- `isInitialized` - Check initialization status
#### Properties
- `productsBox` - Direct access to products box
- `categoriesBox` - Direct access to categories box
- `cartBox` - Direct access to cart box
- `transactionsBox` - Direct access to transactions box
- `settingsBox` - Direct access to settings box
### DatabaseInitializer
**File**: `lib/core/database/database_initializer.dart`
Handles database initialization and seeding.
#### Methods
- `initialize(seedIfEmpty)` - Initialize database and seed if empty
- `seedDatabase(forceReseed)` - Seed database with sample data
- `resetDatabase()` - Clear and reseed database
- `getDatabaseStats()` - Get database statistics
- `compactDatabase()` - Compact database
---
## Sample Data
### Generated Categories (5)
1. **Electronics** - Blue (#2196F3)
- Icon: `devices`
2. **Home Appliances** - Green (#4CAF50)
- Icon: `kitchen`
3. **Sports & Fitness** - Orange (#FF9800)
- Icon: `fitness_center`
4. **Fashion** - Pink (#E91E63)
- Icon: `checkroom`
5. **Books & Media** - Purple (#9C27B0)
- Icon: `book`
### Generated Products (10)
1. Wireless Headphones - $299.99 (Electronics)
2. Smart Watch - $199.99 (Electronics)
3. Laptop Stand - $39.99 (Electronics)
4. Coffee Maker - $79.99 (Appliances)
5. Blender - $59.99 (Appliances)
6. Yoga Mat - $29.99 (Sports)
7. Running Shoes - $89.99 (Sports)
8. Water Bottle - $24.99 (Sports)
9. Leather Backpack - $129.99 (Fashion)
10. Sunglasses - $49.99 (Fashion)
---
## Usage Examples
### Initialize Database
```dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final database = HiveDatabase.instance;
final initializer = DatabaseInitializer(database);
await initializer.initialize(seedIfEmpty: true);
runApp(MyApp());
}
```
### Query Products
```dart
final dataSource = ProductLocalDataSourceHive(HiveDatabase.instance);
// Get all products
final products = await dataSource.getAllProducts();
// Get by category
final electronics = await dataSource.getProductsByCategory('cat_electronics');
// Search products
final results = await dataSource.searchProducts('headphones');
// Get low stock
final lowStock = await dataSource.getLowStockProducts(10);
```
### Manage Cart
```dart
final dataSource = CartLocalDataSource(HiveDatabase.instance);
// Add to cart
await dataSource.addToCart(CartItemModel(
productId: 'prod_123',
productName: 'Wireless Headphones',
price: 299.99,
quantity: 1,
addedAt: DateTime.now(),
));
// Get cart total
final total = await dataSource.getCartTotal();
// Clear cart
await dataSource.clearCart();
```
### Save Transaction
```dart
final dataSource = CartLocalDataSource(HiveDatabase.instance);
await dataSource.saveTransaction(TransactionModel(
id: Uuid().v4(),
items: cartItems,
subtotal: 599.98,
tax: 48.00,
discount: 0.0,
total: 647.98,
completedAt: DateTime.now(),
paymentMethod: 'cash',
));
```
### Update Settings
```dart
final dataSource = SettingsLocalDataSourceHive(HiveDatabase.instance);
// Update theme
await dataSource.updateThemeMode(ThemeMode.dark);
// Update tax rate
await dataSource.updateTaxRate(0.10); // 10%
// Get settings
final settings = await dataSource.getSettings();
```
---
## Code Generation
To generate Hive type adapters after modifying models:
```bash
flutter pub run build_runner build --delete-conflicting-outputs
```
---
## File Locations
```
lib/
core/
constants/
storage_constants.dart # Box names and type IDs
database/
hive_database.dart # Main database class
database_initializer.dart # Initialization logic
seed_data.dart # Sample data generator
features/
products/data/
models/product_model.dart # Product model + adapter
datasources/
product_local_datasource.dart # Interface
product_local_datasource_hive.dart # Hive implementation
categories/data/
models/category_model.dart # Category model + adapter
datasources/
category_local_datasource.dart # Interface
category_local_datasource_hive.dart # Hive implementation
home/data/
models/
cart_item_model.dart # Cart item model + adapter
transaction_model.dart # Transaction model + adapter
datasources/
cart_local_datasource.dart # Cart & transaction operations
settings/data/
models/app_settings_model.dart # Settings model + adapter
datasources/
settings_local_datasource.dart # Interface
settings_local_datasource_hive.dart # Hive implementation
```
---
## Database Statistics
Use `getDatabaseStats()` to monitor database usage:
```dart
final stats = HiveDatabase.instance.getStatistics();
print(stats);
// Output:
// {
// 'products': 10,
// 'categories': 5,
// 'cartItems': 0,
// 'transactions': 0,
// 'isInitialized': true
// }
```
---
## Maintenance
### Compact Database
Optimize storage and improve performance:
```dart
await HiveDatabase.instance.compactAll();
```
### Reset Database
Clear all data and reseed:
```dart
final initializer = DatabaseInitializer(HiveDatabase.instance);
await initializer.resetDatabase();
```
### Clear Specific Data
```dart
// Clear cart only
await HiveDatabase.instance.clearCart();
// Clear all data except settings
await HiveDatabase.instance.clearAllData();
```
---
## Best Practices
1. **Type Safety**: Always use type-safe boxes (`Box<T>`)
2. **Key Strategy**: Use string IDs as keys for easy lookup
3. **Bulk Operations**: Use `putAll()` for multiple items
4. **Error Handling**: Wrap all operations in try-catch blocks
5. **Compaction**: Regularly compact boxes in production
6. **Backups**: Implement backup strategy for transactions
7. **Migration**: Plan for schema migrations as app evolves
8. **Testing**: Test all database operations thoroughly
---
## Performance Considerations
- **Products Box**: ~10-1000 items expected
- **Categories Box**: ~5-50 items expected
- **Cart Box**: ~0-20 items expected
- **Transactions Box**: Growing over time (consider archiving)
- **Settings Box**: Single item only
### Optimization Tips
- Use lazy boxes for large datasets
- Implement pagination for transaction history
- Clear old transactions periodically
- Cache frequently accessed queries
- Use RepaintBoundary for grid items
---
## Security Notes
- Sensitive data (prices, transactions) stored unencrypted
- Consider using `HiveAesCipher` for encryption if needed
- Validate all data before storage
- Implement proper access controls in production
- Never expose raw Hive boxes to UI layer
---
## Migration Strategy
When schema changes are needed:
1. Increment type IDs or use versioning
2. Create migration scripts
3. Test migration thoroughly
4. Backup data before migration
5. Provide rollback mechanism
Example migration:
```dart
Future<void> migrateToV2() async {
final versionBox = await Hive.openBox('version');
final currentVersion = versionBox.get('schema_version', defaultValue: 1);
if (currentVersion < 2) {
// Perform migration
// Update schema version
await versionBox.put('schema_version', 2);
}
}
```
---
**Last Updated**: 2025-10-10
**Schema Version**: 1.0.0
**Hive CE Version**: 2.6.0