Add resource definitions for all 22 API tags, wire client accessors and require tree
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
# The entry point. Holds the connection and exposes the resource accessors.
|
||||
#
|
||||
# client = Fiken::Client.new(token: ENV["FIKEN_TOKEN"])
|
||||
# client.user
|
||||
# client.companies.list
|
||||
# client.contacts("my-company-slug").find(123)
|
||||
# client.invoices("my-company-slug").drafts.create(invoice_attrs)
|
||||
class Client
|
||||
attr_reader :connection
|
||||
|
||||
def initialize(token: nil, access_token: nil, **options)
|
||||
bearer = token || access_token
|
||||
raise ArgumentError, "provide :token or :access_token" if bearer.nil? || bearer.empty?
|
||||
|
||||
@connection = Connection.new(token: bearer, **options)
|
||||
end
|
||||
|
||||
# GET /user
|
||||
def user
|
||||
Object.new(connection.get("/user").body)
|
||||
end
|
||||
|
||||
# GET /companies, GET /companies/{slug}
|
||||
def companies
|
||||
Resources::Companies.new(self)
|
||||
end
|
||||
|
||||
# Convenience: fetch a single company by slug.
|
||||
def company(slug)
|
||||
companies.find(slug)
|
||||
end
|
||||
|
||||
# Company-scoped resources. Each takes the company slug.
|
||||
def accounts(slug) = Resources::Accounts.new(self, slug)
|
||||
def account_balances(slug) = Resources::AccountBalances.new(self, slug)
|
||||
def activities(slug) = Resources::Activities.new(self, slug)
|
||||
def bank_accounts(slug) = Resources::BankAccounts.new(self, slug)
|
||||
def bank_balances(slug) = Resources::BankBalances.new(self, slug)
|
||||
def contacts(slug) = Resources::Contacts.new(self, slug)
|
||||
def credit_notes(slug) = Resources::CreditNotes.new(self, slug)
|
||||
def groups(slug) = Resources::Groups.new(self, slug)
|
||||
def inbox(slug) = Resources::Inbox.new(self, slug)
|
||||
def invoices(slug) = Resources::Invoices.new(self, slug)
|
||||
def journal_entries(slug) = Resources::JournalEntries.new(self, slug)
|
||||
def offers(slug) = Resources::Offers.new(self, slug)
|
||||
def order_confirmations(slug) = Resources::OrderConfirmations.new(self, slug)
|
||||
def products(slug) = Resources::Products.new(self, slug)
|
||||
def projects(slug) = Resources::Projects.new(self, slug)
|
||||
def purchases(slug) = Resources::Purchases.new(self, slug)
|
||||
def sales(slug) = Resources::Sales.new(self, slug)
|
||||
def time_entries(slug) = Resources::TimeEntries.new(self, slug)
|
||||
def time_users(slug) = Resources::TimeUsers.new(self, slug)
|
||||
def transactions(slug) = Resources::Transactions.new(self, slug)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/accounts — find by account code (e.g. "1500:10001").
|
||||
class Accounts < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
|
||||
def resource_path
|
||||
"accounts"
|
||||
end
|
||||
end
|
||||
|
||||
# /companies/{slug}/accountBalances
|
||||
class AccountBalances < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
|
||||
def resource_path
|
||||
"accountBalances"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/activities (time-tracking activities)
|
||||
class Activities < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Creatable
|
||||
include Resource::PatchUpdatable
|
||||
include Resource::Deletable
|
||||
|
||||
def resource_path
|
||||
"activities"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/bankAccounts
|
||||
class BankAccounts < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Creatable
|
||||
|
||||
def resource_path
|
||||
"bankAccounts"
|
||||
end
|
||||
end
|
||||
|
||||
# /companies/{slug}/bankBalances
|
||||
class BankBalances < Resource::Base
|
||||
include Resource::Listable
|
||||
|
||||
def resource_path
|
||||
"bankBalances"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# GET /companies and GET /companies/{companySlug}
|
||||
class Companies < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
|
||||
def resource_path
|
||||
"companies"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,46 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/contacts and nested contact persons.
|
||||
class Contacts < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Creatable
|
||||
include Resource::Updatable # PUT
|
||||
include Resource::Deletable
|
||||
include Resource::Attachable
|
||||
|
||||
def resource_path
|
||||
"contacts"
|
||||
end
|
||||
|
||||
# Contacts only support uploading attachments, not listing them.
|
||||
def attachments_listable?
|
||||
false
|
||||
end
|
||||
|
||||
def contact_persons(contact_id)
|
||||
ContactPersons.new(client, company_slug, "#{base_path}/#{contact_id}")
|
||||
end
|
||||
end
|
||||
|
||||
# /companies/{slug}/contacts/{id}/contactPerson
|
||||
class ContactPersons < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Creatable
|
||||
include Resource::Updatable # PUT
|
||||
include Resource::Deletable
|
||||
|
||||
def initialize(client, company_slug, parent_path)
|
||||
super(client, company_slug)
|
||||
@parent_path = parent_path
|
||||
end
|
||||
|
||||
def base_path
|
||||
"#{@parent_path}/contactPerson"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,32 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/creditNotes
|
||||
class CreditNotes < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Sendable
|
||||
include Resource::HasCounter
|
||||
include Resource::Draftable
|
||||
|
||||
def resource_path
|
||||
"creditNotes"
|
||||
end
|
||||
|
||||
def draft_create_action
|
||||
"createCreditNote"
|
||||
end
|
||||
|
||||
# POST /creditNotes/full — credit a whole invoice.
|
||||
def create_full(attributes)
|
||||
post_create("#{base_path}/full", attributes)
|
||||
end
|
||||
|
||||
# POST /creditNotes/partial — credit selected lines/amounts.
|
||||
def create_partial(attributes)
|
||||
post_create("#{base_path}/partial", attributes)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/groups (contact groups)
|
||||
class Groups < Resource::Base
|
||||
include Resource::Listable
|
||||
|
||||
def resource_path
|
||||
"groups"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/inbox — documents awaiting bookkeeping.
|
||||
class Inbox < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Deletable
|
||||
|
||||
def resource_path
|
||||
"inbox"
|
||||
end
|
||||
|
||||
# POST /inbox — multipart upload of an inbox document.
|
||||
def create(path: nil, io: nil, filename: nil, content_type: "application/octet-stream", **fields)
|
||||
parts = { "file" => build_file_part(path, io, filename, content_type) }
|
||||
fields.each { |key, value| parts[key.to_s] = value.to_s unless value.nil? }
|
||||
build_created(connection.post_multipart(base_path, parts))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/invoices
|
||||
class Invoices < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Creatable
|
||||
include Resource::PatchUpdatable # finalized invoices update via PATCH
|
||||
include Resource::Attachable
|
||||
include Resource::Sendable
|
||||
include Resource::HasCounter
|
||||
include Resource::Draftable
|
||||
|
||||
def resource_path
|
||||
"invoices"
|
||||
end
|
||||
|
||||
def draft_create_action
|
||||
"createInvoice"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/journalEntries
|
||||
class JournalEntries < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Attachable
|
||||
|
||||
def resource_path
|
||||
"journalEntries"
|
||||
end
|
||||
|
||||
# Creation posts to a sibling path: POST /generalJournalEntries
|
||||
def create_general(attributes)
|
||||
post_create("/companies/#{company_slug}/generalJournalEntries", attributes)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/offers
|
||||
class Offers < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Sendable
|
||||
include Resource::HasCounter
|
||||
include Resource::Draftable
|
||||
|
||||
def resource_path
|
||||
"offers"
|
||||
end
|
||||
|
||||
def draft_create_action
|
||||
"createOffer"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/orderConfirmations
|
||||
class OrderConfirmations < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::HasCounter
|
||||
include Resource::Draftable
|
||||
|
||||
def resource_path
|
||||
"orderConfirmations"
|
||||
end
|
||||
|
||||
def draft_create_action
|
||||
"createOrderConfirmation"
|
||||
end
|
||||
|
||||
# POST /{id}/createInvoiceDraft — turn a confirmation into an invoice draft.
|
||||
def create_invoice_draft(confirmation_id)
|
||||
post_create("#{base_path}/#{confirmation_id}/createInvoiceDraft", nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/products
|
||||
class Products < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Creatable
|
||||
include Resource::Updatable # PUT
|
||||
include Resource::Deletable
|
||||
|
||||
def resource_path
|
||||
"products"
|
||||
end
|
||||
|
||||
# POST /products/salesReport — returns an array of per-product report rows.
|
||||
def sales_report(attributes)
|
||||
body = connection.post("#{base_path}/salesReport", attributes).body
|
||||
Array(body).map { |row| wrap(row) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/projects
|
||||
class Projects < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Creatable
|
||||
include Resource::PatchUpdatable
|
||||
include Resource::Deletable
|
||||
|
||||
def resource_path
|
||||
"projects"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,29 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/purchases
|
||||
class Purchases < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Creatable
|
||||
include Resource::Attachable
|
||||
include Resource::Payable
|
||||
include Resource::Draftable
|
||||
|
||||
def resource_path
|
||||
"purchases"
|
||||
end
|
||||
|
||||
def draft_create_action
|
||||
"createPurchase"
|
||||
end
|
||||
|
||||
# PATCH /{id}/delete — delete a purchase (with a reason).
|
||||
def delete(id, attributes = nil)
|
||||
connection.patch("#{base_path}/#{id}/delete", attributes)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/sales
|
||||
class Sales < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Creatable
|
||||
include Resource::Attachable
|
||||
include Resource::Payable
|
||||
include Resource::Draftable
|
||||
|
||||
def resource_path
|
||||
"sales"
|
||||
end
|
||||
|
||||
def draft_create_action
|
||||
"createSale"
|
||||
end
|
||||
|
||||
# PATCH /{id}/settled — mark a sale as settled.
|
||||
def settle(id, attributes = nil)
|
||||
patch_one("#{base_path}/#{id}/settled", attributes)
|
||||
end
|
||||
|
||||
# PATCH /{id}/writeOff — write off a sale as a loss.
|
||||
def write_off(id, attributes = nil)
|
||||
patch_one("#{base_path}/#{id}/writeOff", attributes)
|
||||
end
|
||||
|
||||
# PATCH /{id}/delete — delete a sale (with a reason).
|
||||
def delete(id, attributes = nil)
|
||||
connection.patch("#{base_path}/#{id}/delete", attributes)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/timeEntries
|
||||
class TimeEntries < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
include Resource::Creatable
|
||||
include Resource::PatchUpdatable
|
||||
include Resource::Deletable
|
||||
|
||||
def resource_path
|
||||
"timeEntries"
|
||||
end
|
||||
|
||||
# POST /timeEntries/createInvoiceDraft — invoice selected time entries.
|
||||
def create_invoice_draft(attributes)
|
||||
post_create("#{base_path}/createInvoiceDraft", attributes)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/timeUsers
|
||||
class TimeUsers < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
|
||||
def resource_path
|
||||
"timeUsers"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Fiken
|
||||
module Resources
|
||||
# /companies/{slug}/transactions
|
||||
class Transactions < Resource::Base
|
||||
include Resource::Listable
|
||||
include Resource::Findable
|
||||
|
||||
def resource_path
|
||||
"transactions"
|
||||
end
|
||||
|
||||
# Deletion is a PATCH to /{id}/delete (optionally with a description).
|
||||
def delete(id, attributes = nil)
|
||||
connection.patch("#{base_path}/#{id}/delete", attributes)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user