顧客参照長押しで編集

This commit is contained in:
joe 2026-02-23 20:22:18 +09:00
parent ba04a77062
commit 50aa460064
2 changed files with 74 additions and 64 deletions

131
main.py
View file

@ -1169,7 +1169,7 @@ class FlutterStyleDashboard:
min_lines=2,
max_lines=3,
)
def toggle_edit_mode(_):
"""編集モード切替"""
old_mode = getattr(self, 'is_detail_edit_mode', False)
@ -1190,15 +1190,7 @@ class FlutterStyleDashboard:
validation = validate_invoice_items(normalized_items)
if not validation.ok:
logging.warning(f"伝票保存バリデーションエラー: {validation.errors}")
try:
self.page.snack_bar = ft.SnackBar(
content=ft.Text(validation.errors[0]),
bgcolor=ft.Colors.RED_600,
)
self.page.snack_bar.open = True
self.page.update()
except Exception:
pass
self._show_snack(validation.errors[0], ft.Colors.RED_600)
return
self.editing_invoice.items = normalized_items
@ -1249,11 +1241,7 @@ class FlutterStyleDashboard:
if success:
save_succeeded = True
logging.info(f"伝票作成成功: {self.editing_invoice.invoice_number}")
self.page.snack_bar = ft.SnackBar(
content=ft.Text("伝票を保存しました"),
bgcolor=ft.Colors.GREEN_600,
)
self.page.snack_bar.open = True
self._show_snack("伝票を保存しました", ft.Colors.GREEN_600)
# 一覧を更新して新規作成画面を閉じる
self.invoices = self.app_service.invoice.get_recent_invoices(20)
logging.info(f"更新後伝票件数: {len(self.invoices)}")
@ -1262,12 +1250,7 @@ class FlutterStyleDashboard:
self.update_main_content()
else:
logging.error(f"伝票作成失敗: {self.editing_invoice.invoice_number}")
self.page.snack_bar = ft.SnackBar(
content=ft.Text("保存に失敗しました。編集内容を確認してください。"),
bgcolor=ft.Colors.RED_600,
)
self.page.snack_bar.open = True
self.page.update()
self._show_snack("保存に失敗しました。編集内容を確認してください。", ft.Colors.RED_600)
else:
# 更新
logging.info(f"=== 伝票更新開 ===")
@ -1285,39 +1268,33 @@ class FlutterStyleDashboard:
except Exception as e:
logging.error(f"顧客作成失敗(update側): {e}")
# 既存顧客ならマスタも更新
if getattr(self.editing_invoice.customer, "id", 0) > 0:
try:
self.app_service.customer.update_customer(self.editing_invoice.customer)
except Exception as e:
logging.warning(f"顧客更新失敗(続行): {e}")
success = self.app_service.invoice.update_invoice(self.editing_invoice)
if success:
save_succeeded = True
logging.info(f"伝票更新成功: {self.editing_invoice.invoice_number}")
self.page.snack_bar = ft.SnackBar(
content=ft.Text("伝票を更新しました"),
bgcolor=ft.Colors.GREEN_600,
)
self.page.snack_bar.open = True
self._show_snack("伝票を更新しました", ft.Colors.GREEN_600)
# 一覧データは更新
self.invoices = self.app_service.invoice.get_recent_invoices(20)
# 設定により遷移先を変更
if not self.stay_on_detail_after_save:
self.editing_invoice = None
self.current_tab = 0 # 一覧タブに戻る
self.update_main_content()
else:
logging.error(f"伝票更新失敗: {self.editing_invoice.invoice_number}")
self.page.snack_bar = ft.SnackBar(
content=ft.Text("更新に失敗しました。編集内容を確認してください。"),
bgcolor=ft.Colors.RED_600,
)
self.page.snack_bar.open = True
self.page.update()
self._show_snack("更新に失敗しました。編集内容を確認してください。", ft.Colors.RED_600)
except Exception as e:
logging.error(f"伝票保存エラー: {e}")
import traceback
logging.error(f"詳細エラー: {traceback.format_exc()}")
self.page.snack_bar = ft.SnackBar(
content=ft.Text("保存中にエラーが発生しました"),
bgcolor=ft.Colors.RED_600,
)
self.page.snack_bar.open = True
self.page.update()
self._show_snack("保存中にエラーが発生しました", ft.Colors.RED_600)
save_succeeded = False
if save_succeeded:
@ -1643,12 +1620,22 @@ class FlutterStyleDashboard:
self.page.update()
except Exception as e:
logging.warning(f"TimePicker open error: {e}")
def _show_snack(self, message: str, color=ft.Colors.BLUE_GREY_800):
try:
self.page.snack_bar = ft.SnackBar(content=ft.Text(message), bgcolor=color)
self.page.snack_bar.open = True
self.page.update()
except Exception as e:
logging.warning(f"snack_bar表示失敗: {e}")
def create_new_customer_screen(self) -> ft.Container:
"""新規顧客登録画面"""
name_field = ft.TextField(label="顧客名(略称)")
formal_name_field = ft.TextField(label="正式名称")
address_field = ft.TextField(label="住所")
phone_field = ft.TextField(label="電話番号")
"""新規/既存顧客登録・編集画面"""
editing_customer = getattr(self, "editing_customer_for_form", None)
name_field = ft.TextField(label="顧客名(略称)", value=getattr(editing_customer, "name", ""))
formal_name_field = ft.TextField(label="正式名称", value=getattr(editing_customer, "formal_name", ""))
address_field = ft.TextField(label="住所", value=getattr(editing_customer, "address", ""))
phone_field = ft.TextField(label="電話番号", value=getattr(editing_customer, "phone", ""))
def save_customer(_):
name = (name_field.value or "").strip()
@ -1656,23 +1643,38 @@ class FlutterStyleDashboard:
address = (address_field.value or "").strip()
phone = (phone_field.value or "").strip()
if not name or not formal_name:
try:
self.page.snack_bar = ft.SnackBar(content=ft.Text("顧客名と正式名称は必須です"), bgcolor=ft.Colors.RED_600)
self.page.snack_bar.open = True
self.page.update()
except Exception:
pass
self._show_snack("顧客名と正式名称は必須です", ft.Colors.RED_600)
return
# 既存編集か新規かで分岐
if editing_customer and getattr(editing_customer, "id", 0) > 0:
try:
editing_customer.name = name
editing_customer.formal_name = formal_name
editing_customer.address = address
editing_customer.phone = phone
self.app_service.customer.update_customer(editing_customer)
self.customers = self.app_service.customer.get_all_customers()
self.selected_customer = editing_customer
if self.editing_invoice:
self.editing_invoice.customer = editing_customer
self._show_snack("顧客を更新しました", ft.Colors.GREEN_600)
self.editing_customer_for_form = None
self.is_customer_picker_open = False
self.is_new_customer_form_open = False
self.update_main_content()
return
except Exception as e:
logging.error(f"顧客更新エラー: {e}")
self._show_snack("保存に失敗しました", ft.Colors.RED_600)
return
# 新規登録フロー
try:
new_customer = self.app_service.customer.create_customer(name, formal_name, address, phone)
except Exception as e:
logging.error(f"顧客登録エラー: {e}")
try:
self.page.snack_bar = ft.SnackBar(content=ft.Text("保存に失敗しました"), bgcolor=ft.Colors.RED_600)
self.page.snack_bar.open = True
self.page.update()
except Exception:
pass
self._show_snack("保存に失敗しました", ft.Colors.RED_600)
return
# create_customer がID(int)を返す場合にも対応
@ -1701,17 +1703,14 @@ class FlutterStyleDashboard:
logging.info(f"新規顧客登録: {created_customer_obj.formal_name}")
self.is_customer_picker_open = False
self.is_new_customer_form_open = False
self.editing_customer_for_form = None
self.update_main_content()
else:
logging.error("新規顧客登録失敗")
try:
self.page.snack_bar = ft.SnackBar(content=ft.Text("保存に失敗しました"), bgcolor=ft.Colors.RED_600)
self.page.snack_bar.open = True
self.page.update()
except Exception:
pass
self._show_snack("保存に失敗しました", ft.Colors.RED_600)
def cancel(_):
self.editing_customer_for_form = None
self.is_new_customer_form_open = False
self.update_main_content()
@ -1720,7 +1719,7 @@ class FlutterStyleDashboard:
ft.Container(
content=ft.Row([
ft.IconButton(ft.Icons.ARROW_BACK, on_click=cancel),
ft.Text("新規顧客登録", size=18, weight=ft.FontWeight.BOLD),
ft.Text("顧客登録/編集", size=18, weight=ft.FontWeight.BOLD),
]),
padding=ft.Padding.all(15),
bgcolor=ft.Colors.BLUE_GREY,
@ -1782,6 +1781,13 @@ class FlutterStyleDashboard:
self.is_customer_picker_open = False
self.update_main_content()
def open_edit_customer(c: Customer):
# 長押しで顧客を編集
self.editing_customer_for_form = c
self.is_new_customer_form_open = True
self.is_customer_picker_open = False
self.update_main_content()
customer_cards = []
for c in customers:
customer_cards.append(
@ -1794,6 +1800,7 @@ class FlutterStyleDashboard:
)
),
on_click=lambda _, cu=c: on_pick(cu),
on_long_press=lambda _, cu=c: open_edit_customer(cu),
)
)

View file

@ -354,12 +354,15 @@ class InvoiceRepository:
# 伝票基本情報を更新
cursor.execute('''
UPDATE invoices
SET document_type = ?, customer_id = ?, date = ?,
invoice_number = ?, notes = ?, pdf_generated_at = ?
SET document_type = ?, customer_id = ?, customer_name = ?, customer_address = ?, customer_phone = ?,
date = ?, invoice_number = ?, notes = ?, pdf_generated_at = ?, updated_at = CURRENT_TIMESTAMP
WHERE uuid = ?
''', (
invoice.document_type.value,
invoice.customer.id if hasattr(invoice.customer, 'id') else None,
getattr(invoice.customer, 'formal_name', None),
getattr(invoice.customer, 'address', None),
getattr(invoice.customer, 'phone', None),
invoice.date.isoformat(),
invoice.invoice_number,
invoice.notes,