version?->isPublished() !== true) { return; } $frozen = array_intersect(array_keys($price->getDirty()), self::FROZEN); if ($frozen !== []) { throw new RuntimeException( 'The price of a published plan version is fixed; tried to change: '.implode(', ', $frozen). '. Publish a new version instead — someone may be at the checkout looking at this one.' ); } }); static::deleting(function (self $price) { // Same loophole as editing. Remove the price of a version someone is // checking out on, and their payment lands on a plan that can no // longer be priced — the order is recorded, no contract opens, and // they are left paid-for and unprovisioned. if ($price->version?->isPublished() === true) { throw new RuntimeException( 'The price of a published plan version cannot be deleted. '. 'Close the version\'s availability window instead.' ); } }); } protected function casts(): array { return ['amount_cents' => 'integer']; } public function uniqueIds(): array { return ['uuid']; } public function version(): BelongsTo { return $this->belongsTo(PlanVersion::class, 'plan_version_id'); } }