Module: SplttyCLI::Discovery

Defined in:
lib/spltty_cli/discovery.rb

Overview

Scan accounts/ for ledgers and reconcile them into the config cache.

A ledger is either:

* a root file named "<NAME>.ledger.md"  -> single-file ledger, or
* a subfolder containing "YYYY-MM.md"   -> monthly ledger (e.g. CASA).

Everything else (*.notes.md, README, plain *.md, other files) is ignored.

Constant Summary collapse

LEDGER_SUFFIX =
".ledger.md"
MONTH_FILE =
/\A\d{4}-\d{2}\.md\z/

Class Method Summary collapse

Class Method Details

.detect_schema(file) ⇒ Object

Schema from the table header: "montreal" if it carries the Orig. Value column, otherwise "standard". Defaults to standard when no header exists.



52
53
54
55
56
57
58
59
60
61
# File 'lib/spltty_cli/discovery.rb', line 52

def detect_schema(file)
  return "standard" unless file && File.exist?(file)

  File.foreach(file) do |line|
    next unless line.strip.start_with?("|")

    return line.include?("Orig. Value") ? "montreal" : "standard"
  end
  "standard"
end

.scan(accounts_dir) ⇒ Object

Discover ledgers on disk. Returns an array of hashes:

{ name:, type: "single"|"monthly", file: / dir:, schema:, notes: }


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/spltty_cli/discovery.rb', line 20

def scan(accounts_dir)
  return [] unless Dir.exist?(accounts_dir)

  found = []
  Dir.children(accounts_dir).sort.each do |entry|
    full = File.join(accounts_dir, entry)

    if File.file?(full) && entry.end_with?(LEDGER_SUFFIX)
      name = entry[0...-LEDGER_SUFFIX.length]
      notes = "#{name}.notes.md"
      found << {
        name: name, type: "single", file: entry,
        schema: detect_schema(full),
        notes: (notes if File.exist?(File.join(accounts_dir, notes))),
      }
    elsif File.directory?(full)
      months = Dir.children(full).select { |f| f =~ MONTH_FILE }.sort
      next if months.empty?

      notes = "notes.md"
      found << {
        name: entry, type: "monthly", dir: entry,
        schema: detect_schema(File.join(full, months.last)),
        notes: (notes if File.exist?(File.join(full, notes))),
      }
    end
  end
  found
end

.sync(config) ⇒ Object

Merge discovered ledgers into config.ledgers. Adds new ones, refreshes structural fields (type/file/dir/schema) on existing ones, and preserves user overrides (title, default_responsible, default_currency, notes). Flags config entries whose files vanished as "missing". Returns { added: [names], missing: [names], changed: bool }.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/spltty_cli/discovery.rb', line 68

def sync(config)
  before = JSON.generate(config.ledgers)
  discovered = scan(config.accounts_dir)
  names = discovered.map { |d| d[:name] }

  discovered.each do |d|
    entry = (config.ledgers[d[:name]] ||= {})
    entry["type"] = d[:type]
    entry["schema"] = d[:schema]
    if d[:type] == "monthly"
      entry["dir"] = d[:dir]
      entry.delete("file")
    else
      entry["file"] = d[:file]
      entry.delete("dir")
    end
    entry["notes"] ||= d[:notes] if d[:notes]
    entry.delete("missing")
  end

  added = names - JSON.parse(before).keys
  missing = config.ledgers.keys - names
  missing.each { |m| config.ledgers[m]["missing"] = true }

  { added: added, missing: missing, changed: JSON.generate(config.ledgers) != before }
end