feat(apply): treat "Inserat offline" as its own outcome

Offline listings are a different class of result from real failures:
they mean "this ad is gone", not "the apply pipeline is broken".

- DB migration 0010 adds flats.offline_at; recent_flats() filters those
  out globally so they drop off every user's Wohnungen list
- _is_offline_result() matches the four known offline/deactivated
  phrases (DE + EN translations)
- On an offline result: mark the flat, reset the failure counter
  instead of incrementing, and skip the apply_fail notification
- Bewerbungen history renders a yellow "offline" chip in place of the
  red "fehlgeschlagen" one

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
EiSiMo 2026-04-23 09:56:04 +02:00
parent 64439fd42e
commit abd614604f
3 changed files with 53 additions and 5 deletions

View file

@ -11,7 +11,14 @@
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2 flex-wrap">
{% if a.success == 1 %}<span class="chip chip-ok">ok</span>
{% elif a.success == 0 %}<span class="chip chip-bad">fehlgeschlagen</span>
{% elif a.success == 0 %}
{% set msg_lower = (a.message or '')|lower %}
{% if 'inserat offline' in msg_lower or 'inserat deaktiviert' in msg_lower
or 'ad offline' in msg_lower or 'ad deactivated' in msg_lower %}
<span class="chip chip-warn">offline</span>
{% else %}
<span class="chip chip-bad">fehlgeschlagen</span>
{% endif %}
{% else %}<span class="chip chip-warn">läuft</span>{% endif %}
<span class="chip chip-info">{% if a.triggered_by == 'auto' %}automatisch{% else %}manuell{% endif %}</span>
{% if a.provider %}<span class="chip chip-info">{{ a.provider }}</span>{% endif %}