quickbooks

package
v1.0.49 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 5, 2026 License: AGPL-3.0 Imports: 24 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AccountRef

type AccountRef struct {
	Value string `json:"value"`
	Name  string `json:"name,omitempty"`
}

AccountRef represents a reference to an account

type AccountResponse

type AccountResponse struct {
	ID             string `json:"Id"`
	Name           string `json:"Name"`
	AccountType    string `json:"AccountType"`
	Active         bool   `json:"Active"`
	AccountSubType string `json:"AccountSubType,omitempty"`
}

AccountResponse represents an account response from QuickBooks Used in QueryResponse for querying accounts

type Address

type Address struct {
	Line1                  string `json:"Line1,omitempty"`
	Line2                  string `json:"Line2,omitempty"`
	City                   string `json:"City,omitempty"`
	CountrySubDivisionCode string `json:"CountrySubDivisionCode,omitempty"` // State/Province
	PostalCode             string `json:"PostalCode,omitempty"`
	Country                string `json:"Country,omitempty"`
}

Address represents an address in QuickBooks

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client handles QuickBooks API client setup and configuration

func (*Client) CreateCustomer

func (c *Client) CreateCustomer(ctx context.Context, req *CustomerCreateRequest) (*CustomerResponse, error)

CreateCustomer creates a customer in QuickBooks

func (*Client) CreateInvoice

func (c *Client) CreateInvoice(ctx context.Context, req *InvoiceCreateRequest) (*InvoiceResponse, error)

CreateInvoice creates an invoice in QuickBooks

func (*Client) CreateItem

func (c *Client) CreateItem(ctx context.Context, req *ItemCreateRequest) (*ItemResponse, error)

CreateItem creates an item in QuickBooks

func (*Client) EnsureValidAccessToken

func (c *Client) EnsureValidAccessToken(ctx context.Context) error

EnsureValidAccessToken ensures that a valid access token is available. This method should be called before every API operation: 1. If no access token exists, tries to refresh using refresh_token 2. If access token exists, uses it (no proactive expiration check - relies on reactive refresh on 3200 error) This is the main entry point for token management before API calls.

func (*Client) ExchangeAuthCodeForTokens

func (c *Client) ExchangeAuthCodeForTokens(ctx context.Context) error

ExchangeAuthCodeForTokens exchanges an authorization code for access and refresh tokens. This is called during initial connection setup OR when user re-authenticates after refresh token expiry: 1. Exchanges auth_code (from OAuth redirect) for access_token and refresh_token 2. Encrypts tokens before saving 3. Updates connection in database with encrypted tokens and clears auth_code

func (*Client) GetBaseURL

func (c *Client) GetBaseURL(environment string) string

GetBaseURL returns the QuickBooks API base URL based on environment

func (*Client) GetConnection

func (c *Client) GetConnection(ctx context.Context) (*connection.Connection, error)

GetConnection retrieves the QuickBooks connection for the current context

func (*Client) GetDecryptedQuickBooksConfig

func (c *Client) GetDecryptedQuickBooksConfig(conn *connection.Connection) (*QuickBooksConfig, error)

GetDecryptedQuickBooksConfig decrypts and returns QuickBooks configuration from connection. Decrypts encrypted fields (ClientID, ClientSecret, AccessToken, RefreshToken) using encryption service. RealmID and Environment are stored unencrypted. Defaults to "production" environment if not specified.

func (*Client) GetInvoice

func (c *Client) GetInvoice(ctx context.Context, invoiceID string) (*InvoiceResponse, error)

GetInvoice retrieves an invoice by ID from QuickBooks

func (*Client) GetItem

func (c *Client) GetItem(ctx context.Context, itemID string) (*ItemResponse, error)

GetItem retrieves an item by ID from QuickBooks

func (*Client) GetPayment

func (c *Client) GetPayment(ctx context.Context, paymentID string) (*PaymentResponse, error)

GetPayment retrieves a payment by ID from QuickBooks

func (*Client) GetQuickBooksConfig

func (c *Client) GetQuickBooksConfig(ctx context.Context) (*QuickBooksConfig, error)

GetQuickBooksConfig retrieves and decrypts QuickBooks configuration for the current environment. Validates that required fields (RealmID and AccessToken) are present. Returns decrypted configuration ready for API calls.

func (*Client) HasQuickBooksConnection

func (c *Client) HasQuickBooksConnection(ctx context.Context) bool

HasQuickBooksConnection checks if QuickBooks connection exists for the current environment

func (*Client) QueryCustomerByEmail

func (c *Client) QueryCustomerByEmail(ctx context.Context, email string) (*CustomerResponse, error)

QueryCustomerByEmail queries a customer by email Note: QuickBooks Query API requires backslash escaping for single quotes (e.g., \' )

func (*Client) QueryCustomerByName

func (c *Client) QueryCustomerByName(ctx context.Context, name string) (*CustomerResponse, error)

QueryCustomerByName queries a customer by display name Note: QuickBooks Query API requires backslash escaping for single quotes (e.g., \' )

func (*Client) QueryItemByName

func (c *Client) QueryItemByName(ctx context.Context, name string) (*ItemResponse, error)

QueryItemByName queries an item by name Note: QuickBooks Query API requires backslash escaping for single quotes (e.g., \' )

func (*Client) RefreshAccessToken

func (c *Client) RefreshAccessToken(ctx context.Context) error

RefreshAccessToken refreshes the QuickBooks access token using the refresh token. This method implements OAuth 2.0 token refresh flow: 1. Uses refresh_token to get new access_token and refresh_token from QuickBooks OAuth endpoint 2. Encrypts new tokens before saving 3. Updates connection in database with new encrypted tokens 4. Clears auth_code if present This is called automatically when API calls detect token expiration (error code 3200) or by EnsureValidAccessToken.

type CustomerCreateRequest

type CustomerCreateRequest struct {
	DisplayName      string        `json:"DisplayName"`
	PrimaryEmailAddr *EmailAddress `json:"PrimaryEmailAddr,omitempty"`
	BillAddr         *Address      `json:"BillAddr,omitempty"`
}

CustomerCreateRequest represents the request to create a customer

type CustomerResponse

type CustomerResponse struct {
	ID               string        `json:"Id"`
	SyncToken        string        `json:"SyncToken,omitempty"`
	DisplayName      string        `json:"DisplayName"`
	PrimaryEmailAddr *EmailAddress `json:"PrimaryEmailAddr,omitempty"`
	BillAddr         *Address      `json:"BillAddr,omitempty"`
	MetaData         struct {
		CreateTime      string `json:"CreateTime,omitempty"`
		LastUpdatedTime string `json:"LastUpdatedTime,omitempty"`
	} `json:"MetaData,omitempty"`
}

CustomerResponse represents a customer response from QuickBooks

type CustomerService

type CustomerService struct {
	CustomerServiceParams
}

CustomerService handles QuickBooks customer synchronization

func (*CustomerService) GetOrCreateQuickBooksCustomer

func (s *CustomerService) GetOrCreateQuickBooksCustomer(ctx context.Context, flexpriceCustomer *customerDomain.Customer) (string, error)

GetOrCreateQuickBooksCustomer gets existing or creates a new customer in QuickBooks. This method implements the customer sync strategy: 1. First checks if customer is already mapped in entity_integration_mapping 2. If not mapped, tries to find existing customer in QuickBooks by email 3. If not found, creates a new customer in QuickBooks Returns the QuickBooks customer ID for use in invoice creation.

func (*CustomerService) GetQuickBooksCustomerID

func (s *CustomerService) GetQuickBooksCustomerID(ctx context.Context, flexpriceCustomerID string) (string, error)

GetQuickBooksCustomerID retrieves the QuickBooks customer ID from entity mapping

func (*CustomerService) SyncCustomerToQuickBooks

func (s *CustomerService) SyncCustomerToQuickBooks(ctx context.Context, flexpriceCustomer *customerDomain.Customer) (*CustomerResponse, error)

SyncCustomerToQuickBooks syncs Flexprice customer to QuickBooks. Creates a customer in QuickBooks with DisplayName, email, and billing address. If customer creation fails (e.g., name already exists), attempts to find existing customer by name and creates a mapping for it to avoid duplicate creation attempts.

type CustomerServiceParams

type CustomerServiceParams struct {
	Client                       QuickBooksClient
	CustomerRepo                 customerDomain.Repository
	EntityIntegrationMappingRepo entityintegrationmapping.Repository
	Logger                       *logger.Logger
}

CustomerServiceParams holds dependencies for CustomerService

type EmailAddress

type EmailAddress struct {
	Address string `json:"Address"`
}

EmailAddress represents an email address in QuickBooks

type InvoiceCreateRequest

type InvoiceCreateRequest struct {
	CustomerRef AccountRef        `json:"CustomerRef"`
	Line        []InvoiceLineItem `json:"Line"`
	DueDate     *string           `json:"DueDate,omitempty"` // Format: YYYY-MM-DD
}

InvoiceCreateRequest represents the request to create an invoice

type InvoiceLineItem

type InvoiceLineItem struct {
	LineNum             int                  `json:"LineNum,omitempty"`
	Description         string               `json:"Description,omitempty"`
	Amount              decimal.Decimal      `json:"Amount"`
	DetailType          string               `json:"DetailType"` // "SalesItemLineDetail"
	SalesItemLineDetail *SalesItemLineDetail `json:"SalesItemLineDetail"`
}

InvoiceLineItem represents a line item in invoice request

type InvoiceResponse

type InvoiceResponse struct {
	ID          string            `json:"Id"`
	SyncToken   string            `json:"SyncToken,omitempty"`
	DocNumber   string            `json:"DocNumber,omitempty"`
	TxnDate     string            `json:"TxnDate"`
	DueDate     string            `json:"DueDate,omitempty"`
	CustomerRef AccountRef        `json:"CustomerRef"`
	Line        []InvoiceLineItem `json:"Line,omitempty"`
	SubTotalAmt decimal.Decimal   `json:"SubTotalAmt,omitempty"`
	TotalAmt    decimal.Decimal   `json:"TotalAmt,omitempty"`
	Balance     decimal.Decimal   `json:"Balance,omitempty"`
	MetaData    struct {
		CreateTime      string `json:"CreateTime,omitempty"`
		LastUpdatedTime string `json:"LastUpdatedTime,omitempty"`
	} `json:"MetaData,omitempty"`
}

InvoiceResponse represents an invoice response from QuickBooks

type InvoiceService

type InvoiceService struct {
	InvoiceServiceParams
}

InvoiceService handles QuickBooks invoice operations

func (*InvoiceService) SyncInvoiceToQuickBooks

SyncInvoiceToQuickBooks syncs a Flexprice invoice to QuickBooks. Simple workflow: 1. Check if invoice mapping already exists - if yes, return it 2. Get or create customer in QuickBooks 3. Create invoice in QuickBooks 4. Create mapping

type InvoiceServiceParams

type InvoiceServiceParams struct {
	Client                       QuickBooksClient
	CustomerSvc                  QuickBooksCustomerService
	CustomerRepo                 customer.Repository
	InvoiceRepo                  invoice.Repository
	EntityIntegrationMappingRepo entityintegrationmapping.Repository
	Logger                       *logger.Logger
}

InvoiceServiceParams holds dependencies for InvoiceService

type ItemCreateRequest

type ItemCreateRequest struct {
	Name             string           `json:"Name"`
	Type             string           `json:"Type"` // "Service"
	Description      string           `json:"Description,omitempty"`
	Active           bool             `json:"Active,omitempty"`
	IncomeAccountRef *AccountRef      `json:"IncomeAccountRef"`
	UnitPrice        *decimal.Decimal `json:"UnitPrice,omitempty"` // Default sales price/rate for the item
}

ItemCreateRequest represents the request to create an item

type ItemResponse

type ItemResponse struct {
	ID               string           `json:"Id"`
	SyncToken        string           `json:"SyncToken,omitempty"`
	Name             string           `json:"Name"`
	Type             string           `json:"Type"`
	Description      string           `json:"Description,omitempty"`
	Active           bool             `json:"Active,omitempty"`
	UnitPrice        *decimal.Decimal `json:"UnitPrice,omitempty"` // Default sales price/rate
	IncomeAccountRef *AccountRef      `json:"IncomeAccountRef,omitempty"`
	MetaData         struct {
		CreateTime      string `json:"CreateTime,omitempty"`
		LastUpdatedTime string `json:"LastUpdatedTime,omitempty"`
	} `json:"MetaData,omitempty"`
}

ItemResponse represents an item response from QuickBooks

type ItemSyncService

type ItemSyncService struct {
	ItemSyncServiceParams
}

ItemSyncService handles synchronization of Flexprice plans/prices to QuickBooks items

func (*ItemSyncService) SyncPriceToQuickBooks

func (s *ItemSyncService) SyncPriceToQuickBooks(ctx context.Context, plan *plan.Plan, priceToSync *price.Price) error

SyncPriceToQuickBooks syncs a single Flexprice price to QuickBooks as a Service Item. This method is called when a price is created/updated. Item naming logic: - Usage charge (with meter): "{plan_name}-{meter_name}" - Recurring charge (without meter): "{plan_name}-Recurring"

type ItemSyncServiceParams

type ItemSyncServiceParams struct {
	Client                       QuickBooksClient
	EntityIntegrationMappingRepo entityintegrationmapping.Repository
	MeterRepo                    meter.Repository
	Logger                       *logger.Logger
}

ItemSyncServiceParams holds dependencies for ItemSyncService

type LinkedTxn

type LinkedTxn struct {
	TxnId   string `json:"TxnId"`   // REQUIRED: Invoice ID in QuickBooks
	TxnType string `json:"TxnType"` // REQUIRED: Always "Invoice" for payments
}

LinkedTxn represents a linked transaction (invoice) in a payment

type PaymentLine

type PaymentLine struct {
	Amount    float64     `json:"Amount"`    // REQUIRED: Amount applied to this invoice
	LinkedTxn []LinkedTxn `json:"LinkedTxn"` // REQUIRED: Invoice reference (always single invoice)
}

PaymentLine represents a line item in a payment linking to an invoice We always link to exactly ONE invoice (1:1 relationship)

type PaymentResponse

type PaymentResponse struct {
	ID          string        `json:"Id"`                    // QuickBooks Payment ID
	SyncToken   string        `json:"SyncToken,omitempty"`   // Version control for updates (we don't use)
	TxnDate     string        `json:"TxnDate"`               // Payment date (YYYY-MM-DD)
	TotalAmt    float64       `json:"TotalAmt"`              // Total payment amount
	CustomerRef AccountRef    `json:"CustomerRef"`           // Customer who made payment
	Line        []PaymentLine `json:"Line,omitempty"`        // CRITICAL: Contains which invoices were paid
	PrivateNote string        `json:"PrivateNote,omitempty"` // Our memo: "Payment recorded by: flexprice"
}

PaymentResponse represents a payment response from QuickBooks Returned when we GET a payment or CREATE a payment

type PaymentService

type PaymentService struct {
	// contains filtered or unexported fields
}

PaymentService handles QuickBooks payment operations

func (*PaymentService) HandleExternalPaymentFromWebhook

func (s *PaymentService) HandleExternalPaymentFromWebhook(ctx context.Context, qbPaymentID string, paymentService interfaces.PaymentService, invoiceService interfaces.InvoiceService) error

HandleExternalPaymentFromWebhook processes a QuickBooks payment webhook (INBOUND SYNC)

FLOW: QuickBooks → Flexprice TRIGGER: When a payment is recorded in QuickBooks (via webhook notification)

WHAT IT DOES: 1. Receives webhook notification (minimal data: just payment ID) 2. Calls QuickBooks API to get full payment details (amount, linked invoice, date) 3. Finds the Flexprice invoice via entity mapping 4. Creates a payment record in Flexprice with QuickBooks details in metadata 5. Uses ReconcilePaymentStatus() to update invoice (supports partial payments!)

IMPORTANT: Now creates payment records, supports partial payments!

type PaymentServiceParams

type PaymentServiceParams struct {
	Client                       QuickBooksClient
	InvoiceRepo                  invoice.Repository
	EntityIntegrationMappingRepo entityintegrationmapping.Repository
	Logger                       *logger.Logger
}

PaymentServiceParams contains parameters for creating a PaymentService

type QueryResponse

type QueryResponse struct {
	QueryResponse struct {
		MaxResults    int                `json:"maxResults"`
		StartPosition int                `json:"startPosition"`
		TotalCount    int                `json:"totalCount"`
		Customer      []CustomerResponse `json:"Customer,omitempty"`
		Item          []ItemResponse     `json:"Item,omitempty"`
		Account       []AccountResponse  `json:"Account,omitempty"`
		Payment       []PaymentResponse  `json:"Payment,omitempty"`
	} `json:"QueryResponse"`
}

QueryResponse represents a QuickBooks query API response

type QuickBooksClient

type QuickBooksClient interface {
	// Configuration and initialization
	GetQuickBooksConfig(ctx context.Context) (*QuickBooksConfig, error)
	GetDecryptedQuickBooksConfig(conn *connection.Connection) (*QuickBooksConfig, error)
	HasQuickBooksConnection(ctx context.Context) bool
	GetConnection(ctx context.Context) (*connection.Connection, error)

	// Customer API wrappers
	CreateCustomer(ctx context.Context, req *CustomerCreateRequest) (*CustomerResponse, error)
	QueryCustomerByEmail(ctx context.Context, email string) (*CustomerResponse, error)
	QueryCustomerByName(ctx context.Context, name string) (*CustomerResponse, error)

	// Item API wrappers
	CreateItem(ctx context.Context, req *ItemCreateRequest) (*ItemResponse, error)
	GetItem(ctx context.Context, itemID string) (*ItemResponse, error)
	QueryItemByName(ctx context.Context, name string) (*ItemResponse, error)

	// Invoice API wrappers
	CreateInvoice(ctx context.Context, req *InvoiceCreateRequest) (*InvoiceResponse, error)
	GetInvoice(ctx context.Context, invoiceID string) (*InvoiceResponse, error)

	// Payment API wrappers (inbound only)
	GetPayment(ctx context.Context, paymentID string) (*PaymentResponse, error)

	// Token management
	ExchangeAuthCodeForTokens(ctx context.Context) error
	EnsureValidAccessToken(ctx context.Context) error
	RefreshAccessToken(ctx context.Context) error
}

QuickBooksClient defines the interface for QuickBooks API operations

func NewClient

func NewClient(
	connectionRepo connection.Repository,
	encryptionService security.EncryptionService,
	logger *logger.Logger,
) QuickBooksClient

NewClient creates a new QuickBooks client

type QuickBooksConfig

type QuickBooksConfig struct {
	ClientID             string
	ClientSecret         string
	AccessToken          string
	RefreshToken         string
	RealmID              string
	Environment          string // "sandbox" or "production"
	AuthCode             string // Temporary, for initial token exchange
	RedirectURI          string // Temporary, for initial token exchange
	IncomeAccountID      string // Optional: Custom income account ID for items (defaults to "79")
	WebhookVerifierToken string // Optional: Webhook verifier token from QuickBooks for webhook signature verification
}

QuickBooksConfig holds decrypted QuickBooks configuration

type QuickBooksCustomerService

type QuickBooksCustomerService interface {
	GetOrCreateQuickBooksCustomer(ctx context.Context, flexpriceCustomer *customerDomain.Customer) (string, error)
	GetQuickBooksCustomerID(ctx context.Context, flexpriceCustomerID string) (string, error)
}

QuickBooksCustomerService defines the interface for QuickBooks customer operations

func NewCustomerService

func NewCustomerService(params CustomerServiceParams) QuickBooksCustomerService

NewCustomerService creates a new QuickBooks customer service

type QuickBooksInvoiceService

type QuickBooksInvoiceService interface {
	SyncInvoiceToQuickBooks(ctx context.Context, req QuickBooksInvoiceSyncRequest) (*QuickBooksInvoiceSyncResponse, error)
}

QuickBooksInvoiceService defines the interface for QuickBooks invoice operations

func NewInvoiceService

func NewInvoiceService(params InvoiceServiceParams) QuickBooksInvoiceService

NewInvoiceService creates a new QuickBooks invoice service

type QuickBooksInvoiceSyncRequest

type QuickBooksInvoiceSyncRequest struct {
	InvoiceID string `json:"invoice_id" validate:"required"`
}

QuickBooksInvoiceSyncRequest represents a request to sync an invoice to QuickBooks

type QuickBooksInvoiceSyncResponse

type QuickBooksInvoiceSyncResponse struct {
	QuickBooksInvoiceID string          `json:"quickbooks_invoice_id"`
	Total               decimal.Decimal `json:"total"`
	Currency            string          `json:"currency"`
}

QuickBooksInvoiceSyncResponse represents the response from syncing an invoice to QuickBooks

type QuickBooksItemSyncService

type QuickBooksItemSyncService interface {
	SyncPriceToQuickBooks(ctx context.Context, plan *plan.Plan, priceToSync *price.Price) error
}

QuickBooksItemSyncService defines the interface for QuickBooks item synchronization

func NewItemSyncService

func NewItemSyncService(params ItemSyncServiceParams) QuickBooksItemSyncService

NewItemSyncService creates a new QuickBooks item sync service

type QuickBooksItemType

type QuickBooksItemType string

QuickBooksItemType represents the type of item in QuickBooks

const (
	// ItemTypeService represents a service item in QuickBooks
	ItemTypeService QuickBooksItemType = "Service"
)

type QuickBooksPaymentService

type QuickBooksPaymentService interface {
	// HandleExternalPaymentFromWebhook processes a QuickBooks payment webhook (INBOUND ONLY)
	HandleExternalPaymentFromWebhook(ctx context.Context, qbPaymentID string, paymentService interfaces.PaymentService, invoiceService interfaces.InvoiceService) error
}

QuickBooksPaymentService defines the interface for QuickBooks payment operations

func NewPaymentService

func NewPaymentService(params PaymentServiceParams) QuickBooksPaymentService

NewPaymentService creates a new QuickBooks payment service

type SalesItemLineDetail

type SalesItemLineDetail struct {
	ItemRef   AccountRef       `json:"ItemRef"`
	Qty       *decimal.Decimal `json:"Qty,omitempty"`
	UnitPrice *decimal.Decimal `json:"UnitPrice,omitempty"`
}

SalesItemLineDetail represents sales item line detail

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL