Recording Editorial Decisions

The current schema meets the functional requirements of HopPress for its initial release. Let’s see whether the non-functional requirements are met. Take the legal constraint from Chapter 1: the university must retain a record of every editorial decision. Stated as a requirement, HopPress must record who made each editorial decision, what the decision was, and when it was made.

Check the schema against it. editor_id says which editor is assigned to a post. published_at says when a post was published. That is all. The schema cannot say:

  • when a post was submitted, or by whom
  • when a post was returned, or what the editor said
  • whether a post was returned more than once
  • whether a different editor was assigned before the current one

One fix is to add columns to posts: submitted_at, returned_at, return_note. That records one submission and one return. When the author resubmits and the editor returns the post a second time, the new values overwrite the old ones, and the first decision is gone. The requirement asks for every decision, not the latest.

The solution is to store each decision in its own row in a new table, post_state_changes. Here is a schema for it:

post_state_changes
  change_id          integer   primary key
  post_id            integer   foreign key -> posts, not null
  actor_id           integer   foreign key -> users, not null
  from_state         text      null, check in ('draft', 'submitted', 'published', 'returned')
  to_state           text      not null, check in ('draft', 'submitted', 'published', 'returned')
  note               text      null
  occurred_at        timestamp not null

One row per transition. Creating a draft adds the first row for a post to post_state_changes, with from_state null. Submitting, publishing, and returning each add a row. actor_id is the user who made the change, whether author or editor. note holds the editor’s comment when a post is returned.

erDiagram
    direction LR
    posts ||--o{ post_state_changes : has
    users ||--o{ post_state_changes : makes

The posts table still holds state, editor_id, and published_at. Each can now be derived from post_state_changes. Whether to keep them is the next question.