68 lines
2.4 KiB
Python
68 lines
2.4 KiB
Python
from __future__ import annotations
|
||
|
||
import csv
|
||
import hashlib
|
||
from datetime import datetime
|
||
from typing import Iterable
|
||
|
||
from .base import CSVParserBase, ExpenseRow
|
||
|
||
|
||
class IdemitsuParser(CSVParserBase):
|
||
source = 'idemitsu'
|
||
|
||
def detect(self, header_line: str) -> bool:
|
||
return '出光' in header_line or 'apollostation' in header_line
|
||
|
||
def parse(self, lines: Iterable[str]) -> list[ExpenseRow]:
|
||
rows: list[ExpenseRow] = []
|
||
reader = csv.reader(lines)
|
||
last_row_index: int | None = None
|
||
for columns in reader:
|
||
if not columns:
|
||
continue
|
||
head = columns[0].strip()
|
||
if head in ('カード名称', 'お支払日', '今回ご請求額'):
|
||
continue
|
||
if head == '利用日':
|
||
continue
|
||
if not head:
|
||
if last_row_index is not None:
|
||
extra_desc = columns[1].strip() if len(columns) > 1 else ''
|
||
extra_note = columns[6].strip() if len(columns) > 6 else ''
|
||
if extra_desc:
|
||
rows[last_row_index].description += f' {extra_desc}'
|
||
if extra_note:
|
||
if rows[last_row_index].note:
|
||
rows[last_row_index].note += f' {extra_note}'
|
||
else:
|
||
rows[last_row_index].note = extra_note
|
||
continue
|
||
if len(columns) < 6:
|
||
continue
|
||
try:
|
||
use_date = datetime.strptime(head, '%Y/%m/%d').date()
|
||
except ValueError:
|
||
continue
|
||
description = columns[1].strip()
|
||
amount_text = columns[5].replace(',', '').strip()
|
||
note = columns[6].strip() if len(columns) > 6 else ''
|
||
try:
|
||
amount = int(amount_text)
|
||
except ValueError:
|
||
continue
|
||
raw = f"{use_date.isoformat()}|{description}|{amount}|{note}|{self.source}"
|
||
source_hash = hashlib.sha256(raw.encode('utf-8')).hexdigest()
|
||
rows.append(
|
||
ExpenseRow(
|
||
use_date=use_date,
|
||
description=description,
|
||
amount=amount,
|
||
note=note,
|
||
source=self.source,
|
||
source_hash=source_hash,
|
||
)
|
||
)
|
||
last_row_index = len(rows) - 1
|
||
return rows
|