Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/UseCases/Line/HandleIntentOperationUseCase.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,22 @@ def _execute_pending(self, line_user_id: str) -> None:
)

if count == 0:
self._line_response_service.add_message(f'"{item_name}" が見つかりませんでした。')
if filter_expiry or exclude_expiry:
remaining = self._stock_repository.find(
query={"owner_id": line_user_id, "item_name": item_name, "status": 1}
)
if remaining:
dates = [s.expiry_date.strftime("%Y/%m/%d") if s.expiry_date else "期限なし" for s in remaining]
self._line_response_service.add_message(
f'その条件に一致する "{item_name}" は見つかりませんでした。\n'
f'現在登録中: {", ".join(dates)}'
)
else:
self._line_response_service.add_message(
f'"{item_name}" は見つかりませんでした(削除済みか未登録)。'
)
else:
self._line_response_service.add_message(f'"{item_name}" が見つかりませんでした。')
else:
self._line_response_service.add_message(f'"{item_name}" を削除しました。')
elif intent == "register_habit":
Expand Down
22 changes: 19 additions & 3 deletions src/services/LineIntentParserService.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"type": "function",
"function": {
"name": "delete_stock",
"description": "在庫・タスクを削除する。expiry_dateは完全一致フィルタ、exclude_expiry_dateは除外フィルタ(「以外を削除」)。",
"description": "在庫・タスクを削除する。expiry_dateは完全一致フィルタ(M/D・M月D日・相対日付を今日の日付を基準にYYYY-MM-DDに変換)、exclude_expiry_dateは除外フィルタ(「以外を削除」)。",
"parameters": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -206,8 +206,21 @@


class LineIntentParserService:
@staticmethod
def _normalize(text: str) -> str:
"""全角英数字・記号を半角に正規化する。"""
result = []
for ch in text:
cp = ord(ch)
# 全角英数字・記号 (!〜) → 半角
if 0xFF01 <= cp <= 0xFF5E:
result.append(chr(cp - 0xFEE0))
else:
result.append(ch)
return "".join(result)

def parse(self, message: str) -> Dict[str, Any]:
text = (message or "").strip()
text = self._normalize((message or "").strip())
if not text:
return self._none_result()
lower = text.lower()
Expand Down Expand Up @@ -241,7 +254,10 @@ def _parse_with_function_calling(self, message: str) -> Dict[str, Any]:
f"Today's date is {today_str} (JST).\n"
"You are an intent parser for a Japanese LINE bot.\n"
"Call exactly one tool that matches the user's intent.\n"
"Convert relative dates (今日/明日/明後日) to YYYY-MM-DD.\n"
"Convert all date expressions to YYYY-MM-DD format:\n"
" - Relative: 今日/明日/明後日/昨日\n"
" - M/D or M月D日 format: use the most recent occurrence (past or future based on context)\n"
" - When M/D is in the past (e.g. 2/27 and today is 3/4), interpret as the same year unless context implies otherwise\n"
"If the intent is unclear or unsafe, do NOT call any tool."
)
payload = {
Expand Down
37 changes: 36 additions & 1 deletion src/templates/pages/stock/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,39 @@
<!-- ページヘッダー -->
<div class="page-header d-flex justify-content-between align-items-center">
<h1 class="page-title">アイテム一覧</h1>
<a href="{{ url_for('views_blueprint.view_deleted_stock_list') }}" class="btn btn-outline-secondary btn-sm">
<a href="{{ url_for('views_blueprint.view_deleted_stock_list') }}" class="btn btn-outline-secondary btn-sm">
<i class="fas fa-trash-alt me-1"></i>削除済みアイテム
</a>
</div>

<!-- 通知時刻設定 -->
<div class="app-card p-3 mb-4">
<form
action="{{ url_for('views_blueprint.update_notify_schedule') }}"
method="POST"
class="d-flex align-items-center gap-2"
>
<label for="notify_time" class="form-label m-0 text-nowrap">通知時刻</label>
<input
id="notify_time"
name="notify_time"
type="time"
class="form-control form-control-sm"
value="{{ notify_time }}"
style="max-width: 160px"
required
/>
<button type="submit" class="btn btn-sm btn-outline-primary">
保存
</button>
</form>
</div>

<div class="row">
<div class="col">
{% import 'components/_macros.html' as ui with context %} {{
ui.stock_table(page_contents, form) }}
</div>
</div>
</div>
{% endblock %}