PluginProbe ʕ •ᴥ•ʔ
Appointment Booking Plugin – LatePoint | Calendar & Scheduling for WordPress / 5.6.8
Appointment Booking Plugin – LatePoint | Calendar & Scheduling for WordPress v5.6.8
5.6.8 5.6.7 5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / models / invoice_model.php
latepoint / lib / models Last commit date
activity_model.php 4 months ago agent_meta_model.php 4 months ago agent_model.php 3 months ago booking_meta_model.php 4 months ago booking_model.php 4 days ago bundle_meta_model.php 4 months ago bundle_model.php 2 weeks ago cart_item_model.php 4 months ago cart_meta_model.php 4 months ago cart_model.php 4 days ago connector_model.php 4 months ago customer_meta_model.php 4 months ago customer_model.php 1 month ago invoice_model.php 1 day ago join_bundles_services_model.php 4 months ago location_category_model.php 4 months ago location_model.php 4 months ago meta_model.php 4 months ago model.php 1 week ago off_period_model.php 4 months ago order_intent_meta_model.php 4 months ago order_intent_model.php 2 weeks ago order_item_model.php 4 months ago order_meta_model.php 4 months ago order_model.php 1 month ago otp_model.php 4 months ago payment_request_model.php 4 months ago process_job_model.php 4 months ago process_model.php 1 month ago recurrence_model.php 4 months ago service_category_model.php 4 months ago service_meta_model.php 4 months ago service_model.php 4 months ago session_model.php 4 months ago settings_model.php 4 months ago step_settings_model.php 4 months ago transaction_intent_model.php 4 months ago transaction_model.php 4 months ago transaction_refund_model.php 4 months ago work_period_model.php 4 months ago
invoice_model.php
290 lines
1 <?php
2
3 class OsInvoiceModel extends OsModel {
4 public $id,
5 $order_id,
6 $invoice_number,
7 $data,
8 $charge_amount,
9 $payment_portion,
10 $status,
11 $access_key,
12 $due_at,
13 $updated_at,
14 $created_at;
15
16 function __construct( $id = false ) {
17 parent::__construct();
18 $this->table_name = LATEPOINT_TABLE_ORDER_INVOICES;
19
20 if ( $id ) {
21 $this->load_by_id( $id );
22 }
23 }
24
25 public function get_receipt_url(): string {
26 $transaction = new OsTransactionModel();
27 $transaction = $transaction->where(
28 [
29 'invoice_id' => $this->id,
30 'status' => LATEPOINT_TRANSACTION_STATUS_SUCCEEDED,
31 ]
32 )->set_limit( 1 )->get_results_as_models();
33 if ( $transaction && ! $transaction->is_new_record() ) {
34 return $transaction->get_receipt_url();
35 } else {
36 return $this->get_access_url();
37 }
38 }
39
40 public function properties_to_query(): array {
41 return [
42 'status' => __( 'Status', 'latepoint' ),
43 'payment_portion' => __( 'Payment Portion', 'latepoint' ),
44 ];
45 }
46
47 public function get_customer(): OsCustomerModel {
48 return $this->get_order()->get_customer();
49 }
50
51
52 public function generate_data_vars(): array {
53
54 $vars['id'] = $this->id;
55 $vars['order_id'] = $this->order_id;
56 $vars['invoice_number'] = $this->get_invoice_number();
57 $vars['payment_portion'] = $this->payment_portion;
58 $vars['status'] = $this->status;
59 $vars['data'] = $this->data;
60 $vars['charge_amount'] = $this->charge_amount;
61 $vars['access_key'] = $this->access_key;
62 $vars['due_at'] = $this->due_at;
63
64 $vars['customer'] = $this->get_customer()->get_data_vars();
65 $vars['order'] = $this->get_order()->get_first_level_data_vars();
66 $vars['transactions'] = [];
67
68 $transactions = $this->get_successful_payments();
69 if ( $transactions ) {
70 foreach ( $transactions as $transaction ) {
71 $vars['transactions'][] = $transaction->get_data_vars();
72 }
73 }
74
75 return $vars;
76 }
77
78 public function get_order(): OsOrderModel {
79 if ( $this->order_id ) {
80 if ( ! isset( $this->order ) || ( isset( $this->order ) && ( $this->order->id != $this->order_id ) ) ) {
81 $this->order = new OsOrderModel( $this->order_id );
82 }
83 } else {
84 $this->order = new OsOrderModel();
85 }
86
87 return $this->order;
88 }
89
90 public function get_successful_payments(): array {
91 $transactions = new OsTransactionModel();
92 $transactions = $transactions->where(
93 [
94 'status' => LATEPOINT_TRANSACTION_STATUS_SUCCEEDED,
95 'invoice_id' => $this->id,
96 ]
97 )->get_results_as_models();
98
99 return $transactions;
100 }
101
102 public function get_amount_paid(): float {
103 $total = 0;
104 foreach ( $this->get_successful_payments() as $transaction ) {
105 $total += (float) $transaction->amount;
106 }
107
108 return $total;
109 }
110
111 public function get_amount_due(): float {
112 return (float) $this->charge_amount - $this->get_amount_paid();
113 }
114
115
116 protected function params_to_sanitize() {
117 return [
118 'charge_amount' => 'money',
119 ];
120 }
121
122 /**
123 * @param string $new_status
124 *
125 * @return bool
126 */
127 public function change_status( string $new_status ): bool {
128 $old_status = $this->status;
129 $old_invoice = clone $this;
130 if ( $old_status == $new_status ) {
131 return true;
132 }
133 if ( $this->update_attributes( [ 'status' => $new_status ] ) ) {
134 /**
135 * Invoice status has been changed
136 *
137 * @param {OsInvoiceModel} $invoice invoice model
138 * @param {string} $old_status previous status of the invoice
139 * @param {string} $new_status new status of the invoice
140 *
141 * @since 5.1.0
142 * @hook latepoint_invoice_status_changed
143 *
144 */
145 do_action( 'latepoint_invoice_status_changed', $this, $old_status, $new_status );
146 /**
147 * Invoice was updated
148 *
149 * @param {OsInvoiceModel} $invoice instance of invoice model after it was updated
150 * @param {OsInvoiceModel} $old_invoice instance of invoice model before it was updated
151 *
152 * @since 5.1.0
153 * @hook latepoint_invoice_updated
154 *
155 */
156 do_action( 'latepoint_invoice_updated', $this, $old_invoice );
157
158 return true;
159 } else {
160 return false;
161 }
162 }
163
164 /**
165 * Compose a new invoice number from the current prefix setting and this invoice's id.
166 * Should only be called once (at creation time) so the prefix is frozen on the record.
167 *
168 * @return string
169 */
170 protected function generate_invoice_number(): string {
171 $prefix = OsSettingsHelper::get_settings_value( 'invoices_number_prefix', 'INV-' );
172 if ( false !== stripos( $prefix, '{year}' ) ) {
173 // Resolve to the invoice's creation year so the token reflects the year of issue.
174 // Numbers are frozen at creation, so this is normally the current year; using
175 // created_at also makes the legacy-row fallback in get_invoice_number() correct.
176 // Case-insensitive so {year}, {YEAR}, {Year} all resolve.
177 $year = ! empty( $this->created_at ) ? gmdate( 'Y', strtotime( $this->created_at ) ) : gmdate( 'Y' );
178 $prefix = str_ireplace( '{year}', $year, $prefix );
179 }
180 return $prefix . sprintf( '1%06d', $this->id );
181 }
182
183 public function get_invoice_number(): string {
184 if ( ! empty( $this->invoice_number ) ) {
185 return $this->invoice_number;
186 }
187 if ( empty( $this->id ) ) {
188 return '';
189 }
190 // Fallback for legacy rows that were saved before the number was materialized at creation.
191 // The generated number is persisted immediately so it stays frozen for all future reads.
192 $this->invoice_number = $this->generate_invoice_number();
193 $this->update_attributes( [ 'invoice_number' => $this->invoice_number ] );
194 return $this->invoice_number;
195 }
196
197 /**
198 * Override save() to freeze the invoice number at creation time.
199 * The id is only available after the INSERT, so we assign the number immediately
200 * after the parent insert completes rather than in before_save()/before_create().
201 *
202 * @param bool $alternative_validation
203 * @param bool $skip_validation
204 *
205 * @return bool
206 */
207 public function save( $alternative_validation = false, $skip_validation = false ): bool {
208 $is_new = $this->is_new_record();
209 $saved = parent::save( $alternative_validation, $skip_validation );
210 if ( $saved && $is_new && empty( $this->invoice_number ) ) {
211 $this->invoice_number = $this->generate_invoice_number();
212 $this->update_attributes( [ 'invoice_number' => $this->invoice_number ] );
213 }
214 return $saved;
215 }
216
217
218 protected function before_save() {
219 if ( empty( $this->status ) ) {
220 $this->status = LATEPOINT_INVOICE_STATUS_OPEN;
221 }
222 if ( empty( $this->due_at ) ) {
223 $this->due_at = OsTimeHelper::now_datetime_in_format( LATEPOINT_DATETIME_DB_FORMAT );
224 }
225 if ( empty( $this->access_key ) ) {
226 $this->access_key = OsUtilHelper::generate_uuid();
227 }
228 }
229
230 public function get_readable_due_at(): string {
231 try {
232 return OsTimeHelper::get_readable_date( new OsWpDateTime( $this->due_at, new DateTimeZone( 'UTC' ) ) );
233 } catch ( Exception $e ) {
234 return 'n/a';
235 }
236 }
237
238 public function get_access_url(): string {
239 return OsRouterHelper::build_admin_post_link( [ 'invoices', 'view_by_key' ], [ 'key' => $this->access_key ] );
240 }
241
242 public function get_pay_url(): string {
243 return OsRouterHelper::build_admin_post_link( [ 'invoices', 'summary_before_payment' ], [ 'key' => $this->access_key ] );
244 }
245
246
247 protected function params_to_save( $role = 'admin' ): array {
248 $params_to_save = [
249 'id',
250 'order_id',
251 'invoice_number',
252 'payment_portion',
253 'status',
254 'data',
255 'charge_amount',
256 'access_key',
257 'due_at',
258 ];
259
260 return $params_to_save;
261 }
262
263
264 protected function allowed_params( $role = 'admin' ): array {
265 $allowed_params = [
266 'id',
267 'order_id',
268 'invoice_number',
269 'payment_portion',
270 'status',
271 'data',
272 'charge_amount',
273 'access_key',
274 'due_at',
275 ];
276
277 return $allowed_params;
278 }
279
280
281 protected function properties_to_validate(): array {
282 $validations = [
283 'order_id' => [ 'presence' ],
284 'status' => [ 'presence' ],
285 ];
286
287 return $validations;
288 }
289 }
290