PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.20
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.20
1.10.20 1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 All 164 releases
← All changes | includes/Services/Receipt_Data_Builder.php +140 -246 1.10.2 → 1.10.20 View file →
@@ -18,17 +18,14 @@
18 18 /**
19 19 * Build a canonical receipt payload.
20 20 *
21 21 * @param WC_Abstract_Order $order Receipt order.
22 - * @param string $mode Reserved for caller compatibility; the receipt mode is
23 - * carried in the request, not the payload.
22 + * @param string $mode Receipt mode ('live', 'fiscal', 'preview'), passed unchanged to the receipt data filter.
24 23 * @param object|null $pos_store POS store object. Falls back to order meta or default.
25 24 *
26 25 * @return array
27 26 */
28 27 public function build( WC_Abstract_Order $order, string $mode = 'live', $pos_store = null ): array {
29 - unset( $mode );
30 -
31 28 $wc_status = method_exists( $order, 'get_status' ) ? (string) $order->get_status() : '';
32 29 $status_label = '';
33 30 if ( '' !== $wc_status && function_exists( 'wc_get_order_status_name' ) ) {
34 31 $status_label = (string) wc_get_order_status_name( $wc_status );
@@ -118,9 +115,9 @@
118 115 $customer_name = /* translators: Short WCPOS UI label; keep concise. */ __( 'Guest', 'woocommerce-pos' );
119 116 }
120 117
121 118 $tax_ids = ( new Tax_Id_Reader() )->read_for_order( $order );
122 - $tax_ids = self::with_customer_tax_id_labels( $tax_ids, $presentation_hints['locale'] ?? '' );
119 + $tax_ids = Receipt_Sections::label_tax_ids( $tax_ids, 'customer', $presentation_hints['locale'] ?? '' );
123 120
124 121 $customer = array(
125 122 'id' => $customer_id ? $customer_id : null,
126 123 'name' => $customer_name,
@@ -165,9 +162,8 @@
165 162 : 0.0;
166 163 $price_convenience = $this->get_line_price_convenience_fields(
167 164 $item,
168 165 $order,
169 - $display_incl,
170 166 $qty,
171 167 $unit_subtotal_incl,
172 168 $unit_subtotal_excl,
173 169 $line_subtotal_incl,
@@ -181,29 +177,34 @@
181 177 'sku' => $item->get_product() ? $item->get_product()->get_sku() : '',
182 178 'name' => $item->get_name(),
183 179 'qty' => $qty,
184 180 'qty_refunded' => $qty_refunded,
185 - 'unit_subtotal' => $display_incl ? $unit_subtotal_incl : $unit_subtotal_excl,
186 - 'unit_subtotal_incl' => $unit_subtotal_incl,
187 - 'unit_subtotal_excl' => $unit_subtotal_excl,
188 - 'unit_price' => $display_incl ? $unit_price_incl : $unit_price_excl,
189 - 'unit_price_incl' => $unit_price_incl,
190 - 'unit_price_excl' => $unit_price_excl,
191 - 'line_subtotal' => $display_incl ? $line_subtotal_incl : $line_subtotal_excl,
192 - 'line_subtotal_incl' => $line_subtotal_incl,
193 - 'line_subtotal_excl' => $line_subtotal_excl,
194 - 'discounts' => $display_incl ? $discounts_incl : $discounts_excl,
195 - 'discounts_incl' => $discounts_incl,
196 - 'discounts_excl' => $discounts_excl,
197 - 'line_total' => $display_incl ? $line_total_incl : $line_total_excl,
198 - 'line_total_incl' => $line_total_incl,
199 - 'line_total_excl' => $line_total_excl,
181 + 'unit_subtotal' => array(
182 + 'incl' => $unit_subtotal_incl,
183 + 'excl' => $unit_subtotal_excl,
184 + ),
185 + 'unit_price' => array(
186 + 'incl' => $unit_price_incl,
187 + 'excl' => $unit_price_excl,
188 + ),
189 + 'line_subtotal' => array(
190 + 'incl' => $line_subtotal_incl,
191 + 'excl' => $line_subtotal_excl,
192 + ),
193 + 'discounts' => array(
194 + 'incl' => $discounts_incl,
195 + 'excl' => $discounts_excl,
196 + ),
197 + 'line_total' => array(
198 + 'incl' => $line_total_incl,
199 + 'excl' => $line_total_excl,
200 + ),
200 201 'total_refunded' => $total_refunded,
201 202 'taxes' => $this->get_line_taxes( $item ),
202 203 'meta' => $this->get_item_meta_pairs( $item ),
203 204 'attributes' => $this->get_product_attribute_pairs( $item ),
204 205 );
205 - $lines[] = array_merge( $line, $price_convenience );
206 + $lines[] = Receipt_Sections::line( array_merge( $line, $price_convenience ), $display_incl );
206 207 }
207 208
208 209 $shipping = array();
209 210 foreach ( $order->get_items( 'shipping' ) as $shipping_item ) {
@@ -212,16 +213,18 @@
212 213 }
213 214 $ship_total_excl = (float) $shipping_item->get_total();
214 215 $ship_total_tax = (float) $shipping_item->get_total_tax();
215 216 $ship_total_incl = $ship_total_excl + $ship_total_tax;
216 - $shipping[] = array(
217 - 'label' => $shipping_item->get_name(),
218 - 'method_id' => (string) $shipping_item->get_method_id(),
219 - 'total' => $display_incl ? $ship_total_incl : $ship_total_excl,
220 - 'total_incl' => $ship_total_incl,
221 - 'total_excl' => $ship_total_excl,
222 - 'taxes' => $this->get_item_taxes( $shipping_item ),
223 - 'meta' => $this->get_item_meta_pairs( $shipping_item ),
217 + $shipping[] = Receipt_Sections::shipping(
218 + $shipping_item->get_name(),
219 + (string) $shipping_item->get_method_id(),
220 + array(
221 + 'incl' => $ship_total_incl,
222 + 'excl' => $ship_total_excl,
223 + ),
224 + $this->get_item_taxes( $shipping_item ),
225 + $this->get_item_meta_pairs( $shipping_item ),
226 + $display_incl
224 227 );
225 228 }
226 229
227 230 $fees = array();
@@ -228,15 +231,17 @@
228 231 foreach ( $order->get_fees() as $fee ) {
229 232 $fee_total_excl = (float) $fee->get_total();
230 233 $fee_total_tax = (float) $fee->get_total_tax();
231 234 $fee_total_incl = $fee_total_excl + $fee_total_tax;
232 - $fees[] = array(
233 - 'label' => $fee->get_name(),
234 - 'total' => $display_incl ? $fee_total_incl : $fee_total_excl,
235 - 'total_incl' => $fee_total_incl,
236 - 'total_excl' => $fee_total_excl,
237 - 'taxes' => $this->get_item_taxes( $fee ),
238 - 'meta' => $this->get_item_meta_pairs( $fee ),
235 + $fees[] = Receipt_Sections::fee(
236 + $fee->get_name(),
237 + array(
238 + 'incl' => $fee_total_incl,
239 + 'excl' => $fee_total_excl,
240 + ),
241 + $this->get_item_taxes( $fee ),
242 + $this->get_item_meta_pairs( $fee ),
243 + $display_incl
239 244 );
240 245 }
241 246
242 247 $discounts = array();
@@ -243,17 +248,21 @@
243 248 foreach ( $order->get_items( 'coupon' ) as $coupon_item ) {
244 249 if ( ! $coupon_item instanceof \WC_Order_Item_Coupon ) {
245 250 continue;
246 251 }
252 + $coupon = $this->get_order_coupon( $coupon_item );
247 253 $coupon_excl = (float) $coupon_item->get_discount();
248 254 $coupon_tax = (float) $coupon_item->get_discount_tax();
249 255 $coupon_incl = $coupon_excl + $coupon_tax;
250 - $discounts[] = array(
251 - 'label' => $this->get_coupon_label( $coupon_item ),
252 - 'code' => $coupon_item->get_code(),
253 - 'total' => $display_incl ? $coupon_incl : $coupon_excl,
254 - 'total_incl' => $coupon_incl,
255 - 'total_excl' => $coupon_excl,
256 + $discounts[] = Receipt_Sections::discount(
257 + $this->get_coupon_label( $coupon_item, $coupon ),
258 + $coupon_item->get_code(),
259 + $coupon ? (string) $coupon->get_discount_type() : '',
260 + array(
261 + 'incl' => $coupon_incl,
262 + 'excl' => $coupon_excl,
263 + ),
264 + $display_incl
256 265 );
257 266 }
258 267
259 268 $discount_total_excl = (float) $order->get_discount_total();
@@ -259,116 +268,37 @@
259 268 $discount_total_excl = (float) $order->get_discount_total();
260 269 $discount_total_tax = (float) $order->get_discount_tax();
261 270 $discount_total_incl = $discount_total_excl + $discount_total_tax;
262 271
263 - // Legacy POS lines already include regular-to-selling savings in WooCommerce's
264 - // discount total. Add only current-shape savings to total_saved to avoid overlap.
265 - $sale_savings_totals = array(
266 - 'incl' => 0.0,
267 - 'excl' => 0.0,
268 - );
269 - $additional_savings = array(
270 - 'incl' => 0.0,
271 - 'excl' => 0.0,
272 - );
273 - $savings_complete = array(
274 - 'incl' => true,
275 - 'excl' => true,
276 - );
277 - $price_precision = wc_get_price_decimals();
278 - foreach ( $lines as $line ) {
279 - foreach ( array( 'incl', 'excl' ) as $basis ) {
280 - $key = 'line_savings_' . $basis;
281 - if ( ! isset( $line[ $key ] ) || ! is_numeric( $line[ $key ] ) ) {
282 - $savings_complete[ $basis ] = false;
283 - continue;
284 - }
285 -
286 - $line_savings = (float) $line[ $key ];
287 - $sale_savings_totals[ $basis ] += $line_savings;
288 - if ( empty( $line['savings_in_discounts'] ) ) {
289 - $subtotal_key = 'line_subtotal_' . $basis;
290 - $selling_key = 'line_selling_total_' . $basis;
291 - if (
292 - $line_savings > 0.0
293 - && (
294 - ! isset( $line[ $subtotal_key ], $line[ $selling_key ] )
295 - || round( abs( (float) $line[ $subtotal_key ] - (float) $line[ $selling_key ] ), $price_precision ) > 0.0
296 - )
297 - ) {
298 - $savings_complete[ $basis ] = false;
299 - continue;
300 - }
301 - $additional_savings[ $basis ] += $line_savings;
302 - }
303 - }
304 - }
305 -
306 - $total_saved = array(
307 - 'incl' => $savings_complete['incl'] ? $discount_total_incl + $additional_savings['incl'] : null,
308 - 'excl' => $savings_complete['excl'] ? $discount_total_excl + $additional_savings['excl'] : null,
309 - );
310 - foreach ( array( 'incl', 'excl' ) as $basis ) {
311 - if ( ! $savings_complete[ $basis ] ) {
312 - $sale_savings_totals[ $basis ] = null;
313 - }
314 - }
315 - $display_basis = $display_incl ? 'incl' : 'excl';
316 -
317 - $subtotal_excl = array_sum( array_column( $lines, 'line_subtotal_excl' ) );
318 - $subtotal_incl = array_sum( array_column( $lines, 'line_subtotal_incl' ) );
319 -
320 - // Item count summaries — useful for packing slips and kitchen tickets
321 - // where Mustache can't sum/count an array at render time.
322 - $total_qty = (float) array_sum( array_column( $lines, 'qty' ) );
323 - $line_count = \count( $lines );
324 -
325 272 $tax_total = (float) $order->get_total_tax();
326 - $total = (float) $order->get_total();
327 -
328 - $total_excl = $total - $tax_total;
329 - $refund_total = method_exists( $order, 'get_total_refunded' )
273 + $total = (float) $order->get_total();
274 + $refund_total = method_exists( $order, 'get_total_refunded' )
330 275 ? abs( (float) $order->get_total_refunded() )
331 276 : 0.0;
332 - // Templates render the customer-facing balance after a partial refund.
333 - // Stays at 0 when nothing was refunded so detailed-receipt's section
334 - // guard `{{#totals.net_total}}…{{/totals.net_total}}` collapses.
335 - $net_total = $refund_total > 0 ? max( 0.0, $total - $refund_total ) : 0.0;
336 -
337 - $totals = array(
338 - 'subtotal' => $display_incl ? $subtotal_incl : $subtotal_excl,
339 - 'subtotal_incl' => $subtotal_incl,
340 - 'subtotal_excl' => $subtotal_excl,
341 - 'discount_total' => $display_incl ? $discount_total_incl : $discount_total_excl,
342 - 'discount_total_incl' => $discount_total_incl,
343 - 'discount_total_excl' => $discount_total_excl,
344 - 'sale_savings_total' => $sale_savings_totals[ $display_basis ],
345 - 'sale_savings_total_incl' => $sale_savings_totals['incl'],
346 - 'sale_savings_total_excl' => $sale_savings_totals['excl'],
347 - 'total_saved' => $total_saved[ $display_basis ],
348 - 'total_saved_incl' => $total_saved['incl'],
349 - 'total_saved_excl' => $total_saved['excl'],
350 - 'total_saved_complete' => $savings_complete[ $display_basis ],
351 - 'tax_total' => $tax_total,
352 - 'total' => $display_incl ? $total : $total_excl,
353 - 'total_incl' => $total,
354 - 'total_excl' => $total_excl,
355 - 'paid_total' => $total,
356 - 'change_total' => (float) $order->get_meta( '_pos_cash_change' ),
357 - 'refund_total' => $refund_total,
358 - 'net_total' => $net_total,
359 - 'total_qty' => $total_qty,
360 - 'line_count' => $line_count,
277 + $totals = Receipt_Sections::totals(
278 + $lines,
279 + array(
280 + 'discount_total' => array(
281 + 'incl' => $discount_total_incl,
282 + 'excl' => $discount_total_excl,
283 + ),
284 + 'tax_total' => $tax_total,
285 + 'total' => $total,
286 + 'paid_total' => $total,
287 + 'change_total' => (float) $order->get_meta( '_pos_cash_change' ),
288 + 'refund_total' => $refund_total,
289 + ),
290 + $display_incl
361 291 );
362 292
363 293 $payments = array(
364 - array(
365 - 'method_id' => $order->get_payment_method(),
366 - 'method_title' => $order->get_payment_method_title(),
367 - 'amount' => $total,
368 - 'transaction_id' => (string) $order->get_transaction_id(),
369 - 'tendered' => (float) $order->get_meta( '_pos_cash_amount_tendered' ),
370 - 'change' => (float) $order->get_meta( '_pos_cash_change' ),
294 + Receipt_Sections::payment(
295 + $order->get_payment_method(),
296 + $order->get_payment_method_title(),
297 + $total,
298 + (string) $order->get_transaction_id(),
299 + (float) $order->get_meta( '_pos_cash_amount_tendered' ),
300 + (float) $order->get_meta( '_pos_cash_change' )
371 301 ),
372 302 );
373 303
374 304 $tax_summary = $this->get_tax_summary( $order );
@@ -389,9 +319,9 @@
389 319 'extra_fields' => array(),
390 320 )
391 321 );
392 322
393 - return Receipt_Payload_Assembler::assemble(
323 + $data = Receipt_Payload_Assembler::assemble(
394 324 array(
395 325 'order' => $order_data,
396 326 'store' => $store,
397 327 'cashier' => $cashier,
@@ -408,8 +338,31 @@
408 338 'fiscal' => $fiscal,
409 339 'presentation_hints' => $presentation_hints,
410 340 )
411 341 );
342 +
343 + /**
344 + * Filters the canonical receipt data before it is rendered or snapshotted.
345 + *
346 + * Runs for every receipt this builder produces: live receipts, fiscal
347 + * snapshots captured at payment time, PDF downloads and legacy PHP
348 + * templates. Extensions can add their own keys to any section (for
349 + * example a flag on a `discounts[]` row) or adjust labels. Keys defined
350 + * by Receipt_Data_Schema should keep their documented types.
351 + *
352 + * Sample previews for the template editor and gallery also run through this filter,
353 + * with mode `preview` and an unsaved order whose id is 0; a plugin that needs a
354 + * persisted order should return `$data` unchanged when `$order->get_id()` is 0.
355 + *
356 + * @param array $data Receipt data (see Receipt_Data_Schema).
357 + * @param WC_Abstract_Order $order Order the receipt is for.
358 + * @param string $mode Receipt mode: 'live', 'fiscal' or 'preview', passed unchanged.
359 + *
360 + * @since 1.10.8
361 + *
362 + * @hook woocommerce_pos_receipt_data
363 + */
364 + return (array) apply_filters( 'woocommerce_pos_receipt_data', $data, $order, $mode );
412 365 }
413 366
414 367
415 368 /**
@@ -481,9 +434,8 @@
481 434 * Derive recorded prices and savings without changing WooCommerce discounts.
482 435 *
483 436 * @param \WC_Order_Item_Product $item Order item.
484 437 * @param WC_Abstract_Order $order Receipt order.
485 - * @param bool $display_incl Whether generic values include tax.
486 438 * @param float $qty Item quantity.
487 439 * @param float $unit_subtotal_incl Stored unit subtotal including tax.
488 440 * @param float $unit_subtotal_excl Stored unit subtotal excluding tax.
489 441 * @param float $subtotal_incl Stored line subtotal including tax.
@@ -490,14 +442,13 @@
490 442 * @param float $subtotal_excl Stored line subtotal excluding tax.
491 443 * @param float $total_incl Stored line total including tax.
492 444 * @param float $total_excl Stored line total excluding tax.
493 445 *
494 - * @return array<string,float|bool|null>
446 + * @return array<string,array|bool>
495 447 */
496 448 private function get_line_price_convenience_fields(
497 449 \WC_Order_Item_Product $item,
498 450 WC_Abstract_Order $order,
499 - bool $display_incl,
500 451 float $qty,
501 452 float $unit_subtotal_incl,
502 453 float $unit_subtotal_excl,
503 454 float $subtotal_incl,
@@ -589,58 +540,58 @@
589 540 && $stored_discount >= $recorded_savings;
590 541 break;
591 542 }
592 543
593 - $select = static function ( array $values ) use ( $display_incl ): ?float {
594 - return $display_incl ? $values['incl'] : $values['excl'];
595 - };
596 -
597 544 return array(
598 - 'regular_price' => $select( $regular ),
599 - 'regular_price_incl' => $regular['incl'],
600 - 'regular_price_excl' => $regular['excl'],
601 - 'selling_price' => $select( $selling ),
602 - 'selling_price_incl' => $selling['incl'],
603 - 'selling_price_excl' => $selling['excl'],
604 - 'unit_savings' => $select( $unit_savings ),
605 - 'unit_savings_incl' => $unit_savings['incl'],
606 - 'unit_savings_excl' => $unit_savings['excl'],
607 - 'line_regular_total' => $select( $line_regular ),
608 - 'line_regular_total_incl' => $line_regular['incl'],
609 - 'line_regular_total_excl' => $line_regular['excl'],
610 - 'line_selling_total' => $select( $line_selling ),
611 - 'line_selling_total_incl' => $line_selling['incl'],
612 - 'line_selling_total_excl' => $line_selling['excl'],
613 - 'line_savings' => $select( $line_savings ),
614 - 'line_savings_incl' => $line_savings['incl'],
615 - 'line_savings_excl' => $line_savings['excl'],
616 - 'savings_in_discounts' => $savings_in_discounts,
545 + 'regular_price' => $regular,
546 + 'selling_price' => $selling,
547 + 'unit_savings' => $unit_savings,
548 + 'line_regular_total' => $line_regular,
549 + 'line_selling_total' => $line_selling,
550 + 'line_savings' => $line_savings,
551 + 'savings_in_discounts' => $savings_in_discounts,
617 552 );
618 553 }
619 554
620 555 /**
621 - * Resolve an optional human-facing coupon label for a receipt discount row.
556 + * Load the WooCommerce coupon behind an order coupon line, if it still exists.
622 557 *
623 - * Coupons are identified by code; the code is already exposed as
624 - * `discounts[].code`. Prefer a distinct, user-authored description, but
625 - * fall back to the code so templates that render `label` always have text.
558 + * Order coupon lines only store the code; the coupon post may have been
559 + * deleted since the order was placed, in which case templates fall back to
560 + * the code alone.
626 561 *
627 562 * @param \WC_Order_Item_Coupon $coupon_item Coupon order item.
628 - * @return string
563 + * @return \WC_Coupon|null
629 564 */
630 - private function get_coupon_label( \WC_Order_Item_Coupon $coupon_item ): string {
565 + private function get_order_coupon( \WC_Order_Item_Coupon $coupon_item ): ?\WC_Coupon {
631 566 $code = (string) $coupon_item->get_code();
632 567 if ( '' === $code ) {
633 - return '';
568 + return null;
634 569 }
635 570
636 571 try {
637 572 $coupon = new \WC_Coupon( $code );
638 573 } catch ( \Exception $exception ) {
639 - return $code;
574 + return null;
640 575 }
641 576
642 - if ( ! $coupon->get_id() ) {
577 + return $coupon->get_id() ? $coupon : null;
578 + }
579 +
580 + /**
581 + * Resolve an optional human-facing coupon label for a receipt discount row.
582 + *
583 + * Coupons are identified by code; the code is already exposed as
584 + * `discounts[].code`. Prefer a distinct, user-authored description, but
585 + * fall back to the code so templates that render `label` always have text.
586 + *
587 + * @param \WC_Order_Item_Coupon $coupon_item Coupon order item.
588 + * @param \WC_Coupon|null $coupon Coupon behind the line, when it still exists.
589 + * @return string
590 + */
591 + private function get_coupon_label( \WC_Order_Item_Coupon $coupon_item, ?\WC_Coupon $coupon ): string {
592 + $code = (string) $coupon_item->get_code();
593 + if ( null === $coupon ) {
643 594 return $code;
644 595 }
645 596
646 597 $label = trim( wp_strip_all_tags( (string) $coupon->get_description() ) );
@@ -664,18 +615,16 @@
664 615 $tax_amount = (float) $tax_item->get_tax_total() + (float) $tax_item->get_shipping_tax_total();
665 616 $rate = (float) $tax_item->get_rate_percent();
666 617 $rate_id = (string) $tax_item->get_rate_id();
667 618 $taxable_excl = $taxable_bases[ $rate_id ] ?? null;
668 - $taxable_incl = null !== $taxable_excl ? $taxable_excl + $tax_amount : null;
669 619
670 - $summary[] = array(
671 - 'code' => $rate_id,
672 - 'rate' => $rate > 0 ? $rate : null,
673 - 'label' => $tax_item->get_label( $order ),
674 - 'compound' => method_exists( $tax_item, 'is_compound' ) ? (bool) $tax_item->is_compound() : false,
675 - 'taxable_amount_excl' => $taxable_excl,
676 - 'tax_amount' => $tax_amount,
677 - 'taxable_amount_incl' => $taxable_incl,
620 + $summary[] = Receipt_Sections::tax_summary_entry(
621 + $rate_id,
622 + $rate,
623 + $tax_item->get_label( $order ),
624 + method_exists( $tax_item, 'is_compound' ) ? (bool) $tax_item->is_compound() : false,
625 + $taxable_excl,
626 + $tax_amount
678 627 );
679 628 }
680 629
681 630 return $summary;
@@ -864,22 +813,9 @@
864 813 return $pairs;
865 814 }
866 815
867 816 if ( $product instanceof \WC_Product_Variation ) {
868 - foreach ( $product->get_variation_attributes() as $attribute_key => $attribute_value ) {
869 - if ( '' === (string) $attribute_value ) {
870 - continue;
871 - }
872 -
873 - $taxonomy = preg_replace( '/^attribute_/', '', (string) $attribute_key );
874 - $value = $product->get_attribute( $taxonomy );
875 - $pairs[] = array(
876 - 'key' => wp_strip_all_tags( wc_attribute_label( $taxonomy, $product ) ),
877 - 'value' => wp_strip_all_tags( '' !== $value ? $value : (string) $attribute_value ),
878 - );
879 - }
880 -
881 - return $pairs;
817 + return Receipt_Sections::variation_attribute_pairs( $product );
882 818 }
883 819
884 820 foreach ( $product->get_attributes() as $attribute ) {
885 821 if ( ! $attribute instanceof \WC_Product_Attribute || ! $attribute->get_visible() ) {
@@ -1044,48 +980,6 @@
1044 980 );
1045 981 }
1046 982
1047 983 return $refunds;
1048 - }
1049 -
1050 -
1051 - /**
1052 - * Ensure customer tax IDs include display labels for logicless templates.
1053 - *
1054 - * @param array<int,array<string,mixed>> $tax_ids Customer tax IDs.
1055 - * @param string $locale Receipt locale.
1056 - * @return array<int,array<string,mixed>>
1057 - */
1058 - private static function with_customer_tax_id_labels( array $tax_ids, string $locale = '' ): array {
1059 - return self::with_tax_id_labels( $tax_ids, 'customer', $locale );
1060 - }
1061 -
1062 - /**
1063 - * Resolve a display label for each tax-ID entry. Precedence: explicit
1064 - * `label` → `<scope>_tax_id_label_<type>` i18n key → scope-specific
1065 - * `_other` fallback.
1066 - *
1067 - * @param array<int,array<string,mixed>> $tax_ids Tax IDs.
1068 - * @param string $scope "store" or "customer".
1069 - * @param string $locale Receipt locale.
1070 - * @return array<int,array<string,mixed>>
1071 - */
1072 - private static function with_tax_id_labels( array $tax_ids, string $scope, string $locale = '' ): array {
1073 - $labels = Receipt_I18n_Labels::get_labels( $locale );
1074 - $prefix = $scope . '_tax_id_label_';
1075 -
1076 - return array_map(
1077 - static function ( array $tax_id ) use ( $labels, $prefix ): array {
1078 - if ( ! empty( $tax_id['label'] ) ) {
1079 - return $tax_id;
1080 - }
1081 -
1082 - $type = isset( $tax_id['type'] ) ? (string) $tax_id['type'] : 'other';
1083 - $key = $prefix . $type;
1084 - $tax_id['label'] = $labels[ $key ] ?? $labels[ $prefix . 'other' ];
1085 -
1086 - return $tax_id;
1087 - },
1088 - $tax_ids
1089 - );
1090 984 }
1091 985 }