Repository: CSCfi/rems
Pull request #1201 (2019-05-03 11:06:09)

create rems.db.events namespace
plus some cleanup of rems.db.applications


Patch:
diff --git a/src/clj/rems/api/applications_v2.clj b/src/clj/rems/api/applications_v2.clj
index 4b65a3851..20fd164c6 100644
--- a/src/clj/rems/api/applications_v2.clj
+++ b/src/clj/rems/api/applications_v2.clj
@@ -9,6 +9,7 @@
             [rems.auth.util :refer [throw-forbidden]]
             [rems.db.applications :as applications]
             [rems.db.catalogue :as catalogue]
+            [rems.db.events :as events]
             [rems.db.form :as form]
             [rems.db.licenses :as licenses]
             [rems.db.users :as users]
@@ -35,7 +36,7 @@
   "Returns the full application state without any user permission
    checks and filtering of sensitive information. Don't expose via APIs."
   [application-id]
-  (let [events (applications/get-application-events application-id)
+  (let [events (events/get-application-events application-id)
         cache-key [application-id (count events)]
         build-app (fn [_] (model/build-application-view events injections))]
     (if (empty? events)
diff --git a/src/clj/rems/application/events_cache.clj b/src/clj/rems/application/events_cache.clj
index 0ad639635..fbc75409f 100644
--- a/src/clj/rems/application/events_cache.clj
+++ b/src/clj/rems/application/events_cache.clj
@@ -1,6 +1,6 @@
 (ns rems.application.events-cache
   (:require [conman.core :as conman]
-            [rems.db.applications :as applications]
+            [rems.db.events :as events]
             [rems.db.core :refer [*db*]]
             [rems.util :refer [atom?]]))
 
@@ -15,7 +15,7 @@
 (defn- update-with-new-events [cached update-fn]
   (conman/with-transaction [*db* {:isolation :serializable
                                   :read-only? true}]
-    (let [new-events (applications/get-all-events-since (:last-processed-event-id cached))]
+    (let [new-events (events/get-all-events-since (:last-processed-event-id cached))]
       (if (empty? new-events)
         cached
         {:state (update-fn (:state cached) new-events)
diff --git a/src/clj/rems/db/applications.clj b/src/clj/rems/db/applications.clj
index 2788c8369..cabfb8b1e 100644
--- a/src/clj/rems/db/applications.clj
+++ b/src/clj/rems/db/applications.clj
@@ -1,16 +1,15 @@
 (ns rems.db.applications
   "Query functions for forms and applications."
   (:require [clj-time.core :as time]
-            [clj-time.format :as time-format]
             [clojure.java.jdbc :as jdbc]
             [clojure.test :refer [deftest is]]
             [conman.core :as conman]
-            [rems.application.events :as events]
             [rems.application.model :as model]
             [rems.auth.util :refer [throw-forbidden]]
             [rems.db.catalogue :as catalogue]
             [rems.db.core :as db]
             [rems.db.entitlements :as entitlements]
+            [rems.db.events :as events]
             [rems.db.form :as form]
             [rems.db.licenses :as licenses]
             [rems.db.users :as users]
@@ -20,113 +19,18 @@
             [rems.json :as json]
             [rems.permissions :as permissions]
             [rems.util :refer [secure-token]]
-            [rems.workflow.dynamic :as dynamic]
-            [schema-tools.core :as st]
-            [schema.coerce :as coerce]
-            [schema.utils])
-  (:import [org.joda.time DateTime]))
-
-(declare get-dynamic-application-state)
+            [rems.workflow.dynamic :as dynamic]))
 
 ;;; Query functions
 
-(defn draft?
-  "Is the given `application-id` for an unsaved draft application?"
-  [application-id]
-  (nil? application-id))
-
-(declare is-dynamic-application?)
-(declare fix-workflow-from-db)
-(declare is-dynamic-handler?)
-
-;;; Creating drafts
-
-(defn create-new-draft [user-id wfid]
-  (assert user-id)
-  (assert wfid)
-  (:id (db/create-application! {:user user-id :wfid wfid})))
-
-(defn create-new-draft-at-time [user-id wfid time]
-  (:id (db/create-application! {:user user-id :wfid wfid :start time})))
-
-;;; Dynamic workflows
-;; TODO these should be in their own namespace probably
-
-(defn- fix-workflow-from-db [wf]
-  ;; TODO could use a schema for this coercion
-  (update (json/parse-string wf)
-          :type keyword))
-
-(defn- datestring->datetime [s]
-  (if (string? s)
-    (time-format/parse s)
-    s))
-
-(def ^:private datestring-coercion-matcher
-  {DateTime datestring->datetime})
-
-(defn- coercion-matcher [schema]
-  (or (datestring-coercion-matcher schema)
-      (coerce/string-coercion-matcher schema)))
-
-;; TODO: remove "dynamic" from names
-(def ^:private coerce-dynamic-event-commons
-  (coerce/coercer (st/open-schema events/EventBase) coercion-matcher))
-
-(def ^:private coerce-dynamic-event-specifics
-  (coerce/coercer events/Event coercion-matcher))
-
-(defn- coerce-dynamic-event [event]
-  ;; must coerce the common fields first, so that dynamic/Event can choose the right event schema based on the event type
-  (-> event
-      coerce-dynamic-event-commons
-      coerce-dynamic-event-specifics))
-
-(defn json->event [json]
-  (when json
-    (let [result (coerce-dynamic-event (json/parse-string json))]
-      (when (schema.utils/error? result)
-        ;; similar exception as what schema.core/validate throws
-        (throw (ex-info (str "Value does not match schema: " (pr-str result))
-                        {:schema events/Event :value json :error result})))
-      result)))
-
-(defn event->json [event]
-  (events/validate-event event)
-  (json/generate-string event))
-
-(defn- fix-event-from-db [event]
-  (assoc (-> event :eventdata json->event)
-         :event/id (:id event)))
-
-(defn get-application-events [application-id]
-  (map fix-event-from-db (db/get-application-events {:application application-id})))
-
-(defn get-all-events-since [event-id]
-  (map fix-event-from-db (db/get-application-events-since {:id event-id})))
+;; TODO use also in UI side?
+(defn is-dynamic-application? [application]
+  (= :workflow/dynamic (get-in application [:workflow :type])))
 
-(defn get-dynamic-application-state [application-id] ; TODO: legacy code; remove me
-  (let [application (or (first (db/get-applications {:id application-id}))
-                        (throw (rems.InvalidRequestException.
-                                (str "Application " application-id " not found"))))
-        events (get-application-events application-id)
-        application (assoc application
-                           :state :application.state/draft
-                           :dynamic-events events
-                           :workflow (fix-workflow-from-db (:workflow application))
-                           :last-modified (or (:event/time (last events))
-                                              (:start application)))]
-    (assert (is-dynamic-application? application) (pr-str application))
-    (dynamic/apply-events application events)))
+(defn is-dynamic-handler? [user-id application]
+  (contains? (set (get-in application [:workflow :handlers])) user-id))
 
-(defn add-event! [event]
-  (db/add-application-event! {:application (:application/id event)
-                              :user (:event/actor event)
-                              :comment nil
-                              :round -1
-                              :event (str (:event/type event))
-                              :eventdata (event->json event)})
-  nil)
+;;; Creating applications
 
 (defn allocate-external-id! [prefix]
   (conman/with-transaction [rems.db.core/*db* {:isolation :serializable}]
@@ -175,7 +79,7 @@
        :workflow/type (:type workflow)})))
 
 (defn add-application-created-event! [opts]
-  (add-event! (application-created-event (assoc opts :allocate-external-id? true))))
+  (events/add-event! (application-created-event (assoc opts :allocate-external-id? true))))
 
 (defn- get-workflow-id-for-catalogue-items [catalogue-item-ids]
   (:workflow/id (application-created-event {:catalogue-item-ids catalogue-item-ids})))
@@ -193,6 +97,27 @@
     {:success true
      :application-id app-id}))
 
+;;; Running commands
+
+(defn- fix-workflow-from-db [wf]
+  ;; TODO could use a schema for this coercion
+  (update (json/parse-string wf)
+          :type keyword))
+
+(defn get-dynamic-application-state [application-id] ; TODO: legacy code; remove me
+  (let [application (or (first (db/get-applications {:id application-id}))
+                        (throw (rems.InvalidRequestException.
+                                (str "Application " application-id " not found"))))
+        events (events/get-application-events application-id)
+        application (assoc application
+                           :state :application.state/draft
+                           :dynamic-events events
+                           :workflow (fix-workflow-from-db (:workflow application))
+                           :last-modified (or (:event/time (last events))
+                                              (:start application)))]
+    (assert (is-dynamic-application? application) (pr-str application))
+    (dynamic/apply-events application events)))
+
 (defn- valid-user? [userid]
   (not (nil? (users/get-user-attributes userid))))
 
@@ -216,22 +141,15 @@
   ;; lots of transaction conflicts when there is contention. This lock
   ;; roughly doubles the throughput for rems.db.test-transactions tests.
   (jdbc/execute! db/*db* ["LOCK TABLE application_event IN SHARE ROW EXCLUSIVE MODE"])
-  (let [events (get-application-events (:application-id cmd))
+  (let [events (events/get-application-events (:application-id cmd))
         app (-> nil
                 (dynamic/apply-events events)
                 (model/enrich-workflow-handlers workflow/get-workflow))
         result (dynamic/handle-command cmd app db-injections)]
     (if (:success result)
-      (add-event! (:result result))
+      (events/add-event! (:result result))
       result)))
 
-(defn is-dynamic-handler? [user-id application]
-  (contains? (set (get-in application [:workflow :handlers])) user-id))
-
-;; TODO use also in UI side?
-(defn is-dynamic-application? [application]
-  (= :workflow/dynamic (get-in application [:workflow :type])))
-
 (defn accept-invitation [user-id invitation-token]
   (or (when-let [application-id (:id (db/get-application-by-invitation-token {:token invitation-token}))]
         (let [response (command! {:type :application.command/accept-invitation
diff --git a/src/clj/rems/db/applications/legacy.clj b/src/clj/rems/db/applications/legacy.clj
index 49e4c7e02..045ab5824 100644
--- a/src/clj/rems/db/applications/legacy.clj
+++ b/src/clj/rems/db/applications/legacy.clj
@@ -514,3 +514,13 @@
     (when-not (can-close? user-id application)
       (throw-forbidden))
     (unjudge-application user-id application "close" round msg)))
+
+;;; Creating drafts
+
+(defn create-new-draft [user-id wfid]
+  (assert user-id)
+  (assert wfid)
+  (:id (db/create-application! {:user user-id :wfid wfid})))
+
+(defn create-new-draft-at-time [user-id wfid time]
+  (:id (db/create-application! {:user user-id :wfid wfid :start time})))
diff --git a/src/clj/rems/db/events.clj b/src/clj/rems/db/events.clj
new file mode 100644
index 000000000..0ac540236
--- /dev/null
+++ b/src/clj/rems/db/events.clj
@@ -0,0 +1,66 @@
+(ns rems.db.events
+  (:require [clj-time.format :as time-format]
+            [rems.application.events :as events]
+            [rems.db.core :as db]
+            [rems.json :as json]
+            [schema.coerce :as coerce]
+            [schema.utils]
+            [schema-tools.core :as st])
+  (:import [org.joda.time DateTime]))
+
+(defn- datestring->datetime [s]
+  (if (string? s)
+    (time-format/parse s)
+    s))
+
+(def ^:private datestring-coercion-matcher
+  {DateTime datestring->datetime})
+
+(defn- coercion-matcher [schema]
+  (or (datestring-coercion-matcher schema)
+      (coerce/string-coercion-matcher schema)))
+
+;; TODO: remove "dynamic" from names
+(def ^:private coerce-dynamic-event-commons
+  (coerce/coercer (st/open-schema events/EventBase) coercion-matcher))
+
+(def ^:private coerce-dynamic-event-specifics
+  (coerce/coercer events/Event coercion-matcher))
+
+(defn- coerce-dynamic-event [event]
+  ;; must coerce the common fields first, so that dynamic/Event can choose the right event schema based on the event type
+  (-> event
+      coerce-dynamic-event-commons
+      coerce-dynamic-event-specifics))
+
+(defn json->event [json]
+  (when json
+    (let [result (coerce-dynamic-event (json/parse-string json))]
+      (when (schema.utils/error? result)
+        ;; similar exception as what schema.core/validate throws
+        (throw (ex-info (str "Value does not match schema: " (pr-str result))
+                        {:schema events/Event :value json :error result})))
+      result)))
+
+(defn event->json [event]
+  (events/validate-event event)
+  (json/generate-string event))
+
+(defn- fix-event-from-db [event]
+  (assoc (-> event :eventdata json->event)
+         :event/id (:id event)))
+
+(defn get-application-events [application-id]
+  (map fix-event-from-db (db/get-application-events {:application application-id})))
+
+(defn get-all-events-since [event-id]
+  (map fix-event-from-db (db/get-application-events-since {:id event-id})))
+
+(defn add-event! [event]
+  (db/add-application-event! {:application (:application/id event)
+                              :user (:event/actor event)
+                              :comment nil
+                              :round -1
+                              :event (str (:event/type event))
+                              :eventdata (event->json event)})
+  nil)
diff --git a/src/clj/rems/migrations/convert_to_dynamic_applications.clj b/src/clj/rems/migrations/convert_to_dynamic_applications.clj
index 46f111c8c..4770cae0f 100644
--- a/src/clj/rems/migrations/convert_to_dynamic_applications.clj
+++ b/src/clj/rems/migrations/convert_to_dynamic_applications.clj
@@ -4,6 +4,7 @@
             [rems.db.applications :as applications]
             [rems.db.applications.legacy :as legacy]
             [rems.db.core :refer [*db*] :as db]
+            [rems.db.events :as events]
             [rems.db.workflow :as workflow]
             [rems.db.workflow-actors :as actors]
             [rems.poller.email :as email])
@@ -33,83 +34,83 @@
                                                                            (map :id))
                                                   :time (:start application)
                                                   :actor (:applicantuserid application)})
-    (applications/add-event! {:event/type :application.event/draft-saved
-                              :event/time (:start application)
-                              :event/actor (:applicantuserid application)
-                              :application/id (:id application)
-                              :application/field-values (->> (:items form)
-                                                             (map (fn [item]
-                                                                    [(:id item) (:value item)]))
-                                                             (into {}))})
-    (applications/add-event! {:event/type :application.event/licenses-accepted
-                              :event/time (:start application)
-                              :event/actor (:applicantuserid application)
-                              :application/id (:id application)
-                              :application/accepted-licenses (->> (:licenses form)
-                                                                  (filter :approved)
-                                                                  (map :id)
-                                                                  set)})
+    (events/add-event! {:event/type :application.event/draft-saved
+                        :event/time (:start application)
+                        :event/actor (:applicantuserid application)
+                        :application/id (:id application)
+                        :application/field-values (->> (:items form)
+                                                       (map (fn [item]
+                                                              [(:id item) (:value item)]))
+                                                       (into {}))})
+    (events/add-event! {:event/type :application.event/licenses-accepted
+                        :event/time (:start application)
+                        :event/actor (:applicantuserid application)
+                        :application/id (:id application)
+                        :application/accepted-licenses (->> (:licenses form)
+                                                            (filter :approved)
+                                                            (map :id)
+                                                            set)})
     (doseq [event (:events application)]
       (case (:event event)
         "save" nil ; skip - the draft-saved event is produced separately and the legacy applications don't have form history
-        "apply" (applications/add-event! {:event/type :application.event/submitted
+        "apply" (events/add-event! {:event/type :application.event/submitted
+                                    :event/time (:time event)
+                                    :event/actor (:userid event)
+                                    :application/id (:id application)})
+        "reject" (events/add-event! {:event/type :application.event/rejected
+                                     :event/time (:time event)
+                                     :event/actor (:userid event)
+                                     :application/id (:id application)
+                                     :application/comment (or (:comment event) "")})
+        "approve" (events/add-event! {:event/type :application.event/approved
+                                      :event/time (:time event)
+                                      :event/actor (:userid event)
+                                      :application/id (:id application)
+                                      :application/comment (or (:comment event) "")})
+        "autoapprove" (events/add-event! {:event/type :application.event/approved
                                           :event/time (:time event)
                                           :event/actor (:userid event)
-                                          :application/id (:id application)})
-        "reject" (applications/add-event! {:event/type :application.event/rejected
-                                           :event/time (:time event)
-                                           :event/actor (:userid event)
-                                           :application/id (:id application)
-                                           :application/comment (or (:comment event) "")})
-        "approve" (applications/add-event! {:event/type :application.event/approved
-                                            :event/time (:time event)
-                                            :event/actor (:userid event)
-                                            :application/id (:id application)
-                                            :application/comment (or (:comment event) "")})
-        "autoapprove" (applications/add-event! {:event/type :application.event/approved
-                                                :event/time (:time event)
-                                                :event/actor (:userid event)
-                                                :application/id (:id application)
-                                                :application/comment ""})
-        "return" (applications/add-event! {:event/type :application.event/returned
-                                           :event/time (:time event)
-                                           :event/actor (:userid event)
-                                           :application/id (:id application)
-                                           :application/comment (or (:comment event) "")})
-        "review" (applications/add-event! {:event/type :application.event/commented
-                                           :event/time (:time event)
-                                           :event/actor (:userid event)
-                                           :application/id (:id application)
-                                           ;; TODO: request-id doesn't make much sense for these old applications - make it optional?
-                                           :application/request-id (UUID. 0 0)
-                                           :application/comment (or (:comment event) "")})
-        "review-request" (applications/add-event! {:event/type :application.event/comment-requested
-                                                   :event/time (:time event)
-                                                   ;; TODO: the review request's actor is not known; can we guess the approver?
-                                                   :event/actor (:userid event)
-                                                   :application/id (:id application)
-                                                   :application/request-id (let [request-id (UUID/randomUUID)]
-                                                                             (swap! comment-requests-by-commenter
-                                                                                    assoc (:userid event) request-id)
-                                                                             request-id)
-                                                   :application/commenters [(:userid event)]
-                                                   :application/comment (or (:comment event) "")})
-        "third-party-review" (applications/add-event! {:event/type :application.event/commented
-                                                       :event/time (:time event)
-                                                       :event/actor (:userid event)
-                                                       :application/id (:id application)
-                                                       :application/request-id (get @comment-requests-by-commenter (:userid event))
-                                                       :application/comment (or (:comment event) "")})
-        "withdraw" (applications/add-event! {:event/type :application.event/returned
+                                          :application/id (:id application)
+                                          :application/comment ""})
+        "return" (events/add-event! {:event/type :application.event/returned
+                                     :event/time (:time event)
+                                     :event/actor (:userid event)
+                                     :application/id (:id application)
+                                     :application/comment (or (:comment event) "")})
+        "review" (events/add-event! {:event/type :application.event/commented
+                                     :event/time (:time event)
+                                     :event/actor (:userid event)
+                                     :application/id (:id application)
+                                     ;; TODO: request-id doesn't make much sense for these old applications - make it optional?
+                                     :application/request-id (UUID. 0 0)
+                                     :application/comment (or (:comment event) "")})
+        "review-request" (events/add-event! {:event/type :application.event/comment-requested
                                              :event/time (:time event)
+                                             ;; TODO: the review request's actor is not known; can we guess the approver?
                                              :event/actor (:userid event)
                                              :application/id (:id application)
+                                             :application/request-id (let [request-id (UUID/randomUUID)]
+                                                                       (swap! comment-requests-by-commenter
+                                                                              assoc (:userid event) request-id)
+                                                                       request-id)
+                                             :application/commenters [(:userid event)]
                                              :application/comment (or (:comment event) "")})
-        "close" (applications/add-event! {:event/type :application.event/closed
-                                          :event/time (:time event)
-                                          :event/actor (:userid event)
-                                          :application/id (:id application)
-                                          :application/comment (or (:comment event) "")})))))
+        "third-party-review" (events/add-event! {:event/type :application.event/commented
+                                                 :event/time (:time event)
+                                                 :event/actor (:userid event)
+                                                 :application/id (:id application)
+                                                 :application/request-id (get @comment-requests-by-commenter (:userid event))
+                                                 :application/comment (or (:comment event) "")})
+        "withdraw" (events/add-event! {:event/type :application.event/returned
+                                       :event/time (:time event)
+                                       :event/actor (:userid event)
+                                       :application/id (:id application)
+                                       :application/comment (or (:comment event) "")})
+        "close" (events/add-event! {:event/type :application.event/closed
+                                    :event/time (:time event)
+                                    :event/actor (:userid event)
+                                    :application/id (:id application)
+                                    :application/comment (or (:comment event) "")})))))
 
 (defn migrate-all-applications! [new-workflow-id]
   (conman/with-transaction [*db* {:isolation :serializable}]
diff --git a/src/clj/rems/poller/common.clj b/src/clj/rems/poller/common.clj
index 021dc63a9..0b7fc156d 100644
--- a/src/clj/rems/poller/common.clj
+++ b/src/clj/rems/poller/common.clj
@@ -3,7 +3,7 @@
   (:require [clojure.pprint :refer [pprint]]
             [clojure.test :refer :all]
             [clojure.tools.logging :as log]
-            [rems.db.applications :as applications]
+            [rems.db.events :as events]
             [rems.db.core :as db]
             [rems.json :as json]))
 
@@ -18,7 +18,7 @@
 (defn run-event-poller [name-kw process-event!]
   ;; This isn't thread-safe but ScheduledThreadPoolExecutor guarantees exclusion
   (let [prev-state (get-poller-state name-kw)
-        events (applications/get-all-events-since (:last-processed-event-id prev-state))]
+        events (events/get-all-events-since (:last-processed-event-id prev-state))]
     (log/debug name-kw "running with state" (pr-str prev-state))
     (doseq [event events]
       (when (Thread/interrupted)
@@ -47,7 +47,7 @@
                          (swap! processed conj event))
         poller-state (atom {:last-processed-event-id 0})
         run #(run-event-poller :test process-event!)]
-    (with-redefs [applications/get-all-events-since (fn [id] (filterv #(< id (:event/id %)) @events))
+    (with-redefs [events/get-all-events-since (fn [id] (filterv #(< id (:event/id %)) @events))
                   get-poller-state (fn [_] @poller-state)
                   set-poller-state! (fn [_ state] (reset! poller-state state))]
       (testing "no events, nothing should happen"
diff --git a/src/clj/rems/poller/email.clj b/src/clj/rems/poller/email.clj
index f0844bff1..91f993f6c 100644
--- a/src/clj/rems/poller/email.clj
+++ b/src/clj/rems/poller/email.clj
@@ -6,7 +6,7 @@
             [postal.core :as postal]
             [rems.api.applications-v2 :as applications-v2]
             [rems.config :refer [env]]
-            [rems.db.applications :as applications]
+            [rems.db.events :as events]
             [rems.db.users :as users]
             [rems.poller.common :as common]
             [rems.scheduler :as scheduler]
@@ -162,7 +162,7 @@
 ;; 4. open http://localhost:8025 in your browser to view the emails
 
 (defn mark-all-emails-as-sent! []
-  (let [events (applications/get-all-events-since 0)
+  (let [events (events/get-all-events-since 0)
         last-id (:event/id (last events))]
     (common/set-poller-state! ::poller {:last-processed-event-id last-id})))
 


Test patch:
diff --git a/src/clj/rems/db/test_data.clj b/src/clj/rems/db/test_data.clj
index 3693e87e4..73696be18 100644
--- a/src/clj/rems/db/test_data.clj
+++ b/src/clj/rems/db/test_data.clj
@@ -470,7 +470,7 @@
     value))
 
 (defn- create-draft! [user-id catids wfid field-value & [now]]
-  (let [app-id (applications/create-new-draft-at-time user-id wfid (or now (time/now)))
+  (let [app-id (legacy/create-new-draft-at-time user-id wfid (or now (time/now)))
         catids (if (vector? catids) catids [catids])
         _ (doseq [catid catids]
             (db/add-application-item! {:application app-id :item catid}))
diff --git a/test/clj/rems/application/test_events_cache.clj b/test/clj/rems/application/test_events_cache.clj
index f13f1dfcb..99e6fe540 100644
--- a/test/clj/rems/application/test_events_cache.clj
+++ b/test/clj/rems/application/test_events_cache.clj
@@ -3,8 +3,8 @@
             [clojure.test :refer :all]
             [mount.core :as mount]
             [rems.application.events-cache :as events-cache]
-            [rems.db.applications :as applications]
             [rems.db.core :as db]
+            [rems.db.events :as events]
             [rems.db.testing :refer [test-db-fixture rollback-db-fixture]]
             [rems.db.users :as users])
   (:import [java.util UUID]))
@@ -36,7 +36,7 @@
                :event/time (time/now)
                :event/actor user-id
                :application/id app-id}]
-    (applications/add-event! event)
+    (events/add-event! event)
     event))
 
 ;; in case the cache uses mount and somebody forgets to start it
diff --git a/test/clj/rems/db/test_applications.clj b/test/clj/rems/db/test_applications.clj
index 7a8664cf9..09c7187b5 100644
--- a/test/clj/rems/db/test_applications.clj
+++ b/test/clj/rems/db/test_applications.clj
@@ -10,6 +10,7 @@
             [rems.db.applications.legacy :as legacy]
             [rems.db.catalogue :as catalogue]
             [rems.db.core :as db]
+            [rems.db.events :as db-events]
             [rems.db.form :as form]
             [rems.db.licenses :as licenses]
             [rems.db.resource :as resource]
@@ -37,22 +38,22 @@
     (let [generators {DateTime (generators/fmap #(DateTime. ^long % DateTimeZone/UTC)
                                                 (generators/large-integer* {:min 0}))}]
       (doseq [event (sg/sample 100 events/Event generators)]
-        (is (= event (-> event event->json json->event))))))
+        (is (= event (-> event db-events/event->json db-events/json->event))))))
 
   (testing "event->json validates events"
     (is (not
          (:rems.event/validate-event
-          (try-catch-ex (event->json {}))))))
+          (try-catch-ex (db-events/event->json {}))))))
 
   (testing "json->event validates events"
-    (is (thrown-with-msg? ExceptionInfo #"Value does not match schema" (json->event "{}"))))
+    (is (thrown-with-msg? ExceptionInfo #"Value does not match schema" (db-events/json->event "{}"))))
 
   (testing "json data format"
     (let [event {:event/type :application.event/submitted
                  :event/time (DateTime. 2020 1 1 12 0 0 (DateTimeZone/forID "Europe/Helsinki"))
                  :event/actor "foo"
                  :application/id 123}
-          json (event->json event)]
+          json (db-events/event->json event)]
       (is (str/includes? json "\"event/time\":\"2020-01-01T10:00:00.000Z\"")))))
 
 (deftest test-application-created-event
diff --git a/test/clj/rems/db/test_transactions.clj b/test/clj/rems/db/test_transactions.clj
index cdfd4bc11..8de71d56e 100644
--- a/test/clj/rems/db/test_transactions.clj
+++ b/test/clj/rems/db/test_transactions.clj
@@ -5,6 +5,7 @@
             [rems.db.applications :as applications]
             [rems.db.catalogue :as catalogue]
             [rems.db.core :as db]
+            [rems.db.events :as events]
             [rems.db.form :as form]
             [rems.db.resource :as resource]
             [rems.db.testing :refer [test-db-fixture rollback-db-fixture test-data-fixture]]
@@ -110,11 +111,11 @@
                           (conman/with-transaction [db/*db* {:isolation :serializable
                                                              :read-only? true}]
                             {::app-id app-id
-                             ::events (applications/get-application-events app-id)}))
+                             ::events (events/get-application-events app-id)}))
         read-all-events (fn []
                           (conman/with-transaction [db/*db* {:isolation :serializable
                                                              :read-only? true}]
-                            {::events (applications/get-all-events-since 0)}))
+                            {::events (events/get-all-events-since 0)}))
         thread-pool (Executors/newCachedThreadPool)
         app-events-readers (submit-all thread-pool (for [app-id app-ids]
                                                      (fn [] (sample-until-interrupted
@@ -135,7 +136,7 @@
           writer-results (remove #{::transaction-conflict} writer-attempts)
           app-events-reader-results (flatten (map #(.get ^Future %) app-events-readers))
           all-events-reader-results (flatten (map #(.get ^Future %) all-events-readers))
-          final-events (applications/get-all-events-since 0)
+          final-events (events/get-all-events-since 0)
           final-events-by-app-id (group-by :application/id final-events)]
       (comment
         (prn 'writer-attempts (count writer-attempts))
diff --git a/test/clj/rems/test_db.clj b/test/clj/rems/test_db.clj
index 9be70bdb8..81420a6ff 100644
--- a/test/clj/rems/test_db.clj
+++ b/test/clj/rems/test_db.clj
@@ -62,7 +62,7 @@
                   {:type "text" :user uid :value 0})
           item-b (db/create-form-item!
                   {:type "text" :user uid :value 0})
-          app-id (applications/create-new-draft uid wf-id)]
+          app-id (legacy/create-new-draft uid wf-id)]
       (db/add-application-item! {:application app-id :item item-id})
       (db/link-form-item! {:form form-id :itemorder 2 :item (:id item-b) :user uid :optional false})
       (db/link-form-item! {:form form-id :itemorder 1 :item (:id item-a) :user uid :optional false})
@@ -179,7 +179,7 @@
         form-id (:id (db/create-form! {:organization "abc" :title "internal-title" :user "owner"}))
         item1 (:id (db/create-catalogue-item! {:title "item" :form form-id :resid res1 :wfid wfid}))
         item2 (:id (db/create-catalogue-item! {:title "item" :form form-id :resid res2 :wfid wfid}))
-        app-id (applications/create-new-draft uid wfid)]
+        app-id (legacy/create-new-draft uid wfid)]
     ;; apply for two items at the same time
     (db/add-application-item! {:application app-id :item item1})
     (db/add-application-item! {:application app-id :item item2})
@@ -213,7 +213,7 @@
   (testing "approval flow"
     (let [wf (:id (db/create-workflow! {:organization "abc" :owneruserid "owner" :modifieruserid "owner" :title "" :fnlround 1}))
           item (:id (db/create-catalogue-item! {:title "item" :form nil :resid nil :wfid wf}))
-          app (applications/create-new-draft "applicant" wf)
+          app (legacy/create-new-draft "applicant" wf)
           get-phases (fn [] (legacy/get-application-phases (:state (legacy/get-application-state app))))]
       (db/add-application-item! {:application app :item item})
       (actors/add-approver! wf "approver1" 0)
@@ -252,7 +252,7 @@
   (testing "return flow"
     (let [wf (:id (db/create-workflow! {:organization "abc" :owneruserid "owner" :modifieruserid "owner" :title "" :fnlround 1}))
           item (:id (db/create-catalogue-item! {:title "item" :form nil :resid nil :wfid wf}))
-          app (applications/create-new-draft "applicant" wf)
+          app (legacy/create-new-draft "applicant" wf)
           get-phases (fn [] (legacy/get-application-phases (:state (legacy/get-application-state app))))]
       (db/add-application-item! {:application app :item item})
       (actors/add-approver! wf "approver1" 0)
@@ -283,7 +283,7 @@
   (testing "rejection flow"
     (let [wf (:id (db/create-workflow! {:organization "abc" :owneruserid "owner" :modifieruserid "owner" :title "" :fnlround 1}))
           item (:id (db/create-catalogue-item! {:title "item" :form nil :resid nil :wfid wf}))
-          app (applications/create-new-draft "applicant" wf)
+          app (legacy/create-new-draft "applicant" wf)
           get-phases (fn [] (legacy/get-application-phases (:state (legacy/get-application-state app))))]
       (db/add-application-item! {:application app :item item})
       (actors/add-approver! wf "approver1" 0)
@@ -352,7 +352,7 @@
     (actors/add-approver! wf "event-test-approver" 1)
 
     (testing "submitting, approving"
-      (let [app (applications/create-new-draft uid wf)]
+      (let [app (legacy/create-new-draft uid wf)]
         (db/add-application-item! {:application app :item item})
 
         (is (= {:curround 0 :state "draft"} (fetch app)))
@@ -415,7 +415,7 @@
                     (map #(select-keys % [:round :event :comment])))))))
 
     (testing "rejecting"
-      (let [app (applications/create-new-draft uid wf)]
+      (let [app (legacy/create-new-draft uid wf)]
         (db/add-application-item! {:application app :item item})
 
         (is (= {:curround 0 :state "draft"} (fetch app)))
@@ -425,7 +425,7 @@
         (is (= {:curround 0 :state "rejected"} (fetch app)))))
 
     (testing "returning, resubmitting"
-      (let [app (applications/create-new-draft uid wf)]
+      (let [app (legacy/create-new-draft uid wf)]
         (db/add-application-item! {:application app :item item})
 
         (is (thrown? ForbiddenException (legacy/return-application uid app 0 "comment"))
@@ -451,7 +451,7 @@
     (testing "review"
       (let [rev-wf (:id (db/create-workflow! {:organization "abc" :owneruserid uid :modifieruserid uid :title "Review workflow" :fnlround 1}))
             rev-item (:id (db/create-catalogue-item! {:title "Review item" :resid nil :wfid rev-wf :form nil}))
-            rev-app (applications/create-new-draft uid rev-wf)]
+            rev-app (legacy/create-new-draft uid rev-wf)]
         (db/add-application-item! {:application rev-app :item rev-item})
         (actors/add-reviewer! rev-wf "event-test-reviewer" 0)
         (actors/add-approver! rev-wf uid 1)
@@ -480,12 +480,12 @@
 
     (testing "closing"
       (testing "a draft as the applicant"
-        (let [app (applications/create-new-draft uid wf)]
+        (let [app (legacy/create-new-draft uid wf)]
           (db/add-application-item! {:application app :item item})
           (legacy/close-application uid app 0 "closing draft")
           (is (= {:curround 0 :state "closed"} (fetch app)))))
       (testing "an applied application as the applicant"
-        (let [app (applications/create-new-draft uid wf)]
+        (let [app (legacy/create-new-draft uid wf)]
           (db/add-application-item! {:application app :item item})
           (legacy/submit-application uid app)
           (testing "as approver fails"
@@ -493,7 +493,7 @@
           (legacy/close-application uid app 0 "closing applied")
           (is (= {:curround 0 :state "closed"} (fetch app)))))
       (testing "an approved application as the applicant"
-        (let [app (applications/create-new-draft uid wf)]
+        (let [app (legacy/create-new-draft uid wf)]
           (db/add-application-item! {:application app :item item})
           (legacy/submit-application uid app)
           (legacy/approve-application uid app 0 "c1")
@@ -501,7 +501,7 @@
           (legacy/close-application uid app 1 "closing approved")
           (is (= {:curround 1 :state "closed"} (fetch app)))))
       (testing "an approved application as the approver"
-        (let [app (applications/create-new-draft uid wf)]
+        (let [app (legacy/create-new-draft uid wf)]
           (db/add-application-item! {:application app :item item})
           (legacy/submit-application uid app)
           (legacy/approve-application uid app 0 "c1")
@@ -513,7 +513,7 @@
       (let [res-abc (:id (db/create-resource! {:resid "ABC" :organization "abc" :owneruserid uid :modifieruserid uid}))
             auto-wf (:id (db/create-workflow! {:organization "abc" :modifieruserid uid :owneruserid uid :title "Test workflow" :fnlround 1}))
             auto-item (:id (db/create-catalogue-item! {:title "A" :form nil :resid res-abc :wfid auto-wf}))
-            auto-app (applications/create-new-draft uid auto-wf)]
+            auto-app (legacy/create-new-draft uid auto-wf)]
         (db/add-application-item! {:application auto-app :item auto-item})
         (is (= (fetch auto-app) {:curround 0 :state "draft"}))
         (legacy/submit-application uid auto-app)
@@ -530,7 +530,7 @@
       (db/add-user! {:user "third-party-reviewer", :userattrs (cheshire/generate-string {:eppn "third-party-reviewer" :mail ""})})
       (db/add-user! {:user "another-reviewer", :userattrs (cheshire/generate-string {:eppn "another-reviewer" :mail ""})})
       (testing "3rd party review"
-        (let [new-app (applications/create-new-draft uid new-wf)]
+        (let [new-app (legacy/create-new-draft uid new-wf)]
           (db/add-application-item! {:application new-app :item new-item})
           (legacy/submit-application uid new-app)
           (is (= #{:logged-in} (roles/get-roles "third-party-reviewer"))) ;; default role
@@ -561,10 +561,10 @@
                   {:round 0 :event "third-party-review" :comment "comment"}
                   {:round 0 :event "approve" :comment ""}]))))
       (testing "lazy 3rd party reviewer"
-        (let [app-to-close (applications/create-new-draft uid new-wf)
-              app-to-approve (applications/create-new-draft uid new-wf)
-              app-to-reject (applications/create-new-draft uid new-wf)
-              app-to-return (applications/create-new-draft uid new-wf)]
+        (let [app-to-close (legacy/create-new-draft uid new-wf)
+              app-to-approve (legacy/create-new-draft uid new-wf)
+              app-to-reject (legacy/create-new-draft uid new-wf)
+              app-to-return (legacy/create-new-draft uid new-wf)]
           (db/add-application-item! {:application app-to-close :item new-item})
           (db/add-application-item! {:application app-to-approve :item new-item})
           (db/add-application-item! {:application app-to-reject :item new-item})
diff --git a/test/clj/rems/test_performance.clj b/test/clj/rems/test_performance.clj
index e371a5f27..0ce018d44 100644
--- a/test/clj/rems/test_performance.clj
+++ b/test/clj/rems/test_performance.clj
@@ -5,7 +5,7 @@
             [mount.core :as mount]
             [rems.api.applications-v2 :as applications-v2]
             [rems.api.applications :as applications-api]
-            [rems.db.applications :as applications])
+            [rems.db.events :as events])
   (:import [java.util Locale]))
 
 (defn run-benchmark [benchmark]
@@ -34,10 +34,10 @@
                     (map-vals #(String/format Locale/ENGLISH "%.3f ms" (to-array [(* 1000 %)]))))))))
 
 (defn benchmark-get-events []
-  (let [last-event-id (:event/id (last (applications/get-all-events-since 0)))
-        test-get-all-events-since-beginning #(doall (applications/get-all-events-since 0))
-        test-get-all-events-since-end #(doall (applications/get-all-events-since last-event-id))
-        test-get-application-events #(doall (applications/get-application-events 12))]
+  (let [last-event-id (:event/id (last (events/get-all-events-since 0)))
+        test-get-all-events-since-beginning #(doall (events/get-all-events-since 0))
+        test-get-all-events-since-end #(doall (events/get-all-events-since last-event-id))
+        test-get-application-events #(doall (events/get-application-events 12))]
     (run-benchmarks [{:name "get-all-events-since, all events"
                       :benchmark test-get-all-events-since-beginning}
                      {:name "get-all-events-since, zero new events"