Created
February 3, 2016 15:05
-
-
Save ImaginaryDevelopment/f08bc70e8e3f9fa7c9db to your computer and use it in GitHub Desktop.
Proper architecture attempt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Project.Schema | |
open System | |
open System.Runtime.CompilerServices | |
open System.Collections.Generic | |
// http://blogs.msdn.com/b/jaredpar/archive/2010/07/27/converting-system-func-lt-t1-tn-gt-to-fsharpfunc-lt-t-tresult-gt.aspx | |
[<Extension>] | |
type public FSharpFuncUtil = | |
[<Extension>] | |
static member ToFSharpFunc<'a,'b> (func:Converter<'a,'b>) = func.Invoke | |
[<Extension>] | |
static member ToFSharpFunc<'a,'b> (func:Func<'a,'b>) = fun x -> func.Invoke x | |
[<Extension>] | |
static member ToFSharpFunc<'a,'b,'c> (func:Func<'a,'b,'c>) = fun x y -> func.Invoke (x,y) | |
[<Extension>] | |
static member ToFSharpFunc<'a,'b,'c,'d> (func:Func<'a,'b,'c,'d>) = fun x y z -> func.Invoke (x,y,z) | |
[<Extension>] | |
static member ToFSharpAct<'a> (act: Action<'a>) = fun x -> act.Invoke(x) | |
[<Extension>] | |
static member ToFSharpAct<'a,'b> (act: Action<'a,'b>) = fun x y -> act.Invoke(x,y) | |
static member Create<'a,'b> (func:Func<'a,'b>) = FSharpFuncUtil.ToFSharpFunc func | |
static member Create<'a,'b,'c> (func:Func<'a,'b,'c>) = FSharpFuncUtil.ToFSharpFunc func | |
static member Create<'a,'b,'c,'d> (func:Func<'a,'b,'c,'d>) = FSharpFuncUtil.ToFSharpFunc func |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Project.Domain.Accounting | |
// business logic/rules assembly/project | |
// domain shouldn't depend on something with Entity props, and should be the heart of the app | |
type Patient = {AccountId: int<AccountId>; ForeignEhrId:int; RCopiaId: string} | |
type PatientInfo = {AccountId: int<AccountId>;PatientId:int<PatientId>; LastName:string; FirstName:string;GuarantorId:int<PatientId> option} | |
// create patient, patient info, and patient account | |
let createPatient patient (patientInfo:PatientInfo) (getAccountId: _ -> _) (savePatientAccount: _ -> int<AccountId>) (savePatient: _ -> int<PatientId>) (savePatientInfo: _ -> int<PatientInfoId>) (updatePatientAccount: _ -> _ -> unit) = | |
let patientAccountId,patientAccount = | |
match patientInfo.GuarantorId with | |
| Some guarantorId -> | |
getAccountId guarantorId, None | |
| None -> | |
// create patientAccount pass default for entity identifier, there isn't a valid one yet | |
let patientAccount = Account.createPatientAccount Unchecked.defaultof<_> patientInfo.LastName patientInfo.FirstName | |
savePatientAccount patientAccount, Some patientAccount | |
// create patient // derived from argument | |
let patientId = savePatient {patient with Patient.AccountId = patientAccountId} | |
// createPatientInfo // implied by argument, just needs saving? | |
let patientInfo = {patientInfo with PatientId = patientId; AccountId = patientAccountId} | |
let patientAccount = | |
match patientAccount with | |
| Some patientAccount -> // update the Name | |
let patientAccount = {patientAccount with Name = Account.createPatientAccountName patientId patientInfo.LastName patientInfo.FirstName } | |
patientAccount | |
|> updatePatientAccount patientAccountId | |
Some patientAccount | |
| None -> None | |
//create patientInfo | |
let patientInfoId = savePatientInfo patientInfo | |
patientAccountId,patientAccount,patientInfoId, patientInfo |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// dal layer | |
namespace Project.Foundation.DataModels | |
{ | |
public static class PatientDataAccess | |
{ | |
static Project.Schema.Patients.PatientReturnDataModel CreatePatient(PatientDataModel patient, Connector cn) | |
{ | |
if (patient.PatientID != 0) | |
throw new ArgumentOutOfRangeException("patient", "PatientID should have been 0, but was " + patient.PatientID); | |
Func<int, int> getPatientAccountId = patientId => | |
{ | |
return Project.Dal.AdoHelper.ExecuteScalarInt("select " | |
+ nameof(Project.Schema.DataModels.Patients.PatientRecord.AccountID) | |
+ " from " + Project.Schema.DataModels.Patients.PatientHelpers.Meta.tableName | |
+ " where " + nameof(Project.Schema.DataModels.Patients.PatientRecord.PatientID) | |
+ " = " + patientId, CommandType.Text, cn, null); | |
}; | |
// there is no way at compile time to ensure I'm reading ALL fields from the domain | |
// I could have provided a default value with the intention to come back for that feature/data item | |
// Could have passed something from the ui data model that is now owned/handled in the domain and wasn't previously | |
Func<Project.Domain.Accounting.Patient, int> savePatient = p => | |
{ | |
var @params = new Dictionary<string, object> | |
{ | |
["@PatientID"] = 0, | |
["@PatientInfoID"] = 0, | |
["@ForeignEHRID"] = patient.ForeignEHRID, | |
["@RcopiaID"] = patient.RcopiaID != null ? (object)patient.RcopiaID : System.DBNull.Value, | |
["@AccountID"] = p.AccountId | |
}; | |
//AppDb is a typeprovider so I can compile-time ensure the sproc actually exists | |
return Project.Dal.AdoHelper.ExecuteScalarIdentity(nameof(AppDb.UspPatientsInsUpd), CommandType.StoredProcedure, cn, @params); | |
}; | |
Func<Project.Domain.Accounting.PatientInfo, int> savePatientInfo = pi => | |
{ | |
return UpdatePatientInfo(patient, cn, pi); | |
}; | |
var getPatientAccountId2 = Project.Schema.FSharpFuncUtil.ToFSharpFunc(getPatientAccountId); | |
var insertAccount = Project.Schema.FSharpFuncUtil.ToFSharpFunc(DataAccess.AccountDataAccess.CreateInsertAccountFunc(cn)); | |
var savePatient2 = Project.Schema.FSharpFuncUtil.ToFSharpFunc(savePatient); | |
var savePatientInfo2 = Project.Schema.FSharpFuncUtil.ToFSharpFunc(savePatientInfo); | |
var updateAccount = Project.Schema.FSharpFuncUtil.ToFSharpAct(DataAccess.AccountDataAccess.CreateUpdateAccountFunc(cn)); | |
var result = Project.Domain.Accounting.createPatient( | |
new Project.Domain.Accounting.Patient(0, patient.ForeignEHRID, patient.RcopiaID), | |
new Project.Domain.Accounting.PatientInfo(0, 0, patient.LastName, patient.FirstName, patient.GuarantorID > 0 ? Microsoft.FSharp.Core.FSharpOption<int>.Some(patient.GuarantorID) : Microsoft.FSharp.Core.FSharpOption<int>.None), getPatientAccountId2, insertAccount, savePatient2, savePatientInfo2, updateAccount); | |
patient.AccountID = result.Item1; | |
patient.PatientID = result.Item4.PatientId; | |
patient.PatientInfoID = result.Item3; | |
if (patient.PatientID == 0) | |
throw new InvalidOperationException("patientId wasn't set"); | |
Project.Dal.AdoHelper.ExecuteNonQuery($"update patients set patientinfoid = {patient.PatientInfoID} where patientid = {patient.PatientID}", CommandType.Text, cn, null); | |
return new Project.Schema.Patients.PatientReturnDataModel(patientId: patient.PatientID, patientInfoId: patient.PatientInfoID); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ui-specific class | |
using System; | |
using System.Drawing; | |
using System.Text; | |
using System.Text.RegularExpressions; | |
namespace Project.Foundation.DataModels | |
{ | |
public class PatientDataModel : Project.Schema.DataModels.PatientsInfoes.PatientsInfoN | |
{ | |
int _ForeignEHRID; | |
string _RcopiaID; | |
string _DOBAGE; | |
byte[] _FrontScanData; | |
byte[] _BackScanData; | |
byte[] _FaceScanData; | |
DateTime? _NextAppointment; | |
DateTime? _LastAppointment; | |
Image _BackScan; | |
Image _FaceScan; | |
Image _FrontScan; | |
Guid _PatientGuid; | |
public PatientDataModel() : this(Project.Schema.DataModels.PatientsInfoes.PatientsInfoRecord.Zero(), new Project.Dal.Patients.PatientCoreInfo(null, null, null), 0) { } | |
//alternate constructor for other use cases of the same type | |
public PatientDataModel(Project.Schema.DataModels.PatientsInfoes.PatientsInfoRecord r, Project.Dal.Patients.PatientCoreInfo p, int age) : base(r) | |
{ | |
if (string.IsNullOrEmpty(this.DriversLicenseExpiration)) | |
this.DriversLicenseExpiration = "N/A"; | |
if (string.IsNullOrEmpty(this.Ethnicity)) | |
this.Ethnicity = "Non-hispanic/latino"; | |
if (string.IsNullOrEmpty(this.MaritalStatus)) | |
this.MaritalStatus = "Refused"; | |
this._DOBAGE = r.DOB.ToString("d") + "(" + age + "yr)"; | |
this._PatientGuid = p.PatientGuid.GetValueOrDefault(); | |
this._RcopiaID = p.RcopiaID; | |
this._ForeignEHRID = p.ForeignEhrId.GetValueOrDefault(); | |
this.IsDirty = false; | |
} | |
public new bool IsITIN | |
{ | |
get { return base.IsITIN.GetValueOrDefault() == 1; } | |
set { this.SetAndNotify(nameof(this.IsITIN), base.IsITIN, v => base.IsITIN = v, value ? 1 : 0); } | |
} | |
public new bool IsNoneRefused | |
{ | |
get { return base.IsNoneRefused.GetValueOrDefault() == 1; } | |
set { this.SetAndNotify(nameof(this.IsNoneRefused), base.IsNoneRefused, v => base.IsNoneRefused = v, value ? 1 : 0); } | |
} | |
public new string Address1 | |
{ | |
get { return base.Address1; } | |
set { this.SetAndNotify(nameof(this.Address1), base.Address1, v => base.Address1 = v, value != null ? value.ToUpperInvariant() : value); } | |
} | |
public new string Address2 | |
{ | |
get { return base.Address2; } | |
set { this.SetAndNotify(nameof(this.Address2), base.Address2, v => base.Address2 = v, value != null ? value.ToUpperInvariant() : value); } | |
} | |
public new string City | |
{ | |
get { return base.City; } | |
set { this.SetAndNotify(nameof(this.City), base.City, v => base.City = v, value != null ? value.ToUpperInvariant() : value); } | |
} | |
public new string State | |
{ | |
get { return base.State; } | |
set { this.SetAndNotify(nameof(this.State), base.State, v => base.State = v, value != null ? value.ToUpperInvariant() : value); } | |
} | |
public new bool PrimaryPhoneIsMobile | |
{ | |
get { return base.PrimaryPhoneIsMobile.GetValueOrDefault() == 1; } | |
set { this.SetAndNotify(nameof(this.PrimaryPhoneIsMobile), base.PrimaryPhoneIsMobile, v => base.PrimaryPhoneIsMobile = v, value ? 1 : 0); } | |
} | |
public new bool SecondaryPhoneIsMobile | |
{ | |
get { return base.SecondaryPhoneIsMobile.GetValueOrDefault() == 1; } | |
set { this.SetAndNotify(nameof(this.SecondaryPhoneIsMobile), base.SecondaryPhoneIsMobile, v => base.SecondaryPhoneIsMobile = v, value ? 1 : 0); } | |
} | |
public new bool PrimaryPhoneCanLeaveMessage | |
{ | |
get { return base.PrimaryPhoneCanLeaveMessage.GetValueOrDefault() == 1; } | |
set { this.SetAndNotify(nameof(this.PrimaryPhoneCanLeaveMessage), base.PrimaryPhoneCanLeaveMessage, v => base.PrimaryPhoneCanLeaveMessage = v, value ? 1 : 0); } | |
} | |
public new bool SecondaryPhoneCanLeaveMessage | |
{ | |
get { return base.SecondaryPhoneCanLeaveMessage.GetValueOrDefault() == 1; } | |
set { this.SetAndNotify(nameof(this.SecondaryPhoneCanLeaveMessage), base.SecondaryPhoneCanLeaveMessage, v => base.SecondaryPhoneCanLeaveMessage = v, value ? 1 : 0); } | |
} | |
public new string EmailAddress | |
{ | |
get { return base.EmailAddress; } | |
set { this.SetAndNotify(nameof(this.EmailAddress), base.EmailAddress, v => base.EmailAddress = v, value != null ? value.ToUpperInvariant() : value); } | |
} | |
/// <summary> | |
/// If Patient is a minor this would be the patientId of the guarantor | |
/// </summary> | |
public new int GuarantorID | |
{ | |
get { return base.GuarantorID.GetValueOrDefault(); } | |
set { this.SetAndNotify(nameof(this.GuarantorID), base.GuarantorID, v => base.GuarantorID = v, (int?)value); } | |
} | |
#region Emergency Contact Info | |
public new string EmergencyContactFirstName | |
{ | |
get { return base.EmergencyContactFirstName; } | |
set { this.SetAndNotify(nameof(this.EmergencyContactFirstName), base.EmergencyContactFirstName, v => base.EmergencyContactFirstName = v, value.ToUpperInvariant()); } | |
} | |
public new string EmergencyContactLastName | |
{ | |
get { return base.EmergencyContactLastName; } | |
set { this.SetAndNotify(nameof(this.EmergencyContactLastName), base.EmergencyContactLastName, v => base.EmergencyContactLastName = v, value.ToUpperInvariant()); } | |
} | |
public new string EmergencyContactAddress1 | |
{ | |
get { return base.EmergencyContactAddress1; } | |
set { this.SetAndNotify(nameof(this.EmergencyContactAddress1), base.EmergencyContactAddress1, v => base.EmergencyContactAddress1 = v, value.ToUpperInvariant()); } | |
} | |
public new string EmergencyContactAddress2 | |
{ | |
get { return base.EmergencyContactAddress2; } | |
set { this.SetAndNotify(nameof(this.EmergencyContactAddress2), base.EmergencyContactAddress2, v => base.EmergencyContactAddress2 = v, value.ToUpperInvariant()); } | |
} | |
public new string EmergencyContactAddressCity | |
{ | |
get { return base.EmergencyContactAddressCity; } | |
set { this.SetAndNotify(nameof(this.EmergencyContactAddressCity), base.EmergencyContactAddressCity, v => base.EmergencyContactAddressCity = v, value.ToUpperInvariant()); } | |
} | |
public new string AlertMessage | |
{ | |
get { return base.AlertMessage; } | |
set { this.SetAndNotify(nameof(this.AlertMessage), base.AlertMessage, v => base.AlertMessage = v, value.ToUpperInvariant()); } | |
} | |
public new string EmergencyContactAddressState | |
{ | |
get { return base.EmergencyContactAddressState; } | |
set { this.SetAndNotify(nameof(this.EmergencyContactAddressState), base.EmergencyContactAddressState, v => base.EmergencyContactAddressState = v, value.ToUpperInvariant()); } | |
} | |
public new bool EmergencyContactPrimaryPhoneIsMobile | |
{ | |
get { return base.EmergencyContactPrimaryPhoneIsMobile.GetValueOrDefault() == 1; } | |
set { this.SetAndNotify(nameof(this.EmergencyContactPrimaryPhoneIsMobile), base.EmergencyContactPrimaryPhoneIsMobile, v => base.EmergencyContactPrimaryPhoneIsMobile = v, value ? 1 : 0); } | |
} | |
public new bool EmergencyContactSecondaryPhoneIsMobile | |
{ | |
get { return base.EmergencyContactSecondaryPhoneIsMobile.GetValueOrDefault() == 1; } | |
set { this.SetAndNotify(nameof(this.EmergencyContactSecondaryPhoneIsMobile), base.EmergencyContactSecondaryPhoneIsMobile, v => base.EmergencyContactSecondaryPhoneIsMobile = v, value ? 1 : 0); } | |
} | |
#endregion | |
public new int PCP | |
{ | |
get { return string.IsNullOrEmpty(base.PCP) ? 0 : int.Parse(base.PCP); } | |
set { this.SetAndNotify(nameof(this.PCP), base.PCP, v => base.PCP = v, value.ToString()); } | |
} | |
#region Employer Info | |
public new bool EmploymentStatus | |
{ | |
get { return base.EmploymentStatus == 1; } | |
set { this.SetAndNotify(nameof(this.EmploymentStatus), base.EmploymentStatus, v => base.EmploymentStatus = v, value ? 1 : 0); } | |
} | |
public new string EmployerName | |
{ | |
get { return base.EmployerName; } | |
set { this.SetAndNotify(nameof(this.EmployerName), base.EmployerName, v => base.EmployerName = v, value.ToUpperInvariant()); } | |
} | |
public new string EmployerAddress1 | |
{ | |
get { return base.EmployerAddress1; } | |
set { this.SetAndNotify(nameof(this.EmployerAddress1), base.EmployerAddress1, v => base.EmployerAddress1 = v, value.ToUpperInvariant()); } | |
} | |
public new string EmployerAddress2 | |
{ | |
get { return base.EmployerAddress2; } | |
set { this.SetAndNotify(nameof(this.EmployerAddress2), base.EmployerAddress2, v => base.EmployerAddress2 = v, value.ToUpperInvariant()); } | |
} | |
public new string EmployerCity | |
{ | |
get { return base.EmployerCity; } | |
set { this.SetAndNotify(nameof(this.EmployerCity), base.EmployerCity, v => base.EmployerCity = v, value.ToUpperInvariant()); } | |
} | |
public new string EmployerState | |
{ | |
get { return base.EmployerState; } | |
set { this.SetAndNotify(nameof(this.EmployerState), base.EmployerState, v => base.EmployerState = v, value.ToUpperInvariant()); } | |
} | |
public new string EmployerOccupation | |
{ | |
get { return base.EmployerOccupation; } | |
set { this.SetAndNotify(nameof(this.EmployerOccupation), base.EmployerOccupation, v => base.EmployerOccupation = v, value.ToUpperInvariant()); } | |
} | |
public new string EmployerTitle | |
{ | |
get { return base.EmployerTitle; } | |
set { this.SetAndNotify(nameof(this.EmployerTitle), base.EmployerTitle, v => base.EmployerTitle = v, value.ToUpperInvariant()); } | |
} | |
public new string EmployerSupervisor | |
{ | |
get { return base.EmployerSupervisor; } | |
set { this.SetAndNotify(nameof(this.EmployerSupervisor), base.EmployerSupervisor, v => base.EmployerSupervisor = v, value.ToUpperInvariant()); } | |
} | |
#endregion | |
public new int PatientID | |
{ | |
get { return base.PatientID.GetValueOrDefault(); } | |
set | |
{ | |
base.PatientID = value; | |
RaisePropertyChanged(nameof(IsFirstEntry)); | |
} | |
} | |
public new int LanguageID | |
{ | |
get { return base.LanguageID.GetValueOrDefault(); } | |
set | |
{ | |
base.LanguageID = value == 0 ? (int?)null : value; | |
} | |
} | |
public new string FirstName | |
{ | |
get { return base.FirstName; } | |
set | |
{ | |
if (this.SetAndNotify(nameof(this.FirstName), base.FirstName, v => base.FirstName = v, value != null ? value.ToUpperInvariant() : value)) | |
this.RaisePropertyChanged(nameof(this.LastNameFirstName)); | |
} | |
} | |
public new string MiddleInitial | |
{ | |
get { return base.MiddleInitial; } | |
set { this.SetAndNotify(nameof(this.MiddleInitial), base.MiddleInitial, v => base.MiddleInitial = v, value != null ? value.ToUpperInvariant() : value); } | |
} | |
public new string LastName | |
{ | |
get { return base.LastName; } | |
set | |
{ | |
if (this.SetAndNotify(nameof(this.LastName), base.LastName, v => base.LastName = v, value != null ? value.ToUpperInvariant() : value)) | |
this.RaisePropertyChanged(nameof(this.LastNameFirstName)); | |
} | |
} | |
public new string Gender | |
{ | |
get { return base.Gender; } | |
set { this.SetAndNotify(nameof(this.Gender), base.Gender, v => base.Gender = v, value != null ? value.ToUpperInvariant() : value); } | |
} | |
public new DateTime? DOB | |
{ | |
get { return base.DOB == default(DateTime) ? (DateTime?)null : base.DOB; } | |
set { base.DOB = value.GetValueOrDefault(); } | |
} | |
public new int PatientIdentificationID | |
{ | |
get { return base.PatientIdentificationID.GetValueOrDefault(); } | |
set { base.PatientIdentificationID = value == 0 ? (int?)null : value; ; } | |
} | |
public new string PreferredName | |
{ | |
get { return base.PreferredName; } | |
set { this.SetAndNotify(nameof(this.PreferredName), base.PreferredName, v => base.PreferredName = v, value.ToUpperInvariant()); } | |
} | |
public new string Note | |
{ | |
get { return base.Note; } | |
set { this.SetAndNotify(nameof(this.Note), base.Note, v => base.Note = v, value.ToUpperInvariant()); } | |
} | |
public new int LastUpdateUser | |
{ | |
get { return base.LastUpdateUser.GetValueOrDefault(); } | |
set | |
{ | |
if (this.SetAndNotify(nameof(this.LastUpdateUser), base.LastUpdateUser, v => base.LastUpdateUser = v, value == 0 ? (int?)null : value)) | |
RaisePropertyChanged(nameof(IsFirstEntry)); | |
} | |
} | |
public byte[] FrontScanData | |
{ | |
get { return _FrontScanData; } | |
set { this.SetAndNotify(nameof(this.FrontScanData), ref _FrontScanData, value); } | |
} | |
public int ForeignEHRID | |
{ | |
get { return _ForeignEHRID; } | |
set { this.SetAndNotify(nameof(this.ForeignEHRID), ref _ForeignEHRID, value); } | |
} | |
public string RcopiaID | |
{ | |
get { return _RcopiaID; } | |
set { this.SetAndNotify(nameof(this.RcopiaID), ref _RcopiaID, value); } | |
} | |
public Guid PatientGuid | |
{ | |
get { return _PatientGuid; } | |
set { this.SetAndNotify(nameof(this.PatientGuid), ref _PatientGuid, value); } | |
} | |
public string DOBAGE | |
{ | |
get { return _DOBAGE; } | |
set { this.SetAndNotify(nameof(this.DOBAGE), ref _DOBAGE, value); } | |
} | |
public Image FrontScan | |
{ | |
get { return _FrontScan; } | |
set { this.SetAndNotify(nameof(this.FrontScan), ref _FrontScan, value); } | |
} | |
public byte[] BackScanData | |
{ | |
get { return _BackScanData; } | |
set { this.SetAndNotify(nameof(this.BackScanData), ref _BackScanData, value); } | |
} | |
public Image BackScan | |
{ | |
get { return _BackScan; } | |
set { this.SetAndNotify(nameof(this.BackScan), ref _BackScan, value); } | |
} | |
public byte[] FaceScanData | |
{ | |
get { return _FaceScanData; } | |
set { this.SetAndNotify(nameof(this.FaceScanData), ref _FaceScanData, value); } | |
} | |
public Image FaceScan | |
{ | |
get { return _FaceScan; } | |
set { this.SetAndNotify(nameof(this.FaceScan), ref _FaceScan, value); } | |
} | |
public string CSZ | |
{ | |
get | |
{ | |
string comma = " "; | |
if (!string.IsNullOrWhiteSpace(this.City) && !string.IsNullOrWhiteSpace(this.State)) | |
comma = ", "; | |
return this.City + comma + this.State + " " + this.Zip; | |
} | |
} | |
public string XPMPatientID | |
{ | |
get | |
{ | |
var builder = new StringBuilder(); | |
builder.Append("XPM"); | |
if (!string.IsNullOrWhiteSpace(Convert.ToString(this.PatientID))) | |
builder.Append(Convert.ToString(this.PatientID)); | |
return builder.ToString(); | |
} | |
} | |
public string LastNameFirstNameMiddleInitialPrinted | |
{ | |
get | |
{ | |
var nameBuilder = BuildName(s => " " + s + "."); | |
return nameBuilder.ToString(); | |
} | |
} | |
public string NameAndGender => this.LastNameFirstName + " (" + this.Gender + ")"; | |
public DateTime? NextAppointment | |
{ | |
get { return _NextAppointment; } | |
set { this.SetAndNotify(nameof(this.NextAppointment), ref _NextAppointment, value); } | |
} | |
public DateTime? LastAppointment | |
{ | |
get { return _LastAppointment; } | |
set { this.SetAndNotify(nameof(this.LastAppointment), ref _LastAppointment, value); } | |
} | |
public string FormattedPhoneNumber => PrimaryPhone != null ? Regex.Replace(PrimaryPhone, @"(\d{3})(\d{3})(\d{4})", "$1-$2-$3"): null; | |
public string Formatted_PhoneNumber => PrimaryPhone != null ? Regex.Replace(PrimaryPhone, @"(\d{3})(\d{3})(\d{4})", "($1)$2 $3") : null; | |
public bool IsDirty { get; set; } | |
public string LastNameFirstNameDate | |
{ | |
get | |
{ | |
var builder = BuildName(s => string.Empty); // no middle initial for this format | |
if (this.DOB != null) | |
{ | |
var date = DateTime.Parse(this.DOB.ToString()); | |
builder.Append(" (" + date.ToString("MM/dd/yyyy") + ")"); | |
} | |
return builder.ToString(); | |
} | |
} | |
public string LastNameFirstNameMiddleInitialDate | |
{ | |
get | |
{ | |
var nameBuilder = BuildName(s => " " + s); | |
if (this.DOB != null) | |
{ | |
var date = DateTime.Parse(this.DOB.ToString()); | |
nameBuilder.Append(" (" + date.ToString("MM/dd/yyyy") + ")"); | |
} | |
return nameBuilder.ToString(); | |
} | |
} | |
public string LastNameFirstNameMiddleInitial | |
{ | |
get | |
{ | |
var builder = BuildName(s => " " + s); | |
return builder.ToString(); | |
} | |
} | |
public string LastNameFirstNameDOBGender | |
{ | |
get | |
{ | |
var builder = BuildName(s => string.Empty); // no middle initial for this format | |
if (this.DOB != null) | |
{ | |
var date = DateTime.Parse(this.DOB.ToString()); | |
builder.Append(" (" + date.ToString("MM/dd/yyyy ") + this.Gender + ")"); | |
} | |
return builder.ToString(); | |
} | |
} | |
public string LastNameFirstName | |
{ | |
get | |
{ | |
var builder = BuildName(s => string.Empty); // no middle initial for this format | |
return builder.ToString(); | |
} | |
} | |
StringBuilder BuildName(Func<string, string> middleInitialFormat) | |
{ | |
var builder = new StringBuilder(); | |
if (!string.IsNullOrWhiteSpace(this.LastName)) | |
builder.Append(this.LastName); | |
if (!string.IsNullOrWhiteSpace(this.LastName) && !string.IsNullOrWhiteSpace(this.FirstName)) | |
builder.Append(", "); | |
if (!string.IsNullOrWhiteSpace(this.FirstName)) | |
builder.Append(this.FirstName); | |
if (!string.IsNullOrWhiteSpace(this.MiddleInitial)) | |
builder.Append(middleInitialFormat(this.MiddleInitial)); | |
return builder; | |
} | |
public override string ToString() | |
{ | |
return BuildName(s => s) + "(" + this.PatientID + ")"; | |
} | |
public override void RaisePropertyChanged(string propertyName) | |
{ | |
base.RaisePropertyChanged(propertyName); | |
this.IsDirty = true; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Project.Schema | |
[<Measure>] type PatientId | |
//legacy code base, I'm kind of on the fence with the amount of C# present | |
// if the measures should be pervasive and are helpful/valuable and should be in any of the non-domain or types | |
//so not all representations of patient or any other type have measures, besides almost all of the domain logic types/functions |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Project.Schema.DataModels.Patients // Generated by T4 in namespace Project.Dal | |
// types shared between layers, no behaviors, just shapes go here | |
// something all layers can depend on without taking dependencies on anything platform/ui/dal specific | |
// this file represents a Project.Schema assembly/project | |
open System | |
open System.ComponentModel | |
open System.Linq.Expressions | |
open FSharp.NullHelpers | |
open Project.Schema.Reusable | |
/// 6 properties | |
type IPatient = | |
/// int (4) null | |
abstract member AccountID:int Nullable with get | |
/// int (4) null | |
abstract member ForeignEHRID:int Nullable with get | |
/// uniqueidentifier (16) null | |
abstract member PatientGUID:Guid Nullable with get | |
/// int (4) not null identity | |
abstract member PatientID:int with get | |
/// int (4) null | |
abstract member PatientInfoID:int Nullable with get | |
/// varchar (50) null | |
abstract member RcopiaID:string with get | |
/// 6 properties | |
type IPatientRW = | |
inherit IPatient | |
/// int (4) null | |
abstract member AccountID:int Nullable with get,set | |
/// int (4) null | |
abstract member ForeignEHRID:int Nullable with get,set | |
/// uniqueidentifier (16) null | |
abstract member PatientGUID:Guid Nullable with get,set | |
/// int (4) not null identity | |
abstract member PatientID:int with get,set | |
/// int (4) null | |
abstract member PatientInfoID:int Nullable with get,set | |
/// varchar (50) null | |
abstract member RcopiaID:string with get,set | |
/// 6 properties | |
[<NoComparison>] | |
type PatientRecord = | |
{ | |
/// int (4) null | |
AccountID:int Nullable | |
/// int (4) null | |
ForeignEHRID:int Nullable | |
/// uniqueidentifier (16) null | |
PatientGUID:Guid Nullable | |
/// int (4) not null identity | |
PatientID:int | |
/// int (4) null | |
PatientInfoID:int Nullable | |
/// varchar (50) null | |
RcopiaID:string | |
} | |
interface IPatient with | |
member x.AccountID with get () = x.AccountID | |
member x.ForeignEHRID with get () = x.ForeignEHRID | |
member x.PatientGUID with get () = x.PatientGUID | |
member x.PatientID with get () = x.PatientID | |
member x.PatientInfoID with get () = x.PatientInfoID | |
member x.RcopiaID with get () = x.RcopiaID | |
static member Zero () = | |
{ | |
AccountID = Nullable() | |
ForeignEHRID = Nullable() | |
PatientGUID = Nullable() | |
PatientID = 0 | |
PatientInfoID = Nullable() | |
RcopiaID = null | |
} | |
module PatientHelpers = | |
open Microsoft.FSharp.Core.Operators.Unchecked | |
module Meta = | |
let schemaName = "dbo" | |
let tableName = "Patients" | |
let AccountID = "AccountID" | |
let ForeignEHRID = "ForeignEHRID" | |
let PatientGUID = "PatientGUID" | |
let PatientID = "PatientID" | |
let PatientInfoID = "PatientInfoID" | |
let RcopiaID = "RcopiaID" | |
let ToRecord (iPatient:IPatient) = | |
{ | |
AccountID = iPatient.AccountID | |
ForeignEHRID = iPatient.ForeignEHRID | |
PatientGUID = iPatient.PatientGUID | |
PatientID = iPatient.PatientID | |
PatientInfoID = iPatient.PatientInfoID | |
RcopiaID = iPatient.RcopiaID | |
} | |
let toRecord (patient:IPatient) = | |
{ | |
AccountID = patient.AccountID | |
ForeignEHRID = patient.ForeignEHRID | |
PatientGUID = patient.PatientGUID | |
PatientID = patient.PatientID | |
PatientInfoID = patient.PatientInfoID | |
RcopiaID = patient.RcopiaID | |
} | |
let FromF (camelTypeF:Func<string,obj option>) = | |
{ | |
AccountID = | |
match camelTypeF.Invoke "AccountID" with // int Nullable | |
|Some x -> Nullable (Convert.ToInt32 x ) | |
|None -> Unchecked.defaultof<_> | |
ForeignEHRID = | |
match camelTypeF.Invoke "ForeignEHRID" with // int Nullable | |
|Some x -> Nullable (Convert.ToInt32 x ) | |
|None -> Unchecked.defaultof<_> | |
PatientGUID = | |
match camelTypeF.Invoke "PatientGUID" with // Guid Nullable | |
|Some x -> Nullable (Convert.ToGuid x ) | |
|None -> Unchecked.defaultof<_> | |
PatientID = | |
match camelTypeF.Invoke "PatientID" with // int | |
|Some x -> Convert.ToInt32 x | |
|None -> Unchecked.defaultof<_> | |
PatientInfoID = | |
match camelTypeF.Invoke "PatientInfoID" with // int Nullable | |
|Some x -> Nullable (Convert.ToInt32 x ) | |
|None -> Unchecked.defaultof<_> | |
RcopiaID = | |
match camelTypeF.Invoke "RcopiaID" with // string | |
|Some x -> Convert.ToString x | |
|None -> Unchecked.defaultof<_> | |
} | |
let inline toRecordStp (patient: ^a) = | |
{ | |
AccountID = (^a: (member AccountID: _) patient) | |
ForeignEHRID = (^a: (member ForeignEHRID: _) patient) | |
PatientGUID = (^a: (member PatientGUID: _) patient) | |
PatientID = (^a: (member PatientID: _) patient) | |
PatientInfoID = (^a: (member PatientInfoID: _) patient) | |
RcopiaID = (^a: (member RcopiaID: _) patient) | |
} | |
let createInsert (r:IPatient) = | |
let quoted (s:string) = "'" + s.Replace("'","''") + "'" //varchar | |
[ | |
"AccountID", if isNull (box r.AccountID) then "null" else r.AccountID |> string | |
"ForeignEHRID", if isNull (box r.ForeignEHRID) then "null" else r.ForeignEHRID |> string | |
"PatientGUID", if isNull (box r.PatientGUID) then "null" else r.PatientGUID |> string |> quoted | |
"PatientInfoID", if isNull (box r.PatientInfoID) then "null" else r.PatientInfoID |> string | |
"RcopiaID", if String.IsNullOrEmpty r.RcopiaID then "null" else quoted r.RcopiaID | |
] | |
|> fun pairs -> sprintf "insert into dbo.Patients(%s) values (%s)" (String.Join(",", pairs |> Seq.map fst )) (String.Join(",", pairs |> Seq.map snd)) | |
/// 6 properties | |
type PatientN (model:PatientRecord) = // class for ui inheritance, also implement INPC | |
let propertyChanged = new Event<_, _>() | |
let mutable accountID = model.AccountID | |
let mutable foreignEHRID = model.ForeignEHRID | |
let mutable patientGUID = model.PatientGUID | |
let mutable patientID = model.PatientID | |
let mutable patientInfoID = model.PatientInfoID | |
let mutable rcopiaID = model.RcopiaID | |
interface IPatient with | |
/// int (4) null | |
member x.AccountID with get () = x.AccountID | |
/// int (4) null | |
member x.ForeignEHRID with get () = x.ForeignEHRID | |
/// uniqueidentifier (16) null | |
member x.PatientGUID with get () = x.PatientGUID | |
/// int (4) not null identity | |
member x.PatientID with get () = x.PatientID | |
/// int (4) null | |
member x.PatientInfoID with get () = x.PatientInfoID | |
/// varchar (50) null | |
member x.RcopiaID with get () = x.RcopiaID | |
interface IPatientRW with | |
/// int (4) null | |
member x.AccountID with get () = x.AccountID and set v = x.AccountID <- v | |
/// int (4) null | |
member x.ForeignEHRID with get () = x.ForeignEHRID and set v = x.ForeignEHRID <- v | |
/// uniqueidentifier (16) null | |
member x.PatientGUID with get () = x.PatientGUID and set v = x.PatientGUID <- v | |
/// int (4) not null identity | |
member x.PatientID with get () = x.PatientID and set v = x.PatientID <- v | |
/// int (4) null | |
member x.PatientInfoID with get () = x.PatientInfoID and set v = x.PatientInfoID <- v | |
/// varchar (50) null | |
member x.RcopiaID with get () = x.RcopiaID and set v = x.RcopiaID <- v | |
member x.MakeRecord () = | |
{ | |
AccountID = x.AccountID | |
ForeignEHRID = x.ForeignEHRID | |
PatientGUID = x.PatientGUID | |
PatientID = x.PatientID | |
PatientInfoID = x.PatientInfoID | |
RcopiaID = x.RcopiaID | |
} | |
interface INotifyPropertyChanged with | |
[<CLIEvent>] | |
member x.PropertyChanged = propertyChanged.Publish | |
abstract member RaisePropertyChanged : string -> unit | |
default x.RaisePropertyChanged(propertyName : string) = propertyChanged.Trigger(x, PropertyChangedEventArgs(propertyName)) | |
abstract member SetAndNotify<'t> : string * 't byref * 't -> bool | |
default x.SetAndNotify<'t> (propertyName, field: 't byref, value:'t) = | |
if obj.ReferenceEquals(box field,box value) then false | |
else | |
field <- value | |
x.RaisePropertyChanged(propertyName) | |
true | |
abstract member SetAndNotify<'t,'b> : string * 'b * 't Action * 't -> bool | |
default x.SetAndNotify<'t,'b> (propertyName, baseValue:'b, baseSetter: 't Action, value:'t) = | |
if obj.ReferenceEquals(box baseValue,box value) then false | |
else | |
baseSetter.Invoke value | |
x.RaisePropertyChanged(propertyName) | |
true | |
/// int (4) null | |
member x.AccountID | |
with get() = accountID | |
and set v = | |
accountID <- v | |
x.RaisePropertyChanged "AccountID" | |
/// int (4) null | |
member x.ForeignEHRID | |
with get() = foreignEHRID | |
and set v = | |
foreignEHRID <- v | |
x.RaisePropertyChanged "ForeignEHRID" | |
/// uniqueidentifier (16) null | |
member x.PatientGUID | |
with get() = patientGUID | |
and set v = | |
patientGUID <- v | |
x.RaisePropertyChanged "PatientGUID" | |
/// int (4) not null identity | |
member x.PatientID | |
with get() = patientID | |
and set v = | |
patientID <- v | |
x.RaisePropertyChanged "PatientID" | |
/// int (4) null | |
member x.PatientInfoID | |
with get() = patientInfoID | |
and set v = | |
patientInfoID <- v | |
x.RaisePropertyChanged "PatientInfoID" | |
/// varchar (50) null | |
member x.RcopiaID | |
with get() = rcopiaID | |
and set v = | |
rcopiaID <- v | |
x.RaisePropertyChanged "RcopiaID" |
posted a more focused than I'd like question at http://codereview.stackexchange.com/questions/118781/how-do-i-compile-time-enforce-domain-values-go-into-the-dal
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
apparently github gists don't care what order you put the files in, it will alphabetize, I meant this to be a proper top-down readable deal. with schema -> domain -> dal/ui. everything can/does depend on schema. everything except schema can/does depend on domain (although I'd prefer to rework it so only composition root does that)