Class: Spree::Kashflow::Client
- Inherits:
-
Object
- Object
- Spree::Kashflow::Client
- Defined in:
- lib/spree/kashflow/client.rb
Overview
Stateless SOAP client for the KashFlow API. Only this class may reference Savon —
every public method returns plain Ruby (Integer, Array
Constant Summary collapse
- WSDL =
Returns the WSDL endpoint KashFlow publishes for the SOAP API.
"https://securedwebapp.com/api/service.asmx?WSDL"- AUTH_FAULT =
Returns matches SOAP faults caused by bad credentials.
/invalid.*(username|password)|not authori[sz]ed/i- SUCCESS_STATUS =
The WSDL declares
Statusas a bares:stringon every*Responseelement (minOccurs="0"), with no<s:enumeration>and no<wsdl:documentation>naming the success value — so this constant is KashFlow's documented convention ("OK"), not something the schema pins down. Comparison is case-insensitive, and an absentStatus(legal, sinceminOccurs="0") is treated as success; only a presentStatusthat is not"OK"is a business-level rejection. "OK"
Instance Method Summary collapse
-
#apply_credit_note(credit_note_number:, invoice_number:) ⇒ TrueClass
Applies a credit note to an invoice in KashFlow.
-
#bank_accounts ⇒ Array<Hash>
Bank accounts as
{id:, name:}hashes. -
#create_invoice(payload) ⇒ Integer
Creates an invoice in KashFlow.
-
#currencies ⇒ Array<Hash>
Currencies as
{code:, id:}hashes. -
#initialize(username:, password:) ⇒ Client
constructor
A new instance of Client.
-
#nominal_codes ⇒ Array<Hash>
Nominal codes as
{id:, name:}hashes. -
#payment_methods ⇒ Array<Hash>
Invoice payment methods as
{id:, name:}hashes. -
#record_invoice_payment(payload) ⇒ TrueClass
Records a payment against an invoice in KashFlow.
-
#upsert_customer(payload) ⇒ Integer
Creates or updates a customer in KashFlow, keyed on the customer
Code. -
#verify_credentials ⇒ TrueClass, FalseClass
Verifies the configured credentials against the KashFlow API.
Constructor Details
#initialize(username:, password:) ⇒ Client
Returns a new instance of Client.
35 36 37 38 |
# File 'lib/spree/kashflow/client.rb', line 35 def initialize(username:, password:) @username = username @password = password end |
Instance Method Details
#apply_credit_note(credit_note_number:, invoice_number:) ⇒ TrueClass
Applies a credit note to an invoice in KashFlow.
The WSDL declares applyCreditNoteToInvoiceResult as an s:boolean.
A false is a refusal to link, and swallowing it produces exactly the
orphan credit note SyncRefundJob's precondition guard exists to
prevent — a credit note sitting in KashFlow attached to nothing.
165 166 167 168 169 170 |
# File 'lib/spree/kashflow/client.rb', line 165 def apply_credit_note(credit_note_number:, invoice_number:) response = call(:apply_credit_note_to_invoice, {"InvoiceID" => invoice_number, "CreditNoteID" => credit_note_number}) result = response.dig("applyCreditNoteToInvoiceResponse", "applyCreditNoteToInvoiceResult") assert_accepted!(result, "did not apply credit note #{credit_note_number} to invoice #{invoice_number}") true end |
#bank_accounts ⇒ Array<Hash>
Returns bank accounts as {id:, name:} hashes.
75 76 77 78 |
# File 'lib/spree/kashflow/client.rb', line 75 def bank_accounts rows = extract_rows(call(:get_bank_accounts), "GetBankAccountsResponse", "GetBankAccountsResult", "BankAccount") rows.map { |row| {id: row["AccountID"].to_i, name: row["AccountName"]} } end |
#create_invoice(payload) ⇒ Integer
Creates an invoice in KashFlow.
125 126 127 128 129 |
# File 'lib/spree/kashflow/client.rb', line 125 def create_invoice(payload) response = call(:insert_invoice_type_defined, {"Inv_TD" => payload}) result = response.dig("InsertInvoice_TypeDefinedResponse", "InsertInvoice_TypeDefinedResult") assert_identifier!(result, "invoice number") end |
#currencies ⇒ Array<Hash>
Returns currencies as {code:, id:} hashes.
57 58 59 60 |
# File 'lib/spree/kashflow/client.rb', line 57 def currencies rows = extract_rows(call(:get_currencies), "GetCurrenciesResponse", "GetCurrenciesResult", "Currencies") rows.map { |row| {code: row["CurrencyCode"], id: row["CurrencyId"].to_i} } end |
#nominal_codes ⇒ Array<Hash>
Returns nominal codes as {id:, name:} hashes.
66 67 68 69 |
# File 'lib/spree/kashflow/client.rb', line 66 def nominal_codes rows = extract_rows(call(:get_nominal_codes), "GetNominalCodesResponse", "GetNominalCodesResult", "NominalCode") rows.map { |row| {id: row["id"].to_i, name: row["Name"]} } end |
#payment_methods ⇒ Array<Hash>
Returns invoice payment methods as {id:, name:} hashes.
84 85 86 87 |
# File 'lib/spree/kashflow/client.rb', line 84 def payment_methods rows = extract_rows(call(:get_inv_pay_methods), "GetInvPayMethodsResponse", "GetInvPayMethodsResult", "PaymentMethod") rows.map { |row| {id: row["MethodID"].to_i, name: row["MethodName"]} } end |
#record_invoice_payment(payload) ⇒ TrueClass
Records a payment against an invoice in KashFlow.
The WSDL declares InsertInvoicePaymentResult as an s:int — the id of
the payment KashFlow created. A 0 is therefore a rejection reported
without a Status, and returning true regardless would leave the
invoice permanently unpaid while the caller recorded a successful sync.
144 145 146 147 148 149 |
# File 'lib/spree/kashflow/client.rb', line 144 def record_invoice_payment(payload) response = call(:insert_invoice_payment, {"InvoicePayment" => payload}) result = response.dig("InsertInvoicePaymentResponse", "InsertInvoicePaymentResult") assert_identifier!(result, "payment id") true end |
#upsert_customer(payload) ⇒ Integer
Creates or updates a customer in KashFlow, keyed on the customer Code.
KashFlow publishes no InsertOrUpdateCustomer, so an upsert is a lookup
followed by an UpdateCustomer or an InsertCustomer. The lookup is not
optional: customer codes are stable per customer (that is what keeps one
KashFlow customer per Spree customer rather than one per order), so an
unconditional insert succeeds exactly once and every subsequent order for
that customer is rejected with "Customer Code is not unique" — with no
invoice posted.
108 109 110 111 112 113 114 115 |
# File 'lib/spree/kashflow/client.rb', line 108 def upsert_customer(payload) existing_id = customer_id_for_code(payload["Code"]) return update_customer(existing_id, payload) if existing_id response = call(:insert_customer, {"custr" => payload}) result = response.dig("InsertCustomerResponse", "InsertCustomerResult") assert_identifier!(result, "customer id") end |
#verify_credentials ⇒ TrueClass, FalseClass
Verifies the configured credentials against the KashFlow API. Does not rescue — the caller decides how to handle a raised error.
48 49 50 51 |
# File 'lib/spree/kashflow/client.rb', line 48 def verify_credentials call(:get_currencies) true end |