Skip to content

Instantly share code, notes, and snippets.

@hden
Created April 19, 2016 03:40
Show Gist options
  • Save hden/17f2ae23e996a7a176ed18382a7c2402 to your computer and use it in GitHub Desktop.
Save hden/17f2ae23e996a7a176ed18382a7c2402 to your computer and use it in GitHub Desktop.
Datomic inventory
(ns inventory.core
(:gen-class)
(:require [datomic.api :as d]))
(def uri "datomic:mem://test")
(def schema [{:db/id #db/id[:db.part/db]
:db/ident :stock/in-stock
:db/valueType :db.type/bigint
:db/cardinality :db.cardinality/one
:db/doc "The quantity of hand"
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :stock/committed
:db/valueType :db.type/bigint
:db/cardinality :db.cardinality/one
:db/doc ""
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :stock/awaiting-reorder
:db/valueType :db.type/bigint
:db/cardinality :db.cardinality/one
:db/doc ""
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :stock/awaiting-restock
:db/valueType :db.type/bigint
:db/cardinality :db.cardinality/one
:db/doc ""
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :stock/upper-limit
:db/valueType :db.type/bigint
:db/cardinality :db.cardinality/one
:db/doc ""
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :stock/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc "A product's name"
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :sales/invoice
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc ""
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :sales/shipping-receipt
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/doc ""
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/user]
:db/ident :stock/transfer
:db/fn #db/fn{:lang "clojure"
:params [db id from to amount]
:code "(let [e (datomic.api/entity db id)
x (- (from e) amount)
y (+ (to e) amount)]
(assert (>= x 0))
(assert (>= y 0))
[[:db/add id from x]
[:db/add id to y]])"}}])
(defn stock [id s a b c d e]
(assert (= e (+ a b c d)))
{:db/id id
:stock/name s
:stock/in-stock a
:stock/committed b
:stock/awaiting-reorder c
:stock/awaiting-restock d
:stock/upper-limit e})
(defn -main
"I don't do a whole lot ... yet."
[& args]
(d/create-database uri)
(let [conn (d/connect uri)]
(d/transact conn schema)
;; let's introduce a new product
(d/transact conn [(stock #db/id[:db.part/user] "Apple" 0N 0N 5N 0N 5N)
(stock #db/id[:db.part/user] "Banana" 10N 0N 0N 0N 10N)
(stock #db/id[:db.part/user] "Kiwi" 20N 0N 0N 0N 20N)
{:db/id (datomic.api/tempid :db.part/tx)
:db/doc "new product"}])
(println "=> let's reorder some apples")
(let [[[e]] (seq (d/q '[:find ?e :where [?e :stock/name "Apple"]] (d/db conn)))]
(d/transact conn [[:stock/transfer e :stock/awaiting-reorder :stock/awaiting-restock 5]
{:db/id (datomic.api/tempid :db.part/tx)
:db/doc "reorder apple"}])
(println (d/pull (d/db conn) '[*] e))
(println "=> assume that we have recieved an extra apple")
(d/transact conn [[:stock/transfer e :stock/awaiting-restock :stock/in-stock 1]
{:db/id (datomic.api/tempid :db.part/tx)
:db/doc "apple receipt"}])
(println (d/pull (d/db conn) '[*] e))
(println "=> let's sell the apple")
(d/transact conn [[:stock/transfer e :stock/in-stock :stock/committed 1]
{:db/id (datomic.api/tempid :db.part/tx)
:db/doc "sales invoice #001"
:sales/invoice "001"}])
(println "=> noticed that the apple is not shipped yet!")
(println (d/pull (d/db conn) '[*] e))
(println "=> assume that we have shipped the apple")
(d/transact conn [[:stock/transfer e :stock/committed :stock/awaiting-reorder 1]
{:db/id (datomic.api/tempid :db.part/tx)
:db/doc "shipping receipt for sales invoice #001"
:sales/shipping-receipt "#002"}])
(println (d/pull (d/db conn) '[*] e))
(println "=> when was the apple sold?")
(println (d/q '[:find ?doc ?t
:where [?e :stock/name "Apple"]
[?e :stock/committed _ ?tx]
[?tx :sales/invoice _]
[?tx :db/doc ?doc]
[?tx :db/txInstant ?t]]
(d/history (d/db conn))))
(println "=> when was the apple shipped?")
(println (d/q '[:find ?doc ?t
:where [?e :stock/name "Apple"]
[?e :stock/committed _ ?tx]
[?tx :sales/shipping-receipt _]
[?tx :db/doc ?doc]
[?tx :db/txInstant ?t]]
(d/history (d/db conn)))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment