# Imported history — StartedAt, and raising an event at the time it happened

> For an item whose history began before its run did — a ticket moved from another helpdesk, a seeded month of work — `StartedAt = <DateTime over this.Item>;` starts the run at that instant, and `Raise<Event>(item, at: when)` raises each later step at the time it happened. Every SLA clock then counts from when things really happened.

<!-- id: workflow-imported-history · area: workflow · stability: preview · html: https://osysharp.com/reference/workflow/imported-history/ -->

## Summary        {#summary}
A run starts when its item is created, and an event happens when it is raised — which is right for live work and
wrong for history. Import five hundred tickets and every SLA clock starts at the moment of the import, so the queue
reads 0:59, 0:59, 3:59, 3:59 and a ticket opened a week ago is as fresh as one opened a minute ago. Two surfaces put
the history's own times back:

- `StartedAt = this.Item.OpenedAt;` — a workflow setting: the run is taken to have started then, and every clock it
  arms at the start counts from it.
- `W.RaiseX(item, …, at: when)` — the event happened `when`: the run moves as of that instant, and every clock the
  move arms counts from it.

## Signature      {#signature}
```osy syntax
workflow SupportTicket {
  Tracks    = Ticket.Stage;
  Autostart = true;
  StartedAt = this.Item.Conversation.StartedAt;   // a live ticket: now; an imported one: when it was opened
  …
}

SupportTicket.RaiseReply(t, at: firstReplyAt);
SupportTicket.RaiseHold(t, "Waiting on the carrier", at: heldAt);
```

## Description    {#description}

### When does a run with `StartedAt` start?   {#started-at}
At the instant the setting names, evaluated once as the run starts — never later than now (a run cannot start in the
future, so a value after now is simply now). A live item whose field holds "now" starts exactly as it always did, which
is why a helpdesk can write `StartedAt = this.Item.Conversation.StartedAt;` for every ticket rather than only for
imported ones. A clock whose promise had already run out by the time of the import is missed straight away — the
breach is recorded, as it would have been had the run been there all along.

### What may `at:` be?   {#at}
A `DateTime` no earlier than the moment the run entered the state it is in, and no later than now. History is raised
in the order it happened: an `at:` before the run's current state is refused, naming both instants, and so is one in
the future. Both refusals are `ValidationException`. An event that itself declares a parameter called `at` keeps it —
the parameter wins, as a C# named argument would.

## Examples       {#examples}
```osy title="a desk importing tickets with their history" test app=workflow-imported-history
using Osysharp.Workflow;

enum Stage { New, Open, Done }

entity Ticket {
  [Required, MaxLength(200)] string Title;
  DateTime OpenedAt;
  Stage Stage;
  security { allow read, create, update when IsAuthenticated; }
}

workflow Desk {
  Tracks    = Ticket.Stage;
  Autostart = true;
  Initial   = New;
  StartedAt = this.Item.OpenedAt;

  event Reply();
  event Close();

  state New {
    Expire = TimeSpan.FromHours(4);
    on Expire { }
    subscribe Reply();
    on Reply { goto Open; }
  }
  state Open {
    on Close { goto Done; }
  }
  terminal success Done { }
}

/// One ticket from the old system: opened, and answered, when it really was.
public void ImportTicket(string title, DateTime opened, DateTime? answered) {
  var t = new Ticket { Title = title, OpenedAt = opened };
  UnitOfWork.Commit();
  if (answered != null) { Desk.RaiseReply(t, at: answered.Value); }
}
```

### Testing it   {#testing}
Read the clock the way a list does — `Workflow.WorkByItem<Ticket>()`'s `BreachesAt` — and assert it counts from the
history, not from the test: a ticket opened three hours ago on a four-hour promise has about an hour left.

## See also   {#see-also}
- [Raising a workflow event](https://osysharp.com/reference/workflow/raise/) — raising an event, the live form of `at:`
- [ServiceHours (SLA-accrual windows)](https://osysharp.com/reference/workflow/service-hours/) — the calendar every clock counts on
- [Assigned / Finished (milestones)](https://osysharp.com/reference/workflow/milestone/) — the clocks a move arms
- [Tracks and Initial (the field a workflow drives)](https://osysharp.com/reference/workflow/tracks/) — the item a run is bound to
