Add advanced reconciliation features: retry detection, partial payments, credit notes
New features: - Credit note handling: Exclude negative invoices from GC reconciliation - Retry detection: Flag invoices with multiple GC payment attempts - Partial payment detection: Track invoices where remain_to_pay > 0 - Payout fee CSV: Export detailed fee breakdown per payout - Configurable tolerances: RECONCILIATION_DATE_TOLERANCE, RECONCILIATION_PAYOUT_TOLERANCE Files: - lib/reconciliation/gocardless_payouts_parser.rb (new) - Parse GC payouts CSV - lib/reconciliation/engine.rb - Add retry_group, partial fields to Match struct - lib/reconciliation/reporter.rb - Show partial/retry in report, write payouts CSV - lib/reconciliation/dolibarr_fetcher.rb - Add is_credit_note field, filter negatives - bin/reconcile - Wire up --gc-payouts argument - README.md - Document new features and --gc-payouts usage - .env.example - Add optional tolerance settings Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -10,12 +10,13 @@ options = {
|
||||
from: nil,
|
||||
to: nil,
|
||||
gc: nil,
|
||||
gc_payouts: nil,
|
||||
shine: nil
|
||||
}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = <<~BANNER
|
||||
Usage: bin/reconcile --from DATE --to DATE --gc PATH [--shine PATH] [--fix]
|
||||
Usage: bin/reconcile --from DATE --to DATE --gc PATH [--gc-payouts PATH] [--shine PATH] [--fix]
|
||||
|
||||
Options:
|
||||
BANNER
|
||||
@@ -32,6 +33,10 @@ OptionParser.new do |opts|
|
||||
options[:gc] = v
|
||||
end
|
||||
|
||||
opts.on("--gc-payouts PATH", "GoCardless payouts CSV file path (enables exact fee reporting)") do |v|
|
||||
options[:gc_payouts] = v
|
||||
end
|
||||
|
||||
opts.on("--shine PATH", "Shine bank statement CSV file path (optional)") do |v|
|
||||
options[:shine] = v
|
||||
end
|
||||
@@ -52,6 +57,7 @@ errors << "--from is required" unless options[:from]
|
||||
errors << "--to is required" unless options[:to]
|
||||
errors << "--gc is required" unless options[:gc]
|
||||
errors << "--gc file not found: #{options[:gc]}" if options[:gc] && !File.exist?(options[:gc])
|
||||
errors << "--gc-payouts file not found: #{options[:gc_payouts]}" if options[:gc_payouts] && !File.exist?(options[:gc_payouts])
|
||||
errors << "--shine file not found: #{options[:shine]}" if options[:shine] && !File.exist?(options[:shine])
|
||||
|
||||
unless errors.empty?
|
||||
@@ -60,16 +66,18 @@ unless errors.empty?
|
||||
end
|
||||
|
||||
# Run reconciliation
|
||||
client = Dolibarr::Client.new
|
||||
fetcher = Reconciliation::DolibarrFetcher.new(client, from: options[:from], to: options[:to])
|
||||
gc_data = Reconciliation::GocardlessParser.parse(options[:gc], from: options[:from], to: options[:to])
|
||||
shine_data = options[:shine] ? Reconciliation::ShineParser.parse(options[:shine]) : []
|
||||
client = Dolibarr::Client.new
|
||||
fetcher = Reconciliation::DolibarrFetcher.new(client, from: options[:from], to: options[:to])
|
||||
gc_data = Reconciliation::GocardlessParser.parse(options[:gc], from: options[:from], to: options[:to])
|
||||
gc_payouts = options[:gc_payouts] ? Reconciliation::GocardlessPayoutsParser.parse(options[:gc_payouts]) : []
|
||||
shine_data = options[:shine] ? Reconciliation::ShineParser.parse(options[:shine]) : []
|
||||
|
||||
dolibarr_invoices = fetcher.fetch_invoices
|
||||
|
||||
engine = Reconciliation::Engine.new(
|
||||
dolibarr_invoices: dolibarr_invoices,
|
||||
gc_payments: gc_data,
|
||||
dolibarr_invoices: dolibarr_invoices,
|
||||
gc_payments: gc_data,
|
||||
gc_payouts: gc_payouts,
|
||||
shine_transactions: shine_data,
|
||||
from: options[:from],
|
||||
to: options[:to]
|
||||
|
||||
Reference in New Issue
Block a user