Created
September 24, 2020 12:18
-
-
Save wandersoncferreira/eb53ded04eddd538ae7d3d6ba041d038 to your computer and use it in GitHub Desktop.
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
(ns secland.gen-contract | |
(:require [cadastro-de-pessoa.cnpj :as cnpj] | |
[clojure.test.check.generators :as gen] | |
[java-time :as java-time]) | |
(:import java.time.ZoneId)) | |
(defn date-converter [date] | |
(java-time/java-date | |
(.toInstant | |
(.atStartOfDay date (ZoneId/systemDefault))))) | |
(defn- add-days-to--raw | |
[date n-days] | |
(-> (.toInstant date) | |
(java-time/plus (java-time/days n-days)) | |
(as-> fmt (date-converter fmt)))) | |
(def add-days (memoize add-days-to--raw)) | |
(def gen-cnpj (gen/fmap (fn [_] (cnpj/gen)) (gen/list gen/int))) | |
(def gen-datetime-components | |
(gen/hash-map | |
:year (gen/large-integer* {:min 1990 :max 2200}) | |
:month (gen/large-integer* {:min 1 :max 12}) | |
:day (gen/large-integer* {:min 1 :max 28}) | |
:hour (gen/large-integer* {:min 0 :max 23}) | |
:minute (gen/large-integer* {:min 0 :max 59}) | |
:second (gen/large-integer* {:min 0 :max 59}) | |
:millis (gen/large-integer* {:min 0 :max 1000}))) | |
(defn convert-to-inst [value] | |
(java-time/java-date | |
(.toInstant | |
(.atZone (apply java-time/local-date-time (vals value)) | |
(java.time.ZoneId/systemDefault))))) | |
(def gen-java-util-date | |
(gen/fmap convert-to-inst gen-datetime-components)) | |
(defn merge-hashmap-gen [& args] | |
(gen/fmap (fn [args] (apply merge args)) (apply gen/tuple args))) | |
(def ^:private gen-issue-value (gen/fmap #(* 1000 %) (gen/frequency [[9 (gen/double* {:min 0 | |
:infinite? false | |
:NaN? false})] [1 gen/double]]))) | |
(defn- generate-present-value [issue-value] | |
(gen/frequency [[9 (gen/return issue-value)] | |
[1 (gen/fmap (fn [[denum issue-value]] (* issue-value (/ 1 denum))) | |
(gen/tuple (gen/large-integer* {:min 2 :max 10}) | |
(gen/return issue-value)))]])) | |
(defn- generate-future-value [present-value] | |
(gen/frequency [[9 (gen/fmap (fn [[denum present-value]] (* present-value (inc (/ 1 denum)))) | |
(gen/tuple (gen/large-integer* {:min 2 :max 10}) | |
(gen/return present-value)))] | |
[1 (gen/fmap (fn [[denum present-value]] (* present-value (/ 1 denum))) | |
(gen/tuple (gen/large-integer* {:min 2 :max 10}) | |
(gen/return present-value)))]])) | |
(def generate-installment-values | |
(gen/let [issue-value gen-issue-value | |
present-value (generate-present-value issue-value) | |
future-value (generate-future-value present-value)] | |
(gen/hash-map | |
:installment/issue-value (gen/return issue-value) | |
:installment/present-value (gen/return present-value) | |
:installment/future-value (gen/return future-value)))) | |
(def gen-installment | |
(gen/not-empty (gen/list (merge-hashmap-gen | |
generate-installment-values | |
(gen/hash-map | |
:installment/status gen/keyword))))) | |
(defn- gen-acquisition-date [issue-date] | |
(gen/let [number-additional-days (gen/large-integer* {:min -20 :max 20})] | |
(gen/frequency [[8 (gen/return issue-date)] [2 (gen/return (add-days issue-date number-additional-days))]]))) | |
(def ^:private gen-contract-body | |
(gen/hash-map | |
:contract/category (gen/elements [:ccb :assignment-agreement :trust-assignment-agreement :trade-note]) | |
:contract/portfolio (gen/frequency [[4 (gen/return :default)] [2 (gen/return :secland)] | |
[2 (gen/return :testing)] [2 (gen/return :clj-secland)]]) | |
:contract/lending-rate (gen/fmap #(BigDecimal. (/ % 1000.)) (gen/large-integer* {:min 1 :max 150})) | |
:contract/originator gen/keyword | |
:contract/assignor gen-cnpj | |
:contract/drawee gen-cnpj | |
:contract/indexer (gen/elements [:igpm :cdi :selic :none]) | |
:contract/rating (gen/elements ["A" "B" "C" "D" "E" "F" "G" "H" "I"]) | |
:contract/score (gen/large-integer* {:min 0 :max 1000}) | |
:contract/recourse gen/boolean)) | |
(defn- gen-contract--values [which-key list-installments] | |
(let [contract-value (reduce + (map which-key list-installments))] | |
(gen/frequency [[9 (gen/return contract-value)] | |
[1 (gen/return (* 0.7 contract-value))]]))) | |
(def gen-contract | |
(gen/let [principal-id (gen/return "principal-id") | |
secundary-id (gen/return principal-id) | |
[installments first-pmt-number :as gen-inst] (gen/tuple gen-installment (gen/large-integer* {:min 1})) | |
issue-date gen-java-util-date] | |
(merge-hashmap-gen gen-contract-body | |
(gen/hash-map | |
:type-name (gen/return :contract) | |
:contract/issue-date (gen/return issue-date) | |
:contract/acquisition-date (gen-acquisition-date issue-date) | |
:contract/due-date (gen/return (add-days issue-date (count installments))) | |
:contract/issue-value (gen-contract--values :installment/issue-value installments) | |
:contract/future-value (gen-contract--values :installment/future-value installments) | |
:contract/present-value (gen-contract--values :installment/present-value installments) | |
:contract/principal-external-id (gen/return principal-id) | |
:contract/secundary-external-id (gen/return secundary-id) | |
:contract/number-of-installments (gen/return (count installments)) | |
:contract/installments (gen/fmap (fn [[list-of-maps min-number]] | |
(map #(assoc %1 | |
:installment/pmt-number %2 | |
:installment/due-date (add-days issue-date (* 30 %3)) | |
:installment/unique-id (str principal-id "_" %2)) list-of-maps (iterate inc min-number) (range 1 (inc (count installments))))) | |
(gen/return gen-inst)))))) | |
(def gen-contract<->operation-id (merge-hashmap-gen gen-contract (gen/hash-map :operation-id (gen/fmap str gen/string-ascii)))) | |
(def gen-list-of-contracts (gen/not-empty (gen/list gen-contract))) | |
(def gen-list-of-contracts<->operation-id (gen/not-empty (gen/list gen-contract<->operation-id))) | |
(comment | |
(require '[com.gfredericks.test.chuck.clojure-test :refer [checking]]) | |
(require '[secland.securities.contracts :as contract]) | |
(require '[clojure.spec.alpha :as s]) | |
(require '[clojure.test :refer :all]) | |
(deftest contract-generators | |
(checking "All the contracts generated must be spec'ed" 100 | |
[ct gen-contract] | |
(s/assert ::contract/spec-contract ct))) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment