|
@@ -133,6 +133,12 @@
|
|
|
for ret = (cdr (assoc key alist :test #'equal)) then (cdr (assoc key ret :test #'equal))
|
|
for ret = (cdr (assoc key alist :test #'equal)) then (cdr (assoc key ret :test #'equal))
|
|
|
finally (return ret)))
|
|
finally (return ret)))
|
|
|
|
|
|
|
|
|
|
+(defun get-account-currency (account)
|
|
|
|
|
+ (let ((currency (aget account :currency)))
|
|
|
|
|
+ (cond
|
|
|
|
|
+ ((equal currency "RUR") "RUB")
|
|
|
|
|
+ (t currency))))
|
|
|
|
|
+
|
|
|
(defun get-account-name (account)
|
|
(defun get-account-name (account)
|
|
|
(let ((num (aget account :number)))
|
|
(let ((num (aget account :number)))
|
|
|
(concatenate 'string "assets:Raiffeisen:"
|
|
(concatenate 'string "assets:Raiffeisen:"
|
|
@@ -146,7 +152,7 @@
|
|
|
":"
|
|
":"
|
|
|
num
|
|
num
|
|
|
":"
|
|
":"
|
|
|
- (aget account :currency)))))))
|
|
|
|
|
|
|
+ (get-account-currency account)))))))
|
|
|
|
|
|
|
|
(defun get-move-payee (move)
|
|
(defun get-move-payee (move)
|
|
|
(aget move :short-description))
|
|
(aget move :short-description))
|
|
@@ -158,47 +164,57 @@
|
|
|
(cl-ppcre:regex-replace-all "\\s" full " "))))
|
|
(cl-ppcre:regex-replace-all "\\s" full " "))))
|
|
|
|
|
|
|
|
(defun get-move-account2 (move)
|
|
(defun get-move-account2 (move)
|
|
|
- (if (string= "1" (aget move :type))
|
|
|
|
|
- "income" "expenses"))
|
|
|
|
|
|
|
+ (let ((desc (aget move :short-description)))
|
|
|
|
|
+ (cond
|
|
|
|
|
+ ((equal desc "P/O 001,40817810503000266700RC") "assets:Raiffeisen:Debit")
|
|
|
|
|
+ ((equal desc "P/O 001,40817810203001534278RC") "assets:Raiffeisen:Savings:Renov")
|
|
|
|
|
+ ((equal desc "TINKOFF BANK CARD2CARD MOSCOW") "assets:Tinkoff:Debit")
|
|
|
|
|
+ ((equal (subseq desc 0 (min 7 (length desc))) "RBA ATM") "assets:Cash:RUB")
|
|
|
|
|
+ (t (if (string= "1" (aget move :type)) "income" "expenses")))))
|
|
|
|
|
|
|
|
(defun short-date (date)
|
|
(defun short-date (date)
|
|
|
(cl-ppcre:regex-replace-all "-" (subseq date 0 10) "/"))
|
|
(cl-ppcre:regex-replace-all "-" (subseq date 0 10) "/"))
|
|
|
|
|
|
|
|
(defun moves->journal (account moves)
|
|
(defun moves->journal (account moves)
|
|
|
(let ((account1 (get-account-name account))
|
|
(let ((account1 (get-account-name account))
|
|
|
- (currency (aget account :currency))
|
|
|
|
|
|
|
+ (currency (get-account-currency account))
|
|
|
entries)
|
|
entries)
|
|
|
(loop for move in moves
|
|
(loop for move in moves
|
|
|
for date = (short-date (aget move :commit-date))
|
|
for date = (short-date (aget move :commit-date))
|
|
|
for payee = (get-move-payee move)
|
|
for payee = (get-move-payee move)
|
|
|
for description = (get-move-description move)
|
|
for description = (get-move-description move)
|
|
|
for id = (aget move :id)
|
|
for id = (aget move :id)
|
|
|
- for amount = (aget move :amount)
|
|
|
|
|
|
|
+ for amount = (read-from-string (aget move :amount))
|
|
|
for account2 = (get-move-account2 move)
|
|
for account2 = (get-move-account2 move)
|
|
|
for expense = (equal "0" (aget move :type))
|
|
for expense = (equal "0" (aget move :type))
|
|
|
- do (push (format nil "~A~@[ (~A)~] ~A~@[ ; ~A~]~% ~37A ~A~A ~A~% ~37A ~A~A ~A"
|
|
|
|
|
|
|
+ do (push (format nil "~A~@[ (~A)~] ~A~@[ ; ~A~]~% ~37A ~A~,2F ~A~% ~37A ~A~,2F ~A"
|
|
|
date nil payee description
|
|
date nil payee description
|
|
|
account1 (if expense "-" " ") amount currency
|
|
account1 (if expense "-" " ") amount currency
|
|
|
account2 (if expense " " "-") amount currency)
|
|
account2 (if expense " " "-") amount currency)
|
|
|
entries))
|
|
entries))
|
|
|
;; Total account balance
|
|
;; Total account balance
|
|
|
- (push (format nil "; balance ~A ~A = ~A"
|
|
|
|
|
|
|
+ (push (format nil "; balance ~A ~A = ~,2F ~A"
|
|
|
(short-date (aget account :balance-date))
|
|
(short-date (aget account :balance-date))
|
|
|
account1
|
|
account1
|
|
|
- (aget account :balance))
|
|
|
|
|
|
|
+ (read-from-string (aget account :balance))
|
|
|
|
|
+ (get-account-currency account))
|
|
|
entries)
|
|
entries)
|
|
|
(nreverse entries)))
|
|
(nreverse entries)))
|
|
|
|
|
|
|
|
(defun main (argv)
|
|
(defun main (argv)
|
|
|
- (destructuring-bind (type login pass) argv
|
|
|
|
|
|
|
+ (destructuring-bind (login pass type) argv
|
|
|
(rc/perform-login login pass)
|
|
(rc/perform-login login pass)
|
|
|
(let* ((accounts (get-accounts (rc/get-batch-response)))
|
|
(let* ((accounts (get-accounts (rc/get-batch-response)))
|
|
|
- (now (get-universal-time))
|
|
|
|
|
- (week-ago (- now (* 60 60 24 7)))
|
|
|
|
|
|
|
+ (end (get-universal-time))
|
|
|
|
|
+ (start (- end (* 60 60 24 (cond
|
|
|
|
|
+ ((equal type "week") 7)
|
|
|
|
|
+ ((equal type "day") 1)
|
|
|
|
|
+ ((equal type "month") 30)
|
|
|
|
|
+ (t 7)))))
|
|
|
(moves (mapcar (lambda (a) (cons (node->alist a)
|
|
(moves (mapcar (lambda (a) (cons (node->alist a)
|
|
|
(mapcar #'node->alist
|
|
(mapcar #'node->alist
|
|
|
(if (string= type "last")
|
|
(if (string= type "last")
|
|
|
(nreverse (rc/get-last-account-movements a 10))
|
|
(nreverse (rc/get-last-account-movements a 10))
|
|
|
- (rc/get-account-movements a week-ago now)))))
|
|
|
|
|
|
|
+ (rc/get-account-movements a start end)))))
|
|
|
accounts)))
|
|
accounts)))
|
|
|
(format t "~{~A~^~%~%~}~%" (loop for (a . m) in moves append (moves->journal a m))))))
|
|
(format t "~{~A~^~%~%~}~%" (loop for (a . m) in moves append (moves->journal a m))))))
|