ollama/gpt-oss:20bにスイッチ

This commit is contained in:
user 2026-02-08 10:55:57 +09:00
parent 37f66413fe
commit 4f9c24c1a2
4 changed files with 148 additions and 6 deletions

View file

@ -4,6 +4,9 @@ A new Flutter project.
## Getting Started
!! 日本語が主体のアプリです。アプリの基本言語は日本語です。コメントも日本語と英語併記です。!!
!! 可読性は重視しません。AIの開発効率を最大に上げて下さい。!!
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
@ -14,3 +17,28 @@ A few resources to get you started if this is your first Flutter project:
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
## 販売アシスト1号の機能
販売アシスト1号は、営業マンの販売業務を支援するためのアプリケーションです。主な機能は以下の通りです。
- ファイル名の規則 "{date}({請求等}){顧客名}_{件名}_{金額カンマ付}円_{sha256}" 20251202(請求)佐々木製作所_あの件_20,000円_25ab85cc9988
- 伝票(件名)の管理
- 管理ではファイルの様にオブジェクトとして管理します。
- 顧客マスター管理
- 商品マスター管理
- 見積納品請求領収証の作成
- 見積納品請求領収証の一覧表示
- 見積納品請求領収証のPDF出力
- PDFの管理
- GPSと顧客マスターを連携し座標の履歴を記録する機能
- フォーム入力時にGPS情報で自動的に顧客マスターから候補を選出する機能
- 入力時にQRコードやOCRをGoogleレンズを使ってアシストします
- レシート印刷するポータブルプリンタを使って領収証印刷する機能
- 印刷時にQRコードを印刷する機能
- Googleドライブにバックアップする機能
- 未来の機能(今は実装しない可能にしておく)odooとの同期・連携 伝票単位で同期
アプリの基本言語は日本語です。コメントも日本語と英語併記です。可読性は重視しません。AIの開発効率を最大に上げるものです。
表示言語は日本語です。環境により英語を表示する機能は未来に実装予定です。
見積・納品・請求・領収証はフォームがほぼ同じですが、項目が時間と共に変化するので件名が同じでも明細は異なる場合があります。
伝票はsqliteで管理します。

View file

@ -1,6 +1,7 @@
// lib/main.dart
// version: 1.4.3c (Bug Fix: PDF layout error) - Refactored for modularity
import 'package:flutter/material.dart';
import 'screens/pdf_list_screen.dart'; // PDF一覧画面
// --- ---
import 'models/invoice_models.dart'; // Invoice, InvoiceItem
@ -60,6 +61,20 @@ class _InvoiceFlowScreenState extends State<InvoiceFlowScreen> {
appBar: AppBar(
title: const Text("販売アシスト1号 V1.4.3c"),
backgroundColor: Colors.blueGrey,
actions: [
IconButton(
icon: const Icon(Icons.picture_as_pdf),
tooltip: 'PDF一覧',
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const PdfListScreen(),
),
);
},
),
],
),
//
body: InvoiceInputForm(

View file

@ -0,0 +1,99 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:open_filex/open_filex.dart';
class PdfListScreen extends StatefulWidget {
const PdfListScreen({super.key});
@override
State<PdfListScreen> createState() => _PdfListScreenState();
}
class _PdfListScreenState extends State<PdfListScreen> {
List<FileSystemEntity> _pdfFiles = [];
bool _loading = true;
@override
void initState() {
super.initState();
_fetchPdfFiles();
}
Future<void> _fetchPdfFiles() async {
// Request storage permission
final status = await Permission.storage.request();
if (!status.isGranted) {
setState(() {
_loading = false;
});
return;
}
// Prefer to look in the Downloads folder if available
Directory? downloadsDir;
if (Platform.isAndroid) {
downloadsDir = await getExternalStorageDirectory();
// The Downloads folder may be a subdirectory; adjust as needed
if (downloadsDir != null) {
downloadsDir = Directory('${downloadsDir.path}/Download');
}
} else if (Platform.isIOS) {
downloadsDir = await getApplicationDocumentsDirectory();
} else {
downloadsDir = await getApplicationDocumentsDirectory();
}
if (downloadsDir == null || !await downloadsDir.exists()) {
setState(() {
_loading = false;
});
return;
}
final files = downloadsDir
.listSync()
.where((f) => f.path.toLowerCase().endsWith('.pdf'))
.toList();
setState(() {
_pdfFiles = files;
_loading = false;
});
}
void _openFile(FileSystemEntity file) async {
final result = await OpenFilex.open(file.path);
if (result.type != ResultType.success) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Could not open ${file.path}')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('PDF ファイル一覧'),
),
body: _loading
? const Center(child: CircularProgressIndicator())
: _pdfFiles.isEmpty
? const Center(child: Text('PDF ファイルが見つかりません。'))
: ListView.builder(
itemCount: _pdfFiles.length,
itemBuilder: (context, index) {
final file = _pdfFiles[index];
final fileName = file.path.split(Platform.pathSeparator).last;
return ListTile(
leading: const Icon(Icons.picture_as_pdf),
title: Text(fileName),
onTap: () => _openFile(file),
);
},
),
);
}
}

View file

@ -172,10 +172,10 @@ packages:
dependency: transitive
description:
name: hooks
sha256: "5d309c86e7ce34cd8e37aa71cb30cb652d3829b900ab145e4d9da564b31d59f7"
sha256: "7a08a0d684cb3b8fb604b78455d5d352f502b68079f7b80b831c62220ab0a4f6"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
version: "1.0.1"
image:
dependency: transitive
description:
@ -276,10 +276,10 @@ packages:
dependency: transitive
description:
name: objective_c
sha256: "983c7fa1501f6dcc0cb7af4e42072e9993cb28d73604d25ebf4dab08165d997e"
sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52"
url: "https://pub.dev"
source: hosted
version: "9.2.5"
version: "9.3.0"
open_filex:
dependency: "direct main"
description:
@ -481,10 +481,10 @@ packages:
dependency: transitive
description:
name: source_span
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
url: "https://pub.dev"
source: hosted
version: "1.10.1"
version: "1.10.2"
stack_trace:
dependency: transitive
description: