appydave-tools 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 697361623a5f429c2a7c06047d5669c8a9fcf27ebfb2b7f15ebf6037a4f4e39f
4
- data.tar.gz: a612fe3a884667a7961b3b1306758e405a8988afdddd06ec9f1550b6b50b92c9
3
+ metadata.gz: 14a6bd2963b58f85f247282a6cf8c537495b9a18300b04c3a3794ef5df4ecaa1
4
+ data.tar.gz: 5ec47924ab4268377a297e1f02f6fa6b4f62207179f21fe8ccdcd69d62cd4f8d
5
5
  SHA512:
6
- metadata.gz: 055b7a37ab1651f8650635f5ea84b9b0df06c91600e92cad505255dd3ed2702c5113b837ddd68cf82d312621591c8a3a4d076db91111b30a0cf565c1c651278c
7
- data.tar.gz: 6bbd3a0a492d0a8a55eee674fd2655b89e9f52953da0357d07cbaf938654009fb1ecf678fa8a432bf41f935001e37840cf92d3a5776f2c736092296e74caa19b
6
+ metadata.gz: 253546f33096bad9f9daaa5776fa9d98142a4e7cb43607bf2040ab648d49f83712c8f491b8730de4bd602bcd4080a9360cb9bdd082a1b249df4210d66083ebf6
7
+ data.tar.gz: f1f638a4a299df238694c8b4e42c008e8663a08cb2b83931a953796ec6679fa83038bebe3f749b0351a7edd848220cb906c53ff076abbf953564ff0356347b29
data/.rubocop.yml CHANGED
@@ -80,6 +80,7 @@ Style/EmptyMethod:
80
80
  Metrics/ParameterLists:
81
81
  Exclude:
82
82
  - "**/spec/**/*"
83
+ - "**/models/**/*"
83
84
  Layout/EmptyLineBetweenDefs:
84
85
  Exclude:
85
86
  - "**/spec/**/*"
@@ -115,3 +116,17 @@ RSpec/DescribeClass:
115
116
 
116
117
  RSpec/PendingWithoutReason:
117
118
  Enabled: false
119
+
120
+ Metrics/AbcSize:
121
+ Max: 25
122
+ Exclude:
123
+ - "bin/*"
124
+ Metrics/CyclomaticComplexity:
125
+ Exclude:
126
+ - "**/models/**/*"
127
+ - "lib/appydave/tools/bank_reconciliation/clean/mapper.rb"
128
+ Metrics/PerceivedComplexity:
129
+ Exclude:
130
+ - "**/models/**/*"
131
+ RSpec/MultipleMemoizedHelpers:
132
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [0.6.1](https://github.com/klueless-io/appydave-tools/compare/v0.6.0...v0.6.1) (2024-05-26)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * improved configuration printing ([89d769d](https://github.com/klueless-io/appydave-tools/commit/89d769d0741fc75b44db90931cf981feea83027f))
7
+
8
+ # [0.6.0](https://github.com/klueless-io/appydave-tools/compare/v0.5.0...v0.6.0) (2024-05-26)
9
+
10
+
11
+ ### Features
12
+
13
+ * refactor channels with locations, removed channel projects ([6b64574](https://github.com/klueless-io/appydave-tools/commit/6b645742b0029a001792c8d405dcae0b1036f2c0))
14
+
1
15
  # [0.5.0](https://github.com/klueless-io/appydave-tools/compare/v0.4.1...v0.5.0) (2024-05-26)
2
16
 
3
17
 
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
5
+
6
+ require 'pry'
7
+ require 'appydave/tools'
8
+
9
+ # !/usr/bin/env ruby
10
+ # frozen_string_literal: true
11
+
12
+ # Process command line arguments for any bank reconciliation operations
13
+ class BankReconciliationCLI
14
+ def initialize
15
+ @commands = {
16
+ 'clean' => method(:clean_transactions),
17
+ 'process' => method(:process_transactions),
18
+ 'filter' => method(:filter_transactions)
19
+ }
20
+ end
21
+
22
+ def run
23
+ command, *args = ARGV
24
+ if @commands.key?(command)
25
+ @commands[command].call(args)
26
+ else
27
+ puts "Unknown command: #{command}"
28
+ print_help
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def clean_transactions(args)
35
+ options = {}
36
+ OptionParser.new do |opts|
37
+ opts.banner = 'Usage: bank_reconciliation.rb clean [options]'
38
+ opts.on('-i', '--include PATTERN', 'GLOB pattern for source transaction files') { |v| options[:include] = v }
39
+ opts.on('-f', '--transaction FOLDER', 'Transaction CSV folder where original banking CSV files are stored') { |v| options[:transaction_folder] = v }
40
+ opts.on('-o', '--output FILE', 'Output CSV file name') { |v| options[:output] = v }
41
+ opts.on_tail('-h', '--help', 'Show this message') do
42
+ puts opts
43
+ exit
44
+ end
45
+ end.parse!(args)
46
+
47
+ # Implement cleaning and normalizing transactions
48
+ puts "Cleaning transactions with options: #{options}"
49
+ end
50
+
51
+ def process_transactions(args)
52
+ options = {}
53
+ OptionParser.new do |opts|
54
+ opts.banner = 'Usage: bank_reconciliation.rb process [options]'
55
+ opts.on('-i', '--input FILE', 'Input CSV file with transactions') { |v| options[:input] = v }
56
+ opts.on_tail('-h', '--help', 'Show this message') do
57
+ puts opts
58
+ exit
59
+ end
60
+ end.parse!(args)
61
+
62
+ # Implement processing transactions with chart of accounts lookup
63
+ puts "Processing transactions with options: #{options}"
64
+ end
65
+
66
+ def filter_transactions(args)
67
+ options = {}
68
+ OptionParser.new do |opts|
69
+ opts.banner = 'Usage: bank_reconciliation.rb filter [options]'
70
+ opts.on('-i', '--input FILE', 'Input CSV file with processed transactions') { |v| options[:input] = v }
71
+ opts.on('-y', '--year YEAR', 'Filter by financial year') { |v| options[:year] = v }
72
+ opts.on('-b', '--begin DATE', 'Filter by dates greater than or eqaul to DDMMYY') { |v| options[:year] = v }
73
+ opts.on('-e', '--end DATE', 'Filter by dates less than or eqaul to DDMMYY') { |v| options[:year] = v }
74
+ opts.on('-c', '--codes CODES', 'Filter by chart of account codes (comma-separated)') { |v| options[:codes] = v }
75
+ opts.on('-w', '--wild TEXT', 'Wildcard text match') { |v| options[:text] = v }
76
+ opts.on('-d', '--display', 'Display filtered transactions in table format') { |v| options[:display] = v }
77
+ opts.on('-o', '--output FILE', 'Output CSV file name') { |v| options[:output] = v }
78
+ opts.on_tail('-h', '--help', 'Show this message') do
79
+ puts opts
80
+ exit
81
+ end
82
+ end.parse!(args)
83
+
84
+ # Implement filtering of processed transactions
85
+ puts "Filtering transactions with options: #{options}"
86
+ end
87
+
88
+ def print_help
89
+ puts 'Usage: bank_reconciliation.rb [command] [options]'
90
+ puts 'Commands:'
91
+ puts ' clean Clean and normalize transaction files'
92
+ puts ' process Process transaction list via chart of accounts lookup'
93
+ puts ' filter Filter processed transaction list'
94
+ puts "Run 'bank_reconciliation.rb [command] --help' for more information on a command."
95
+ end
96
+ end
97
+
98
+ BankReconciliationCLI.new.run
99
+ # BankReconciliationCLI.new.run if __FILE__ == $PROGRAM_NAME
data/bin/configuration.rb CHANGED
@@ -1,12 +1,19 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ # Example of a simple command line tool to manage configuration files
5
+ # ad_config -p settings,channels
6
+ # ad_config -p
7
+ # ad_config -l
8
+ # ad_config -c
9
+ # ad_config -e
10
+
4
11
  $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
5
12
 
6
13
  require 'pry'
7
14
  require 'appydave/tools'
8
15
 
9
- options = {}
16
+ options = { keys: [] }
10
17
 
11
18
  OptionParser.new do |opts|
12
19
  opts.banner = 'Usage: config_tool.rb [options]'
@@ -23,8 +30,9 @@ OptionParser.new do |opts|
23
30
  options[:command] = :create
24
31
  end
25
32
 
26
- opts.on('-p', '--print', 'Print configuration details') do
33
+ opts.on('-p', '--print [KEYS]', Array, 'Print configuration details for specified keys') do |keys|
27
34
  options[:command] = :print
35
+ options[:keys] = keys
28
36
  end
29
37
 
30
38
  opts.on_tail('-h', '--help', 'Show this message') do
@@ -41,13 +49,13 @@ when :list
41
49
  configurations = Appydave::Tools::Configuration::Config.configurations.map do |name, config|
42
50
  { name: name, path: config.config_path, exists: File.exist?(config.config_path) }
43
51
  end
44
- tp configurations, :name, :exists, { config_path => { column_width: 150 } }
52
+ tp configurations, :name, :exists, { path: { width: 150 } }
45
53
  when :create
46
54
  Appydave::Tools::Configuration::Config.configure
47
55
  Appydave::Tools::Configuration::Config.save
48
56
  when :print
49
57
  Appydave::Tools::Configuration::Config.configure
50
- Appydave::Tools::Configuration::Config.print
58
+ Appydave::Tools::Configuration::Config.print(*options[:keys])
51
59
  else
52
60
  puts 'No valid command provided. Use --help for usage information.'
53
61
  end
@@ -0,0 +1,36 @@
1
+ # Bank reconciliation
2
+
3
+ [ChatGPT conversation](https://chatgpt.com/c/5d382562-95e5-4243-9b74-c3807d363486)
4
+
5
+
6
+ ## Code structure
7
+
8
+ ```bash
9
+ ├─ lib
10
+ │ ├─ appydave
11
+ │ │ └─ tools
12
+ │ │ ├─ bank_reconciliation
13
+ │ │ │ ├─ clean
14
+ │ │ │ │ ├─ read_transactions.rb
15
+ │ │ │ │ ├─ transaction_cleaner.rb
16
+ │ │ │ ├─ models
17
+ │ │ │ │ ├─ raw_transaction.rb
18
+ │ │ │ │ └─ reconciled_transaction.rb
19
+ │ │ └─ configuration
20
+ │ │ └─ models
21
+ │ │ └─ bank_reconciliation_config.rb
22
+ └─ spec
23
+ ├─ appydave
24
+ │ ├─ tools
25
+ │ │ ├─ bank_reconciliation
26
+ │ │ │ ├─ clean
27
+ │ │ │ │ ├─ read_transactions_spec.rb
28
+ │ │ │ ├─ models
29
+ │ │ │ │ └─ raw_transaction_spec.rb
30
+ │ │ └─ configuration
31
+ │ │ └─ models
32
+ │ │ └─ bank_reconciliation_config_spec.rb
33
+ └─ fixtures
34
+ └─ bank-reconciliation
35
+ └─ bank-west.csv
36
+ ```
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appydave
4
+ module Tools
5
+ module BankReconciliation
6
+ module Clean
7
+ # Clean transactions
8
+ class CleanTransactions
9
+ include Appydave::Tools::Configuration::Configurable
10
+ include KLog::Logging
11
+
12
+ attr_reader :transaction_folder
13
+ attr_reader :transactions
14
+
15
+ # (config_file)
16
+ def initialize(transaction_folder: '/Volumes/Expansion/Sync/bank-reconciliation/original-transactions')
17
+ @transaction_folder = transaction_folder
18
+ end
19
+
20
+ def clean_transactions(input_globs, _output_file)
21
+ raw_transactions = grab_raw_transactions(input_globs)
22
+ transactions, duplicates_count = deduplicate(raw_transactions)
23
+
24
+ transactions = Mapper.new.map(transactions)
25
+ # tp transactions
26
+
27
+ log.kv 'Deduped consolidated transactions', duplicates_count if duplicates_count.positive?
28
+
29
+ # transactions = normalize(transactions)
30
+ # save_to_csv(transactions, output_file)
31
+ @transactions = transactions
32
+ end
33
+
34
+ private
35
+
36
+ def grab_raw_transactions(input_globs)
37
+ original_dir = Dir.pwd
38
+ transactions = []
39
+
40
+ begin
41
+ Dir.chdir(transaction_folder)
42
+
43
+ input_globs.each do |glob|
44
+ Dir.glob(glob).each do |file|
45
+ raw_transactions = ReadTransactions.new(file).read
46
+ deduped_transactions, duplicates_count = deduplicate(raw_transactions)
47
+
48
+ if duplicates_count.positive?
49
+ log.kv 'Duplicates count', duplicates_count
50
+ log.kv 'File', file
51
+ end
52
+
53
+ transactions += deduped_transactions
54
+ end
55
+ end
56
+ ensure
57
+ Dir.chdir(original_dir)
58
+ end
59
+
60
+ transactions
61
+ end
62
+
63
+ def deduplicate(transactions)
64
+ unique_transactions = transactions.uniq do |transaction|
65
+ [
66
+ transaction.bsb_number,
67
+ transaction.account_number,
68
+ transaction.transaction_date,
69
+ transaction.narration,
70
+ transaction.cheque_number,
71
+ transaction.debit,
72
+ transaction.credit,
73
+ transaction.balance,
74
+ transaction.transaction_type
75
+ ]
76
+ end
77
+
78
+ duplicates = transactions.size - unique_transactions.size
79
+
80
+ [unique_transactions, duplicates]
81
+ end
82
+
83
+ def save_to_csv(transactions, output_file)
84
+ CSV.open(output_file, 'w') do |csv|
85
+ csv << ReconciledTransaction.csv_headers
86
+ transactions.each do |transaction|
87
+ csv << transaction.to_csv_row
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appydave
4
+ module Tools
5
+ module BankReconciliation
6
+ module Clean
7
+ # Map transactions to chart of accounts and bank accounts
8
+ class Mapper
9
+ include Appydave::Tools::Configuration::Configurable
10
+
11
+ # "bank_accounts": [
12
+ # {
13
+ # "account_number": "5435 6859 0116 7736",
14
+ # "bsb": "",
15
+ # "name": "Mastercard",
16
+ # "platform": "Bankwest"
17
+ # },
18
+ # {
19
+ # "account_number": "303-092",
20
+ # "bsb": "1361644",
21
+ # "name": "atcall",
22
+ # "platform": "Bankwest"
23
+ # },
24
+
25
+ def map(transactions)
26
+ transactions.map do |original_transaction|
27
+ transaction = original_transaction.dup
28
+
29
+ transaction = map_chart_of_account(transaction)
30
+ map_bank_account(transaction)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def map_chart_of_account(transaction)
37
+ equality_match(transaction) ||
38
+ trigram_match(transaction, 0.9, '90%') ||
39
+ trigram_match(transaction, 0.8, '80%') ||
40
+ trigram_match(transaction, 0.7, '70%') ||
41
+ trigram_match(transaction, 0.6, '60%') ||
42
+ trigram_match(transaction, 0.5, '50%') ||
43
+ transaction
44
+ end
45
+
46
+ def map_bank_account(transaction)
47
+ bank_account = config.bank_reconciliation.get_bank_account(transaction.account_number, transaction.bsb_number)
48
+
49
+ if bank_account
50
+ transaction.account_name = bank_account.name
51
+ transaction.platform = bank_account.platform
52
+ end
53
+
54
+ transaction
55
+ end
56
+
57
+ def equality_match(transaction)
58
+ coa = config.bank_reconciliation.chart_of_accounts.find do |chart_of_account|
59
+ chart_of_account.narration.to_s.delete(' ') == transaction.narration.delete(' ')
60
+ end
61
+
62
+ return nil unless coa
63
+
64
+ transaction.coa_match_type = 'equality'
65
+ transaction.coa_code = coa.code
66
+ transaction
67
+ end
68
+
69
+ def trigram_match(transaction, score_threshold, match_type)
70
+ scored_transactions = config.bank_reconciliation.chart_of_accounts.map do |coa|
71
+ {
72
+ coa: coa,
73
+ score: compare(coa.narration, transaction.narration)
74
+ }
75
+ end
76
+
77
+ scored_transactions.sort_by! { |t| t[:score] }.reverse!
78
+
79
+ best = scored_transactions.first
80
+
81
+ return nil unless best
82
+ return nil if best[:score] < score_threshold
83
+
84
+ coa = best[:coa]
85
+
86
+ transaction.coa_match_type = match_type
87
+ transaction.coa_code = coa.code
88
+ transaction
89
+ end
90
+
91
+ def compare(text1, text2)
92
+ text1_trigs = trigramify(text1)
93
+ text2_trigs = trigramify(text2)
94
+
95
+ all_cnt = (text1_trigs | text2_trigs).size
96
+ same_cnt = (text1_trigs & text2_trigs).size
97
+
98
+ same_cnt.to_f / all_cnt
99
+ end
100
+
101
+ def trigramify(text)
102
+ trigs = []
103
+ text.chars.each_cons(3) { |v| trigs << v.join }
104
+ trigs
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appydave
4
+ module Tools
5
+ module BankReconciliation
6
+ module Clean
7
+ # Read transactions from a CSV file
8
+ class ReadTransactions
9
+ attr_reader :platform
10
+ attr_reader :transactions
11
+
12
+ def initialize(file)
13
+ @file = file
14
+ end
15
+
16
+ def read
17
+ csv_lines = File.read(@file).lines
18
+
19
+ @platform = detect_platform(csv_lines)
20
+
21
+ case platform
22
+ when :bankwest
23
+ read_bankwest(csv_lines)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def read_bankwest(csv_lines)
30
+ @transactions = []
31
+
32
+ # Skip the header line and parse each subsequent line
33
+ CSV.parse(csv_lines.join, headers: true).each do |row|
34
+ transaction = Models::Transaction.new(
35
+ bsb_number: row['BSB Number'],
36
+ account_number: row['Account Number'],
37
+ transaction_date: row['Transaction Date'],
38
+ narration: row['Narration'],
39
+ cheque_number: row['Cheque Number'],
40
+ debit: row['Debit'],
41
+ credit: row['Credit'],
42
+ balance: row['Balance'],
43
+ transaction_type: row['Transaction Type']
44
+ )
45
+ @transactions << transaction
46
+ end
47
+
48
+ @transactions
49
+ end
50
+
51
+ # For bankwest the first row is the CSV will look like:
52
+ # BSB Number,Account Number,Transaction Date,Narration,Cheque Number,Debit,Credit,Balance,Transaction Type
53
+ def detect_platform(csv_lines)
54
+ return :bankwest if csv_lines.first.start_with?('BSB Number,Account Number,Transaction Date,Narration,Cheque Number,Debit,Credit,Balance,Transaction Type')
55
+
56
+ raise Appydave::Tools::Error, 'Unknown platform'
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appydave
4
+ module Tools
5
+ module BankReconciliation
6
+ module Models
7
+ # Unified transaction model for raw and reconciled data
8
+ class Transaction
9
+ attr_accessor :bsb_number,
10
+ :account_number,
11
+ :transaction_date,
12
+ :narration,
13
+ :cheque_number,
14
+ :debit,
15
+ :credit,
16
+ :balance,
17
+ :transaction_type,
18
+ :platform,
19
+ :coa_code,
20
+ :coa_match_type,
21
+ :account_name
22
+
23
+ def initialize(bsb_number: nil,
24
+ account_number: nil,
25
+ transaction_date: nil,
26
+ narration: nil,
27
+ cheque_number: nil,
28
+ debit: nil,
29
+ credit: nil,
30
+ balance: nil,
31
+ transaction_type: nil,
32
+ platform: nil,
33
+ coa_code: nil,
34
+ coa_match_type: nil,
35
+ account_name: nil)
36
+ @bsb_number = bsb_number&.strip
37
+ @account_number = account_number&.strip
38
+ @transaction_date = transaction_date&.strip
39
+ @transaction_date = Date.strptime(@transaction_date, '%d/%m/%Y')
40
+ @narration = narration&.gsub(/\s{2,}/, ' ')&.strip
41
+ @cheque_number = cheque_number&.strip
42
+ @debit = debit&.strip
43
+ @credit = credit&.strip
44
+ @balance = balance&.strip
45
+ @transaction_type = transaction_type&.strip
46
+ @platform = platform
47
+ @coa_code = coa_code
48
+ @coa_match_type = coa_match_type
49
+ @account_name = account_name
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -63,9 +63,25 @@ module Appydave
63
63
  configurations.each_value(&:debug)
64
64
  end
65
65
 
66
- def print
67
- log.kv 'Configuration Path', config_path
68
- configurations.each_value(&:print)
66
+ # def print
67
+ # log.kv 'Configuration Path', config_path
68
+ # configurations.each_value(&:print)
69
+ # end
70
+
71
+ def print(*keys)
72
+ if keys.empty?
73
+ keys = configurations.keys
74
+ else
75
+ keys.map!(&:to_sym)
76
+ end
77
+
78
+ keys.each do |key|
79
+ if configurations[key]
80
+ configurations[key].print
81
+ else
82
+ log.error "Configuration not available: #{key}"
83
+ end
84
+ end
69
85
  end
70
86
 
71
87
  private
@@ -6,6 +6,7 @@ module Appydave
6
6
  module Models
7
7
  # Bank reconciliation configuration
8
8
  class BankReconciliationConfig < ConfigBase
9
+ # def
9
10
  # Retrieve all bank accounts
10
11
  def bank_accounts
11
12
  data['bank_accounts'].map do |account|
@@ -34,7 +35,13 @@ module Appydave
34
35
  end
35
36
 
36
37
  def print
37
- log.heading 'Bank Reconciliation Configuration'
38
+ log.subheading 'Bank Reconciliation - Accounts'
39
+
40
+ tp bank_accounts, :account_number, :bsb, :name, :bank
41
+
42
+ log.subheading 'Bank Reconciliation - Chart of Accounts'
43
+
44
+ tp chart_of_accounts, :code, :narration
38
45
  end
39
46
 
40
47
  private
@@ -48,13 +55,13 @@ module Appydave
48
55
 
49
56
  # Inner class to represent a bank account
50
57
  class BankAccount
51
- attr_accessor :account_number, :bsb, :name, :bank
58
+ attr_accessor :account_number, :bsb, :name, :platform
52
59
 
53
60
  def initialize(data)
54
61
  @account_number = data['account_number']
55
62
  @bsb = data['bsb']
56
63
  @name = data['name']
57
- @bank = data['bank']
64
+ @platform = data['platform']
58
65
  end
59
66
 
60
67
  def to_h
@@ -62,7 +69,7 @@ module Appydave
62
69
  'account_number' => @account_number,
63
70
  'bsb' => @bsb,
64
71
  'name' => @name,
65
- 'bank' => @bank
72
+ 'platform' => @platform
66
73
  }
67
74
  end
68
75
  end
@@ -39,11 +39,30 @@ module Appydave
39
39
  def print
40
40
  log.heading 'Channel Configuration'
41
41
 
42
- tp channels, :key, :code, :name, :youtube_handle
42
+ print_channels = channels.map do |channel|
43
+ {
44
+ key: channel.key,
45
+ code: channel.code,
46
+ name: channel.name,
47
+ youtube_handle: channel.youtube_handle,
48
+ content_projects: print_location(channel.locations.content_projects),
49
+ video_projects: print_location(channel.locations.video_projects),
50
+ published_projects: print_location(channel.locations.published_projects),
51
+ abandoned_projects: print_location(channel.locations.abandoned_projects)
52
+ }
53
+ end
54
+
55
+ tp print_channels, :key, :code, :name, :youtube_handle, :content_projects, :video_projects, :published_projects, :abandoned_projects
43
56
  end
44
57
 
45
58
  private
46
59
 
60
+ def print_location(location)
61
+ return 'Not Set' unless location
62
+
63
+ File.exist?(location) ? 'TRUE' : 'false'
64
+ end
65
+
47
66
  def default_data
48
67
  { 'channels' => {} }
49
68
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Appydave
4
4
  module Tools
5
- VERSION = '0.6.0'
5
+ VERSION = '0.7.0'
6
6
  end
7
7
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'clipboard'
4
+ require 'csv'
4
5
  require 'fileutils'
5
6
  require 'json'
6
7
  require 'open3'
@@ -19,6 +20,10 @@ require 'appydave/tools/configuration/models/settings_config'
19
20
  require 'appydave/tools/configuration/models/bank_reconciliation_config'
20
21
  require 'appydave/tools/configuration/models/channels_config'
21
22
  require 'appydave/tools/name_manager/project_name'
23
+ require 'appydave/tools/bank_reconciliation/clean/clean_transactions'
24
+ require 'appydave/tools/bank_reconciliation/clean/read_transactions'
25
+ require 'appydave/tools/bank_reconciliation/clean/mapper'
26
+ require 'appydave/tools/bank_reconciliation/models/transaction'
22
27
 
23
28
  Appydave::Tools::Configuration::Config.set_default do |config|
24
29
  config.config_path = File.expand_path('~/.config/appydave')
data/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "appydave-tools",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "appydave-tools",
9
- "version": "0.6.0",
9
+ "version": "0.7.0",
10
10
  "devDependencies": {
11
11
  "@klueless-js/semantic-release-rubygem": "github:klueless-js/semantic-release-rubygem",
12
12
  "@semantic-release/changelog": "^6.0.3",
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appydave-tools",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "AppyDave YouTube Automation Tools",
5
5
  "scripts": {
6
6
  "release": "semantic-release"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appydave-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cruwys
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-26 00:00:00.000000000 Z
11
+ date: 2024-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: csv
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: dotenv
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -86,12 +100,18 @@ files:
86
100
  - LICENSE.txt
87
101
  - README.md
88
102
  - Rakefile
103
+ - bin/bank_reconciliation.rb
89
104
  - bin/configuration.rb
90
105
  - bin/console
91
106
  - bin/gpt_context.rb
92
107
  - bin/setup
93
108
  - images.log
94
109
  - lib/appydave/tools.rb
110
+ - lib/appydave/tools/bank_reconciliation/_doc.md
111
+ - lib/appydave/tools/bank_reconciliation/clean/clean_transactions.rb
112
+ - lib/appydave/tools/bank_reconciliation/clean/mapper.rb
113
+ - lib/appydave/tools/bank_reconciliation/clean/read_transactions.rb
114
+ - lib/appydave/tools/bank_reconciliation/models/transaction.rb
95
115
  - lib/appydave/tools/configuration/_doc.md
96
116
  - lib/appydave/tools/configuration/config.rb
97
117
  - lib/appydave/tools/configuration/configurable.rb