myPrayerJournal v2 #27
@ -44,6 +44,7 @@ type Recurrence =
|
|||||||
| Weeks
|
| Weeks
|
||||||
module Recurrence =
|
module Recurrence =
|
||||||
/// The string reprsentation used in the database and the web app
|
/// The string reprsentation used in the database and the web app
|
||||||
|
// TODO/FIXME: will this be true in v2? it's not in the database...
|
||||||
let toString x =
|
let toString x =
|
||||||
match x with
|
match x with
|
||||||
| Immediate -> "immediate"
|
| Immediate -> "immediate"
|
||||||
@ -67,13 +68,30 @@ module Recurrence =
|
|||||||
| Weeks -> 604800000L
|
| Weeks -> 604800000L
|
||||||
|
|
||||||
|
|
||||||
|
/// The action taken on a request as part of a history entry
|
||||||
|
type RequestAction =
|
||||||
|
| Created
|
||||||
|
| Prayed
|
||||||
|
| Updated
|
||||||
|
| Answered
|
||||||
|
module RequestAction =
|
||||||
|
/// Create a RequestAction from a string
|
||||||
|
let fromString x =
|
||||||
|
match x with
|
||||||
|
| "Created" -> Created
|
||||||
|
| "Prayed" -> Prayed
|
||||||
|
| "Updated" -> Updated
|
||||||
|
| "Answered" -> Answered
|
||||||
|
| _ -> (sprintf "Bad request action %s" >> invalidOp) x
|
||||||
|
|
||||||
|
|
||||||
/// History is a record of action taken on a prayer request, including updates to its text
|
/// History is a record of action taken on a prayer request, including updates to its text
|
||||||
[<CLIMutable; NoComparison; NoEquality>]
|
[<CLIMutable; NoComparison; NoEquality>]
|
||||||
type History =
|
type History =
|
||||||
{ /// The time when this history entry was made
|
{ /// The time when this history entry was made
|
||||||
asOf : Ticks
|
asOf : Ticks
|
||||||
/// The status for this history entry
|
/// The status for this history entry
|
||||||
status : string
|
status : RequestAction
|
||||||
/// The text of the update, if applicable
|
/// The text of the update, if applicable
|
||||||
text : string option
|
text : string option
|
||||||
}
|
}
|
||||||
@ -81,7 +99,7 @@ with
|
|||||||
/// An empty history entry
|
/// An empty history entry
|
||||||
static member empty =
|
static member empty =
|
||||||
{ asOf = Ticks 0L
|
{ asOf = Ticks 0L
|
||||||
status = ""
|
status = Created
|
||||||
text = None
|
text = None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ module Request =
|
|||||||
history = [
|
history = [
|
||||||
{ History.empty with
|
{ History.empty with
|
||||||
asOf = now
|
asOf = now
|
||||||
status = "Created"
|
status = Created
|
||||||
text = Some r.requestText
|
text = Some r.requestText
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -197,14 +197,15 @@ module Request =
|
|||||||
| Some req ->
|
| Some req ->
|
||||||
let! hist = ctx.BindJsonAsync<Models.HistoryEntry> ()
|
let! hist = ctx.BindJsonAsync<Models.HistoryEntry> ()
|
||||||
let now = jsNow ()
|
let now = jsNow ()
|
||||||
|
let act = RequestAction.fromString hist.status
|
||||||
{ History.empty with
|
{ History.empty with
|
||||||
asOf = now
|
asOf = now
|
||||||
status = hist.status
|
status = act
|
||||||
text = match hist.updateText with null | "" -> None | x -> Some x
|
text = match hist.updateText with null | "" -> None | x -> Some x
|
||||||
}
|
}
|
||||||
|> sess.AddHistory reqId
|
|> sess.AddHistory reqId
|
||||||
match hist.status with
|
match act with
|
||||||
| "Prayed" ->
|
| Prayed ->
|
||||||
(Ticks.toLong now) + (Recurrence.duration req.recurType * int64 req.recurCount)
|
(Ticks.toLong now) + (Recurrence.duration req.recurType * int64 req.recurCount)
|
||||||
|> (Ticks >> sess.UpdateShowAfter reqId)
|
|> (Ticks >> sess.UpdateShowAfter reqId)
|
||||||
| _ -> ()
|
| _ -> ()
|
||||||
|
94
src/migrate/Program.fs
Normal file
94
src/migrate/Program.fs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
|
||||||
|
open Microsoft.FSharpLu.Json
|
||||||
|
open MyPrayerJournal
|
||||||
|
open Npgsql
|
||||||
|
open Raven.Client.Documents
|
||||||
|
|
||||||
|
type NpgsqlDataReader with
|
||||||
|
member this.getShort = this.GetOrdinal >> this.GetInt16
|
||||||
|
member this.getString = this.GetOrdinal >> this.GetString
|
||||||
|
member this.getTicks = this.GetOrdinal >> this.GetInt64 >> Ticks
|
||||||
|
member this.isNull = this.GetOrdinal >> this.IsDBNull
|
||||||
|
|
||||||
|
let pgConn () =
|
||||||
|
let c = new NpgsqlConnection "Host=severus-server;Database=mpj;Username=mpj;Password=devpassword;Application Name=myPrayerJournal"
|
||||||
|
c.Open ()
|
||||||
|
c
|
||||||
|
|
||||||
|
let isValidStatus stat =
|
||||||
|
try
|
||||||
|
(RequestAction.fromString >> ignore) stat
|
||||||
|
true
|
||||||
|
with _ -> false
|
||||||
|
|
||||||
|
let getHistory reqId =
|
||||||
|
use conn = pgConn ()
|
||||||
|
use cmd = conn.CreateCommand ()
|
||||||
|
cmd.CommandText <- """SELECT "asOf", status, text FROM mpj.history WHERE "requestId" = @reqId ORDER BY "asOf" """
|
||||||
|
(cmd.Parameters.Add >> ignore) (NpgsqlParameter ("@reqId", reqId :> obj))
|
||||||
|
use rdr = cmd.ExecuteReader ()
|
||||||
|
seq {
|
||||||
|
while rdr.Read () do
|
||||||
|
match (rdr.getString >> isValidStatus) "status" with
|
||||||
|
| true ->
|
||||||
|
yield
|
||||||
|
{ asOf = rdr.getTicks "asOf"
|
||||||
|
status = (rdr.getString >> RequestAction.fromString) "status"
|
||||||
|
text = match rdr.isNull "text" with true -> None | false -> (rdr.getString >> Some) "text"
|
||||||
|
}
|
||||||
|
| false ->
|
||||||
|
printf "Invalid status %s; skipped history entry %s/%i\n" (rdr.getString "status") reqId
|
||||||
|
((rdr.getTicks >> Ticks.toLong) "asOf")
|
||||||
|
}
|
||||||
|
|> List.ofSeq
|
||||||
|
|
||||||
|
let getNotes reqId =
|
||||||
|
use conn = pgConn ()
|
||||||
|
use cmd = conn.CreateCommand ()
|
||||||
|
cmd.CommandText <- """SELECT "asOf", notes FROM mpj.note WHERE "requestId" = @reqId"""
|
||||||
|
(cmd.Parameters.Add >> ignore) (NpgsqlParameter ("@reqId", reqId :> obj))
|
||||||
|
use rdr = cmd.ExecuteReader ()
|
||||||
|
seq {
|
||||||
|
while rdr.Read () do
|
||||||
|
yield
|
||||||
|
{ asOf = rdr.getTicks "asOf"
|
||||||
|
notes = rdr.getString "notes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> List.ofSeq
|
||||||
|
|
||||||
|
let migrateRequests (store : IDocumentStore) =
|
||||||
|
use sess = store.OpenSession ()
|
||||||
|
use conn = pgConn ()
|
||||||
|
use cmd = conn.CreateCommand ()
|
||||||
|
cmd.CommandText <-
|
||||||
|
"""SELECT "requestId", "enteredOn", "userId", "snoozedUntil", "showAfter", "recurType", "recurCount" FROM mpj.request"""
|
||||||
|
use rdr = cmd.ExecuteReader ()
|
||||||
|
while rdr.Read () do
|
||||||
|
let reqId = rdr.getString "requestId"
|
||||||
|
sess.Store (
|
||||||
|
{ Id = (RequestId.fromIdString >> RequestId.toString) reqId
|
||||||
|
enteredOn = rdr.getTicks "enteredOn"
|
||||||
|
userId = (rdr.getString >> UserId) "userId"
|
||||||
|
snoozedUntil = rdr.getTicks "snoozedUntil"
|
||||||
|
showAfter = rdr.getTicks "showAfter"
|
||||||
|
recurType = (rdr.getString >> Recurrence.fromString) "recurType"
|
||||||
|
recurCount = rdr.getShort "recurCount"
|
||||||
|
history = getHistory reqId
|
||||||
|
notes = getNotes reqId
|
||||||
|
})
|
||||||
|
sess.SaveChanges ()
|
||||||
|
|
||||||
|
[<EntryPoint>]
|
||||||
|
let main argv =
|
||||||
|
let raven = new DocumentStore (Urls = [| "http://localhost:8080" |], Database = "myPrayerJournal")
|
||||||
|
raven.Conventions.CustomizeJsonSerializer <-
|
||||||
|
fun x ->
|
||||||
|
x.Converters.Add (RequestIdJsonConverter ())
|
||||||
|
x.Converters.Add (TicksJsonConverter ())
|
||||||
|
x.Converters.Add (UserIdJsonConverter ())
|
||||||
|
x.Converters.Add (CompactUnionJsonConverter ())
|
||||||
|
let store = raven.Initialize ()
|
||||||
|
migrateRequests store
|
||||||
|
printfn "fin"
|
||||||
|
0 // return an integer exit code
|
20
src/migrate/migrate.fsproj
Normal file
20
src/migrate/migrate.fsproj
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Program.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FSharp.Core" Version="4.6.2" />
|
||||||
|
<PackageReference Include="Microsoft.FSharpLu.Json" Version="0.11.2" />
|
||||||
|
<PackageReference Include="Npgsql" Version="4.0.8" />
|
||||||
|
<PackageReference Include="RavenDb.Client" Version="4.2.2" />
|
||||||
|
<ProjectReference Include="../MyPrayerJournal.Api/MyPrayerJournal.Api.fsproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
Loading…
Reference in New Issue
Block a user