feat: backdated reported date for old active tickets

Wahab can now enter historical tickets that keep their true reported date:

- Add nullable tickets.reported_at (DateTime) via alembic d5e0f2a1c3b4;
  backfill existing rows from created_at so nothing shows empty.
- TicketCreate.reported_at (optional) is persisted by create_ticket and
  defaults to now when omitted, so existing create behavior is unchanged.
- New-issue form gains a 'Reported Date' date picker (defaults to today,
  past dates allowed, future blocked) and sends reported_at in the payload.
- List and detail pages show 'Reported' next to 'Created' (date-only,
  labeled) so backdated tickets are obvious; SLA deadline is unchanged and
  still runs from creation time so backfilling never instantly breaches.
- Tests: backdated create persists + is exposed on list/detail; omitted
  reported_at defaults to now; SLA window unchanged; full datetime round trip.
This commit is contained in:
root
2026-08-03 09:40:23 +00:00
parent 30c0c01c59
commit e0a7479c3e
9 changed files with 217 additions and 3 deletions
+21 -1
View File
@@ -154,6 +154,15 @@
</div>
</div>
<!-- Reported date (backdating support) -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Reported Date</label>
<input type="date" x-model="form.reported_date" :max="todayStr" class="w-full px-4 py-2.5 rounded-lg border border-gray-300 focus:ring-2 focus:ring-denya-500 focus:border-transparent outline-none">
<p class="mt-1 text-xs text-gray-400">Defaults to today. Use a past date when entering an old/backlogged issue — it stays active in the normal workflow.</p>
</div>
</div>
<!-- Photo Upload -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Photos (Before)</label>
@@ -205,8 +214,10 @@
priority: '',
description: '',
reporter: '',
reported_via: ''
reported_via: '',
reported_date: ''
},
todayStr: '',
priorityAuto: false,
categories: [],
subCategories: [],
@@ -223,6 +234,14 @@
async init() {
await this.loadCategories();
await this.loadUnits();
// Default reported date to today (local), allow backdating via the date picker
this.todayStr = this.localDateStr(new Date());
if (!this.form.reported_date) this.form.reported_date = this.todayStr;
},
localDateStr(d) {
const offset = d.getTimezoneOffset();
return new Date(d.getTime() - offset * 60000).toISOString().slice(0, 10);
},
// ── Report mode ──────────────────────────────────────────
@@ -384,6 +403,7 @@
unit_id: this.form.unit.id,
customer_name: this.form.customer_name || null,
phone: this.form.phone || null,
reported_at: this.form.reported_date || null,
};
const ticket = await app().apiPost('/api/tickets', payload);