diff --git a/README.md b/README.md
index 22bf17d..b01d01a 100644
--- a/README.md
+++ b/README.md
@@ -90,7 +90,7 @@
| 機能 | ファイル | 状態 |
|------|---------|----|
-| **見積入力** | `lib/screens/estimate_screen.dart` | ✅ 完了(エラーハンドリング追加)
- 得意先選択・商品追加
- DatabaseHelper を介した保存
- エラーハンドリング完全化
📝 次のステップ:PDF 帳票出力テンプレート実装
+| **見積入力** | `lib/screens/estimate_screen.dart` | ✅ 完了(エラーハンドリング追加)
- 得意先選択・商品追加
- DatabaseHelper を介した保存
- エラーハンドリング完全化
📝 次のステップ:売上入力画面実装
| DB CRUD API | `lib/services/database_helper.dart` | ✅ Estimate テーブル対応
・insertEstimate
・getEstimates
・estimate CRUD |
| Estimate モデル | `lib/models/estimate.dart` | ✅ LineItem ネスト構造
・toMap/fromMap 実装 |
diff --git a/lib/models/sale.dart b/lib/models/sale.dart
new file mode 100644
index 0000000..82ec412
--- /dev/null
+++ b/lib/models/sale.dart
@@ -0,0 +1,73 @@
+// Version: 1.1 (売上モデル実装)
+import 'dart:convert';
+
+class Sale {
+ int? id;
+ String? saleNo;
+ String customerName;
+ DateTime date;
+ double totalAmount;
+ double taxRate;
+ Map? items; // LineItem ネスト構造
+ DateTime createdAt;
+ DateTime updatedAt;
+
+ Sale({
+ this.id,
+ this.saleNo,
+ required this.customerName,
+ required this.date,
+ required this.totalAmount,
+ this.taxRate = 10,
+ this.items,
+ DateTime? createdAt,
+ DateTime? updatedAt,
+ }) : createdAt = createdAt ?? DateTime.now(),
+ updatedAt = updatedAt ?? DateTime.now();
+
+ Map toMap() {
+ return {
+ 'id': id,
+ 'sale_no': saleNo,
+ 'customer_name': customerName,
+ 'date': date.toIso8601String(),
+ 'total_amount': totalAmount,
+ 'tax_rate': taxRate,
+ 'items': items,
+ 'created_at': createdAt.toIso8601String(),
+ 'updated_at': updatedAt.toIso8601String(),
+ };
+ }
+
+ factory Sale.fromMap(Map map) {
+ return Sale(
+ id: map['id'] as int?,
+ saleNo: map['sale_no'] as String?,
+ customerName: map['customer_name'] as String,
+ date: DateTime.parse(map['date'] as String),
+ totalAmount: (map['total_amount'] as num).toDouble(),
+ taxRate: map['tax_rate'] as double? ?? 10,
+ items: map['items'] as Map? ,
+ createdAt: map['created_at'] != null ? DateTime.parse(map['created_at']) : DateTime.now(),
+ updatedAt: map['updated_at'] != null ? DateTime.parse(map['updated_at']) : DateTime.now(),
+ );
+ }
+
+ String toJson() => json.encode(toMap());
+
+ factory Sale.fromJson(String source) => Sale.fromMap(json.decode(source) as Map);
+
+ @override
+ String toString() {
+ return 'Sale(id: $id, saleNo: $saleNo, customerName: $customerName, date: $date, totalAmount: $totalAmount, taxRate: $taxRate, items: $items)';
+ }
+
+ @override
+ bool operator ==(covariant Sale other) {
+ if (identical(this, other)) return true;
+ return other.id == id && other.saleNo == saleNo;
+ }
+
+ @override
+ int get hashCode => id ^ saleNo;
+}
\ No newline at end of file
diff --git a/lib/services/database_helper.dart b/lib/services/database_helper.dart
index cb1c44b..5b3f42f 100644
--- a/lib/services/database_helper.dart
+++ b/lib/services/database_helper.dart
@@ -108,6 +108,22 @@ class DatabaseHelper {
)
''');
+ // sales テーブル(売用书)
+ await db.execute('''
+ CREATE TABLE sales (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ sale_no TEXT NOT NULL UNIQUE,
+ customer_id INTEGER,
+ customer_name TEXT NOT NULL,
+ date TEXT NOT NULL,
+ total_amount REAL NOT NULL,
+ tax_rate REAL DEFAULT 10,
+ items_json TEXT NOT NULL,
+ created_at TEXT NOT NULL,
+ updated_at TEXT NOT NULL
+ )
+ ''');
+
// customer_snapshots テーブル(イベントソーシング用)
await db.execute('''
CREATE TABLE customer_snapshots (