PluginProbe
Tiered Pricing Table for WooCommerce / 8.0.2
Tiered Pricing Table for WooCommerce v8.0.2
8.0.2 7.1.7 7.1.5 7.1.4 7.1.1 6.5.0 6.4.0 6.1.0 trunk 1.0 1.1 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 2.3.1 2.3.2 2.3.3 All 91 releases
tier-pricing-table / src / Addons / ManualOrders / ManualOrdersAddon.php

ManualOrdersAddon.php in Tiered Pricing Table for WooCommerce 8.0.2, at src/Addons/ManualOrders/ManualOrdersAddon.php

214 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php namespace TierPricingTable\Addons\ManualOrders;
2
3 use TierPricingTable\Addons\AbstractAddon;
4 use TierPricingTable\CalculationLogic;
5 use TierPricingTable\PriceManager;
6 use WC_Order;
7 use WC_Order_Item;
8 use WC_Order_Item_Product;
9
10 class ManualOrdersAddon extends AbstractAddon {
11
12 protected $items = array();
13
14 public function getName(): string {
15 return __( 'Tiered pricing for manual orders', 'tier-pricing-table' );
16 }
17
18 public function getDescription(): string {
19 return __( 'Apply tiered pricing to orders created manually in the admin area.', 'tier-pricing-table' );
20 }
21
22 public function getIcon(): string {
23 return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 14H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/></svg>';
24 }
25
26 public function getSlug(): string {
27 return 'manual-orders';
28 }
29
30 public function getItemPrice( WC_Order_Item_Product $item ) {
31 $product = $item->get_product();
32
33 // Product (or its variation) may have been deleted after the order was created.
34 if ( ! $product ) {
35 $quantity = $item->get_quantity();
36
37 return $quantity ? ( (float) $item->get_total() / $quantity ) : (float) $item->get_total();
38 }
39
40 $productPrice = $product->get_price();
41 $tieredPricingRule = PriceManager::getPricingRule( $product->get_id() );
42
43 // Item has no tiered pricing rule. Return regular price (which also can be adjusted by pricing rule, but on the get_price hook)
44 if ( ! $tieredPricingRule->getRules() ) {
45 return $productPrice;
46 }
47
48 $tieredPrice = $tieredPricingRule->getTierPrice( $this->getTotalItemQuantity( $item ), false );
49
50 return false !== $tieredPrice ? $tieredPrice : $productPrice;
51 }
52
53 public function getTotalItemQuantity( WC_Order_Item_Product $baseItem ): int {
54
55 $quantity = $baseItem->get_quantity();
56
57 $orderItems = $baseItem->get_order()->get_items();
58
59 if ( empty( $orderItems ) || count( $orderItems ) < 2 ) {
60 return $quantity;
61 }
62
63 $calculatedItems = [ $baseItem->get_id() ];
64
65 // Consider different variations
66 if ( CalculationLogic::considerProductVariationAsOneProduct() ) {
67 foreach ( $orderItems as $item ) {
68
69 /**
70 * Item type
71 *
72 * @var WC_Order_Item_Product $item
73 */
74
75 // Item quantity is already calculated
76 if ( in_array( $item->get_id(), $calculatedItems ) ) {
77 continue;
78 }
79
80 if ( $item->get_product_id() === $baseItem->get_product_id() ) {
81 $quantity += $item->get_quantity();
82 $calculatedItems[] = $item->get_id();
83 }
84 }
85 }
86
87 $baseItemPricingRule = PriceManager::getPricingRule( $baseItem->get_product_id() );
88
89 if ( 'global-rules' !== $baseItemPricingRule->provider ) {
90 return $quantity;
91 }
92
93 if ( empty( $baseItemPricingRule->providerData['applying_type'] ) || 'cross' !== $baseItemPricingRule->providerData['applying_type'] ) {
94 return $baseItem->get_quantity();
95 }
96
97 foreach ( $orderItems as $item ) {
98
99 // Item quantity is already calculated
100 if ( in_array( $item->get_id(), $calculatedItems ) ) {
101 continue;
102 }
103
104 $pricingRule = PriceManager::getPricingRule( $item->get_product_id() );
105
106 if ( 'global-rules' !== $pricingRule->provider ) {
107 continue;
108 }
109
110 if ( empty( $pricingRule->providerData['rule_id'] ) || $pricingRule->providerData['rule_id'] !== $baseItemPricingRule->providerData['rule_id'] ) {
111 continue;
112 }
113
114 $quantity += $item->get_quantity();
115 }
116
117 return $quantity;
118 }
119
120 public function run() {
121
122 // Store items before calculating
123 add_action( 'woocommerce_before_save_order_items', function ( $orderId, $items ) {
124 $this->items[ $orderId ] = $items;
125 }, 10, 2 );
126
127 add_action( 'woocommerce_before_save_order_item', function ( WC_Order_Item $item ) {
128
129 if ( ! ( $item instanceof WC_Order_Item_Product ) ) {
130 return;
131 }
132
133 if ( ! apply_filters( 'tiered_pricing_table/manual_created_orders/modify_item_price', true, $item ) ) {
134 return;
135 }
136
137 // Need to be calculated with tiered pricing
138 if ( ! empty( $this->items[ $item->get_order_id() ]['calculate_tiered_pricing'] ) ) {
139
140 $GLOBALS['tpt_current_user_id'] = $item->get_order()->get_customer_id();
141
142 $itemPrice = $this->getItemPrice( $item );
143
144 $product = $item->get_product() ? $item->get_product() : false;
145
146 if ( ! $product ) {
147 return;
148 }
149
150 $itemTotal = wc_get_price_excluding_tax( $product, array(
151 'price' => $itemPrice,
152 'qty' => $item->get_quantity(),
153 ) );
154
155 // Nothing to change
156 if ( ( float ) $item->get_total() === $itemTotal ) {
157 return;
158 }
159
160 // translators: %1$s: item name, %2$s: original price, %3$s: new price
161 $note = sprintf( __( 'Tiered pricing recalculations for %1$s: %2$s → %3$s', 'tier-pricing-table' ),
162 $item->get_name(), wc_price( $item->get_total() / $item->get_quantity() ),
163 wc_price( $itemPrice ) );
164
165 $item->set_subtotal( $itemTotal );
166 $item->set_total( $itemTotal );
167
168 $item->calculate_taxes();
169
170 $item->get_order()->add_order_note( $note );
171 }
172
173 }, 10, 2 );
174
175 add_action( 'woocommerce_admin_order_items_after_line_items', function () {
176 ?>
177 <tr style="display: none;">
178 <td>
179 <input type="checkbox" name="calculate_tiered_pricing">
180 </td>
181 </tr>
182 <?php
183 } );
184
185 add_action( 'admin_head', function () {
186 ?>
187 <script>
188 jQuery(document).ready(function ($) {
189 $('#woocommerce-order-items').on('click', '.calculate-tiered-pricing', function () {
190 jQuery('[name=calculate_tiered_pricing]').prop('checked', true);
191
192 jQuery('#woocommerce-order-items button.calculate-action').trigger('click');
193 });
194 });
195
196 jQuery(document.body).on('order-totals-recalculate-complete', function () {
197 jQuery('[name=calculate_tiered_pricing]').prop('checked', false);
198 });
199 </script>
200 <?php
201 } );
202
203 add_action( 'woocommerce_order_item_add_action_buttons', function ( WC_Order $order ) {
204 if ( $order->is_editable() ) {
205 ?>
206 <button type="button" class="button button-primary calculate-tiered-pricing">
207 <?php esc_html_e( 'Re-calculate with tiered pricing', 'tier-pricing-table' ); ?>
208 </button>
209 <?php
210 }
211 } );
212 }
213 }
214