diff --git a/spec/ataru/kk_application_payment/kk_application_payment_status_updater_job_spec.clj b/spec/ataru/kk_application_payment/kk_application_payment_status_updater_job_spec.clj index ed8e17e14b..3dd722040f 100644 --- a/spec/ataru/kk_application_payment/kk_application_payment_status_updater_job_spec.clj +++ b/spec/ataru/kk_application_payment/kk_application_payment_status_updater_job_spec.clj @@ -10,7 +10,7 @@ [clojure.java.jdbc :as jdbc] [clojure.string :as str] [speclj.core :refer [it describe should-not-throw stub should-have-invoked should-not-have-invoked - tags with-stubs should= around before]] + should-be-nil tags with-stubs should= around before]] [ataru.kk-application-payment.kk-application-payment :as payment] [ataru.fixtures.application :as application-fixtures] [ataru.fixtures.form :as form-fixtures] @@ -85,6 +85,23 @@ (declare conn) (declare spec) +(defn- get-tuition-payment-obligation-review [application-key hakukohde] + (jdbc/with-db-transaction [conn {:datasource (db/get-datasource :db)}] + (->> (jdbc/query + conn + ["select * FROM application_hakukohde_reviews WHERE application_key = ? AND requirement = ? AND hakukohde = ?" + application-key "payment-obligation" hakukohde]) + first))) + +(defn- store-tuition-fee-not-required-review [application-key hakukohde] + (jdbc/with-db-transaction [conn {:datasource (db/get-datasource :db)}] + (jdbc/insert! conn "application_hakukohde_reviews" + {:application_key application-key + :requirement "payment-obligation" + :hakukohde hakukohde + :state "not-obligated"}))) + + (defn- clear! [] (jdbc/with-db-transaction [conn {:datasource (db/get-datasource :db)}] (jdbc/delete! conn :applications []) @@ -383,4 +400,106 @@ (should-have-invoked :start-job {:with [:* :* "ataru.kk-application-payment.kk-application-payment-email-job" - check-mail-fn]}))))) + check-mail-fn]})))) + + (it "should set tuition fee obligation for non fi/sv hakukohde when payment state changes to awaiting" + ; Initial state: hakukohde in the application has only english as teaching language, + ; and the application / person has no exemption, meaning the application should require both + ; application fee AND tuition fee for the hakukohde. + (let [application-id (unit-test-db/init-db-fixture + form-fixtures/payment-exemption-test-form + application-fixtures/application-without-hakemusmaksu-exemption + nil) + _ (updater-job/update-kk-payment-status-for-person-handler + {:person_oid test-person-oid :term test-term :year test-year} runner) + application-key (:key (application-store/get-application application-id)) + payment (first (payment/get-raw-payments [application-key])) + obligation (get-tuition-payment-obligation-review application-key "payment-info-test-kk-hakukohde")] + (should= (:awaiting payment/all-states) (:state payment)) + (should= {:application_key application-key, :requirement "payment-obligation", + :state "obligated", :hakukohde "payment-info-test-kk-hakukohde"} + (select-keys obligation [:application_key :requirement :state :hakukohde])))) + + (it "should set tuition fee obligation for non fi/sv hakukohde when payment state changes to ok-by-proxy" + ; Initial state: hakukohde in both applications has only english as teaching language, + ; and the application / person has no exemption, and we mark one of the applications paid manually. + ; This means the other application should not require application payment BUT should still require + ; tuition fee. + (let [application-ids (unit-test-db/init-db-fixture + form-fixtures/payment-exemption-test-form + [application-fixtures/application-without-hakemusmaksu-exemption + application-fixtures/application-without-hakemusmaksu-exemption]) + [first-key second-key] (map #(:key (application-store/get-application %)) application-ids) + _ (payment-store/create-or-update-kk-application-payment! + {:application-key first-key + :state (:paid payment/all-states) + :reason nil + :due-date (time-format/unparse payment/default-time-format + (time/plus (time/today-at 12 0 0) + (time/days 3))) + :total-sum payment/kk-application-payment-amount + :maksut-secret test-maksut-secret + :required-at "now()" + :notification-sent-at nil + :approved-at "now()"}) + _ (updater-job/update-kk-payment-status-for-person-handler + {:person_oid test-person-oid :term test-term :year test-year} runner) + payment (first (payment/get-raw-payments [second-key])) + obligation (get-tuition-payment-obligation-review second-key "payment-info-test-kk-hakukohde")] + (should= (:ok-by-proxy payment/all-states) (:state payment)) + (should= {:application_key second-key, :requirement "payment-obligation", + :state "obligated", :hakukohde "payment-info-test-kk-hakukohde"} + (select-keys obligation [:application_key :requirement :state :hakukohde])))) + + (it "should not set tuition fee obligation for non fi/sv hakukohde when payment state changes to not-required" + ; Initial state: hakukohde in the application has only english as teaching language, + ; but the application / person has an exemption, meaning the application should require neither + ; application fee nor tuition fee for the hakukohde. + (let [application-id (unit-test-db/init-db-fixture + form-fixtures/payment-exemption-test-form + application-fixtures/application-with-hakemusmaksu-exemption + nil) + _ (updater-job/update-kk-payment-status-for-person-handler + {:person_oid test-person-oid :term test-term :year test-year} runner) + application-key (:key (application-store/get-application application-id)) + payment (first (payment/get-raw-payments [application-key])) + obligation (get-tuition-payment-obligation-review application-key "payment-info-test-kk-hakukohde")] + (should= (:not-required payment/all-states) (:state payment)) + (should-be-nil obligation))) + + (it "should not set tuition fee obligation for fi/sv hakukohde" + ; Initial state: hakukohde in the application has swedish and/or finnish in its teaching languages, + ; so even the application / person has no exemption, the application should require only an + ; application fee, but no tuition fee for the hakukohde. + (let [application-id (unit-test-db/init-db-fixture + form-fixtures/payment-exemption-test-form + (merge + application-fixtures/application-without-hakemusmaksu-exemption + {:hakukohde ["payment-info-test-kk-fisv-hakukohde"]}) + nil) + _ (updater-job/update-kk-payment-status-for-person-handler + {:person_oid test-person-oid :term test-term :year test-year} runner) + application-key (:key (application-store/get-application application-id)) + payment (first (payment/get-raw-payments [application-key])) + obligation (get-tuition-payment-obligation-review application-key "payment-info-test-kk-fisv-hakukohde")] + (should= (:awaiting payment/all-states) (:state payment)) + (should-be-nil obligation))) + + (it "should not override a non-automatic obligation" + ; Initial state: hakukohde in the application has only english as teaching language, + ; and application / person has no exemption, but there's a human review already for the tuition. + ; Application fee should be required, but tuition fee state should not change automatically anymore. + (let [application-id (unit-test-db/init-db-fixture + form-fixtures/payment-exemption-test-form + application-fixtures/application-without-hakemusmaksu-exemption + nil) + application-key (:key (application-store/get-application application-id)) + _ (store-tuition-fee-not-required-review application-key "payment-info-test-kk-hakukohde") + _ (updater-job/update-kk-payment-status-for-person-handler + {:person_oid test-person-oid :term test-term :year test-year} runner) + payment (first (payment/get-raw-payments [application-key])) + obligation (get-tuition-payment-obligation-review application-key "payment-info-test-kk-hakukohde")] + (should= (:awaiting payment/all-states) (:state payment)) + (should= {:application_key application-key, :requirement "payment-obligation", + :state "not-obligated", :hakukohde "payment-info-test-kk-hakukohde"} + (select-keys obligation [:application_key :requirement :state :hakukohde]))))) diff --git a/src/clj/ataru/applications/application_store.clj b/src/clj/ataru/applications/application_store.clj index 537357951c..71f5a2ed94 100644 --- a/src/clj/ataru/applications/application_store.clj +++ b/src/clj/ataru/applications/application_store.clj @@ -842,6 +842,8 @@ (queries/yesql-add-application-event> (:opetuskieli-koodi-urit hakukohde) + (map #(first (str/split % #"#"))) + set)] + (and (seq codes) + (not (contains? codes "oppilaitoksenopetuskieli_1")) ; fi + (not (contains? codes "oppilaitoksenopetuskieli_2")) ; sv + (not (contains? codes "oppilaitoksenopetuskieli_3"))))) ; fi/sv + +(defn- mark-tuition-fee-obligated + "Marks tuition fee (lukuvuosimaksu) obligation for application key for every hakukohde that does not organize + studies in Finnish and/or Swedish." + [{:keys [tarjonta-service]} application-key] + (let [application (application-store/get-latest-application-by-key application-key) + hakukohde-oids (:hakukohde application) + hakukohteet (tarjonta/get-hakukohteet + tarjonta-service + (remove nil? hakukohde-oids)) + tuition-hakukohde-oids (remove nil? + (map #(when (needs-tuition-fee? %) (:oid %)) hakukohteet))] + (doseq [hakukohde-oid tuition-hakukohde-oids] + (log/info "Marking tuition payment obligation due to kk application fee eligibility for application key" + application-key "and hakukohde oid" hakukohde-oid) + (application-store/save-payment-obligation-automatically-changed + application-key + hakukohde-oid + "payment-obligation" + "obligated")))) + (defn- invalidate-maksut-payments-if-needed "Whenever a payment for a term is made, other payment invoices for the person and term should be invalidated to avoid accidental double payments." @@ -132,8 +163,9 @@ (defn update-kk-payment-status-for-person-handler "Updates payment requirement status for a single (person oid, term, year) either directly or - via an application id/key. Creates payments and sends e-mails when necessary. Marking status as paid/overdue - is done separately via kk-application-payment-maksut-poller-job, never here." + via an application id/key. Creates payments and sends e-mails when necessary. Also marks tuition fee obligation + if necessary. Marking status as paid/overdue is done separately via kk-application-payment-maksut-poller-job, + never here." [{:keys [person_oid term year application_id application_key]} {:keys [ohjausparametrit-service person-service tarjonta-service koodisto-cache get-haut-cache maksut-service] :as job-runner}] @@ -151,7 +183,13 @@ (let [new-state (:state payment)] (cond (= (:awaiting payment/all-states) new-state) - (create-payment-and-send-email job-runner maksut-service payment)))) + (do + (create-payment-and-send-email job-runner maksut-service payment) + ; If application payment is required, tuition fee will be always required as well. + (mark-tuition-fee-obligated job-runner (:application-key payment))) + + (= (:ok-by-proxy payment/all-states) new-state) + (mark-tuition-fee-obligated job-runner (:application-key payment))))) (doseq [application-payment existing-payments] (let [{:keys [application payment]} application-payment] diff --git a/src/clj/ataru/tarjonta_service/mock_tarjonta_service.clj b/src/clj/ataru/tarjonta_service/mock_tarjonta_service.clj index b6223841a7..1dbc2c6ad5 100644 --- a/src/clj/ataru/tarjonta_service/mock_tarjonta_service.clj +++ b/src/clj/ataru/tarjonta_service/mock_tarjonta_service.clj @@ -550,7 +550,14 @@ :payment-info-test-kk-hakukohde (merge base-kouta-hakukohde {:oid "payment-info-test-kk-hakukohde" - :johtaaTutkintoon true}) + :johtaaTutkintoon true + :opetuskieliKoodiUrit ["oppilaitoksenopetuskieli_4#2"]}) + :payment-info-test-kk-fisv-hakukohde (merge + base-kouta-hakukohde + {:oid "payment-info-test-kk-fisv-hakukohde" + :johtaaTutkintoon true + :opetuskieliKoodiUrit ["oppilaitoksenopetuskieli_2#2" + "oppilaitoksenopetuskieli_4#2"]}) :payment-info-test-kk-no-tutkinto-hakukohde (merge base-kouta-hakukohde {:oid "payment-info-test-kk-no-tutkinto-hakukohde"