Created
April 30, 2014 15:54
-
-
Save holyjak/61d780888f12c3a31b60 to your computer and use it in GitHub Desktop.
Code for http://wp.me/pTHiC-10R, part 1
This file contains 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
(require '[cheshire.core :refer [parse-string]]) | |
(defn db-array [col] (reify java.sql.Array (getArray [_] (object-array col)))) | |
(defn- json->data [data fields] | |
(map (fn [data] | |
(reduce (fn [data field] | |
(assoc data field (parse-string (get data field) true))) | |
data fields)) data)) | |
(defn- discount-size [discount] | |
(if (or | |
(> (:amount discount) 10000) | |
(> (:percent discount) 5)) | |
:high | |
:normal)) | |
(defn- jdbc-array-to-set | |
"Convert a PostgreSQL JDBC4Array inside the map `m` - at the key `k` - into a se" | |
[key m] (update-in m [key] #(some->> % (.getArray) (into #{})))) | |
(defn- compute-discount | |
"Derive the :discount map based on the car's own discount and its active campaign, if applicable" | |
[car] | |
(let [{:keys [json campaign_discount_amount campaign_discount_percent]} car | |
{:keys [discount_amount discount_percent]} json | |
discount? (:use_campaign car) | |
amount (if discount? | |
(apply + (remove nil? [discount_amount campaign_discount_amount])) | |
discount_amount) | |
percent (if discount? | |
(apply + (remove nil? [discount_percent campaign_discount_percent])) | |
discount_percent) | |
discount {:amount amount | |
:percent percent} | |
discount-size (discount-size discount) | |
] | |
(assoc car :discount discount :discount-size discount-size))) | |
(defn merge-campaigns | |
"Given vector of car+campaign for a particular car, return a single car map | |
with a selected campaign. | |
" | |
[car+campaigns] | |
{:pre [(sequential? car+campaigns) :id]} | |
(let [campaign-ks [:use_campaign :campaign_discount_amount :campaign_discount_percent :active] | |
car (apply dissoc | |
(first car+campaigns) | |
campaign-ks) | |
campaign (->> car+campaigns | |
(map #(select-keys % campaign-ks)) | |
(filter :active) | |
(sort-by :use_campaign) ;; true, if any, will be last | |
last)] | |
(assoc car :best-campaign campaign))) | |
(defn refine-cars | |
"Process get-cars query result set - derive additional data, transform values into better ones | |
There is one row per car and campaign, a car may have more campaigns - we pick the best one. | |
" | |
[cars-raw] | |
(->> cars-raw | |
(#(json->data % [:json])) | |
(#(map merge-campaigns | |
(vals (group-by :id %)))) | |
(map (comp ;; reminder - the 1st fn is executed last | |
compute-discount | |
(fn [m] (update-in m [:keywords] (partial remove nil?))) ;; {NULL} => [] | |
(partial jdbc-array-to-set :keywords) | |
(partial jdbc-array-to-set :category_ref) | |
)) | |
)) | |
(refine-cars [ | |
{:id 1 | |
:json "{\"discount_amount\":9000,\"discount_percent\":0}" | |
:campaign_discount_amount 2000 | |
:campaign_discount_percent nil | |
:use_campaign false | |
:active true | |
:keywords (db-array ["fast"]) | |
:category_ref (db-array [])}]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment