# frozen_string_literal: true module Reconciliation # Applies fixes to Dolibarr: marks invoices as paid using GoCardless payment data. class Fixer def initialize(client) @client = client end # Accepts an array of Engine::Match objects with flag GC_PAID_DOLIBARR_OPEN def apply(matches) return if matches.empty? gc_payment_id = ENV.fetch("DOLIBARR_GC_PAYMENT_ID", nil)&.to_i bank_id = ENV.fetch("DOLIBARR_BANK_ACCOUNT_ID", "1").to_i if gc_payment_id.nil? warn "[Fixer] DOLIBARR_GC_PAYMENT_ID not set in .env — cannot fix. " \ "Run: GET /setup/dictionary/payment_types to find the GoCardless payment type ID." return end puts "" puts "APPLYING FIXES (#{matches.size} invoices)..." matches.each do |m| inv = m.invoice pay = m.payment payload = { arrayofamounts: { inv.id.to_s => { amount: "%.2f" % (inv.amount_cents / 100.0), multicurrency_amount: nil } }, datepaye: pay.charge_date.to_time.to_i, paymentid: gc_payment_id, closepaidinvoices: "yes", accountid: bank_id, num_payment: pay.id, comment: "GoCardless payment — auto-reconciled (#{pay.charge_date})" } begin @client.post("/invoices/paymentsdistributed", payload) puts " ✓ Marked #{inv.ref} as paid (GC: #{pay.id})" rescue Dolibarr::Client::ValidationError => e puts " ✗ #{inv.ref} — validation error: #{e.message}" rescue Dolibarr::Client::Error => e puts " ✗ #{inv.ref} — API error: #{e.message}" end end end end end