下書きが保存出来るようになった
This commit is contained in:
parent
d9aad0d35b
commit
be14fa7eb2
2 changed files with 154 additions and 71 deletions
102
main.py
102
main.py
|
|
@ -222,6 +222,21 @@ class FlutterStyleDashboard:
|
||||||
"amount_color": "#2F3C7E",
|
"amount_color": "#2F3C7E",
|
||||||
"tag_text_color": "#4B4F67",
|
"tag_text_color": "#4B4F67",
|
||||||
"tag_bg": "#E7E9FB",
|
"tag_bg": "#E7E9FB",
|
||||||
|
"draft_card_bg": "#F5EEE4",
|
||||||
|
"draft_border": "#D7C4AF",
|
||||||
|
"draft_badge_bg": "#A7743A",
|
||||||
|
"draft_shadow_highlight": ft.BoxShadow(
|
||||||
|
blur_radius=8,
|
||||||
|
spread_radius=0,
|
||||||
|
color="#FFFFFF",
|
||||||
|
offset=ft.Offset(-2, -2),
|
||||||
|
),
|
||||||
|
"draft_shadow_depth": ft.BoxShadow(
|
||||||
|
blur_radius=14,
|
||||||
|
spread_radius=2,
|
||||||
|
color="#C3A88C",
|
||||||
|
offset=ft.Offset(4, 6),
|
||||||
|
),
|
||||||
"badge_bg": "#35C46B",
|
"badge_bg": "#35C46B",
|
||||||
}
|
}
|
||||||
self.doc_type_palette = {
|
self.doc_type_palette = {
|
||||||
|
|
@ -443,24 +458,57 @@ class FlutterStyleDashboard:
|
||||||
|
|
||||||
is_locked = getattr(self.editing_invoice, 'final_locked', False)
|
is_locked = getattr(self.editing_invoice, 'final_locked', False)
|
||||||
is_view_mode = not getattr(self, 'is_detail_edit_mode', False)
|
is_view_mode = not getattr(self, 'is_detail_edit_mode', False)
|
||||||
|
is_draft = bool(getattr(self.editing_invoice, 'is_draft', False))
|
||||||
|
|
||||||
def set_doc_type(dt: DocumentType):
|
def set_doc_type(dt: DocumentType):
|
||||||
self.select_document_type(dt)
|
self.select_document_type(dt)
|
||||||
self.update_main_content()
|
self.update_main_content()
|
||||||
|
|
||||||
doc_type_items = [ft.PopupMenuItem(content=ft.Text(dt.value), on_click=lambda _, d=dt: set_doc_type(d)) for dt in DocumentType]
|
doc_type_items = [ft.PopupMenuItem(content=ft.Text(dt.value), on_click=lambda _, d=dt: set_doc_type(d)) for dt in DocumentType if dt != DocumentType.DRAFT]
|
||||||
|
# ドラフト切替
|
||||||
|
def toggle_draft(e):
|
||||||
|
self.editing_invoice.is_draft = bool(e.control.value)
|
||||||
|
self.update_main_content()
|
||||||
|
|
||||||
|
draft_toggle = ft.PopupMenuItem(
|
||||||
|
content=ft.Row([
|
||||||
|
ft.Text("下書き", size=12),
|
||||||
|
ft.Checkbox(value=is_draft, on_change=toggle_draft),
|
||||||
|
], alignment=ft.MainAxisAlignment.SPACE_BETWEEN, vertical_alignment=ft.CrossAxisAlignment.CENTER),
|
||||||
|
)
|
||||||
|
doc_type_items.insert(0, draft_toggle)
|
||||||
|
|
||||||
|
draft_suffix = " (下書き)" if is_draft else ""
|
||||||
|
|
||||||
if not getattr(self, 'is_detail_edit_mode', False):
|
if not getattr(self, 'is_detail_edit_mode', False):
|
||||||
# 閲覧時は単なるテキスト表示
|
title_ctrl = ft.Text(
|
||||||
title_ctrl = ft.Text(self.selected_document_type.value, size=18, weight=ft.FontWeight.BOLD, color=ft.Colors.BLUE_GREY_800)
|
f"{self.selected_document_type.value}{draft_suffix}",
|
||||||
|
size=18,
|
||||||
|
weight=ft.FontWeight.BOLD,
|
||||||
|
color=ft.Colors.BLUE_GREY_800,
|
||||||
|
)
|
||||||
doc_type_menu = None
|
doc_type_menu = None
|
||||||
else:
|
else:
|
||||||
doc_type_menu = ft.PopupMenuButton(
|
doc_type_menu = ft.PopupMenuButton(
|
||||||
content=ft.Text(self.selected_document_type.value, size=18, weight=ft.FontWeight.BOLD, color=ft.Colors.BLUE_GREY_800),
|
content=ft.Text(
|
||||||
|
f"{self.selected_document_type.value}{draft_suffix}",
|
||||||
|
size=18,
|
||||||
|
weight=ft.FontWeight.BOLD,
|
||||||
|
color=ft.Colors.BLUE_GREY_800,
|
||||||
|
),
|
||||||
items=doc_type_items,
|
items=doc_type_items,
|
||||||
tooltip="帳票タイプ変更",
|
tooltip="帳票タイプ変更",
|
||||||
)
|
)
|
||||||
title_ctrl = doc_type_menu
|
title_ctrl = doc_type_menu
|
||||||
|
|
||||||
|
draft_badge = ft.Container(
|
||||||
|
content=ft.Text("下書き", size=11, weight=ft.FontWeight.BOLD, color=ft.Colors.BROWN_800),
|
||||||
|
padding=ft.Padding.symmetric(horizontal=8, vertical=4),
|
||||||
|
bgcolor=ft.Colors.BROWN_100,
|
||||||
|
border_radius=12,
|
||||||
|
visible=is_draft,
|
||||||
|
)
|
||||||
|
|
||||||
app_bar = AppBar(
|
app_bar = AppBar(
|
||||||
title="伝票詳細",
|
title="伝票詳細",
|
||||||
show_back=True,
|
show_back=True,
|
||||||
|
|
@ -470,11 +518,15 @@ class FlutterStyleDashboard:
|
||||||
action_icon=ft.Icons.SAVE if getattr(self, 'is_detail_edit_mode', False) else ft.Icons.EDIT,
|
action_icon=ft.Icons.SAVE if getattr(self, 'is_detail_edit_mode', False) else ft.Icons.EDIT,
|
||||||
action_tooltip="保存" if getattr(self, 'is_detail_edit_mode', False) else "編集",
|
action_tooltip="保存" if getattr(self, 'is_detail_edit_mode', False) else "編集",
|
||||||
bottom=None,
|
bottom=None,
|
||||||
trailing_controls=[doc_type_menu] if doc_type_menu else [],
|
trailing_controls=([draft_badge] + ([doc_type_menu] if doc_type_menu else [])) if is_draft else ([doc_type_menu] if doc_type_menu else []),
|
||||||
title_control=title_ctrl,
|
title_control=title_ctrl,
|
||||||
)
|
)
|
||||||
|
|
||||||
body = self._create_edit_existing_screen()
|
body = self._create_edit_existing_screen()
|
||||||
|
body = ft.Container(
|
||||||
|
content=body,
|
||||||
|
bgcolor=ft.Colors.BROWN_50 if is_draft else None,
|
||||||
|
)
|
||||||
|
|
||||||
return ft.Column([
|
return ft.Column([
|
||||||
app_bar,
|
app_bar,
|
||||||
|
|
@ -745,6 +797,7 @@ class FlutterStyleDashboard:
|
||||||
"document_type": invoice.document_type.value if getattr(invoice, "document_type", None) else None,
|
"document_type": invoice.document_type.value if getattr(invoice, "document_type", None) else None,
|
||||||
"date": invoice.date.isoformat() if getattr(invoice, "date", None) else None,
|
"date": invoice.date.isoformat() if getattr(invoice, "date", None) else None,
|
||||||
"notes": getattr(invoice, "notes", ""),
|
"notes": getattr(invoice, "notes", ""),
|
||||||
|
"is_draft": bool(getattr(invoice, "is_draft", False)),
|
||||||
"customer": {
|
"customer": {
|
||||||
"id": getattr(getattr(invoice, "customer", None), "id", None),
|
"id": getattr(getattr(invoice, "customer", None), "id", None),
|
||||||
"formal_name": getattr(getattr(invoice, "customer", None), "formal_name", None),
|
"formal_name": getattr(getattr(invoice, "customer", None), "formal_name", None),
|
||||||
|
|
@ -777,6 +830,8 @@ class FlutterStyleDashboard:
|
||||||
return True
|
return True
|
||||||
if snapshot.get("notes", "") != getattr(invoice, "notes", ""):
|
if snapshot.get("notes", "") != getattr(invoice, "notes", ""):
|
||||||
return True
|
return True
|
||||||
|
if snapshot.get("is_draft", False) != bool(getattr(invoice, "is_draft", False)):
|
||||||
|
return True
|
||||||
|
|
||||||
snap_cust = snapshot.get("customer", {}) or {}
|
snap_cust = snapshot.get("customer", {}) or {}
|
||||||
cust = getattr(invoice, "customer", None)
|
cust = getattr(invoice, "customer", None)
|
||||||
|
|
@ -831,6 +886,7 @@ class FlutterStyleDashboard:
|
||||||
first_item = description or "(明細なし)"
|
first_item = description or "(明細なし)"
|
||||||
extra_count = 0
|
extra_count = 0
|
||||||
|
|
||||||
|
is_draft_card = isinstance(slip, Invoice) and bool(getattr(slip, "is_draft", False))
|
||||||
icon_bg = palette.get(slip_type, theme["icon_default_bg"])
|
icon_bg = palette.get(slip_type, theme["icon_default_bg"])
|
||||||
display_amount = -abs(amount) if isinstance(slip, Invoice) and getattr(slip, "is_offset", False) else amount
|
display_amount = -abs(amount) if isinstance(slip, Invoice) and getattr(slip, "is_offset", False) else amount
|
||||||
|
|
||||||
|
|
@ -938,6 +994,28 @@ class FlutterStyleDashboard:
|
||||||
|
|
||||||
status_chip = ft.Text("✓ LOCK", size=9, color=theme["tag_text_color"]) if final_locked else ft.Container()
|
status_chip = ft.Text("✓ LOCK", size=9, color=theme["tag_text_color"]) if final_locked else ft.Container()
|
||||||
|
|
||||||
|
if is_draft_card:
|
||||||
|
status_chip = ft.Row(
|
||||||
|
[
|
||||||
|
ft.Container(
|
||||||
|
content=ft.Text("DRAFT", size=9, weight=ft.FontWeight.BOLD, color=ft.Colors.WHITE),
|
||||||
|
padding=ft.Padding.symmetric(horizontal=6, vertical=2),
|
||||||
|
bgcolor=theme["draft_badge_bg"],
|
||||||
|
border_radius=999,
|
||||||
|
),
|
||||||
|
status_chip or ft.Container(),
|
||||||
|
],
|
||||||
|
spacing=4,
|
||||||
|
vertical_alignment=ft.CrossAxisAlignment.CENTER,
|
||||||
|
)
|
||||||
|
|
||||||
|
card_bg = theme["draft_card_bg"] if is_draft_card else theme["card_bg"]
|
||||||
|
card_border = ft.Border.all(1, theme["draft_border"]) if is_draft_card else None
|
||||||
|
card_shadow = [
|
||||||
|
theme["draft_shadow_highlight"],
|
||||||
|
theme["draft_shadow_depth"]
|
||||||
|
] if is_draft_card else [theme["shadow"]]
|
||||||
|
|
||||||
card_body = ft.Container(
|
card_body = ft.Container(
|
||||||
content=ft.Column(
|
content=ft.Column(
|
||||||
[left_column, status_chip],
|
[left_column, status_chip],
|
||||||
|
|
@ -945,9 +1023,10 @@ class FlutterStyleDashboard:
|
||||||
expand=True,
|
expand=True,
|
||||||
),
|
),
|
||||||
padding=ft.Padding.symmetric(horizontal=12, vertical=8),
|
padding=ft.Padding.symmetric(horizontal=12, vertical=8),
|
||||||
bgcolor=theme["card_bg"],
|
bgcolor=card_bg,
|
||||||
border_radius=theme["card_radius"],
|
border_radius=theme["card_radius"],
|
||||||
shadow=[theme["shadow"]],
|
border=card_border,
|
||||||
|
shadow=card_shadow,
|
||||||
)
|
)
|
||||||
|
|
||||||
return ft.GestureDetector(
|
return ft.GestureDetector(
|
||||||
|
|
@ -1129,11 +1208,12 @@ class FlutterStyleDashboard:
|
||||||
customer=default_customer,
|
customer=default_customer,
|
||||||
date=datetime.now(),
|
date=datetime.now(),
|
||||||
items=[],
|
items=[],
|
||||||
document_type=DocumentType.DRAFT,
|
document_type=DocumentType.INVOICE,
|
||||||
invoice_number="NEW-" + str(int(datetime.now().timestamp()))
|
invoice_number="NEW-" + str(int(datetime.now().timestamp()))
|
||||||
)
|
)
|
||||||
|
self.editing_invoice.is_draft = True
|
||||||
self.selected_customer = default_customer
|
self.selected_customer = default_customer
|
||||||
self.selected_document_type = DocumentType.DRAFT
|
self.selected_document_type = DocumentType.INVOICE
|
||||||
self.is_detail_edit_mode = True
|
self.is_detail_edit_mode = True
|
||||||
self.is_edit_mode = True
|
self.is_edit_mode = True
|
||||||
self.is_customer_picker_open = False
|
self.is_customer_picker_open = False
|
||||||
|
|
@ -1161,6 +1241,7 @@ class FlutterStyleDashboard:
|
||||||
"""既存伝票の編集画面(新規・編集共通)"""
|
"""既存伝票の編集画面(新規・編集共通)"""
|
||||||
# 編集不可チェック(新規作成時はFalse)
|
# 編集不可チェック(新規作成時はFalse)
|
||||||
is_new_invoice = self.editing_invoice.invoice_number.startswith("NEW-")
|
is_new_invoice = self.editing_invoice.invoice_number.startswith("NEW-")
|
||||||
|
edit_bg = ft.Colors.BROWN_50
|
||||||
|
|
||||||
# LOCK条件:明示的に確定された場合のみLOCK
|
# LOCK条件:明示的に確定された場合のみLOCK
|
||||||
# PDF生成だけではLOCKしない(お試しPDFを許可)
|
# PDF生成だけではLOCKしない(お試しPDFを許可)
|
||||||
|
|
@ -1199,6 +1280,7 @@ class FlutterStyleDashboard:
|
||||||
value=self.editing_invoice.customer.name if self.editing_invoice.customer.name != "選択してください" else "",
|
value=self.editing_invoice.customer.name if self.editing_invoice.customer.name != "選択してください" else "",
|
||||||
disabled=is_locked,
|
disabled=is_locked,
|
||||||
width=260,
|
width=260,
|
||||||
|
bgcolor=edit_bg,
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_customer_name(e):
|
def update_customer_name(e):
|
||||||
|
|
@ -1319,6 +1401,7 @@ class FlutterStyleDashboard:
|
||||||
multiline=True,
|
multiline=True,
|
||||||
min_lines=2,
|
min_lines=2,
|
||||||
max_lines=3,
|
max_lines=3,
|
||||||
|
bgcolor=edit_bg if not is_view_mode and not is_locked else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
def toggle_edit_mode(_):
|
def toggle_edit_mode(_):
|
||||||
|
|
@ -2297,7 +2380,6 @@ class FlutterStyleDashboard:
|
||||||
|
|
||||||
self.selected_document_type = resolved_type
|
self.selected_document_type = resolved_type
|
||||||
logging.info(f"帳票種類を選択: {resolved_type.value}")
|
logging.info(f"帳票種類を選択: {resolved_type.value}")
|
||||||
self.update_main_content()
|
|
||||||
|
|
||||||
def create_slip(self, e=None):
|
def create_slip(self, e=None):
|
||||||
"""伝票作成 - サービス層を使用"""
|
"""伝票作成 - サービス層を使用"""
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ class InvoiceRepository:
|
||||||
ensure_column("invoices", "pdf_generated_at", "pdf_generated_at TEXT")
|
ensure_column("invoices", "pdf_generated_at", "pdf_generated_at TEXT")
|
||||||
ensure_column("invoices", "pdf_sha256", "pdf_sha256 TEXT")
|
ensure_column("invoices", "pdf_sha256", "pdf_sha256 TEXT")
|
||||||
ensure_column("invoices", "submitted_to_tax_authority", "submitted_to_tax_authority INTEGER DEFAULT 0")
|
ensure_column("invoices", "submitted_to_tax_authority", "submitted_to_tax_authority INTEGER DEFAULT 0")
|
||||||
|
ensure_column("invoices", "is_draft", "is_draft INTEGER DEFAULT 0")
|
||||||
|
|
||||||
# Explorer向けインデックス(大量データ閲覧時の検索性能を確保)
|
# Explorer向けインデックス(大量データ閲覧時の検索性能を確保)
|
||||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_invoices_date ON invoices(date)")
|
cursor.execute("CREATE INDEX IF NOT EXISTS idx_invoices_date ON invoices(date)")
|
||||||
|
|
@ -292,8 +293,8 @@ class InvoiceRepository:
|
||||||
payload_json, payload_hash, prev_chain_hash, chain_hash,
|
payload_json, payload_hash, prev_chain_hash, chain_hash,
|
||||||
pdf_template_version, company_info_version,
|
pdf_template_version, company_info_version,
|
||||||
is_offset, offset_target_uuid,
|
is_offset, offset_target_uuid,
|
||||||
pdf_generated_at, pdf_sha256, submitted_to_tax_authority)
|
pdf_generated_at, pdf_sha256, submitted_to_tax_authority, is_draft)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
''', (
|
''', (
|
||||||
invoice.uuid,
|
invoice.uuid,
|
||||||
invoice.document_type.value,
|
invoice.document_type.value,
|
||||||
|
|
@ -319,7 +320,8 @@ class InvoiceRepository:
|
||||||
getattr(invoice, "offset_target_uuid", None),
|
getattr(invoice, "offset_target_uuid", None),
|
||||||
getattr(invoice, "pdf_generated_at", None),
|
getattr(invoice, "pdf_generated_at", None),
|
||||||
getattr(invoice, "pdf_sha256", None),
|
getattr(invoice, "pdf_sha256", None),
|
||||||
0 # submitted_to_tax_authority = false by default
|
0, # submitted_to_tax_authority = false by default
|
||||||
|
1 if getattr(invoice, "is_draft", False) else 0
|
||||||
))
|
))
|
||||||
|
|
||||||
invoice_id = cursor.lastrowid
|
invoice_id = cursor.lastrowid
|
||||||
|
|
@ -355,7 +357,7 @@ class InvoiceRepository:
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
UPDATE invoices
|
UPDATE invoices
|
||||||
SET document_type = ?, customer_id = ?, customer_name = ?, customer_address = ?, customer_phone = ?,
|
SET document_type = ?, customer_id = ?, customer_name = ?, customer_address = ?, customer_phone = ?,
|
||||||
date = ?, invoice_number = ?, notes = ?, pdf_generated_at = ?, updated_at = CURRENT_TIMESTAMP
|
date = ?, invoice_number = ?, notes = ?, pdf_generated_at = ?, is_draft = ?, updated_at = CURRENT_TIMESTAMP
|
||||||
WHERE uuid = ?
|
WHERE uuid = ?
|
||||||
''', (
|
''', (
|
||||||
invoice.document_type.value,
|
invoice.document_type.value,
|
||||||
|
|
@ -367,6 +369,7 @@ class InvoiceRepository:
|
||||||
invoice.invoice_number,
|
invoice.invoice_number,
|
||||||
invoice.notes,
|
invoice.notes,
|
||||||
getattr(invoice, 'pdf_generated_at', None),
|
getattr(invoice, 'pdf_generated_at', None),
|
||||||
|
1 if getattr(invoice, 'is_draft', False) else 0,
|
||||||
invoice.uuid
|
invoice.uuid
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
@ -374,8 +377,9 @@ class InvoiceRepository:
|
||||||
cursor.execute('SELECT id FROM invoices WHERE uuid = ?', (invoice.uuid,))
|
cursor.execute('SELECT id FROM invoices WHERE uuid = ?', (invoice.uuid,))
|
||||||
result = cursor.fetchone()
|
result = cursor.fetchone()
|
||||||
if not result:
|
if not result:
|
||||||
logging.error(f"伝票ID取得失敗: {invoice.uuid}")
|
logging.warning(f"伝票ID取得失敗: {invoice.uuid} -> 新規保存にフォールバックします")
|
||||||
return False
|
conn.rollback()
|
||||||
|
return self.save_invoice(invoice)
|
||||||
invoice_id = result[0]
|
invoice_id = result[0]
|
||||||
|
|
||||||
# 明細を一度削除して再挿入
|
# 明細を一度削除して再挿入
|
||||||
|
|
@ -524,75 +528,72 @@ class InvoiceRepository:
|
||||||
"""DB行をInvoiceオブジェクトに変換"""
|
"""DB行をInvoiceオブジェクトに変換"""
|
||||||
try:
|
try:
|
||||||
invoice_id = row[0]
|
invoice_id = row[0]
|
||||||
logging.info(f"変換開始: invoice_id={invoice_id}, row_length={len(row)}")
|
col_map = {desc[0]: idx for idx, desc in enumerate(cursor.description or [])}
|
||||||
|
|
||||||
# 明細取得
|
def val(name, default=None):
|
||||||
cursor.execute('''
|
idx = col_map.get(name)
|
||||||
SELECT description, quantity, unit_price, is_discount
|
if idx is None or idx >= len(row):
|
||||||
FROM invoice_items
|
return default
|
||||||
WHERE invoice_id = ?
|
return row[idx]
|
||||||
''', (invoice_id,))
|
|
||||||
|
|
||||||
item_rows = cursor.fetchall()
|
# 基本フィールド
|
||||||
|
doc_type_val = val("document_type", DocumentType.INVOICE.value)
|
||||||
|
doc_type = DocumentType(doc_type_val) if doc_type_val in DocumentType._value2member_map_ else DocumentType.INVOICE
|
||||||
|
date_str = val("date") or datetime.now().isoformat()
|
||||||
|
date_obj = datetime.fromisoformat(date_str)
|
||||||
|
|
||||||
|
customer_name = val("customer_name", "")
|
||||||
|
customer = Customer(
|
||||||
|
id=val("customer_id", 0) or 0,
|
||||||
|
name=customer_name or "",
|
||||||
|
formal_name=customer_name or "",
|
||||||
|
address=val("customer_address", "") or "",
|
||||||
|
phone=val("customer_phone", "") or "",
|
||||||
|
)
|
||||||
|
|
||||||
|
is_draft = bool(val("is_draft", 0))
|
||||||
|
|
||||||
|
# 明細取得は別カーソルで行い、元カーソルのdescriptionを汚染しない
|
||||||
|
item_cursor = cursor.connection.cursor()
|
||||||
|
item_cursor.execute(
|
||||||
|
'SELECT description, quantity, unit_price, is_discount, product_id FROM invoice_items WHERE invoice_id = ?',
|
||||||
|
(invoice_id,),
|
||||||
|
)
|
||||||
|
item_rows = item_cursor.fetchall()
|
||||||
items = [
|
items = [
|
||||||
InvoiceItem(
|
InvoiceItem(
|
||||||
description=ir[0],
|
description=ir[0],
|
||||||
quantity=ir[1],
|
quantity=ir[1],
|
||||||
unit_price=ir[2],
|
unit_price=ir[2],
|
||||||
is_discount=bool(ir[3])
|
is_discount=bool(ir[3]),
|
||||||
) for ir in item_rows
|
) for ir in item_rows
|
||||||
]
|
]
|
||||||
|
|
||||||
# 顧客情報
|
|
||||||
customer = Customer(
|
|
||||||
id=row[3] or 0, # customer_idフィールド
|
|
||||||
name=row[4], # customer_nameフィールド
|
|
||||||
formal_name=row[4], # customer_nameフィールド
|
|
||||||
address=row[5] or "", # customer_addressフィールド
|
|
||||||
phone=row[6] or "" # customer_phoneフィールド
|
|
||||||
)
|
|
||||||
|
|
||||||
# 伝票タイプ
|
|
||||||
doc_type = DocumentType.SALES
|
|
||||||
for dt in DocumentType:
|
|
||||||
if dt.value == row[2]:
|
|
||||||
doc_type = dt
|
|
||||||
break
|
|
||||||
|
|
||||||
# 日付変換
|
|
||||||
date_str = row[10] # 正しいdateフィールドのインデックス
|
|
||||||
logging.info(f"日付変換: {date_str}")
|
|
||||||
date_obj = datetime.fromisoformat(date_str)
|
|
||||||
|
|
||||||
inv = Invoice(
|
inv = Invoice(
|
||||||
customer=customer,
|
customer=customer,
|
||||||
date=date_obj,
|
date=date_obj,
|
||||||
items=items,
|
items=items,
|
||||||
file_path=row[13], # 正しいfile_pathフィールドのインデックス
|
file_path=val("file_path"),
|
||||||
invoice_number=row[11] or "", # 正しいinvoice_numberフィールドのインデックス
|
invoice_number=val("invoice_number", ""),
|
||||||
notes=row[12], # 正しいnotesフィールドのインデックス
|
notes=val("notes", ""),
|
||||||
document_type=doc_type,
|
document_type=doc_type,
|
||||||
uuid=row[1],
|
uuid=val("uuid"),
|
||||||
|
is_draft=is_draft,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 監査用フィールド(存在していれば付与)
|
# 監査・チェーン関連のフィールドは動的属性として保持
|
||||||
try:
|
inv.node_id = val("node_id")
|
||||||
inv.node_id = row[14]
|
inv.payload_json = val("payload_json")
|
||||||
inv.payload_json = row[15]
|
inv.payload_hash = val("payload_hash")
|
||||||
inv.payload_hash = row[16]
|
inv.prev_chain_hash = val("prev_chain_hash")
|
||||||
inv.prev_chain_hash = row[17]
|
inv.chain_hash = val("chain_hash")
|
||||||
inv.chain_hash = row[18]
|
inv.pdf_template_version = val("pdf_template_version")
|
||||||
inv.pdf_template_version = row[19]
|
inv.company_info_version = val("company_info_version")
|
||||||
inv.company_info_version = row[20]
|
inv.is_offset = bool(val("is_offset", 0))
|
||||||
inv.is_offset = bool(row[21])
|
inv.offset_target_uuid = val("offset_target_uuid")
|
||||||
inv.offset_target_uuid = row[22]
|
inv.pdf_generated_at = val("pdf_generated_at")
|
||||||
inv.pdf_generated_at = row[23]
|
inv.pdf_sha256 = val("pdf_sha256")
|
||||||
inv.pdf_sha256 = row[24]
|
inv.submitted_to_tax_authority = bool(val("submitted_to_tax_authority", 0))
|
||||||
inv.submitted_to_tax_authority = bool(row[27])
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
logging.info(f"変換成功: {inv.invoice_number}")
|
|
||||||
return inv
|
return inv
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue