48 lines
1.7 KiB
PHP
48 lines
1.7 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
/**
|
|
* One Stripe Price for one module, at one amount, on one interval.
|
|
*
|
|
* The module catalogue lives in config and has no rows of its own, so this is
|
|
* where the mirror into Stripe is remembered — the same job `plan_prices`
|
|
* does for packages. See the migration for why a module needs more than one
|
|
* Price: a booking is frozen at the price it was booked at, and a Stripe Price
|
|
* cannot be edited.
|
|
*
|
|
* `amount_cents` is what the Price CHARGES; `net_cents` is the catalogue figure
|
|
* it was formed from, which is what a booking is frozen at. A Price superseded by
|
|
* a rate change is archived rather than deleted, because a contract may still be
|
|
* billing on it.
|
|
*
|
|
* `reverse_charge` is the other half of a module's identity, and it is why there
|
|
* are four Prices per module and not two. A customer who is charged VAT pays the
|
|
* gross of the catalogue figure; a business in another member state with a
|
|
* verified VAT id owes the bare net and is charged exactly that, so for them
|
|
* `amount_cents` and `net_cents` are the same number. Which of the two a booking
|
|
* bills on is TaxTreatment's decision — see App\Services\Billing\AddonPrices.
|
|
*/
|
|
class StripeAddonPrice extends Model
|
|
{
|
|
protected $guarded = [];
|
|
|
|
protected function casts(): array
|
|
{
|
|
return [
|
|
'amount_cents' => 'integer',
|
|
'net_cents' => 'integer',
|
|
'reverse_charge' => 'boolean',
|
|
'archived_at' => 'datetime',
|
|
];
|
|
}
|
|
|
|
/** Is this the Price a new booking of this module would be put on? */
|
|
public function isLive(): bool
|
|
{
|
|
return $this->archived_at === null;
|
|
}
|
|
}
|