mirror of
https://github.com/mruwnik/invoices.git
synced 2025-06-08 21:34:44 +02:00
Custom functions
This commit is contained in:
parent
505aadbaa8
commit
ea4294f138
11
README.md
11
README.md
@ -55,8 +55,8 @@ The buyer can have the following keys
|
|||||||
|
|
||||||
### Items
|
### Items
|
||||||
|
|
||||||
The list of items should contain maps with two required keys (:vat and :title), and a key
|
The list of items should contain maps with a required :title, an optional :vat (if not provided it is assumed that
|
||||||
providing the cost of the item. The price can be provided in one of three ways:
|
item is VAT free), and a key providing the cost of the item. The price can be provided in one of the following ways:
|
||||||
|
|
||||||
* :netto - is a set price and will be displayed as provided
|
* :netto - is a set price and will be displayed as provided
|
||||||
* :hourly - is an hourly price - JIRA will be queried in order to work out how many hours should be billed
|
* :hourly - is an hourly price - JIRA will be queried in order to work out how many hours should be billed
|
||||||
@ -69,6 +69,10 @@ providing the cost of the item. The price can be provided in one of three ways:
|
|||||||
be :base. Otherwise the final price will be scaled accordingly. This is pretty much equivalent
|
be :base. Otherwise the final price will be scaled accordingly. This is pretty much equivalent
|
||||||
to working out what the hourly rate should be in a given month and multiplying it by the number
|
to working out what the hourly rate should be in a given month and multiplying it by the number
|
||||||
of hours worked in that month
|
of hours worked in that month
|
||||||
|
* :function - an S-expression describing how to calculate the net value. Only numbers, basic mathematical
|
||||||
|
operations (+, -, /, *) and timesheet specific variables are supported (:worked, :required,
|
||||||
|
:to, :from).
|
||||||
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
@ -81,6 +85,9 @@ Examples:
|
|||||||
; 23% VAT, working part time with a base salary of 5000
|
; 23% VAT, working part time with a base salary of 5000
|
||||||
{:vat 23 :base 5000 :per-day 4 :title "Part time job at 5000"}]
|
{:vat 23 :base 5000 :per-day 4 :title "Part time job at 5000"}]
|
||||||
|
|
||||||
|
; 23% VAT, with a custom function
|
||||||
|
{:vat 23 :function (* :worked (/ 10000 :required)) :title "Custom function"}]
|
||||||
|
|
||||||
|
|
||||||
### Credentials
|
### Credentials
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
:nip 9875645342}
|
:nip 9875645342}
|
||||||
:items [{:vat 8 :netto 123.21 :title "Buty kowbojskie"}
|
:items [{:vat 8 :netto 123.21 :title "Buty kowbojskie"}
|
||||||
{:vat 21 :hourly 43.12 :title "Usługa szewska"}
|
{:vat 21 :hourly 43.12 :title "Usługa szewska"}
|
||||||
|
{:netto 321.45 :title "Usługa szewska bez VAT"}
|
||||||
|
{:vat 23 :function (* :worked (+ 1 2 3 (- 23 13))) :title "Pucowania obuwia"}
|
||||||
{:vat 23 :base 4300.00 :per-day 4 :title "Praca za ladą"}]
|
{:vat 23 :base 4300.00 :per-day 4 :title "Praca za ladą"}]
|
||||||
:font-path "/usr/share/fonts/truetype/freefont/FreeSans.ttf"
|
:font-path "/usr/share/fonts/truetype/freefont/FreeSans.ttf"
|
||||||
:credentials {:tempo-token "5zq7zF9LADefEGAs12eDDas3FDttiM"
|
:credentials {:tempo-token "5zq7zF9LADefEGAs12eDDas3FDttiM"
|
||||||
|
@ -9,25 +9,36 @@
|
|||||||
(defn invoice-number [when number]
|
(defn invoice-number [when number]
|
||||||
(->> [(or number 1) (-> when .getMonthValue) (-> when .getYear)] (map str) (str/join "/")))
|
(->> [(or number 1) (-> when .getMonthValue) (-> when .getYear)] (map str) (str/join "/")))
|
||||||
|
|
||||||
(defn calc-part-time [when creds {base :base per-day :per-day}]
|
(defn parse-custom [work-log func]
|
||||||
(let [{worked :worked total :required} (prev-timesheet when creds)
|
(cond
|
||||||
hourly (/ (* base 8) (* total per-day))]
|
(and (list? func) (some #{(first func)} '(+ - * /))) (apply (resolve (first func))
|
||||||
|
(map (partial parse-custom work-log) (rest func)))
|
||||||
|
(list? func) (throw (IllegalArgumentException. (str "Invalid functor provided: " (first func))))
|
||||||
|
(some #{func} '(:worked :required :to :from)) (func work-log)
|
||||||
|
:else func))
|
||||||
|
|
||||||
|
(defn calc-part-time [{worked :worked total :required} {base :base per-day :per-day}]
|
||||||
|
(let [hourly (/ (* base 8) (* total per-day))]
|
||||||
(float (* hourly worked))))
|
(float (* hourly worked))))
|
||||||
|
|
||||||
(defn calc-hourly [when creds {hourly :hourly}]
|
(defn calc-hourly [{worked :worked} {hourly :hourly}]
|
||||||
(-> (prev-timesheet when creds) :worked (* hourly)))
|
(* worked hourly))
|
||||||
|
|
||||||
|
(defn calc-custom [worked {function :function}]
|
||||||
|
(parse-custom worked function))
|
||||||
|
|
||||||
|
|
||||||
(defn set-price [when creds item]
|
(defn set-price [worked item]
|
||||||
(cond
|
(cond
|
||||||
(contains? item :hourly) (assoc item :netto (calc-hourly when creds item))
|
(contains? item :function) (assoc item :netto (calc-custom worked item))
|
||||||
(contains? item :base) (assoc item :netto (calc-part-time when creds item))
|
(contains? item :hourly) (assoc item :netto (calc-hourly worked item))
|
||||||
|
(contains? item :base) (assoc item :netto (calc-part-time worked item))
|
||||||
(not (contains? item :netto)) (assoc item :netto 0)
|
(not (contains? item :netto)) (assoc item :netto 0)
|
||||||
:else item))
|
:else item))
|
||||||
|
|
||||||
(defn for-month [when {seller :seller buyer :buyer items :items creds :credentials font-path :font-path} & [number]]
|
(defn for-month [when {seller :seller buyer :buyer items :items creds :credentials font-path :font-path} & [number]]
|
||||||
(pdf/render seller buyer
|
(pdf/render seller buyer
|
||||||
(map (partial set-price when creds) items)
|
(map (partial set-price (prev-timesheet when creds)) items)
|
||||||
(pdf/last-working-day when)
|
(pdf/last-working-day when)
|
||||||
(invoice-number when number)
|
(invoice-number when number)
|
||||||
font-path))
|
font-path))
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
(float (/ (Math/round (* val 100.0)) 100)))
|
(float (/ (Math/round (* val 100.0)) 100)))
|
||||||
|
|
||||||
(defn vat [{netto :netto vat-level :vat}]
|
(defn vat [{netto :netto vat-level :vat}]
|
||||||
(round (* netto (/ vat-level 100))))
|
(if-not vat-level 0 (* netto (/ vat-level 100))))
|
||||||
|
|
||||||
(defn brutto [{netto :netto :as item}] (round (+ netto (vat item))))
|
(defn brutto [{netto :netto :as item}] (round (+ netto (vat item))))
|
||||||
|
|
||||||
@ -22,7 +22,11 @@
|
|||||||
(defn format-product [{netto :netto vat-level :vat title :title :as item}]
|
(defn format-product [{netto :netto vat-level :vat title :title :as item}]
|
||||||
(concat
|
(concat
|
||||||
[[:cell {:colspan 4} title]]
|
[[:cell {:colspan 4} title]]
|
||||||
(map str [1 (-> netto round str) (str vat-level "%") (vat item) (brutto item)])))
|
(map str [1
|
||||||
|
(-> netto round str)
|
||||||
|
(if-not vat-level "zw." (str vat-level "%"))
|
||||||
|
(-> item vat round str)
|
||||||
|
(brutto item)])))
|
||||||
|
|
||||||
|
|
||||||
(defn get-title [team who which]
|
(defn get-title [team who which]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user