I've been wanting to try out F# for some real world programming so I decided to try rewriting a program that is being used at work.
It can be reduced to a few steps:
- Get report templates. In this step I query a DB and get some templates for reports
- Update data that the reports are working on. In this step I query some banking services and save our data on our DB
- Generate new reports. In this step I call a stored procedure that generates a new report
I'm trying to do this outside in and have been using Mark Seemann's blog and Scott Wlaschin's guide as a guide and this is what I've got so far:
module Helpers =
let getValuesInListOfOptions list =
List.choose (fun x ->
match x with
| Some value -> Some value
| _ -> None ) list
module PaymentVelocityReports =
open System;
open Helpers;
type ReportTemplateName = string
type ReportTemplate = {
Id: int
GroupId: int
ReportOwnerSSN: string
Name: ReportTemplateName
Description: string
Enabled: bool
DayOfMonthToRun: int
DateFrom: DateTime
DateTo: DateTime option
UpdateData: bool}
type Claimant = {
Id: decimal
Ssn: string
}
type BankingService = {
Id: decimal
ClaimantId: decimal
Bank: string
Username: string
Password: string
Enabled: bool
}
type ClaimantTemplates ={
ReportTemplates: ReportTemplate list
Claimant: Claimant
BankingServices: BankingService list
}
let updateClaimantData saveNewGiros saveNewPayments (dateFrom: DateTime) (dateTo: DateTime) (bankingServices: BankingService list) =
List.iter (fun x -> saveNewGiros dateFrom dateTo x) bankingServices
List.iter (fun x -> saveNewPayments dateFrom dateTo x) bankingServices
let updateData updateClaimantData (claimantTemplates: ClaimantTemplates) : ReportTemplateName list =
if List.exists (fun x -> x.UpdateData) claimantTemplates.ReportTemplates then
let minDate = List.map (fun x -> x.DateFrom) claimantTemplates.ReportTemplates |> List.min
let maxDateWithNone = List.map (fun x -> x.DateTo) claimantTemplates.ReportTemplates |> List.max
let maxDateWithoutNone = List.map (fun x -> x.DateTo) claimantTemplates.ReportTemplates |> getValuesInListOfOptions |> List.max
match maxDateWithNone with
| None -> updateClaimantData minDate DateTime.Today claimantTemplates.BankingServices
| _ -> updateClaimantData minDate maxDateWithoutNone claimantTemplates.BankingServices
List.map (fun x -> x.Name) claimantTemplates.ReportTemplates
let getClaimantTemplates data createClaimantTemplate : ClaimantTemplates list =
data |> List.map createClaimantTemplate
//The root of the program
let generateReports (getClaimantTemplates: unit -> ClaimantTemplates list) (updateData: ClaimantTemplates -> ReportTemplateName list) (createReport: ReportTemplateName -> unit) =
getClaimantTemplates () |> List.map updateData |> List.concat |> List.map createReport |> ignore
I'm at the point where the updateClaimantData
and getClaimantTemplates
require data access and the createReport
function that generateReports
needs is also a data access function.
I was hoping to get some criticism to see if I'm on the right track. I'm both new to the language and functional languages as well.