diff --git a/src/Informedica.ZIndex.Lib/BST000T.fs b/src/Informedica.ZIndex.Lib/BST000T.fs index 052d28a..4b9e4cf 100644 --- a/src/Informedica.ZIndex.Lib/BST000T.fs +++ b/src/Informedica.ZIndex.Lib/BST000T.fs @@ -47,6 +47,9 @@ module BST000T = } + /// + /// Create a BST000T record + /// let create mc nm ds rl st ua dl al nw tt = { MUTKOD = mc @@ -68,6 +71,9 @@ module BST000T = let pickList = [1] @ [2; 3] @ [5] @ [9..14] + /// + /// Get all the records from the BST000T file + /// let records _ = Parser.getData name posl pickList |> Array.map (Array.map String.trim) @@ -81,11 +87,20 @@ module BST000T = create d[0] d[1] d[2] rl d[4] ua dl al nw tt) + /// + /// Get a specific record from the BST000T file + /// + /// The name of the table let table n = records () |> Array.find (fun r -> r.MDBST = n) + /// + /// Creat a code comment for a table. + /// + /// The name of the table + /// The picklist of columns to include in the comment let commentString n pl = printfn $"processing: {n} {pl}" let tab = " " diff --git a/src/Informedica.ZIndex.Lib/BST001T.fs b/src/Informedica.ZIndex.Lib/BST001T.fs index fd996c8..51535ce 100644 --- a/src/Informedica.ZIndex.Lib/BST001T.fs +++ b/src/Informedica.ZIndex.Lib/BST001T.fs @@ -15,6 +15,10 @@ module BST001T = [] let name = "BST001T" + + /// + /// Position of the fields in the record + /// let posl = [ 0004; 0001; 0020; 0003; 0010; 0050; 0008; 0002; 0001; 0004; 0002; 0006; 0017 ] @@ -47,6 +51,9 @@ module BST001T = } + /// + /// Create a BST001T record + /// let create mk tb vn nm bs ke tp ln dc fm = { MUTKOD = mk @@ -62,6 +69,9 @@ module BST001T = } + /// + /// Picklist of fields to use + /// let pickList = [1..5] @ [7..11] @@ -91,6 +101,10 @@ module BST001T = let _records = records () + /// + /// Get the position of the fields in the record + /// + /// The name of the file let getPosl name = _records |> Array.toList @@ -98,21 +112,35 @@ module BST001T = |> List.map (fun d -> d.MDRLEN) + /// + /// Get the length of the record + /// + /// The name of the file let recordLength n = _records |> Seq.filter (fun r -> r.MDBST = n) |> Seq.sumBy (fun r -> r.MDRLEN) + /// + /// Get the all colums for a file + /// let columns n = _records |> Seq.filter (fun r -> r.MDBST = n) |> Seq.filter (fun r -> r.MDRNAM <> "******") + /// Get the column count for a file let columnCount n = columns n |> Seq.length + /// + /// Get the column names for a file as a single + /// F# record string. + /// + /// The name of the file + /// The picklist of fields to use let recordString n pl = let tab = " " let s = $"type %s{n} =\n" @@ -130,6 +158,12 @@ module BST001T = s + $"%s{tab}%s{tab}%s{tab}}}\n" + /// + /// Get the column names for a file as a single + /// F# create function string. + /// + /// The name of the file + /// The picklist of fields to use let createString n pl = let tab = " " let cs = diff --git a/src/Informedica.ZIndex.Lib/CodeGen.fs b/src/Informedica.ZIndex.Lib/CodeGen.fs index 48a561e..20be42d 100644 --- a/src/Informedica.ZIndex.Lib/CodeGen.fs +++ b/src/Informedica.ZIndex.Lib/CodeGen.fs @@ -51,6 +51,12 @@ module Zindex = """ + + /// + /// Generates the code for a single table. + /// + /// The name of the table. + /// The picklist of the table. let generate n pl = let cm = BST000T.commentString n pl let rc = BST001T.recordString n pl @@ -112,6 +118,10 @@ module Zindex = ] + /// + /// Generates the Z-Index file. + /// + /// The table list. let generateZIndex tl = let code = tl diff --git a/src/Informedica.ZIndex.Lib/FilePath.fs b/src/Informedica.ZIndex.Lib/FilePath.fs index 6cde3fb..30cab2e 100644 --- a/src/Informedica.ZIndex.Lib/FilePath.fs +++ b/src/Informedica.ZIndex.Lib/FilePath.fs @@ -12,28 +12,39 @@ module FilePath = [] let GStandPath = data + "zindex/" + + /// Get the path to the Substance cache file let substanceCache useDemo = if not useDemo then data + "cache/substance.cache" else data + "cache/substance.demo" + + /// Get the path to the Product cache file let productCache useDemo = if not useDemo then data + "cache/product.cache" else data + "cache/product.demo" + + /// Get the path to the Rule cache file let ruleCache useDemo = if not useDemo then data + "cache/rule.cache" else data + "cache/rule.demo" + + /// Get the path to the Group cache file let groupCache useDemo = if not useDemo then data + "cache/group.cache" else data + "cache/group.demo" + //https://docs.google.com/spreadsheets/d/1AEVYnqjAbVniu3VuczeoYvMu3RRBu930INhr3QzSDYQ/edit?usp=sharing let [] genpres = "1AEVYnqjAbVniu3VuczeoYvMu3RRBu930INhr3QzSDYQ" let [] GENPRES_PROD = "GENPRES_PROD" + /// Check whether the demo version of + /// the cache files should be used. let useDemo () = Env.getItem GENPRES_PROD |> Option.map ((<>) "1") diff --git a/src/Informedica.ZIndex.Lib/Json.fs b/src/Informedica.ZIndex.Lib/Json.fs index eb62d91..7d0ad64 100644 --- a/src/Informedica.ZIndex.Lib/Json.fs +++ b/src/Informedica.ZIndex.Lib/Json.fs @@ -8,25 +8,50 @@ module Json = open Informedica.Utils.Lib - /// + /// + /// Serializes an object to a JSON string + /// + /// The object to serialize let serialize x = JsonConvert.SerializeObject(x) + /// + /// Deserializes a JSON string to an object + /// + /// The JSON string to deserialize let deSerialize<'T> (s: string) = JsonConvert.DeserializeObject<'T>(s) + + /// + /// Serialize an object to a JSON string + /// and write it to a file + /// + /// The path to the file + /// The object to serialize let cache p o = o |> serialize |> File.writeTextToFile p + + /// + /// Clear the cache files for either a product + /// or a demo version of the cache. + /// + /// Whether to clear the demo cache files let clearCache useDemo = File.Delete(FilePath.groupCache useDemo) File.Delete(FilePath.substanceCache useDemo) File.Delete(FilePath.productCache useDemo) File.Delete(FilePath.ruleCache useDemo) + + /// + /// Read a cache file and deserialize it to an object + /// + /// The path to the file let getCache<'T> p = ConsoleWriter.writeInfoMessage $"Reading cache: %s{p}" true false diff --git a/src/Informedica.ZIndex.Lib/Parser.fs b/src/Informedica.ZIndex.Lib/Parser.fs index 7a0b2e4..5ae43f4 100644 --- a/src/Informedica.ZIndex.Lib/Parser.fs +++ b/src/Informedica.ZIndex.Lib/Parser.fs @@ -6,6 +6,12 @@ module Parser = open Informedica.Utils.Lib.BCL open Informedica.Utils.Lib + + /// + /// Split a string into an array of strings, based on the given positions. + /// + /// The given positions. + /// The string let splitRecord pl (s: string) = pl |> List.mapi (fun i p -> @@ -13,6 +19,13 @@ module Parser = s.Substring(start, p)) |> List.toArray + + /// + /// Get the data from a file. + /// + /// The name of the file. + /// The positions of the fields. + /// The fields to pick. let getData name posl pick = let data = FilePath.GStandPath + "/" + name @@ -25,6 +38,10 @@ module Parser = data |> Array.map (Array.pickArray pick) + + /// + /// Check wether a string is a decimal format. + /// let isDecimalFormat s = let s = s |> String.replace "(" "" |> String.replace ")" "" if s |> String.contains "," then @@ -33,6 +50,13 @@ module Parser = | _ -> false else false + + /// + /// Parse a string to a decimal a return as a string + /// + /// String that is 'N'if numerical + /// The format of the numerical string + /// The string to format let parseValue st sf (s: string) = if st = "N" then let vf = sf |> String.replace "(" "" |> String.replace ")" "" diff --git a/src/Informedica.ZIndex.Lib/Scripts/Script.fsx b/src/Informedica.ZIndex.Lib/Scripts/Script.fsx index 7ce8ce6..e3b94f5 100644 --- a/src/Informedica.ZIndex.Lib/Scripts/Script.fsx +++ b/src/Informedica.ZIndex.Lib/Scripts/Script.fsx @@ -328,4 +328,7 @@ printfn "Loading Substance" Substance.load () -GenPresProduct.search "amikacine" +GenPresProduct.search "adrenaline" +|> Array.head +|> fun gpp -> gpp.GenericProducts |> Array.head + diff --git a/src/Informedica.ZIndex.Lib/Types.fs b/src/Informedica.ZIndex.Lib/Types.fs index a588081..b3047b7 100644 --- a/src/Informedica.ZIndex.Lib/Types.fs +++ b/src/Informedica.ZIndex.Lib/Types.fs @@ -7,7 +7,7 @@ module Types = module Names = - /// The naming for the different types of names + /// Different types of names type Name = Full | Short | Memo | Label @@ -103,21 +103,46 @@ module Types = } + /// /// A Z-Index Substance + /// + /// + /// The substance contains a Mole and MoleReal this + /// corresponds to the substance and the full + /// generic form of the Substance. + /// see: https://www.z-index.nl/documentatie/bestandsbeschrijvingen/veld?veldnaam=GNMOLS + /// type Substance = { + /// The Id of the Substance Id : int + /// The Id for the full Generic Substance Name Pk : int + /// The name of the substance Name : string + /// The molar mass of the substance + /// https://www.z-index.nl/documentatie/bestandsbeschrijvingen/veld?veldnaam=GNMOLS Mole : float + /// The molar mass of the real substance + /// https://www.z-index.nl/documentatie/bestandsbeschrijvingen/veld?veldnaam=GNMOLE MoleReal : float + /// The chemical formula of the substance Formula : string + /// The unit of the substance Unit : string + /// The density of the substance Density : float } + /// /// A Z-Index Consumer Product + /// + /// + /// A consumer product is a trade product with the + /// total amount of products. I.e. a paracetmol + /// product in a box of 10 tablets. + /// type ConsumerProduct = { Id : int @@ -129,7 +154,13 @@ module Types = } + /// /// A Z-Index Trade Product + /// + /// + /// A trade product is a prescription product + /// with the trade name and associated traits. + /// type TradeProduct = { Id: int @@ -144,49 +175,100 @@ module Types = } + /// /// A Z-Index Prescription Product + /// /> + /// + /// A prescription product is a generic product with + /// the quantity and container of the product. + /// type PrescriptionProduct = { + /// The id of the prescription product, i.e. PRK. Id : int + /// The full name of the product. Name : string + /// The label of the product. Label : string + /// The pharmocological shape quantity of the product. Quantity : float + /// The pharmocological shape unit of the product. Unit : string + /// The container of the product. Container : string + /// The trade products of the prescription product. TradeProducts : TradeProduct [] } + /// /// A Z-Index Generic Product + /// + /// + /// A generic product is the most basic Z-index product. + /// It contains the substances along with the substance + /// concentration. Note that 2 ampoules, one of 1 mL en one + /// of 5 mL with the same substance concentration comprise + /// the same generic product. + /// type GenericProduct = { + /// The id of the generic product,i.e. GPK. Id : int + /// The full name of the product. Name : string + /// The label of the product. Label : string + /// The ATC-5 code of the product. + /// The code is a string of 7 characters. ATC : string + /// The ATC-5 name of the product. ATCName : string + /// The pharmacological shape of the product. Shape : string + /// The route of administration of the product. Route : string [] + /// The substances of the product. Substances : ProductSubstance [] + /// The prescription products of the generic product. PrescriptionProducts : PrescriptionProduct [] } - + /// A substance in a product. and ProductSubstance = { + /// The id of the substance. SubstanceId : int + /// The order in which the substances are listed + /// in a GenericProduct and GenPresProduct name. SortOrder : int + /// The name of the substance. + /// For example: 'NORADRENALINE' SubstanceName : string + /// The quantity of the substance. SubstanceQuantity : float + /// The unit of the substance. SubstanceUnit : string + /// The id of the generic substance (salt form). GenericId : int + /// The full name (salt form) of the substance. + /// For example: 'NORADRENALINE WATERSTOFTARTRAAT-1-WATER' GenericName : string + /// The quantity of the generic substance (salt form). GenericQuantity : float + /// The unit of the generic substance (salt form). GenericUnit : string + /// The pharmacological shape unit in which the substance is contained. ShapeUnit : string } + /// /// A GenPresProduct + /// + /// + /// A GenPres product is a higher level product. It contains + /// the generic products with the same substance composition. + /// type GenPresProduct = { Name : string @@ -200,21 +282,24 @@ module Types = } + /// A Z-Index rule Frequency. type RuleFrequency = { Frequency: float; Time: string } + /// A Z-Index rule MinMax. type RuleMinMax = { Min: float Option; Max: float Option } + /// A Z-Index dose rule. type DoseRule = { - /// The id of the doserule + /// The id of the DoseRule Id : int - /// The caregroup the doserule applies to + /// The care group the DoseRule applies to /// this is either 'intensieve' or 'niet-intensieve' or 'all' CareGroup : string /// This is the usage of the dose rule, can be therapeutic or - /// profylactic + /// prophylactic. Usage : string /// The dose type, 'standaard' means that the dose rule applies without /// a specific indication, 'verbyzondering' means the dose rule needs @@ -305,9 +390,9 @@ module Types = (DoseRule -> RuleMinMax) * (RuleMinMax -> DoseRule -> DoseRule) = (fun dr -> dr.AbsM2) , (fun mm dr -> { dr with AbsM2 = mm }) - + /// A Z-Index trade or consumer product that is part of a dose rule. and RuleProduct = { Id: int; Name: string } - + /// A Z-Index generic product that is part of a dose rule. and RuleGenericProduct = { Id: int @@ -316,10 +401,11 @@ module Types = Unit: string Substances : RuleSubstance [] } - + /// A Z-Index substance that is part of a RuleGenericProduct. and RuleSubstance = { Name: string; Quantity: float; Unit: string } + /// The ATC group coding type ATCGroup = { ATC1 : string @@ -350,6 +436,8 @@ module Types = type BSAInM2 = float Option + /// The patient filter to get the + /// DoseRules for a specific patient. type PatientFilter = { Age: AgeInMo @@ -358,6 +446,8 @@ module Types = } + /// The ProductFilter to get the + /// DoseRules for a specific product. type ProductFilter = | GPKRoute of (int * string) | GenericShapeRoute of GenericShapeRoute @@ -370,6 +460,8 @@ module Types = } + /// The Filter to get the DoseRules + /// for a specific patient and product. type Filter = { Patient: PatientFilter @@ -377,13 +469,14 @@ module Types = } + /// The DoseRules that belong to a specific + /// GenPresProduct. type RuleResult = { Product: GenPresProduct DoseRules: string [] Doses: FreqDose [] } - and FreqDose = { /// The frequency of the dose rule @@ -405,10 +498,16 @@ module Types = } + /// The Assortment Product that is + /// available as a GenericProduct. type Assortment = { + /// The GPK code GPK: int + /// The generic name Generic: string + /// The TallMan alternative name TallMan : string + /// The Divisibility of the product Divisible : int }