;; ;; members-payments.scm ;; ;; Adding payment information to member records from bank account statement. ;; ;; ISC License ;; ;; Copyright 2023 Brmlab, z.s. ;; Dominik Pantůček ;; ;; Permission to use, copy, modify, and/or distribute this software ;; for any purpose with or without fee is hereby granted, provided ;; that the above copyright notice and this permission notice appear ;; in all copies. ;; ;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL ;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED ;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE ;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR ;; CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS ;; OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, ;; NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ;; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ;; (declare (unit members-payments)) (module members-payments ( members-payments-process member-payments-total ) (import scheme (chicken base) (chicken string) (chicken io) (chicken irregex) bank-account member-record members-base bank-fio dictionary member-fees) ;; Extract probable member-id from transaction (define (transaction-extract-member-id transaction) (if (equal? (bank-transaction-type transaction) "Poplatek") #f (let* ((varsym-id0 (string->number (bank-transaction-varsym transaction))) (varsym-id (or varsym-id0 (let* ((msg (bank-transaction-message transaction)) (ci (substring-index "," msg)) (vs (if ci (substring msg 0 ci) msg))) (string->number vs))))) varsym-id))) ;; Merges bank account statement into members payment keys. The ;; payment key will be a list of transactions. (define (members-payments-process-bank mb ba) (let loop ((mb mb) (transactions (bank-account-transactions ba))) (if (null? transactions) mb (let* ((transaction (car transactions)) (varsym-id (transaction-extract-member-id transaction))) (loop (members-base-update mb (lambda (mr) (eq? (member-id mr) varsym-id)) (lambda (mr) (member-record-add-payment mr transaction))) (cdr transactions)))))) ;; Reads the payments (define (load-accounts-list apikeys) (map (compose car string-split) (read-lines (open-input-file apikeys)))) ;; Loads all accounts - it expects .csv files in the current ;; directory. (define (load-accounts accounts-list) (map (lambda (acc) (bank-fio-parse (string-append acc ".csv"))) accounts-list)) ;; If apikeys is not #f, loads the account numbers, loads bank ;; accounts and processes transactions. (define (members-payments-process mb apikeys-file) (if apikeys-file (let* ((accounts (load-accounts (load-accounts-list apikeys-file)))) (map member-add-balance (foldl members-payments-process-bank mb accounts))) mb)) ;; Adds all balances - payments are converted to CZK. (define (member-add-balance mr) (dict-set mr 'balance (make-dict `((fees . ,(member-fees-total mr)) (credit . ,(member-credit-total mr)) (payment . ,(member-payments-total mr)))))) ;; Total amount paid (define (member-payments-total mr) (foldl + 0 (map (lambda (tr) (let ((amount (bank-transaction-amount tr)) (currency (bank-transaction-currency tr))) (case currency ((CZK) amount) ((EUR) (* amount 25)) (else 0)))) (member-payments mr)))) )