fix: create expense report immediately — remove broken confirmation gate
The old flow required a "confirm" reply after showing a parsed-receipt table, but that follow-up dispatch call carries no receipts (they only exist in the /upload context). The confirmation gate was architecturally broken: the second turn would always create nothing. Fix: create the expense sheet immediately when receipts are present. Byte-exact and semantic duplicates are auto-skipped; the count of skipped items is reported in the success message. The report is always created in Odoo as a draft so users can review amounts and submit manually via Odoo > Expenses. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -186,18 +186,14 @@ class ExpensesAgent(BaseAgent):
|
||||
else:
|
||||
deduped.append((receipt, parsed))
|
||||
|
||||
# Always show confirmation summary before creating — lets user verify
|
||||
# parsed amounts and review flagged duplicates in one step.
|
||||
if not user_confirmed:
|
||||
self._gathered_data['mode'] = 'awaiting_confirmation'
|
||||
self._confirmation_items = [
|
||||
(receipt, parsed, i in dup_indices)
|
||||
for i, (receipt, parsed) in enumerate(paired)
|
||||
]
|
||||
self._deduped = deduped
|
||||
return []
|
||||
|
||||
# User confirmed — apply dup decision
|
||||
# Auto-skip semantic duplicates by default; keep_all only if user explicitly asked.
|
||||
# Receipts are only available in this single /upload request — there is no
|
||||
# persistent receipt store across turns, so a "confirm then create" flow would
|
||||
# always fail on the follow-up turn (no receipts in context). Creating
|
||||
# immediately in draft state is the correct approach: users review and
|
||||
# submit inside Odoo > Expenses.
|
||||
n_skipped = len(paired) - len(deduped)
|
||||
self._gathered_data['n_skipped'] = n_skipped
|
||||
final_list = paired if user_dup_decision == 'keep_all' else deduped
|
||||
|
||||
sheet_name = f'Expense Report - {_date.today().isoformat()}'
|
||||
@@ -384,44 +380,15 @@ class ExpensesAgent(BaseAgent):
|
||||
data = self._gathered_data
|
||||
directive_id = self._directive.directive_id if self._directive else ''
|
||||
|
||||
if data.get('mode') == 'awaiting_confirmation':
|
||||
items = getattr(self, '_confirmation_items', [])
|
||||
n_dups = sum(1 for _, _, is_dup in items if is_dup)
|
||||
lines = [f'I parsed {len(items)} receipt(s). Please review before I create the expense report:\n']
|
||||
lines.append(f' {"#":>3} {"Vendor":<30} {"Amount":>8} {"Date":<12}')
|
||||
lines.append(f' {"---":>3} {"-"*30} {"-"*8} {"-"*12}')
|
||||
for i, (receipt, parsed, is_dup) in enumerate(items, 1):
|
||||
vendor = str(parsed.get('vendor') or receipt.get('filename', '?'))[:30]
|
||||
amt = float(parsed.get('amount') or 0)
|
||||
dt = str(parsed.get('date') or '')
|
||||
flag = ' !! duplicate' if is_dup else ''
|
||||
lines.append(f' {i:>3}. {vendor:<30} ${amt:>7.2f} {dt}{flag}')
|
||||
lines.append('')
|
||||
if n_dups:
|
||||
lines.append(
|
||||
f'{n_dups} item(s) marked "!! duplicate" appear to be the same receipt '
|
||||
f'as another entry (possibly an OCR amount mismatch).'
|
||||
)
|
||||
lines.append(
|
||||
'Reply "confirm" to create the report and exclude duplicates (recommended).'
|
||||
)
|
||||
lines.append(
|
||||
'Reply "confirm, keep all" to include every item even if duplicated.'
|
||||
)
|
||||
else:
|
||||
lines.append('Reply "confirm" to create the expense report.')
|
||||
return AgentReport(
|
||||
directive_id=directive_id, agent=self.name, status='complete',
|
||||
summary='\n'.join(lines), data=data,
|
||||
escalations=[], actions_taken=[])
|
||||
|
||||
if data.get('mode') == 'create_from_receipts':
|
||||
if self._actions_taken:
|
||||
lines = '\n'.join(f' • {a}' for a in self._actions_taken)
|
||||
n_skipped = data.get('n_skipped', 0)
|
||||
dup_note = f'\n({n_skipped} duplicate receipt(s) were automatically skipped.)' if n_skipped else ''
|
||||
summary = (
|
||||
f'Expense report created successfully:\n{lines}\n\n'
|
||||
'The report is in draft. Please open Odoo › Expenses, '
|
||||
'review the entries, and click Submit to send for approval.'
|
||||
f'Expense report created successfully:\n{lines}{dup_note}\n\n'
|
||||
'The report is in draft — open Odoo › Expenses, '
|
||||
'review the amounts, and click Submit to send for approval.'
|
||||
)
|
||||
status = 'complete'
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user