h-1.flutter.4/docs/project_specification.md

12 KiB
Raw Permalink Blame History

制作小プロジェクト - 企画設計指示書

1. プロジェクト概要

1.1 目的

リッチなマスター編集機能を持つ販売アシスタントアプリを効率的に開発するための、AILLMによる自動コーディングを支援する企画設計指示書。

1.2 スコープ

  • マスターデータの CRUD 機能強化
  • リッチな入力フィールド(画像/動画アップロード、QR コード生成)
  • フォームバリデーションとヒント表示
  • 汎用ウィジェットによるコード削減

2. コンテンツ定義

2.1 データモデル一覧

Customer得意先

プロパティ タイプ キー ビルンール ヒント
id int? PK autoincrement -
name String UK not null, max 50 例:株式会社〇〇、個人名で可
email String unique, nullable, max 100 メールアドレス形式(*@example.com
phone String nullable, max 20 電話番号区切りなし090-1234-5678→09012345678
address String nullable, max 200 住所(省スペース表示・多言語対応)
created_at DateTime? - null allow DB レコード作成時

Product商品

プロパティ タイプ キー ビルンール ヒント
id int? PK autoincrement -
name String UK not null, max 50 iPhone、ートパソコンなど
price double? - null allow 円単位(小数点以下 2 桁)
stock int? - null allow 在庫数
description String - nullable, max 500 商品の説明・特徴
created_at DateTime? - null allow DB レコード作成時

Supplier仕入先

プロパティ タイプ キー ビルンール ヒント
id int? PK autoincrement -
name String UK not null, max 50 例:株式会社〇〇、個人名で可
email String unique, nullable, max 100 メールアドレス形式(*@example.com
phone String nullable, max 20 電話番号(区切りなし)
address String nullable, max 200 住所
created_at DateTime? - null allow DB レコード作成時

Warehouse倉庫

プロパティ タイプ キー ビルンール ヒント
id int? PK autoincrement -
name String UK not null, max 50 例:東京都千代田区〇丁目倉庫、大阪支店倉庫
address String nullable, max 200 住所
capacity int? - null allow 保管容量(単位:坪)
created_at DateTime? - null allow DB レコード作成時

Employee担当者

プロパティ タイプ キー ビルンール ヒント
id int? PK autoincrement -
name String UK not null, max 50 例:田中太郎、鈴木花子
email String unique, nullable, max 100 メールアドレス形式(*@example.com
phone String nullable, max 20 電話番号(区切りなし)
role String - nullable, max 30 例:管理者、営業、倉庫員など
created_at DateTime? - null allow DB レコード作成時

3. UI コンポーネント定義

3.1 汎用ウィジェット一覧

RichMasterTextFieldテキスト入力

RichMasterTextField(
  label: '商品名',
  initialValue: 'iPhone',
  hintText: '例iPhone、ートパソコンなど',
  maxLines: 1,
)

RichMasterNumberField数値入力

RichMasterNumberField(
  label: '価格',
  initialValue: 128000.0,
  hintText: '例128,000円、98,500 円など',
  decimalDigits: 2,
)

RichMasterDateField日付選択

RichMasterDateField(
  label: '作成日',
  initialValue: DateTime.now(),
  hintText: '例2024/03/10、今日などの指定可',
)

RichMasterAddressField住所入力・省スペース

RichMasterAddressField(
  label: '住所',
  initialValue: '東京都千代田区〇丁目 1-1',
  hintText: '例:都道府県名から検索可',
)

RichMasterFileUploaderファイル・画像アップロード

RichMasterFileUploader(
  label: '商品画像',
  onPickImage: () => print('画像選択'),
  onPickVideo: () => print('動画選択'), // Android 限定
)

RichMasterQRCodeGeneratorQR コード生成)

RichMasterQRCodeGenerator(
  label: 'QR コード',
  text: 'https://example.com/product/123',
)

RichMasterCheckboxFieldチェックボックス

RichMasterCheckboxField(
  label: '在庫あり',
  initialValue: true,
  onChanged: (value) => print(value),
)

RichMasterDropdownFieldドロップダウンリスト

RichMasterDropdownField<String>(
  label: '担当部署',
  initialValue: '営業部',
  items: ['営業部', '総務部', '開発部'],
  itemToString: (item) => item,
)

3.2 アプリバーAppBar定義

ID 名乘
/S1. 見積書 Sales - Estimate
/S2. 請求書 Sales - Invoice
/S3. 受発注一覧 Order List
/S4. 売上入力(レジ) Sales Register
/S5. 売上返品入力 Return Input
/M1. 商品マスタ Master - Product
/M2. 得意先マスタ Master - Customer
/M3. 仕入先マスタ Master - Supplier
/M4. 倉庫マスタ Master - Warehouse
/M5. 担当者マスタ Master - Employee

4. ビヘイビア仕様

4.1 フォームバリデーション

  • 必須フィールド: 空文字の場合は赤いエラー表示 + ヒント文の再表示
  • メール形式検証: *@example.com の形式のみ許可(正規表現:^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$
  • 電話番号検証: 数字のみ、最大 11 桁まで許可
  • 数値フィールド: 小数点以下指定桁数を超える入力時の自動補正

4.2 ヒント・エラー表示

// エラー状態
TextField(
  errorText: hintText, // 初期値がヒントとなる
)

// カスタムエラー
TextField(
  decoration: InputDecoration(errorText: '必須入力をしてください'),
)

4.3 ショートカットキー対応(オプション)

RichMasterShortcutSettings(
  label: '編集ヘルプ',
  showShortcuts: true,
  shortcuts: {
    'Ctrl+S': () => print('保存'),
    'Ctrl+Z': () => print('取り消し'),
  },
)

4.4 セクション分割表示

RichMasterSectionHeader(
  title: '基本情報',
  icon: Icons.info_outline,
  color: Colors.blue.shade700,
)

5. コーディングワークフロー

5.1 マスタ画面作成手順

ステップ 1: モデル定義

// lib/models/customer.dart
class Customer {
  int? id;
  String name = '';
  String? email;
  String? phone;
  String? address;
  DateTime? createdAt;

  Customer({
    this.id,
    required this.name,
    this.email,
    this.phone,
    this.address,
    this.createdAt,
  });

  factory Customer.fromJson(Map<String, dynamic> json) => Customer(
    id: json['id'] as int?,
    name: json['name'] as String,
    email: json['email'] as String?,
    phone: json['phone'] as String?,
    address: json['address'] as String?,
    createdAt: json['created_at'] != null ? DateTime.parse(json['created_at']) : null,
  );

  Map<String, dynamic> toJson() => {
    'id': id,
    'name': name,
    'email': email,
    'phone': phone,
    'address': address,
    'created_at': createdAt?.toIso8601String(),
  };

  Customer copyWith({
    int? id,
    String? name,
    String? email,
    String? phone,
    String? address,
    DateTime? createdAt,
  }) => Customer(
    id: id ?? this.id,
    name: name ?? this.name,
    email: email ?? this.email,
    phone: phone ?? this.phone,
    address: address ?? this.address,
    createdAt: createdAt ?? this.createdAt,
  );
}

ステップ 2: スクリーン定義master_edit_fields.dart を使用)

// lib/screens/master/customer_master_screen.dart
class CustomerMasterScreen extends StatefulWidget {
  const CustomerMasterScreen({super.key});

  @override
  State<CustomerMasterScreen> createState() => _CustomerMasterScreenState();
}

class _CustomerMasterScreenState extends State<CustomerMasterScreen> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  // データモデル(データベース連携)
  late Customer _customer;

  @override
  void initState() {
    super.initState();
    _customer = Customer(name: ''); // 初期値設定
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('/M2. 得意先マスタ')),
      body: Form(
        key: _formKey,
        child: ListView(
          children: [
            // RichMasterTextField商品名
            RichMasterTextField(
              label: '得意先名',
              initialValue: _customer.name,
              hintText: '例:株式会社〇〇、個人名で可',
              onChanged: (value) => setState(() => _customer.name = value),
            ),

            // RichMasterTextFieldメール
            RichMasterTextField(
              label: 'メールアドレス',
              initialValue: _customer.email,
              keyboardType: TextInputType.emailAddress,
              hintText: '@example.com の形式info@example.com',
              onChanged: (value) => setState(() => _customer.email = value),
            ),

            // RichMasterNumberField電話番号
            RichMasterTextField(
              label: '電話番号',
              initialValue: _customer.phone,
              hintText: '例090-1234-5678、区切り不要',
              onChanged: (value) => setState(() => _customer.phone = value),
            ),

            // RichMasterDateField作成日
            RichMasterDateField(
              label: '登録日',
              initialValue: _customer.createdAt?.toLocal(),
              hintText: '例2024/03/10、今日などの指定可',
            ),

            // 保存ボタン
            SizedBox(
              width: double.infinity,
              child: ElevatedButton(
                onPressed: () => Navigator.pop(context, _customer.toJson()),
                child: Text('保存'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

5.2 汎用マスター作成テンプレートAI 生成用)

AI に自動生成させるためのプロンプト例:

以下のデータモデルでマスター画面を作成してください:

- データモデル: {model_definition}
- スクリーン ID: {screen_id, e.g., /M3. 仕入先マスタ}
- 使用ウィジェット: RichMasterTextField, RichMasterNumberField, RichMasterDateField などmaster_edit_fields.dart を参照)

要件:
1. AppBar に「{screen_id}」を表示
2. フォームキーでバリデーションを行う
3. 保存ボタンでデータを JSON 形式で返す
4. 必須フィールドは空文字をエラー扱いに

6. テスト用データ

6.1 Customer得意先テストデータ

{
  "name": "株式会社 ABC",
  "email": "info@abc-company.com",
  "phone": "03-1234-5678",
  "address": "東京都千代田区〇丁目 1-1"
}

6.2 Product商品テストデータ

{
  "name": "iPhone 15 Pro Max",
  "price": 199440.0,
  "description": "チタニウム素材の高級スマートフォン。A17 Pro チップ搭載。"
}

6.3 Warehouse倉庫テストデータ

{
  "name": "東京都千代田区支店倉庫",
  "address": "東京都千代田区〇丁目 1-1",
  "capacity": 50
}

7. まとめ

この指示書を使用することで、以下が可能になります:

  1. AI による自動コーディング: データモデルから画面コードを生成
  2. 一貫性のある UI: 汎用ウィジェットでデザイン統一
  3. 保守性の向上: 部品レベルでの再利用・修正
  4. 開発効率化: テンプレートベースの迅速な実装

この指示書を元に、LLMGPT-4 など)に自動コーディングを依頼するか、自前で実装を進めてください。