Skip to content
Last updated

WHMCS\Billing\Invoice

Class · extends AbstractModel · implements ImmutableModelInterface, TaxableInterface

A customer's invoice.

The Invoice is the central mechanic upon which the entire WHMCS billing process is built upon. Orders request Services based on Products, which are turned into Invoices to handle payments. Future payments are then made against invoices until such time as the Client makes a CancellationRequest for the Product.

Each Invoice is attached to a specific clientId, and contains one or more invoice line items which actually define the products and prices paid on the invoice.

Tax Rules are configured in Setup -> Payments -> Tax Rules.

Multiple tax rules from each level may be valid for an Invoice, but only the lowest-numbered-ID tax rule will actually be applied to the Invoice.

Note that $id and $invoiceNumber are completely separate entities. The $id is used internally to track the invoice, while the $invoiceNumber is provided to the client and may be used for other tracking purposes; for example, VAT tax compliance.

Traits

  • ImmutableModelTrait

Constants

NameDescription
STATUS_CANCELLED
STATUS_COLLECTIONS
STATUS_DRAFT
STATUS_PAID
STATUS_PAYMENT_PENDING
STATUS_REFUNDED
STATUS_UNPAID
PAYMENT_CONFIRMATION_EMAIL
CC_CONFIRMATION_EMAIL
CC_FAILED_EMAIL
CC_PENDING_EMAIL
DD_CONFIRMATION_EMAIL
DD_FAILED_EMAIL
DD_PENDING_EMAIL
INVOICE_PAYMENT_EMAILS
PAYMENT_CONFIRMATION_EMAILS
PAYMENT_FAILED_EMAILS
PAYMENT_PENDING_EMAILS

Properties

TypeNameDescription
?BillingModelCollection$billingAdjustments

Methods

factoryWithoutStatusIndex

public static function factoryWithoutStatusIndex(): self

Returns self

boot

public static function boot()

isImmutable

public function isImmutable(): bool

throwImmutabilityException

public function throwImmutabilityException(string $message = '', string $column = ''): never

Parameters

TypeNameDescription
string$messageException message, leave empty for default
string$columnIf specified, offending column name will be added to the exception message.

Returns never

validStatusTransitionMap

public static function validStatusTransitionMap(): array

Returns array<string, — array<string>>

terminalStatuses

public static function terminalStatuses(): array

Returns array<string>

isStatusTransitionAllowed

public function isStatusTransitionAllowed(string $toStatus): bool

validateMutability

public function validateMutability(?string $attribute): void

getViewInvoiceUrl

public function getViewInvoiceUrl(?array $additionalQueryStringParams = null): string

Get view invoice url.

Parameters

TypeNameDescription
array|null$additionalQueryStringParams

Returns string

getClientViewLinkMarkup

public function getClientViewLinkMarkup(?string $targetValue = null): string

getAdminViewLinkMarkup

public function getAdminViewLinkMarkup()

getEditInvoiceUrl

public function getEditInvoiceUrl(?array $additionalQueryStringParams = null): string

Get Edit Invoice URL.

Parameters

TypeNameDescription
array|null$additionalQueryStringParams

Returns string

getEditInvoiceTabUrl

public function getEditInvoiceTabUrl(int $tab, $additionalQueryStringParams = null): string

getRefundInvoiceUrl

public function getRefundInvoiceUrl(?array $additionalQueryStringParams = null): string

getInvoiceNumber

public function getInvoiceNumber()

getCurrency

public function getCurrency()

Get currency object for the invoice.

Returns array

getCurrencyCodeAttribute

public function getCurrencyCodeAttribute()

Get currency code.

Returns string

getCurrencyModel

public function getCurrencyModel(): ?Currency

client

public function client()

Each invoice belongs to one client.

Returns \Illuminate\Database\Eloquent\Relations\BelongsTo

transactions

public function transactions()

Each invoice can have many transactions.

Returns \Illuminate\Database\Eloquent\Relations\hasMany

items

public function items()

Each invoice can have many line items.

Returns \Illuminate\Database\Eloquent\Relations\HasMany

snapshot

public function snapshot()

Each invoice can have one set of invoice snapshot data.

Returns \Illuminate\Database\Eloquent\Relations\hasOne

order

public function order()

An invoice can belong to a single order.

Returns BelongsTo

servicesProduct

public function servicesProduct(): BelongsToMany

servicesAddon

public function servicesAddon(): BelongsToMany

servicesDomain

public function servicesDomain(): BelongsToMany

scopeUnpaid

public function scopeUnpaid(Builder $query)

Where status is unpaid.

Parameters

TypeNameDescription
\Illuminate\Database\Eloquent\Builder$query

Returns \Illuminate\Database\Eloquent\Builder

scopeOverdue

public function scopeOverdue(Builder $query)

Where status is overdue.

Parameters

TypeNameDescription
\Illuminate\Database\Eloquent\Builder$query

Returns \Illuminate\Database\Eloquent\Builder

scopePaid

public function scopePaid(Builder $query)

Where status is paid.

Parameters

TypeNameDescription
\Illuminate\Database\Eloquent\Builder$query

Returns \Illuminate\Database\Eloquent\Builder

scopeCancelled

public function scopeCancelled(Builder $query)

Where status is cancelled.

Parameters

TypeNameDescription
\Illuminate\Database\Eloquent\Builder$query

Returns \Illuminate\Database\Eloquent\Builder

scopeRefunded

public function scopeRefunded(Builder $query)

Where status is refunded.

Parameters

TypeNameDescription
\Illuminate\Database\Eloquent\Builder$query

Returns \Illuminate\Database\Eloquent\Builder

scopeCollections

public function scopeCollections(Builder $query)

Where status is collections.

Parameters

TypeNameDescription
\Illuminate\Database\Eloquent\Builder$query

Returns \Illuminate\Database\Eloquent\Builder

scopePaymentPending

public function scopePaymentPending(Builder $query)

Where status is payment-pending.

Parameters

TypeNameDescription
\Illuminate\Database\Eloquent\Builder$query

Returns \Illuminate\Database\Eloquent\Builder

scopeUnpaidOrPaymentPending

public function scopeUnpaidOrPaymentPending(Builder $query)

Where status is unpaid or payment-pending.

Parameters

TypeNameDescription
\Illuminate\Database\Eloquent\Builder$query

Returns \Illuminate\Database\Eloquent\Builder

scopeMassPay

public function scopeMassPay(Builder $query, $isMassPay = true)

Where the invoice does not contain a line item that is of type "Invoice".

Parameters

TypeNameDescription
\Illuminate\Database\Eloquent\Builder$query
bool$isMassPayTrue if you want to find only Mass Pay invoices, false only non Mass Pay

Returns \Illuminate\Database\Eloquent\Builder

scopeWithLastCaptureAttempt

public function scopeWithLastCaptureAttempt(Builder $query, Carbon $date)

Where the last capture date is on a specific date

Parameters

TypeNameDescription
Builder$query
Carbon$dateThe carbon object for the date to obtain data for

Returns \Illuminate\Database\Eloquent\Builder

getBalanceAttribute

public function getBalanceAttribute()

Calculate balance remaining for the invoice.

Returns float

getInvoiceAmountAttribute

public function getInvoiceAmountAttribute(): float

getPaymentGatewayNameAttribute

public function getPaymentGatewayNameAttribute()

Returns string

getAmountPaidAttribute

public function getAmountPaidAttribute()

Returns float

hasRemainingBalanceDue

public function hasRemainingBalanceDue(): bool

Remaining balance is the invoice total minus the sum of all transactions towards the invoice, with consideration of the currency's decimal/no-decimal format.

Ex. if the invoice total was set to 666.66, and the payment history was in Japanese Yen (JPY), once there is enough transactions totalling >= 666.50, this method would return FALSE. If the payment history was in USD, the target sum would be >= 666.66 for this method to return FALSE.

Returns bool

addPayment

public function addPayment($amount, $transactionId = '', $fees = 0.0, $gateway = '', $suppressEmail = false, Carbon $date = null)

"add a payment" means to record a transaction for an invoice, and per this method, also means updating the invoice status, managing overpayments, updating services referenced in the invoice, and other invoice-adjacent observable events.

Parameters

TypeNameDescription
float$amount
string$transactionId
float$fees
string$gateway
bool$suppressEmail
Carbon|null$date

Returns bool

addPaymentIfNotExists

public function addPaymentIfNotExists($amount, $transactionId = '', $fees = 0.0, $gateway = '', $noEmail = false, Carbon $date = null)

Parameters

TypeNameDescription
float$amount
string$transactionId
float$fees
string$gateway
bool$noEmail
Carbon|null$date

Returns bool

getBillingValues

public function getBillingValues()

Calculate recurring billing data for each invoice item. Each row data subarray can contain additional fields if the payment doesn't cover the entire amount.

Returns array — payment data [ 'overdue' => bool, [ 'itemId' => string, 'amount' => string, 'setupFee' => string, 'recurringCyclePeriod' => float, 'recurringCycleUnits' => "Months"|"Years"|"Days", 'description' => string, 'lineItemAmount' => string, // If a balance remains on the invoice, the following keys will be present: 'firstPaymentAmount' => string, 'firstCyclePeriod' => float, 'firstCycleUnits' => "Months"|"Years"|"Days" ], [ 'itemId' => string, // ... ] ]

shouldRenewRun

public function shouldRenewRun($relatedId, $registrationDate, $type = 'Hosting')

Checks if the module renewal should run for a provided related id, registration date and type of item.

Parameters

TypeNameDescription
integer$relatedIdThe id of the item for the invoice being paid. tblhosting.id or tblhostingaddons.id
string$registrationDatein mysql date format
string$typeEither one of Hosting or Addon. Exception will be thrown for other item types.

Returns bool

vat

public function vat()

Returns Vat

newInvoice

public static function newInvoice($clientId, $gateway = null, $taxRate1 = null, $taxRate2 = null)

Create a new invoice in Draft and return the instance to be updated and saved.

Parameters

TypeNameDescription
integer$clientId
string$gateway
float$taxRate1
float$taxRate2

Returns Invoice

setStatusUnpaid

public function setStatusUnpaid()

Set invoice status to unpaid.

Returns Invoice

setStatusPending

public function setStatusPending()

Set invoice status to payment pending.

Returns Invoice

setStatusRefunded

public function setStatusRefunded()

Set invoice status to refunded.

Returns Invoice

setStatusCancelled

public function setStatusCancelled()

Set invoice status to cancelled.

Returns Invoice

data

public function data()

Each invoice can have one set of invoice data.

Returns \Illuminate\Database\Eloquent\Relations\hasOne

transactionHistory

public function transactionHistory()

Returns \Illuminate\Database\Eloquent\Relations\HasMany\|History[]

debitNotes

public function debitNotes()

Returns Builder\|DebitNote[]

payMethod

public function payMethod()

Returns \Illuminate\Database\Eloquent\Relations\BelongsTo\|PayMethod

getPayMethodRemoteToken

public function getPayMethodRemoteToken()

Returns string

setPayMethodRemoteToken

public function setPayMethodRemoteToken($remoteToken)

deletePayMethod

public function deletePayMethod()

convertLocalCardToRemote

public function convertLocalCardToRemote($remoteToken)

convertLocalBankAccountToRemote

public function convertLocalBankAccountToRemote($remoteToken)

saveRemoteCard

public function saveRemoteCard($cardLastFour, $cardType, $expiryDate, $remoteToken)

saveRemoteBankAccount

public function saveRemoteBankAccount($bankName, $remoteToken)

cart

public function cart()

Build a cart object based on the current invoice.

Returns CartCalculator

runCreationHooks

public function runCreationHooks($source)

Run invoice creation hooks.

Parameters

TypeNameDescription
string$sourceOne of 'adminarea', 'api', 'autogen' or 'clientarea'

Returns self

getSubscriptionIds

public function getSubscriptionIds($paymentMethods = null)

Get subscription IDs from items that belong to this invoice.

Parameters

TypeNameDescription
array|null$paymentMethods

Returns SupportCollection

saveSubscriptionId

public function saveSubscriptionId($subscriptionId)

Save subscription ID.

Parameters

TypeNameDescription
string$subscriptionId

Returns self

scopeSubscriptionId

public function scopeSubscriptionId(Builder $query, $subscriptionId)

Where the invoices contain items that have a given subscription ID.

Parameters

TypeNameDescription
\Illuminate\Database\Eloquent\Builder$query
string$subscriptionId

Returns \Illuminate\Database\Eloquent\Builder

public function getLink()
public function getAdminViewLink(): string

setPaymentMethod

public function setPaymentMethod($gatewayName)

Set the invoice Payment Method.

Parameters

TypeNameDescription
string$gatewayNameThe name of the gateway. (e.g. 'paypal')

Returns $this

setPayMethodId

public function setPayMethodId($payMethodId)

Set the Pay Method ID for the invoice.

Parameters

TypeNameDescription
int$payMethodIdThe ID of the clients Pay Method to associate.

Returns $this

clearPayMethodId

public function clearPayMethodId()

Clear the associated Pay Method

Returns $this

getTaxrateAttribute

public function getTaxrateAttribute()

getTaxrate2Attribute

public function getTaxrate2Attribute()

getGatewayInterface

public function getGatewayInterface(): Gateway

Returns Gateway

updateInvoiceTotal

public function updateInvoiceTotal()

Update invoice totals will refresh the model loaded and then process all the invoice items and appropriate taxes to update the totals on the invoice and then save. A save is required prior to calling this method to ensure any 'dirty' data is not lost. The save should happen before any invoice hooks are run to ensure that any hook functions have the most up to date information on the invoice at the point of the hook running.

calculateInvoiceTotal

public function calculateInvoiceTotal()

removeCredit

public function removeCredit($amount)

Parameters

TypeNameDescription
scalar$amount

paidAffiliateCommissions

public function paidAffiliateCommissions(): Relation

pendingAffiliateCommissions

public function pendingAffiliateCommissions(): Relation

requiresPayment

public function requiresPayment(): bool

Is the invoice in a state in which initiating payment against it is desirable?

Returns bool

isUnpaid

public function isUnpaid(): bool

Is the invoice marked as unpaid?

Returns bool

isAwaitingPayment

public function isAwaitingPayment(): bool

Is the invoice expecting a previously initiated payment's completion?

Returns bool

isDraft

public function isDraft(): bool

isPaid

public function isPaid(): bool

isCollections

public function isCollections(): bool

isRefunded

public function isRefunded(): bool

isCancelled

public function isCancelled(): bool

canPaymentBeApplied

public function canPaymentBeApplied(): bool

Is the invoice in a state in which applying a payment is expected and possible.

Returns bool

isProformaInvoice

public function isProformaInvoice(): bool

productGroups

public function productGroups(): SupportCollection

All groups related to products of services itemized in the invoice.

Returns SupportCollection<int, — Group> Group keyed by Group ID

billingPaymentGateway

public function billingPaymentGateway(): ?PaymentGatewayInterface

If the invoice has a PaymentGateway assigned, return it, otherwise NULL.

NOTE: the instance of PaymentGatewayInterface may not be serviceable or active.

Returns PaymentGatewayInterface\|null — NULL if nothing assigned

allAvailablePaymentGatewayOptions

public function allAvailablePaymentGatewayOptions(): Collection

Legacy understanding, and limited contextual consideration, of "All Gateways" for use with this invoice.

Callers should consider using {@see Invoice::paymentGatewayOptionsFactory()} and refining a list appropriate to their context.

Considerations for the returned collection:

  • Excluded: non-active or non-serviceable PaymentGateway on the system
  • Excluded: PaymentGateways which are "hidden"
  • Excluded: The disallowed PaymentGateways of Product Groups related to invoice's line item Services.
  • Included: The payment gateway currently assigned to the invoice, if active and serviceable (regardless of "hidden" state)

Note: Currency support is not a consideration due to external contexts

Returns Collection<string, — PaymentGatewayInterface>

paymentGatewayOptionsFactory

public function paymentGatewayOptionsFactory(): PaymentGatewayOptions

A PaymentGatewayOptions factory, primed with an instance of this class.

Returns PaymentGatewayOptions

adjustInvoiceForPaymentGatewayOptions

public function adjustInvoiceForPaymentGatewayOptions(PaymentGatewayOptions $options): self

Inspect the invoice's assigned PaymentGateway relative to the provided PaymentGatewayOptions and update the payment method based on those options.

Parameters

TypeNameDescription
PaymentGatewayOptions$options

Returns $this

credits

public function credits(): HasMany

Returns HasMany

isFullLineItemSet

public function isFullLineItemSet(SupportCollection $lineItems): bool

Returns true if the provided collection of line items matches the full set of invoice line items (in no specific order)

Parameters

TypeNameDescription
SupportCollection$lineItems

Returns bool

addPaymentForRemainingBalance

public function addPaymentForRemainingBalance()

"Mark Paid" with blind application of payment for the remaining balance.

Returns null\|Event\InvoicePayment;

allowances

public function allowances(): Allowances

getTax1Amount

public function getTax1Amount(): float

getTax2Amount

public function getTax2Amount(): float

getSubtotal

public function getSubtotal(): float

getAppliedCreditAttribute

public function getAppliedCreditAttribute(): float

appliedCreditAggregator

public function appliedCreditAggregator()