|null $extras Extras payload. * @param array|null $custom_fields Custom fields. * @param Money $price Line price. * @param int|null $hold_id Soft-hold booking FK. * @param int $sort_order Display order. * * @throws DomainException When invariants fail. */ public function __construct( private ?int $id, private int $cart_id, private int $service_id, private ?int $duration_id, private ?int $agent_id, private ?int $location_id, private ?DateTimeImmutable $start_utc, private ?DateTimeImmutable $end_utc, private ?DateTimeImmutable $buffer_start_utc, private ?DateTimeImmutable $buffer_end_utc, private ?string $timezone, private int $attendees, private ?array $extras, private ?array $custom_fields, private Money $price, private ?int $hold_id, private int $sort_order, ) { if ( $this->cart_id < 1 || $this->service_id < 1 ) { throw new DomainException( 'cart_item.fk', 'cart_id and service_id must be positive.' ); } if ( $this->attendees < 1 ) { throw new DomainException( 'cart_item.attendees', 'attendees must be at least 1.' ); } if ( $this->price->is_negative() ) { throw new DomainException( 'cart_item.price', 'price must not be negative.' ); } if ( null !== $this->hold_id && $this->hold_id < 1 ) { throw new DomainException( 'cart_item.hold_id', 'hold_id must be positive when set.' ); } if ( null !== $this->start_utc && null !== $this->end_utc && $this->end_utc <= $this->start_utc ) { throw new DomainException( 'cart_item.range', 'end_utc must be after start_utc.' ); } } /** * Database id. * * @since 0.1.0 */ public function id(): ?int { return $this->id; } /** * Cart id. * * @since 0.1.0 */ public function cart_id(): int { return $this->cart_id; } /** * Service id. * * @since 0.1.0 */ public function service_id(): int { return $this->service_id; } /** * Duration id. * * @since 0.1.0 */ public function duration_id(): ?int { return $this->duration_id; } /** * Agent id. * * @since 0.1.0 */ public function agent_id(): ?int { return $this->agent_id; } /** * Location id. * * @since 0.1.0 */ public function location_id(): ?int { return $this->location_id; } /** * Start UTC. * * @since 0.1.0 */ public function start_utc(): ?DateTimeImmutable { return $this->start_utc; } /** * End UTC. * * @since 0.1.0 */ public function end_utc(): ?DateTimeImmutable { return $this->end_utc; } /** * Buffer start UTC. * * @since 0.1.0 */ public function buffer_start_utc(): ?DateTimeImmutable { return $this->buffer_start_utc; } /** * Buffer end UTC. * * @since 0.1.0 */ public function buffer_end_utc(): ?DateTimeImmutable { return $this->buffer_end_utc; } /** * Timezone. * * @since 0.1.0 */ public function timezone(): ?string { return $this->timezone; } /** * Attendees. * * @since 0.1.0 */ public function attendees(): int { return $this->attendees; } /** * Extras. * * @return array|null * * @since 0.1.0 */ public function extras(): ?array { return $this->extras; } /** * Custom fields. * * @return array|null * * @since 0.1.0 */ public function custom_fields(): ?array { return $this->custom_fields; } /** * Price. * * @since 0.1.0 */ public function price(): Money { return $this->price; } /** * Hold booking id. * * @since 0.1.0 */ public function hold_id(): ?int { return $this->hold_id; } /** * Sort order. * * @since 0.1.0 */ public function sort_order(): int { return $this->sort_order; } /** * Assign id after insert. * * @param int $id New id. * * @throws DomainException When already assigned. * * @since 0.1.0 */ public function assign_id( int $id ): void { if ( null !== $this->id ) { throw new DomainException( 'cart_item.id_assigned', 'Cart item id is already assigned.' ); } if ( $id < 1 ) { throw new DomainException( 'cart_item.id_invalid', 'Cart item id must be positive.' ); } $this->id = $id; } /** * Attach or clear a soft hold. * * @param int|null $hold_id Hold booking id. * * @throws DomainException When hold id is invalid. * * @since 0.1.0 */ public function set_hold_id( ?int $hold_id ): void { if ( null !== $hold_id && $hold_id < 1 ) { throw new DomainException( 'cart_item.hold_id', 'hold_id must be positive when set.' ); } $this->hold_id = $hold_id; } }