Import v7.1 files

This commit is contained in:
Daniel J. Summers
2019-02-17 19:25:07 -06:00
parent d6ed11687a
commit e18cd888f3
111 changed files with 12462 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
namespace PrayerTracker
open Microsoft.EntityFrameworkCore
open PrayerTracker.Entities
/// EF Core data context for PrayerTracker
[<AllowNullLiteral>]
type AppDbContext (options : DbContextOptions<AppDbContext>) =
inherit DbContext (options)
[<DefaultValue>]
val mutable private churches : DbSet<Church>
[<DefaultValue>]
val mutable private members : DbSet<Member>
[<DefaultValue>]
val mutable private prayerRequests : DbSet<PrayerRequest>
[<DefaultValue>]
val mutable private preferences : DbSet<ListPreferences>
[<DefaultValue>]
val mutable private smallGroups : DbSet<SmallGroup>
[<DefaultValue>]
val mutable private timeZones : DbSet<TimeZone>
[<DefaultValue>]
val mutable private users : DbSet<User>
[<DefaultValue>]
val mutable private userGroupXref : DbSet<UserSmallGroup>
/// Churches
member this.Churches
with get() = this.churches
and set v = this.churches <- v
/// Small group members
member this.Members
with get() = this.members
and set v = this.members <- v
/// Prayer requests
member this.PrayerRequests
with get() = this.prayerRequests
and set v = this.prayerRequests <- v
/// Request list preferences (by class)
member this.Preferences
with get() = this.preferences
and set v = this.preferences <- v
/// Small groups
member this.SmallGroups
with get() = this.smallGroups
and set v = this.smallGroups <- v
/// Time zones
member this.TimeZones
with get() = this.timeZones
and set v = this.timeZones <- v
/// Users
member this.Users
with get() = this.users
and set v = this.users <- v
/// User / small group cross-reference
member this.UserGroupXref
with get() = this.userGroupXref
and set v = this.userGroupXref <- v
/// F#-style async for saving changes
member this.AsyncSaveChanges () =
this.SaveChangesAsync () |> Async.AwaitTask
override __.OnModelCreating (modelBuilder : ModelBuilder) =
base.OnModelCreating modelBuilder
modelBuilder.HasDefaultSchema "pt" |> ignore
[ Church.configureEF
ListPreferences.configureEF
Member.configureEF
PrayerRequest.configureEF
SmallGroup.configureEF
TimeZone.configureEF
User.configureEF
UserSmallGroup.configureEF
]
|> List.iter (fun x -> x modelBuilder)

View File

@@ -0,0 +1,300 @@
[<AutoOpen>]
module PrayerTracker.DataAccess
open FSharp.Control.Tasks.ContextInsensitive
open Microsoft.EntityFrameworkCore
open PrayerTracker.Entities
open System.Collections.Generic
open System.Linq
/// EF can return null for record types with the CLIMutable attribute; this converts a possibly-null record type to an
/// option
let optRec<'T> (r : 'T) =
match box r with null -> None | _ -> Some r
type AppDbContext with
(*-- DISCONNECTED DATA EXTENSIONS --*)
/// Add an entity entry to the tracked data context with the status of Added
member this.AddEntry<'TEntity when 'TEntity : not struct> (e : 'TEntity) =
this.Entry<'TEntity>(e).State <- EntityState.Added
/// Add an entity entry to the tracked data context with the status of Updated
member this.UpdateEntry<'TEntity when 'TEntity : not struct> (e : 'TEntity) =
this.Entry<'TEntity>(e).State <- EntityState.Modified
/// Add an entity entry to the tracked data context with the status of Deleted
member this.RemoveEntry<'TEntity when 'TEntity : not struct> (e : 'TEntity) =
this.Entry<'TEntity>(e).State <- EntityState.Deleted
(*-- CHURCH EXTENSIONS --*)
/// Find a church by its Id
member this.TryChurchById cId =
task {
let! church = this.Churches.AsNoTracking().FirstOrDefaultAsync (fun c -> c.churchId = cId)
return optRec church
}
/// Find all churches
member this.AllChurches () =
task {
let! churches = this.Churches.AsNoTracking().OrderBy(fun c -> c.name).ToListAsync ()
return List.ofSeq churches
}
(*-- MEMBER EXTENSIONS --*)
/// Get a small group member by its Id
member this.TryMemberById mId =
task {
let! mbr = this.Members.AsNoTracking().FirstOrDefaultAsync (fun m -> m.memberId = mId)
return optRec mbr
}
/// Find all members for a small group
member this.AllMembersForSmallGroup gId =
task {
let! mbrs =
this.Members.AsNoTracking()
.Where(fun m -> m.smallGroupId = gId)
.OrderBy(fun m -> m.memberName)
.ToListAsync ()
return List.ofSeq mbrs
}
/// Count members for a small group
member this.CountMembersForSmallGroup gId =
this.Members.CountAsync (fun m -> m.smallGroupId = gId)
(*-- PRAYER REQUEST EXTENSIONS *)
/// Get a prayer request by its Id
member this.TryRequestById reqId =
task {
let! req = this.PrayerRequests.AsNoTracking().FirstOrDefaultAsync (fun pr -> pr.prayerRequestId = reqId)
return optRec req
}
/// Get all (or active) requests for a small group as of now or the specified date
member this.AllRequestsForSmallGroup (grp : SmallGroup) clock listDate activeOnly : PrayerRequest seq =
let theDate = match listDate with Some dt -> dt | _ -> grp.localDateNow clock
upcast (
this.PrayerRequests.AsNoTracking().Where(fun pr -> pr.smallGroupId = grp.smallGroupId)
|> function
// Filter
| query when activeOnly ->
let asOf = theDate.AddDays(-(float grp.preferences.daysToExpire)).Date
query.Where(fun pr ->
(pr.updatedDate > asOf
|| pr.doNotExpire
|| RequestType.Recurring = pr.requestType
|| RequestType.Expecting = pr.requestType)
&& not pr.isManuallyExpired)
| query -> query
|> function
// Sort
| query when grp.preferences.requestSort = "D" ->
query.OrderByDescending(fun pr -> pr.updatedDate)
.ThenByDescending(fun pr -> pr.enteredDate)
.ThenBy(fun pr -> pr.requestor)
| query ->
query.OrderBy(fun pr -> pr.requestor)
.ThenByDescending(fun pr -> pr.updatedDate)
.ThenByDescending(fun pr -> pr.enteredDate))
/// Count prayer requests for the given small group Id
member this.CountRequestsBySmallGroup gId =
this.PrayerRequests.CountAsync (fun pr -> pr.smallGroupId = gId)
/// Count prayer requests for the given church Id
member this.CountRequestsByChurch cId =
this.PrayerRequests.CountAsync (fun pr -> pr.smallGroup.churchId = cId)
(*-- SMALL GROUP EXTENSIONS --*)
/// Find a small group by its Id
member this.TryGroupById gId =
task {
let! grp =
this.SmallGroups.AsNoTracking()
.Include(fun sg -> sg.preferences)
.FirstOrDefaultAsync (fun sg -> sg.smallGroupId = gId)
return optRec grp
}
/// Get small groups that are public or password protected
member this.PublicAndProtectedGroups () =
task {
let! grps =
this.SmallGroups.AsNoTracking()
.Include(fun sg -> sg.preferences)
.Include(fun sg -> sg.church)
.Where(fun sg ->
sg.preferences.isPublic || (sg.preferences.groupPassword <> null && sg.preferences.groupPassword <> ""))
.OrderBy(fun sg -> sg.church.name)
.ThenBy(fun sg -> sg.name)
.ToListAsync ()
return List.ofSeq grps
}
/// Get small groups that are password protected
member this.ProtectedGroups () =
task {
let! grps =
this.SmallGroups.AsNoTracking()
.Include(fun sg -> sg.church)
.Where(fun sg -> sg.preferences.groupPassword <> null && sg.preferences.groupPassword <> "")
.OrderBy(fun sg -> sg.church.name)
.ThenBy(fun sg -> sg.name)
.ToListAsync ()
return List.ofSeq grps
}
/// Get all small groups
member this.AllGroups () =
task {
let! grps =
this.SmallGroups.AsNoTracking()
.Include(fun sg -> sg.church)
.Include(fun sg -> sg.preferences)
.Include(fun sg -> sg.preferences.timeZone)
.OrderBy(fun sg -> sg.name)
.ToListAsync ()
return List.ofSeq grps
}
/// Get a small group list by their Id, with their church prepended to their name
member this.GroupList () =
task {
let! grps =
this.SmallGroups.AsNoTracking()
.Include(fun sg -> sg.church)
.OrderBy(fun sg -> sg.church.name)
.ThenBy(fun sg -> sg.name)
.ToListAsync ()
return grps
|> Seq.map (fun grp -> grp.smallGroupId.ToString "N", sprintf "%s | %s" grp.church.name grp.name)
|> Map.ofSeq
}
/// Log on a small group
member this.TryGroupLogOnByPassword gId pw =
task {
let! grp = this.TryGroupById gId
match grp with
| None -> return None
| Some g ->
match pw = g.preferences.groupPassword with
| true -> return grp
| _ -> return None
}
/// Check a cookie log on for a small group
member this.TryGroupLogOnByCookie gId pwHash (hasher : string -> string) =
task {
let! grp = this.TryGroupById gId
match grp with
| None -> return None
| Some g ->
match pwHash = hasher g.preferences.groupPassword with
| true -> return grp
| _ -> return None
}
/// Count small groups for the given church Id
member this.CountGroupsByChurch cId =
this.SmallGroups.CountAsync (fun sg -> sg.churchId = cId)
(*-- TIME ZONE EXTENSIONS --*)
/// Get a time zone by its Id
member this.TryTimeZoneById tzId =
task {
let! tz = this.TimeZones.FirstOrDefaultAsync (fun t -> t.timeZoneId = tzId)
return optRec tz
}
/// Get all time zones
member this.AllTimeZones () =
task {
let! tzs = this.TimeZones.OrderBy(fun t -> t.sortOrder).ToListAsync ()
return List.ofSeq tzs
}
(*-- USER EXTENSIONS --*)
/// Find a user by its Id
member this.TryUserById uId =
task {
let! user = this.Users.AsNoTracking().FirstOrDefaultAsync (fun u -> u.userId = uId)
return optRec user
}
/// Find a user by its e-mail address and authorized small group
member this.TryUserByEmailAndGroup email gId =
task {
let! user =
this.Users.AsNoTracking().FirstOrDefaultAsync (fun u ->
u.emailAddress = email
&& u.smallGroups.Any (fun xref -> xref.smallGroupId = gId))
return optRec user
}
/// Find a user by its Id (tracked entity), eagerly loading the user's groups
member this.TryUserByIdWithGroups uId =
task {
let! user = this.Users.Include(fun u -> u.smallGroups).FirstOrDefaultAsync (fun u -> u.userId = uId)
return optRec user
}
/// Get a list of all users
member this.AllUsers () =
task {
let! usrs = this.Users.AsNoTracking().OrderBy(fun u -> u.lastName).ThenBy(fun u -> u.firstName).ToListAsync ()
return List.ofSeq usrs
}
/// Get all PrayerTracker users as members (used to send e-mails)
member this.AllUsersAsMembers () =
task {
let! usrs =
this.Users.AsNoTracking().OrderBy(fun u -> u.lastName).ThenBy(fun u -> u.firstName).ToListAsync ()
return usrs
|> Seq.map (fun u -> { Member.empty with email = u.emailAddress; memberName = u.fullName })
|> List.ofSeq
}
/// Find a user based on their credentials
member this.TryUserLogOnByPassword email pwHash gId =
task {
let! user =
this.Users.FirstOrDefaultAsync (fun u ->
u.emailAddress = email
&& u.passwordHash = pwHash
&& u.smallGroups.Any (fun xref -> xref.smallGroupId = gId))
return optRec user
}
/// Find a user based on credentials stored in a cookie
member this.TryUserLogOnByCookie uId gId pwHash =
task {
let! user = this.TryUserByIdWithGroups uId
match user with
| None -> return None
| Some u ->
match pwHash = u.passwordHash && u.smallGroups |> Seq.exists (fun xref -> xref.smallGroupId = gId) with
| true ->
this.Entry<User>(u).State <- EntityState.Detached
return Some { u with passwordHash = ""; salt = None; smallGroups = List<UserSmallGroup>() }
| _ -> return None
}
/// Count the number of users for a small group
member this.CountUsersBySmallGroup gId =
this.Users.CountAsync (fun u -> u.smallGroups.Any (fun xref -> xref.smallGroupId = gId))
/// Count the number of users for a church
member this.CountUsersByChurch cId =
this.Users.CountAsync (fun u -> u.smallGroups.Any (fun xref -> xref.smallGroup.churchId = cId))

View File

@@ -0,0 +1,565 @@
namespace PrayerTracker.Entities
open FSharp.EFCore.OptionConverter
open Microsoft.EntityFrameworkCore
open NodaTime
open System
open System.Collections.Generic
(*-- CONSTANTS --*)
/// Constants to use for the e-mail type parameter
[<RequireQualifiedAccess>]
module EmailType =
/// HTML e-mail
[<Literal>]
let Html = "Html"
/// Plain Text e-mail
[<Literal>]
let PlainText = "PlainText"
/// E-mail with the list as an attached PDF
[<Literal>]
let AttachedPdf = "AttachedPdf"
/// These values match those in the RequestType document store
[<RequireQualifiedAccess>]
module RequestType =
/// Current Requests (follow expiration rules)
let Current = "Current"
/// Long-Term / Recurring Requests (do not automatically expire)
let Recurring = "Recurring"
/// Praise Reports (follow expiration rules)
let Praise = "Praise"
/// Expectant Mothers (do not automatically expire)
let Expecting = "Expecting"
/// Announcements (follow expiration rules)
let Announcement = "Announcement"
(*-- SUPPORT TYPES --*)
/// Statistics for churches
[<NoComparison; NoEquality>]
type ChurchStats =
{ /// The number of small groups in the church
smallGroups : int
/// The number of prayer requests in the church
prayerRequests : int
/// The number of users who can access small groups in the church
users : int
}
/// PK type for the Church entity
type ChurchId = Guid
/// PK type for the Member entity
type MemberId = Guid
/// PK type for the PrayerRequest entity
type PrayerRequestId = Guid
/// PK type for the SmallGroup entity
type SmallGroupId = Guid
/// PK type for the TimeZone entity
type TimeZoneId = string
/// PK type for the User entity
type UserId = Guid
/// PK for User/SmallGroup cross-reference table
type UserSmallGroupKey =
{ userId : UserId
smallGroupId : SmallGroupId
}
(*-- ENTITIES --*)
/// This represents a church
type [<CLIMutable; NoComparison; NoEquality>] Church =
{ /// The Id of this church
churchId : ChurchId
/// The name of the church
name : string
/// The city where the church is
city : string
/// The state where the church is
st : string
/// Does this church have an active interface with Virtual Prayer Room?
hasInterface : bool
/// The address for the interface
interfaceAddress : string option
/// Small groups for this church
smallGroups : ICollection<SmallGroup>
}
with
/// An empty church
// aww... how sad :(
static member empty =
{ churchId = Guid.Empty
name = ""
city = ""
st = ""
hasInterface = false
interfaceAddress = None
smallGroups = List<SmallGroup> ()
}
/// Configure EF for this entity
static member internal configureEF (mb : ModelBuilder) =
mb.Entity<Church> (
fun m ->
m.ToTable "Church" |> ignore
m.Property(fun e -> e.churchId).HasColumnName "ChurchId" |> ignore
m.Property(fun e -> e.name).HasColumnName("Name").IsRequired () |> ignore
m.Property(fun e -> e.city).HasColumnName("City").IsRequired () |> ignore
m.Property(fun e -> e.st).HasColumnName("ST").IsRequired().HasMaxLength 2 |> ignore
m.Property(fun e -> e.hasInterface).HasColumnName "HasVirtualPrayerRoomInterface" |> ignore
m.Property(fun e -> e.interfaceAddress).HasColumnName "InterfaceAddress" |> ignore)
|> ignore
mb.Model.FindEntityType(typeof<Church>).FindProperty("interfaceAddress")
.SetValueConverter(OptionConverter<string> ())
/// Preferences for the form and format of the prayer request list
and [<CLIMutable; NoComparison; NoEquality>] ListPreferences =
{ /// The Id of the small group to which these preferences belong
smallGroupId : SmallGroupId
/// The days after which regular requests expire
daysToExpire : int
/// The number of days a new or updated request is considered new
daysToKeepNew : int
/// The number of weeks after which long-term requests are flagged for follow-up
longTermUpdateWeeks : int
/// The name from which e-mails are sent
emailFromName : string
/// The e-mail address from which e-mails are sent
emailFromAddress : string
/// The fonts to use in generating the list of prayer requests
listFonts : string
/// The color for the prayer request list headings
headingColor : string
/// The color for the lines offsetting the prayer request list headings
lineColor : string
/// The font size for the headings on the prayer request list
headingFontSize : int
/// The font size for the text on the prayer request list
textFontSize : int
/// The order in which the prayer requests are sorted
requestSort : string
/// The password used for "small group login" (view-only request list)
groupPassword : string
/// The default e-mail type for this class
defaultEmailType : string
/// Whether this class makes its request list public
isPublic : bool
/// The time zone which this class uses (use tzdata names)
timeZoneId : TimeZoneId
/// The time zone information
timeZone : TimeZone
}
with
/// A set of preferences with their default values
static member empty =
{ smallGroupId = Guid.Empty
daysToExpire = 14
daysToKeepNew = 7
longTermUpdateWeeks = 4
emailFromName = "PrayerTracker"
emailFromAddress = "prayer@djs-consulting.com"
listFonts = "Century Gothic,Tahoma,Luxi Sans,sans-serif"
headingColor = "maroon"
lineColor = "navy"
headingFontSize = 16
textFontSize = 12
requestSort = "D"
groupPassword = ""
defaultEmailType = EmailType.Html
isPublic = false
timeZoneId = "America/Denver"
timeZone = TimeZone.empty
}
/// Configure EF for this entity
static member internal configureEF (mb : ModelBuilder) =
mb.Entity<ListPreferences> (
fun m ->
m.ToTable "ListPreference" |> ignore
m.HasKey (fun e -> e.smallGroupId :> obj) |> ignore
m.Property(fun e -> e.smallGroupId).HasColumnName "SmallGroupId" |> ignore
m.Property(fun e -> e.daysToKeepNew)
.HasColumnName("DaysToKeepNew")
.IsRequired()
.HasDefaultValue(7)
|> ignore
m.Property(fun e -> e.daysToExpire)
.HasColumnName("DaysToExpire")
.IsRequired()
.HasDefaultValue(14)
|> ignore
m.Property(fun e -> e.longTermUpdateWeeks)
.HasColumnName("LongTermUpdateWeeks")
.IsRequired()
.HasDefaultValue(4)
|> ignore
m.Property(fun e -> e.emailFromName)
.HasColumnName("EmailFromName")
.IsRequired()
.HasDefaultValue("PrayerTracker")
|> ignore
m.Property(fun e -> e.emailFromAddress)
.HasColumnName("EmailFromAddress")
.IsRequired()
.HasDefaultValue("prayer@djs-consulting.com")
|> ignore
m.Property(fun e -> e.listFonts)
.HasColumnName("ListFonts")
.IsRequired()
.HasDefaultValue("Century Gothic,Tahoma,Luxi Sans,sans-serif")
|> ignore
m.Property(fun e -> e.headingColor)
.HasColumnName("HeadingColor")
.IsRequired()
.HasDefaultValue("maroon")
|> ignore
m.Property(fun e -> e.lineColor)
.HasColumnName("LineColor")
.IsRequired()
.HasDefaultValue("navy")
|> ignore
m.Property(fun e -> e.headingFontSize)
.HasColumnName("HeadingFontSize")
.IsRequired()
.HasDefaultValue(16)
|> ignore
m.Property(fun e -> e.textFontSize)
.HasColumnName("TextFontSize")
.IsRequired()
.HasDefaultValue(12)
|> ignore
m.Property(fun e -> e.requestSort)
.HasColumnName("RequestSort")
.IsRequired()
.HasMaxLength(1)
.HasDefaultValue("D")
|> ignore
m.Property(fun e -> e.groupPassword)
.HasColumnName("GroupPassword")
.IsRequired()
.HasDefaultValue("")
|> ignore
m.Property(fun e -> e.defaultEmailType)
.HasColumnName("DefaultEmailType")
.IsRequired()
.HasDefaultValue(EmailType.Html)
|> ignore
m.Property(fun e -> e.isPublic)
.HasColumnName("IsPublic")
.IsRequired()
.HasDefaultValue(false)
|> ignore
m.Property(fun e -> e.timeZoneId)
.HasColumnName("TimeZoneId")
.IsRequired()
.HasDefaultValue("America/Denver")
|> ignore)
|> ignore
/// A member of a small group
and [<CLIMutable; NoComparison; NoEquality>] Member =
{ /// The Id of the member
memberId : MemberId
/// The Id of the small group to which this member belongs
smallGroupId : SmallGroupId
/// The name of the member
memberName : string
/// The e-mail address for the member
email : string
/// The type of e-mail preferred by this member (see <see cref="EmailTypes"/> constants)
format : string option
/// The small group to which this member belongs
smallGroup : SmallGroup
}
with
/// An empty member
static member empty =
{ memberId = Guid.Empty
smallGroupId = Guid.Empty
memberName = ""
email = ""
format = None
smallGroup = SmallGroup.empty
}
/// Configure EF for this entity
static member internal configureEF (mb : ModelBuilder) =
mb.Entity<Member> (
fun m ->
m.ToTable "Member" |> ignore
m.Property(fun e -> e.memberId).HasColumnName "MemberId" |> ignore
m.Property(fun e -> e.smallGroupId).HasColumnName "SmallGroupId" |> ignore
m.Property(fun e -> e.memberName).HasColumnName("MemberName").IsRequired() |> ignore
m.Property(fun e -> e.email).HasColumnName("Email").IsRequired() |> ignore
m.Property(fun e -> e.format).HasColumnName "Format" |> ignore)
|> ignore
mb.Model.FindEntityType(typeof<Member>).FindProperty("format").SetValueConverter(OptionConverter<string> ())
/// This represents a single prayer request
and [<CLIMutable; NoComparison; NoEquality>] PrayerRequest =
{ /// The Id of this request
prayerRequestId : PrayerRequestId
/// The type of the request
requestType : string
/// The user who entered the request
userId : UserId
/// The small group to which this request belongs
smallGroupId : SmallGroupId
/// The date/time on which this request was entered
enteredDate : DateTime
/// The date/time this request was last updated
updatedDate : DateTime
/// The name of the requestor or subject, or title of announcement
requestor : string option
/// The text of the request
text : string
/// Whether this request is exempt from standard expiration rules
doNotExpire : bool
/// Whether the chaplain should be notified for this request
notifyChaplain : bool
/// Whether this request has been expired manually
isManuallyExpired : bool
/// The user who entered this request
user : User
/// The small group to which this request belongs
smallGroup : SmallGroup
}
with
/// An empty request
static member empty =
{ prayerRequestId = Guid.Empty
requestType = RequestType.Current
userId = Guid.Empty
smallGroupId = Guid.Empty
enteredDate = DateTime.MinValue
updatedDate = DateTime.MinValue
requestor = None
text = ""
doNotExpire = false
notifyChaplain = false
isManuallyExpired = false
user = User.empty
smallGroup = SmallGroup.empty
}
/// Is this request expired?
member this.isExpired (curr : DateTime) expDays =
match this.isManuallyExpired with
| true -> true // Manual expiration
| false ->
let nonExpiringTypes = [ RequestType.Recurring; RequestType.Expecting ]
match this.doNotExpire || List.contains this.requestType nonExpiringTypes with
| true -> false // No expiration
| false -> curr.AddDays(-(float expDays)) > this.updatedDate // Automatic expiration
/// Is an update required for this long-term request?
member this.updateRequired curr expDays updWeeks =
match this.isExpired curr expDays with
| true -> false
| _ -> curr.AddDays(-(float (updWeeks * 7))) > this.updatedDate
/// Configure EF for this entity
static member internal configureEF (mb : ModelBuilder) =
mb.Entity<PrayerRequest> (
fun m ->
m.ToTable "PrayerRequest" |> ignore
m.Property(fun e -> e.prayerRequestId).HasColumnName "PrayerRequestId" |> ignore
m.Property(fun e -> e.requestType).HasColumnName("RequestType").IsRequired() |> ignore
m.Property(fun e -> e.userId).HasColumnName "UserId" |> ignore
m.Property(fun e -> e.smallGroupId).HasColumnName "SmallGroupId" |> ignore
m.Property(fun e -> e.enteredDate).HasColumnName "EnteredDate" |> ignore
m.Property(fun e -> e.updatedDate).HasColumnName "UpdatedDate" |> ignore
m.Property(fun e -> e.requestor).HasColumnName "Requestor" |> ignore
m.Property(fun e -> e.text).HasColumnName("Text").IsRequired() |> ignore
m.Property(fun e -> e.doNotExpire).HasColumnName "DoNotExpire" |> ignore
m.Property(fun e -> e.notifyChaplain).HasColumnName "NotifyChaplain" |> ignore
m.Property(fun e -> e.isManuallyExpired).HasColumnName "IsManuallyExpired" |> ignore)
|> ignore
mb.Model.FindEntityType(typeof<PrayerRequest>).FindProperty("requestor")
.SetValueConverter(OptionConverter<string> ())
/// This represents a small group (Sunday School class, Bible study group, etc.)
and [<CLIMutable; NoComparison; NoEquality>] SmallGroup =
{ /// The Id of this small group
smallGroupId : SmallGroupId
/// The church to which this group belongs
churchId : ChurchId
/// The name of the group
name : string
/// The church to which this small group belongs
church : Church
/// The preferences for the request list
preferences : ListPreferences
/// The members of the group
members : ICollection<Member>
/// Prayer requests for this small group
prayerRequests : ICollection<PrayerRequest>
/// The users authorized to manage this group
users : ICollection<UserSmallGroup>
}
with
/// An empty small group
static member empty =
{ smallGroupId = Guid.Empty
churchId = Guid.Empty
name = ""
church = Church.empty
preferences = ListPreferences.empty
members = List<Member> ()
prayerRequests = List<PrayerRequest> ()
users = List<UserSmallGroup> ()
}
/// Get the local date for this group
member this.localTimeNow (clock : IClock) =
match clock with null -> nullArg "clock" | _ -> ()
let tz =
match DateTimeZoneProviders.Tzdb.Ids.Contains this.preferences.timeZoneId with
| true -> DateTimeZoneProviders.Tzdb.[this.preferences.timeZoneId]
| false -> DateTimeZone.Utc
clock.GetCurrentInstant().InZone(tz).ToDateTimeUnspecified()
/// Get the local date for this group
member this.localDateNow clock =
(this.localTimeNow clock).Date
/// Configure EF for this entity
static member internal configureEF (mb : ModelBuilder) =
mb.Entity<SmallGroup> (
fun m ->
m.ToTable "SmallGroup" |> ignore
m.Property(fun e -> e.smallGroupId).HasColumnName "SmallGroupId" |> ignore
m.Property(fun e -> e.churchId).HasColumnName "ChurchId" |> ignore
m.Property(fun e -> e.name).HasColumnName("Name").IsRequired() |> ignore
m.HasOne(fun e -> e.preferences) |> ignore)
|> ignore
/// This represents a time zone in which a class may reside
and [<CLIMutable; NoComparison; NoEquality>] TimeZone =
{ /// The Id for this time zone (uses tzdata names)
timeZoneId : TimeZoneId
/// The description of this time zone
description : string
/// The order in which this timezone should be displayed
sortOrder : int
/// Whether this timezone is active
isActive : bool
}
with
/// An empty time zone
static member empty =
{ timeZoneId = ""
description = ""
sortOrder = 0
isActive = false
}
/// Configure EF for this entity
static member internal configureEF (mb : ModelBuilder) =
mb.Entity<TimeZone> (
fun m ->
m.ToTable "TimeZone" |> ignore
m.Property(fun e -> e.timeZoneId).HasColumnName "TimeZoneId" |> ignore
m.Property(fun e -> e.description).HasColumnName("Description").IsRequired() |> ignore
m.Property(fun e -> e.sortOrder).HasColumnName "SortOrder" |> ignore
m.Property(fun e -> e.isActive).HasColumnName "IsActive" |> ignore)
|> ignore
/// This represents a user of PrayerTracker
and [<CLIMutable; NoComparison; NoEquality>] User =
{ /// The Id of this user
userId : UserId
/// The first name of this user
firstName : string
/// The last name of this user
lastName : string
/// The e-mail address of the user
emailAddress : string
/// Whether this user is a PrayerTracker system administrator
isAdmin : bool
/// The user's hashed password
passwordHash : string
/// The salt for the user's hashed password
salt : Guid option
/// The small groups which this user is authorized
smallGroups : ICollection<UserSmallGroup>
}
with
/// An empty user
static member empty =
{ userId = Guid.Empty
firstName = ""
lastName = ""
emailAddress = ""
isAdmin = false
passwordHash = ""
salt = None
smallGroups = List<UserSmallGroup> ()
}
/// The full name of the user
member this.fullName =
sprintf "%s %s" this.firstName this.lastName
/// Configure EF for this entity
static member internal configureEF (mb : ModelBuilder) =
mb.Entity<User> (
fun m ->
m.ToTable "User" |> ignore
m.Ignore(fun e -> e.fullName :> obj) |> ignore
m.Property(fun e -> e.userId).HasColumnName "UserId" |> ignore
m.Property(fun e -> e.firstName).HasColumnName("FirstName").IsRequired() |> ignore
m.Property(fun e -> e.lastName).HasColumnName("LastName").IsRequired() |> ignore
m.Property(fun e -> e.emailAddress).HasColumnName("EmailAddress").IsRequired() |> ignore
m.Property(fun e -> e.isAdmin).HasColumnName "IsSystemAdmin" |> ignore
m.Property(fun e -> e.passwordHash).HasColumnName("PasswordHash").IsRequired() |> ignore
m.Property(fun e -> e.salt).HasColumnName "Salt" |> ignore)
|> ignore
mb.Model.FindEntityType(typeof<User>).FindProperty("salt")
.SetValueConverter(OptionConverter<Guid> ())
/// Cross-reference between user and small group
and [<CLIMutable; NoComparison; NoEquality>] UserSmallGroup =
{ /// The Id of the user who has access to the small group
userId : UserId
/// The Id of the small group to which the user has access
smallGroupId : SmallGroupId
/// The user who has access to the small group
user : User
/// The small group to which the user has access
smallGroup : SmallGroup
}
with
/// An empty user/small group xref
static member empty =
{ userId = Guid.Empty
smallGroupId = Guid.Empty
user = User.empty
smallGroup = SmallGroup.empty
}
/// Configure EF for this entity
static member internal configureEF (mb : ModelBuilder) =
mb.Entity<UserSmallGroup> (
fun m ->
m.ToTable "User_SmallGroup" |> ignore
m.HasKey(fun e -> { userId = e.userId; smallGroupId = e.smallGroupId } :> obj) |> ignore
m.Property(fun e -> e.userId).HasColumnName "UserId" |> ignore
m.Property(fun e -> e.smallGroupId).HasColumnName "SmallGroupId" |> ignore
m.HasOne(fun e -> e.user)
.WithMany(fun e -> e.smallGroups :> IEnumerable<UserSmallGroup>)
.HasForeignKey(fun e -> e.userId :> obj)
|> ignore
m.HasOne(fun e -> e.smallGroup)
.WithMany(fun e -> e.users :> IEnumerable<UserSmallGroup>)
.HasForeignKey(fun e -> e.smallGroupId :> obj)
|> ignore)
|> ignore

View File

@@ -0,0 +1,510 @@
namespace PrayerTracker.Migrations
open Microsoft.EntityFrameworkCore
open Microsoft.EntityFrameworkCore.Infrastructure
open Microsoft.EntityFrameworkCore.Migrations
open Microsoft.EntityFrameworkCore.Migrations.Operations
open Microsoft.EntityFrameworkCore.Migrations.Operations.Builders
open Npgsql.EntityFrameworkCore.PostgreSQL.Metadata
open PrayerTracker
open PrayerTracker.Entities
open System
type ChurchTable =
{ churchId : OperationBuilder<AddColumnOperation>
city : OperationBuilder<AddColumnOperation>
hasInterface : OperationBuilder<AddColumnOperation>
interfaceAddress : OperationBuilder<AddColumnOperation>
name : OperationBuilder<AddColumnOperation>
st : OperationBuilder<AddColumnOperation>
}
type ListPreferencesTable =
{ smallGroupId : OperationBuilder<AddColumnOperation>
daysToExpire : OperationBuilder<AddColumnOperation>
daysToKeepNew : OperationBuilder<AddColumnOperation>
defaultEmailType : OperationBuilder<AddColumnOperation>
emailFromAddress : OperationBuilder<AddColumnOperation>
emailFromName : OperationBuilder<AddColumnOperation>
groupPassword : OperationBuilder<AddColumnOperation>
headingColor : OperationBuilder<AddColumnOperation>
headingFontSize : OperationBuilder<AddColumnOperation>
isPublic : OperationBuilder<AddColumnOperation>
lineColor : OperationBuilder<AddColumnOperation>
listFonts : OperationBuilder<AddColumnOperation>
longTermUpdateWeeks : OperationBuilder<AddColumnOperation>
requestSort : OperationBuilder<AddColumnOperation>
textFontSize : OperationBuilder<AddColumnOperation>
timeZoneId : OperationBuilder<AddColumnOperation>
}
type MemberTable =
{ memberId : OperationBuilder<AddColumnOperation>
email : OperationBuilder<AddColumnOperation>
format : OperationBuilder<AddColumnOperation>
memberName : OperationBuilder<AddColumnOperation>
smallGroupId : OperationBuilder<AddColumnOperation>
}
type PrayerRequestTable =
{ prayerRequestId : OperationBuilder<AddColumnOperation>
doNotExpire : OperationBuilder<AddColumnOperation>
enteredDate : OperationBuilder<AddColumnOperation>
isManuallyExpired : OperationBuilder<AddColumnOperation>
notifyChaplain : OperationBuilder<AddColumnOperation>
requestType : OperationBuilder<AddColumnOperation>
requestor : OperationBuilder<AddColumnOperation>
smallGroupId : OperationBuilder<AddColumnOperation>
text : OperationBuilder<AddColumnOperation>
updatedDate : OperationBuilder<AddColumnOperation>
userId : OperationBuilder<AddColumnOperation>
}
type SmallGroupTable =
{ smallGroupId : OperationBuilder<AddColumnOperation>
churchId : OperationBuilder<AddColumnOperation>
name : OperationBuilder<AddColumnOperation>
}
type TimeZoneTable =
{ timeZoneId : OperationBuilder<AddColumnOperation>
description : OperationBuilder<AddColumnOperation>
isActive : OperationBuilder<AddColumnOperation>
sortOrder : OperationBuilder<AddColumnOperation>
}
type UserSmallGroupTable =
{ userId : OperationBuilder<AddColumnOperation>
smallGroupId : OperationBuilder<AddColumnOperation>
}
type UserTable =
{ userId : OperationBuilder<AddColumnOperation>
emailAddress : OperationBuilder<AddColumnOperation>
firstName : OperationBuilder<AddColumnOperation>
isAdmin : OperationBuilder<AddColumnOperation>
lastName : OperationBuilder<AddColumnOperation>
passwordHash : OperationBuilder<AddColumnOperation>
salt : OperationBuilder<AddColumnOperation>
}
[<DbContext (typeof<AppDbContext>)>]
[<Migration "20161217153124_InitialDatabase">]
type InitialDatabase () =
inherit Migration ()
override __.Up (migrationBuilder : MigrationBuilder) =
migrationBuilder.EnsureSchema (name = "pt")
|> ignore
migrationBuilder.CreateTable (
name = "Church",
schema = "pt",
columns =
(fun table ->
{ churchId = table.Column<Guid> (name = "ChurchId", nullable = false)
city = table.Column<string> (name = "City", nullable = false)
hasInterface = table.Column<bool> (name = "HasVirtualPrayerRoomInterface", nullable = false)
interfaceAddress = table.Column<string> (name = "InterfaceAddress", nullable = true)
name = table.Column<string> (name = "Name", nullable = false)
st = table.Column<string> (name = "ST", maxLength = Nullable<int> 2, nullable = false)
}),
constraints =
fun table ->
table.PrimaryKey ("PK_Church", fun x -> upcast x.churchId) |> ignore)
|> ignore
migrationBuilder.CreateTable (
name = "TimeZone",
schema = "pt",
columns =
(fun table ->
{ timeZoneId = table.Column<string> (name = "TimeZoneId", nullable = false)
description = table.Column<string> (name = "Description", nullable = false)
isActive = table.Column<bool> (name = "IsActive", nullable = false)
sortOrder = table.Column<int> (name = "SortOrder", nullable = false)
}),
constraints =
fun table ->
table.PrimaryKey ("PK_TimeZone", fun x -> upcast x.timeZoneId) |> ignore)
|> ignore
migrationBuilder.CreateTable (
name = "User",
schema = "pt",
columns =
(fun table ->
{ userId = table.Column<Guid> (name = "UserId", nullable = false)
emailAddress = table.Column<string> (name = "EmailAddress", nullable = false)
firstName = table.Column<string> (name = "FirstName", nullable = false)
isAdmin = table.Column<bool> (name = "IsSystemAdmin", nullable = false)
lastName = table.Column<string> (name = "LastName", nullable = false)
passwordHash = table.Column<string> (name = "PasswordHash", nullable = false)
salt = table.Column<Guid> (name = "Salt", nullable = true)
}),
constraints =
fun table ->
table.PrimaryKey("PK_User", fun x -> upcast x.userId) |> ignore)
|> ignore
migrationBuilder.CreateTable (
name = "SmallGroup",
schema = "pt",
columns =
(fun table ->
{ smallGroupId = table.Column<Guid> (name = "SmallGroupId", nullable = false)
churchId = table.Column<Guid> (name = "ChurchId", nullable = false)
name = table.Column<string> (name = "Name", nullable = false)
}),
constraints =
fun table ->
table.PrimaryKey ("PK_SmallGroup", fun x -> upcast x.smallGroupId) |> ignore
table.ForeignKey (
name = "FK_SmallGroup_Church_ChurchId",
column = (fun x -> upcast x.churchId),
principalSchema = "pt",
principalTable = "Church",
principalColumn = "ChurchId",
onDelete = ReferentialAction.Cascade)
|> ignore)
|> ignore
migrationBuilder.CreateTable (
name = "ListPreference",
schema = "pt",
columns =
(fun table ->
{ smallGroupId = table.Column<Guid> (name = "SmallGroupId", nullable = false)
daysToExpire = table.Column<int> (name = "DaysToExpire", nullable = false, defaultValue = 14)
daysToKeepNew = table.Column<int> (name = "DaysToKeepNew", nullable = false, defaultValue = 7)
defaultEmailType = table.Column<string> (name = "DefaultEmailType", nullable = false, defaultValue = "Html")
emailFromAddress = table.Column<string> (name = "EmailFromAddress", nullable = false, defaultValue = "prayer@djs-consulting.com")
emailFromName = table.Column<string> (name = "EmailFromName", nullable = false, defaultValue = "PrayerTracker")
groupPassword = table.Column<string> (name = "GroupPassword", nullable = false, defaultValue = "")
headingColor = table.Column<string> (name = "HeadingColor", nullable = false, defaultValue = "maroon")
headingFontSize = table.Column<int> (name = "HeadingFontSize", nullable = false, defaultValue = 16)
isPublic = table.Column<bool> (name = "IsPublic", nullable = false, defaultValue = false)
lineColor = table.Column<string> (name = "LineColor", nullable = false, defaultValue = "navy")
listFonts = table.Column<string> (name = "ListFonts", nullable = false, defaultValue = "Century Gothic,Tahoma,Luxi Sans,sans-serif")
longTermUpdateWeeks = table.Column<int> (name = "LongTermUpdateWeeks", nullable = false, defaultValue = 4)
requestSort = table.Column<string> (name = "RequestSort", maxLength = Nullable<int> 1, nullable = false, defaultValue = "D")
textFontSize = table.Column<int> (name = "TextFontSize", nullable = false, defaultValue = 12)
timeZoneId = table.Column<string> (name = "TimeZoneId", nullable = false, defaultValue = "America/Denver")
}),
constraints =
fun table ->
table.PrimaryKey ("PK_ListPreference", fun x -> upcast x.smallGroupId) |> ignore
table.ForeignKey (
name = "FK_ListPreference_SmallGroup_SmallGroupId",
column = (fun x -> upcast x.smallGroupId),
principalSchema = "pt",
principalTable = "SmallGroup",
principalColumn = "SmallGroupId",
onDelete = ReferentialAction.Cascade)
|> ignore
table.ForeignKey (
name = "FK_ListPreference_TimeZone_TimeZoneId",
column = (fun x -> upcast x.timeZoneId),
principalSchema = "pt",
principalTable = "TimeZone",
principalColumn = "TimeZoneId",
onDelete = ReferentialAction.Cascade)
|> ignore)
|> ignore
migrationBuilder.CreateTable (
name = "Member",
schema = "pt",
columns =
(fun table ->
{ memberId = table.Column<Guid> (name = "MemberId", nullable = false)
email = table.Column<string> (name = "Email", nullable = false)
format = table.Column<string> (name = "Format", nullable = true)
memberName = table.Column<string> (name = "MemberName", nullable = false)
smallGroupId = table.Column<Guid> (name = "SmallGroupId", nullable = false)
}),
constraints =
fun table ->
table.PrimaryKey ("PK_Member", fun x -> upcast x.memberId) |> ignore
table.ForeignKey (
name = "FK_Member_SmallGroup_SmallGroupId",
column = (fun x -> upcast x.smallGroupId),
principalSchema = "pt",
principalTable = "SmallGroup",
principalColumn = "SmallGroupId",
onDelete = ReferentialAction.Cascade)
|> ignore)
|> ignore
migrationBuilder.CreateTable (
name = "PrayerRequest",
schema = "pt",
columns =
(fun table ->
{ prayerRequestId = table.Column<Guid> (name = "PrayerRequestId", nullable = false)
doNotExpire = table.Column<bool> (name = "DoNotExpire", nullable = false)
enteredDate = table.Column<DateTime> (name = "EnteredDate", nullable = false)
isManuallyExpired = table.Column<bool> (name = "IsManuallyExpired", nullable = false)
notifyChaplain = table.Column<bool> (name = "NotifyChaplain", nullable = false)
requestType = table.Column<string> (name = "RequestType", nullable = false)
requestor = table.Column<string> (name = "Requestor", nullable = true)
smallGroupId = table.Column<Guid> (name = "SmallGroupId", nullable = false)
text = table.Column<string> (name = "Text", nullable = false)
updatedDate = table.Column<DateTime> (name = "UpdatedDate", nullable = false)
userId = table.Column<Guid> (name = "UserId", nullable = false)
}),
constraints =
fun table ->
table.PrimaryKey ("PK_PrayerRequest", fun x -> upcast x.prayerRequestId) |> ignore
table.ForeignKey (
name = "FK_PrayerRequest_SmallGroup_SmallGroupId",
column = (fun x -> upcast x.smallGroupId),
principalSchema = "pt",
principalTable = "SmallGroup",
principalColumn = "SmallGroupId",
onDelete = ReferentialAction.Cascade)
|> ignore
table.ForeignKey (
name = "FK_PrayerRequest_User_UserId",
column = (fun x -> upcast x.userId),
principalSchema = "pt",
principalTable = "User",
principalColumn = "UserId",
onDelete = ReferentialAction.Cascade)
|> ignore)
|> ignore
migrationBuilder.CreateTable(
name = "User_SmallGroup",
schema = "pt",
columns =
(fun table ->
{ userId = table.Column<Guid> (name = "UserId", nullable = false)
smallGroupId = table.Column<Guid> (name = "SmallGroupId", nullable = false)
}),
constraints =
fun table ->
table.PrimaryKey ("PK_User_SmallGroup", fun x -> upcast x) |> ignore
table.ForeignKey (
name = "FK_User_SmallGroup_SmallGroup_SmallGroupId",
column = (fun x -> upcast x.smallGroupId),
principalSchema = "pt",
principalTable = "SmallGroup",
principalColumn = "SmallGroupId",
onDelete = ReferentialAction.Cascade)
|> ignore
table.ForeignKey (
name = "FK_User_SmallGroup_User_UserId",
column = (fun x -> upcast x.userId),
principalSchema = "pt",
principalTable = "User",
principalColumn = "UserId",
onDelete = ReferentialAction.Cascade)
|> ignore)
|> ignore
migrationBuilder.CreateIndex (name = "IX_ListPreference_TimeZoneId", schema = "pt", table = "ListPreference", column = "TimeZoneId") |> ignore
migrationBuilder.CreateIndex (name = "IX_Member_SmallGroupId", schema = "pt", table = "Member", column = "SmallGroupId") |> ignore
migrationBuilder.CreateIndex (name = "IX_PrayerRequest_SmallGroupId", schema = "pt", table = "PrayerRequest", column = "SmallGroupId") |> ignore
migrationBuilder.CreateIndex (name = "IX_PrayerRequest_UserId", schema = "pt", table = "PrayerRequest", column = "UserId") |> ignore
migrationBuilder.CreateIndex (name = "IX_SmallGroup_ChurchId", schema = "pt", table = "SmallGroup", column = "ChurchId") |> ignore
migrationBuilder.CreateIndex (name = "IX_User_SmallGroup_SmallGroupId", schema = "pt", table = "User_SmallGroup", column = "SmallGroupId") |> ignore
override __.Down (migrationBuilder : MigrationBuilder) =
migrationBuilder.DropTable (name = "ListPreference", schema = "pt") |> ignore
migrationBuilder.DropTable (name = "Member", schema = "pt") |> ignore
migrationBuilder.DropTable (name = "PrayerRequest", schema = "pt") |> ignore
migrationBuilder.DropTable (name = "User_SmallGroup", schema = "pt") |> ignore
migrationBuilder.DropTable (name = "TimeZone", schema = "pt") |> ignore
migrationBuilder.DropTable (name = "SmallGroup", schema = "pt") |> ignore
migrationBuilder.DropTable (name = "User", schema = "pt") |> ignore
migrationBuilder.DropTable (name = "Church", schema = "pt") |> ignore
override __.BuildTargetModel (modelBuilder : ModelBuilder) =
modelBuilder
.HasDefaultSchema("pt")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.HasAnnotation("ProductVersion", "1.1.0-rtm-22752")
|> ignore
modelBuilder.Entity (
typeof<Church>,
fun b ->
b.Property<Guid>("churchId").ValueGeneratedOnAdd() |> ignore
b.Property<string>("city").IsRequired() |> ignore
b.Property<bool>("hasInterface") |> ignore
b.Property<string>("interfaceAddress") |> ignore
b.Property<string>("name").IsRequired() |> ignore
b.Property<string>("st").IsRequired().HasMaxLength(2) |> ignore
b.HasKey("churchId") |> ignore
b.ToTable("Church") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<ListPreferences>,
fun b ->
b.Property<Guid>("smallGroupId") |> ignore
b.Property<int>("daysToExpire").ValueGeneratedOnAdd().HasDefaultValue(14) |> ignore
b.Property<int>("daysToKeepNew").ValueGeneratedOnAdd().HasDefaultValue(7) |> ignore
b.Property<string>("defaultEmailType").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("Html") |> ignore
b.Property<string>("emailFromAddress").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("prayer@djs-consulting.com") |> ignore
b.Property<string>("emailFromName").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("PrayerTracker") |> ignore
b.Property<string>("groupPassword").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("") |> ignore
b.Property<string>("headingColor").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("maroon") |> ignore
b.Property<int>("headingFontSize").ValueGeneratedOnAdd().HasDefaultValue(16) |> ignore
b.Property<bool>("isPublic").ValueGeneratedOnAdd().HasDefaultValue(false) |> ignore
b.Property<string>("lineColor").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("navy") |> ignore
b.Property<string>("listFonts").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("Century Gothic,Tahoma,Luxi Sans,sans-serif") |> ignore
b.Property<int>("longTermUpdateWeeks").ValueGeneratedOnAdd().HasDefaultValue(4) |> ignore
b.Property<string>("requestSort").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("D").HasMaxLength(1) |> ignore
b.Property<int>("textFontSize").ValueGeneratedOnAdd().HasDefaultValue(12) |> ignore
b.Property<string>("timeZoneId").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("America/Denver") |> ignore
b.HasKey("smallGroupId") |> ignore
b.HasIndex("timeZoneId") |> ignore
b.ToTable("ListPreference") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<Member>,
fun b ->
b.Property<Guid>("memberId").ValueGeneratedOnAdd() |> ignore
b.Property<string>("email").IsRequired() |> ignore
b.Property<string>("format") |> ignore
b.Property<string>("memberName").IsRequired() |> ignore
b.Property<Guid>("smallGroupId") |> ignore
b.HasKey("memberId") |> ignore
b.HasIndex("smallGroupId") |> ignore
b.ToTable("Member") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<PrayerRequest>,
fun b ->
b.Property<Guid>("prayerRequestId").ValueGeneratedOnAdd() |> ignore
b.Property<bool>("doNotExpire") |> ignore
b.Property<DateTime>("enteredDate") |> ignore
b.Property<bool>("isManuallyExpired") |> ignore
b.Property<bool>("notifyChaplain") |> ignore
b.Property<string>("requestType").IsRequired() |> ignore
b.Property<string>("requestor") |> ignore
b.Property<Guid>("smallGroupId") |> ignore
b.Property<string>("text").IsRequired() |> ignore
b.Property<DateTime>("updatedDate") |> ignore
b.Property<Guid>("userId") |> ignore
b.HasKey("prayerRequestId") |> ignore
b.HasIndex("smallGroupId") |> ignore
b.HasIndex("userId") |> ignore
b.ToTable("PrayerRequest") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<SmallGroup>,
fun b ->
b.Property<Guid>("smallGroupId").ValueGeneratedOnAdd() |> ignore
b.Property<Guid>("churchId") |> ignore
b.Property<string>("name").IsRequired() |> ignore
b.HasKey("smallGroupId") |> ignore
b.HasIndex("churchId") |> ignore
b.ToTable("SmallGroup") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<PrayerTracker.Entities.TimeZone>,
fun b ->
b.Property<string>("timeZoneId").ValueGeneratedOnAdd() |> ignore
b.Property<string>("description").IsRequired() |> ignore
b.Property<bool>("isActive") |> ignore
b.Property<int>("sortOrder") |> ignore
b.HasKey("timeZoneId") |> ignore
b.ToTable("TimeZone") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<User>,
fun b ->
b.Property<Guid>("userId").ValueGeneratedOnAdd() |> ignore
b.Property<string>("emailAddress").IsRequired() |> ignore
b.Property<string>("firstName").IsRequired() |> ignore
b.Property<bool>("isAdmin") |> ignore
b.Property<string>("lastName").IsRequired() |> ignore
b.Property<string>("passwordHash").IsRequired() |> ignore
b.Property<Guid>("salt") |> ignore
b.HasKey("userId") |> ignore
b.ToTable("User") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<UserSmallGroup>,
fun b ->
b.Property<Guid>("userId") |> ignore
b.Property<Guid>("smallGroupId") |> ignore
b.HasKey("userId", "smallGroupId") |> ignore
b.HasIndex("smallGroupId") |> ignore
b.ToTable("User_SmallGroup") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<ListPreferences>,
fun b ->
b.HasOne("PrayerTracker.Entities.SmallGroup")
.WithOne("preferences")
.HasForeignKey("PrayerTracker.Entities.ListPreferences", "smallGroupId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore
b.HasOne("PrayerTracker.Entities.TimeZone", "timeZone")
.WithMany()
.HasForeignKey("timeZoneId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore)
|> ignore
modelBuilder.Entity (
typeof<Member>,
fun b ->
b.HasOne("PrayerTracker.Entities.SmallGroup", "smallGroup")
.WithMany("members")
.HasForeignKey("smallGroupId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore)
|> ignore
modelBuilder.Entity (
typeof<PrayerRequest>,
fun b ->
b.HasOne("PrayerTracker.Entities.SmallGroup", "smallGroup")
.WithMany("prayerRequests")
.HasForeignKey("smallGroupId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore
b.HasOne("PrayerTracker.Entities.User", "user")
.WithMany()
.HasForeignKey("userId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore)
|> ignore
modelBuilder.Entity (
typeof<SmallGroup>,
fun b ->
b.HasOne("PrayerTracker.Entities.Church", "Church")
.WithMany("SmallGroups")
.HasForeignKey("ChurchId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore)
|> ignore
modelBuilder.Entity (
typeof<UserSmallGroup>,
fun b ->
b.HasOne("PrayerTracker.Entities.SmallGroup", "smallGroup")
.WithMany("users")
.HasForeignKey("smallGroupId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore
b.HasOne("PrayerTracker.Entities.User", "user")
.WithMany("smallGroups")
.HasForeignKey("userId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore)
|> ignore

View File

@@ -0,0 +1,199 @@
namespace PrayerTracker.Migrations
open Microsoft.EntityFrameworkCore
open Microsoft.EntityFrameworkCore.Infrastructure
open Npgsql.EntityFrameworkCore.PostgreSQL.Metadata
open PrayerTracker
open PrayerTracker.Entities
open System
[<DbContext (typeof<AppDbContext>)>]
type AppDbContextModelSnapshot () =
inherit ModelSnapshot ()
override __.BuildModel (modelBuilder : ModelBuilder) =
modelBuilder
.HasDefaultSchema("pt")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.HasAnnotation("ProductVersion", "1.1.0-rtm-22752")
|> ignore
modelBuilder.Entity (
typeof<Church>,
fun b ->
b.Property<Guid>("churchId").ValueGeneratedOnAdd() |> ignore
b.Property<string>("city").IsRequired() |> ignore
b.Property<bool>("hasInterface") |> ignore
b.Property<string>("interfaceAddress") |> ignore
b.Property<string>("name").IsRequired() |> ignore
b.Property<string>("st").IsRequired().HasMaxLength(2) |> ignore
b.HasKey("churchId") |> ignore
b.ToTable("Church") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<ListPreferences>,
fun b ->
b.Property<Guid>("smallGroupId") |> ignore
b.Property<int>("daysToExpire").ValueGeneratedOnAdd().HasDefaultValue(14) |> ignore
b.Property<int>("daysToKeepNew").ValueGeneratedOnAdd().HasDefaultValue(7) |> ignore
b.Property<string>("defaultEmailType").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("Html") |> ignore
b.Property<string>("emailFromAddress").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("prayer@djs-consulting.com") |> ignore
b.Property<string>("emailFromName").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("PrayerTracker") |> ignore
b.Property<string>("groupPassword").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("") |> ignore
b.Property<string>("headingColor").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("maroon") |> ignore
b.Property<int>("headingFontSize").ValueGeneratedOnAdd().HasDefaultValue(16) |> ignore
b.Property<bool>("isPublic").ValueGeneratedOnAdd().HasDefaultValue(false) |> ignore
b.Property<string>("lineColor").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("navy") |> ignore
b.Property<string>("listFonts").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("Century Gothic,Tahoma,Luxi Sans,sans-serif") |> ignore
b.Property<int>("longTermUpdateWeeks").ValueGeneratedOnAdd().HasDefaultValue(4) |> ignore
b.Property<string>("requestSort").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("D").HasMaxLength(1) |> ignore
b.Property<int>("textFontSize").ValueGeneratedOnAdd().HasDefaultValue(12) |> ignore
b.Property<string>("timeZoneId").IsRequired().ValueGeneratedOnAdd().HasDefaultValue("America/Denver") |> ignore
b.HasKey("smallGroupId") |> ignore
b.HasIndex("timeZoneId") |> ignore
b.ToTable("ListPreference") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<Member>,
fun b ->
b.Property<Guid>("memberId").ValueGeneratedOnAdd() |> ignore
b.Property<string>("email").IsRequired() |> ignore
b.Property<string>("format") |> ignore
b.Property<string>("memberName").IsRequired() |> ignore
b.Property<Guid>("smallGroupId") |> ignore
b.HasKey("memberId") |> ignore
b.HasIndex("smallGroupId") |> ignore
b.ToTable("Member") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<PrayerRequest>,
fun b ->
b.Property<Guid>("prayerRequestId").ValueGeneratedOnAdd() |> ignore
b.Property<bool>("doNotExpire") |> ignore
b.Property<DateTime>("enteredDate") |> ignore
b.Property<bool>("isManuallyExpired") |> ignore
b.Property<bool>("notifyChaplain") |> ignore
b.Property<string>("requestType").IsRequired() |> ignore
b.Property<string>("requestor") |> ignore
b.Property<Guid>("smallGroupId") |> ignore
b.Property<string>("text").IsRequired() |> ignore
b.Property<DateTime>("updatedDate") |> ignore
b.Property<Guid>("userId") |> ignore
b.HasKey("prayerRequestId") |> ignore
b.HasIndex("smallGroupId") |> ignore
b.HasIndex("userId") |> ignore
b.ToTable("PrayerRequest") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<SmallGroup>,
fun b ->
b.Property<Guid>("smallGroupId").ValueGeneratedOnAdd() |> ignore
b.Property<Guid>("churchId") |> ignore
b.Property<string>("name").IsRequired() |> ignore
b.HasKey("smallGroupId") |> ignore
b.HasIndex("churchId") |> ignore
b.ToTable("SmallGroup") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<PrayerTracker.Entities.TimeZone>,
fun b ->
b.Property<string>("timeZoneId").ValueGeneratedOnAdd() |> ignore
b.Property<string>("description").IsRequired() |> ignore
b.Property<bool>("isActive") |> ignore
b.Property<int>("sortOrder") |> ignore
b.HasKey("timeZoneId") |> ignore
b.ToTable("TimeZone") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<User>,
fun b ->
b.Property<Guid>("userId").ValueGeneratedOnAdd() |> ignore
b.Property<string>("emailAddress").IsRequired() |> ignore
b.Property<string>("firstName").IsRequired() |> ignore
b.Property<bool>("isAdmin") |> ignore
b.Property<string>("lastName").IsRequired() |> ignore
b.Property<string>("passwordHash").IsRequired() |> ignore
b.Property<Guid>("salt") |> ignore
b.HasKey("userId") |> ignore
b.ToTable("User") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<UserSmallGroup>,
fun b ->
b.Property<Guid>("userId") |> ignore
b.Property<Guid>("smallGroupId") |> ignore
b.HasKey("userId", "smallGroupId") |> ignore
b.HasIndex("smallGroupId") |> ignore
b.ToTable("User_SmallGroup") |> ignore)
|> ignore
modelBuilder.Entity (
typeof<ListPreferences>,
fun b ->
b.HasOne("PrayerTracker.Entities.SmallGroup")
.WithOne("preferences")
.HasForeignKey("PrayerTracker.Entities.ListPreferences", "smallGroupId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore
b.HasOne("PrayerTracker.Entities.TimeZone", "timeZone")
.WithMany()
.HasForeignKey("timeZoneId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore)
|> ignore
modelBuilder.Entity (
typeof<Member>,
fun b ->
b.HasOne("PrayerTracker.Entities.SmallGroup", "smallGroup")
.WithMany("members")
.HasForeignKey("smallGroupId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore)
|> ignore
modelBuilder.Entity (
typeof<PrayerRequest>,
fun b ->
b.HasOne("PrayerTracker.Entities.SmallGroup", "smallGroup")
.WithMany("prayerRequests")
.HasForeignKey("smallGroupId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore
b.HasOne("PrayerTracker.Entities.User", "user")
.WithMany()
.HasForeignKey("userId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore)
|> ignore
modelBuilder.Entity (
typeof<SmallGroup>,
fun b ->
b.HasOne("PrayerTracker.Entities.Church", "Church")
.WithMany("SmallGroups")
.HasForeignKey("ChurchId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore)
|> ignore
modelBuilder.Entity (
typeof<UserSmallGroup>,
fun b ->
b.HasOne("PrayerTracker.Entities.SmallGroup", "smallGroup")
.WithMany("users")
.HasForeignKey("smallGroupId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore
b.HasOne("PrayerTracker.Entities.User", "user")
.WithMany("smallGroups")
.HasForeignKey("userId")
.OnDelete(DeleteBehavior.Cascade)
|> ignore)
|> ignore

View File

@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyVersion>7.0.0.0</AssemblyVersion>
<FileVersion>7.0.0.0</FileVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="Entities.fs" />
<Compile Include="AppDbContext.fs" />
<Compile Include="DataAccess.fs" />
<Compile Include="Migrations\20161217153124_InitialDatabase.fs" />
<Compile Include="Migrations\AppDbContextModelSnapshot.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FSharp.EFCore.OptionConverter" Version="1.0.0" />
<PackageReference Include="NodaTime" Version="2.4.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.1.2" />
<PackageReference Include="TaskBuilder.fs" Version="2.1.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="FSharp.Core" Version="4.5.2" />
</ItemGroup>
</Project>