           wrappers))
 
 (def wrapped-routes
-  (wrap-routes (routes open-routes
-                       api-routes
-                       protected-routes)
+  (wrap-routes all-routes
+               [wrap-models                         "models"]
+               [wrap-integer-id-params              "multipart params"]
                [wrap-multipart-params               "multipart params" (complement api?)]
                [wrap-keyword-params                 "keyword params"   (complement api?)]
                [wrap-json-params                    "json params"      api?]

            [clj-money.web.users :as users]
            [clj-money.web.grants :as grants]))

(defmacro model-route
  [method path handler]
  `(~method ~path req# (-> ~handler
                           wrap-models
                           wrap-integer-id-params)))

(defroutes protected-routes
  ; Entities
  (model-route GET "/entities" entities/index)
  (model-route GET "/entities/new" entities/new-entity)
  (model-route POST "/entities" entities/create-entity)
  (model-route GET "/entities/:id/edit" entities/edit-entity)
  (model-route POST "/entities/:id" entities/update)
  (model-route POST "/entities/:id/delete" entities/delete)

  ; User grants
  (model-route GET "/entities/:entity-id/grants" grants/index)
  (model-route GET "/entities/:entity-id/grants/new" grants/new-grant)
  (model-route POST "/entities/:entity-id/grants" grants/create)
  (model-route GET "/grants/:id/edit" grants/edit)
  (model-route POST "/grants/:id" grants/update)
  (model-route POST "/grants/:id/delete" grants/delete)

  ; Accounts
  (model-route GET "/entities/:entity-id/accounts" accounts/index)
  (model-route GET "/entities/:entity-id/accounts/new" accounts/new-account)
  (model-route POST "/entities/:entity-id/accounts" accounts/create)
  (model-route GET "/accounts/:id" accounts/show)
  (model-route GET "/accounts/:id/edit" accounts/edit)
  (model-route POST "/accounts/:id" accounts/update)
  (model-route POST "/accounts/:id/delete" accounts/delete)

  ; Budgets
  (model-route GET "/entities/:entity-id/budgets" budgets/index)
  (model-route GET "/entities/:entity-id/budgets/new" budgets/new-budget)
  (model-route POST "/entities/:entity-id/budgets" budgets/create)
  (model-route GET "/budgets/:id/edit" budgets/edit)
  (model-route POST "/budgets/:id" budgets/update)
  (model-route POST "/budgets/:id/delete" budgets/delete)
  (model-route GET "/budgets/:id" budgets/show)

  ; Budget items
  (model-route GET "/budgets/:budget-id/items/new/:method" budgets/new-item)
  (model-route POST "/budgets/:budget-id/items" budgets/create-item)
  (model-route GET "/budget-items/:id/edit/:method" budgets/edit-item)
  (model-route POST "/budget-items/:id" budgets/update-item)
  (model-route POST "/budget-items/:id/delete" budgets/delete-item)

  ; Budget monitors
  (model-route GET "/entities/:entity-id/monitors" entities/monitors)
  (model-route POST "/entities/:entity-id/monitors" entities/create-monitor)
  (model-route POST "/entities/:entity-id/monitors/:account-id/delete" entities/delete-monitor)

  ; Commodities
  (model-route GET "/entities/:entity-id/commodities" commodities/index)
  (model-route GET "/entities/:entity-id/commodities/new" commodities/new-commodity)
  (model-route POST "/entities/:entity-id/commodities" commodities/create)
  (model-route GET "/commodities/:id/edit" commodities/edit)
  (model-route POST "/commodities/:id" commodities/update)
  (model-route POST "/commodities/:id/delete" commodities/delete)

  ; Prices
  (model-route GET "/commodities/:commodity-id/prices" prices/index)
  (model-route GET "/commodities/:commodity-id/prices/new" prices/new-price)
  (model-route POST "/commodities/:commodity-id/prices" prices/create)
  (model-route POST "/commodities/:commodity-id/prices/fetch" prices/fetch)
  (model-route POST "/entities/:entity-id/prices/fetch" prices/fetch-all)
  (model-route POST "/prices/:id/delete" prices/delete)

  ; Transactions
  (model-route GET "/entities/:entity-id/transactions" transactions/index)
  (model-route GET "/entities/:entity-id/transactions/new" transactions/new-transaction)
  (model-route POST "/entities/:entity-id/transactions" transactions/create)
  (model-route GET "/transactions/:transaction-date/:id/edit" transactions/edit)
  (model-route POST "/transactions/:transaction-date/:id" transactions/update)
  (model-route POST "/transactions/:transaction-date/:id/delete" transactions/delete)

  ; Attachments
  (model-route GET "/transactions/:transaction-id/attachments" attachments/index)
  (model-route GET "/transactions/:transaction-id/attachments" attachments/index)
  (model-route GET "/transactions/:transaction-id/attachments/new" attachments/new-attachment)
  (model-route POST "/transactions/:transaction-id/attachments" attachments/create)
  (model-route GET "/attachments/:id/edit" attachments/edit)
  (model-route POST "/attachments/:id" attachments/update)
  (model-route POST "/attachments/:id/delete" attachments/delete)

  ; Images
  (model-route GET "/images/:image-id" images/show)

  ; Trading
  (model-route GET "/accounts/:account-id/purchases/new" trading/new-purchase)
  (model-route POST "/accounts/:account-id/purchases" trading/purchase)
  (model-route GET "/accounts/:account-id/sales/new" trading/new-sale)
  (model-route POST "/accounts/:account-id/sales" trading/sell)
  (model-route POST "/transactions/:transaction-id/unbuy" trading/unbuy)

  ; Lots
  (model-route GET "/accounts/:account-id/lots" lots/index)

  ; Reconciliations
  (model-route GET "/accounts/:account-id/reconciliations/new" reconciliations/new-reconciliation)
  (model-route POST "/accounts/:account-id/reconciliations" reconciliations/create)
  (model-route GET "/reconciliations/:id" reconciliations/show)
  (model-route GET "/reconciliations/:id/edit" reconciliations/edit)
  (model-route POST "/reconciliations/:id" reconciliations/update)
  (model-route POST "/reconciliations/:id/delete" reconciliations/delete)

  ; Imports
  (model-route GET "/imports/new" imports/new-import)
  
  ; Reports
  (model-route GET "/entities/:entity-id/reports" reports/render)
  (model-route GET "/entities/:entity-id/reports/:type" reports/render)

  ; Single page apps
  (model-route GET "/apps" apps/index)
  (model-route GET "/apps/:id" apps/show))

(defroutes api-routes
  (model-route GET "/api/entities" entities-api/index)
  (model-route DELETE "/api/entities/:id" entities-api/delete)

  ; Imports
  (model-route POST "/api/imports" imports-api/create)
  (model-route GET "/api/imports/:id" imports-api/show))

(defroutes open-routes
  (model-route GET "/" pages/home)
  (model-route GET "/login" pages/login)
  (model-route GET "/signup" users/new-user)
  (model-route POST "/users" users/create-user)
  (model-route GET "/users/:token/password" users/new-password)
  (model-route POST "/users/:token/password" users/set-password))

(def ^:private accept-map
  {"application/json" :json})

                    (conj wrapper (constantly true))
                    wrapper)]
    (fn [{:keys [request-method uri] :as request}]
      (when (test-fn request)
        (pprint {(str "enter " description " " request-method " " uri) (select-keys request [:cookies :session :headers])}))
      (let [apply? (test-fn request)
            working-handler (if apply?
                              (wrapper-fn handler)
                              handler)
            response (working-handler request)]
        (when apply?
          (pprint {(str "exit " description " " request-method " " uri) (select-keys response [:cookies :session :headers])}))
        response))))

(defn-  wrap-routes
  [handler & wrappers]
