Skip to content

Instantly share code, notes, and snippets.

@gcoda
Created February 21, 2022 11:15
Show Gist options
  • Save gcoda/d4f395b90f243d36d167f25253acc054 to your computer and use it in GitHub Desktop.
Save gcoda/d4f395b90f243d36d167f25253acc054 to your computer and use it in GitHub Desktop.
module Domain
open Fable.Core
open Fable.Import
open System
// type Guid = Guid of string
type NoneEmptyString = private NoneEmptyString of string
module NoneEmptyString =
let create str =
if String.IsNullOrWhiteSpace str then
"Cannot be empty" |> Error
else
str |> NoneEmptyString |> Ok
type CustomerId = private CustomerId of Guid
module CustomerId =
let create id =
if id = Guid.Empty then
"Cannot be empty" |> Error
else
id |> CustomerId |> Ok
let newPerson = Guid.NewGuid()
let newCustomerId = CustomerId.create newPerson
type Email = Email of NoneEmptyString
type CheckInDate = CheckInDate of DateTime
type AcceptDate = AcceptedDate of DateTime
type VerifiedDate = VerifiedDate of DateTime
type ContactInformation =
{ FirstName: NoneEmptyString
LastName: NoneEmptyString
Email: Email
PhoneNumber: NoneEmptyString option }
type Address =
{ StreetAddress1: NoneEmptyString
StreetAddress2: NoneEmptyString option
ZipCode: NoneEmptyString
City: NoneEmptyString
Country: NoneEmptyString }
type CustomerDetails =
{ ContactInformation: ContactInformation
Address: Address }
type InvitedCustomer =
private
{ Id: CustomerId
Email: Email }
type DetailsOnly =
private
{ Id: CustomerId
Details: CustomerDetails }
type AcceptedGDPR =
private
{ Id: CustomerId
AcceptDate: AcceptDate
Details: CustomerDetails }
type CheckedIn =
private
{ Id: CustomerId
CheckInDate: CheckInDate
Details: CustomerDetails }
type Complete =
private
{ Id: CustomerId
AcceptDate: AcceptDate
CheckInDate: CheckInDate
Details: CustomerDetails }
type VerifiedCustomer =
private
{ Id: CustomerId
AcceptDate: AcceptDate
CheckedInDate: CheckInDate
VerifiedDate: VerifiedDate
Details: CustomerDetails }
type ActiveCustomer =
private
| DetailsOnly of DetailsOnly
| AcceptedGDPR of AcceptedGDPR
| CheckedIn of CheckedIn
| Complete of Complete
type UnverifiedCustomer =
private
| Invited of InvitedCustomer
| Active of ActiveCustomer
let invite id email = { Id = id; Email = email }
// UnverifiedCustomer -> CustomerDetails -> ActiveCustomer
let updateDetails (customer: UnverifiedCustomer) details =
match customer with
| Invited { Id = id } -> DetailsOnly { Id = id; Details = details }
| Active activeCustomer ->
match activeCustomer with
| DetailsOnly c -> DetailsOnly { c with Details = details }
| AcceptedGDPR c -> AcceptedGDPR { c with Details = details }
| CheckedIn c -> CheckedIn { c with Details = details }
| Complete c -> Complete { c with Details = details }
// ActiveCustomer -> AcceptDate -> ActiveCustomer
let acceptGDPR (customer: ActiveCustomer) date =
match customer with
| DetailsOnly c ->
AcceptedGDPR
{ Id = c.Id
Details = c.Details
AcceptDate = date }
| AcceptedGDPR c -> AcceptedGDPR { c with AcceptDate = date }
| CheckedIn c ->
Complete
{ Id = c.Id
Details = c.Details
CheckInDate = c.CheckInDate
AcceptDate = date }
| Complete c -> Complete { c with AcceptDate = date }
// ActiveCustomer -> CheckInDate -> ActiveCustomer
let checkIn (customer: ActiveCustomer) date =
match customer with
| DetailsOnly c ->
CheckedIn
{ Id = c.Id
Details = c.Details
CheckInDate = date }
| AcceptedGDPR c ->
Complete
{ Id = c.Id
Details = c.Details
AcceptDate = c.AcceptDate
CheckInDate = date }
| CheckedIn c -> CheckedIn { c with CheckInDate = date }
| Complete c -> Complete { c with CheckInDate = date }
// ActiveCustomer -> VerifiedDate -> VerifiedCustomer
let verify (customer: Complete) date =
{ Id = customer.Id
Details = customer.Details
AcceptDate = customer.AcceptDate
CheckedInDate = customer.CheckInDate
VerifiedDate = date }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment