Untitled

mail@pastecode.io avatar
unknown
plain_text
23 days ago
38 kB
3
Indexable
Never
	public function salesking_register_order_calculate_earnings($order_id, $posted_data = array(), $order = array()){

		// check order post type / compatibility with plugins
		$type = get_post_type($order_id);
		if ($type !== 'shop_order'){
			$order = wc_get_order($order_id);
			if (!$order){
				$order_id = intval($order_id)-1;
			}
		}

		// sanity
		// if order already has an earning, then clearly the earnings have been calculated
		$order = wc_get_order($order_id);
		if ($order){

			$earning_id_check = $order->get_meta('salesking_earning_id');
			if (!empty($earning_id_check)){
				$order->update_meta_data('_salesking_calculated_earnings', 'yes');
				$order->save();
			}
		}

		// for marketking multivendor orders, skip, because we calculate for each order
		if (defined('MARKETKINGCORE_DIR')){
			if (marketking()->is_multivendor_order($order_id)){
				$order->update_meta_data('_salesking_calculated_earnings', 'yes');
				$order->save();
			}
		}

		// check it has not already been calculated
		if ($order->get_meta('_salesking_calculated_earnings') !== 'yes'){

			// Determine if this order should be assigned to any agent, by checking all assignment possibilities
			/*
			5 possibilities:
			- customer is assigned to agent and places order
			- a user places an order and uses agent coupon
			- agent uses shop as customer to place order on behalf of customer, customer only pays it
			- cart sharing:
			same as coupons, user gets assigned to agent + order appears as placed by customer
			- customer shops with affiliate cookie
			*/
			if ($order){

				$order->update_meta_data('_salesking_calculated_earnings', 'yes');
				$order->save();

				$assign_customer_to_agent = true; // assign the customer to the agent found, or not


				// STEP 1: we find the assigned agent for this order
				$order_assigned_agent = 0;
				$customer_id = $order->get_customer_id();


				// if all agents can shop for all customers, then customer's assigned agent no longer takes priority
				if (intval(get_option( 'salesking_all_agents_shop_all_customers_setting', 0 )) === 0 || ! apply_filters('salesking_agent_shop_customer_use_commission', true)){
					// CUSTOMER ALREADY ASSIGNED
					$customer_agent = get_user_meta($customer_id,'salesking_assigned_agent', true);
					if (!empty($customer_agent)){
						if ($this->is_agent($customer_agent)){
							$order_assigned_agent = $customer_agent;
						}
					}
					if ($order_assigned_agent === 0){
						$customer_agent = get_user_meta($customer_id,'salesking_agent', true);
						if (!empty($customer_agent)){
							if ($this->is_agent($customer_agent)){
								$order_assigned_agent = $customer_agent;
							}
						}
					}

					if (defined('B2BKING_DIR') || defined('B2BKINGCORE_DIR')){
						// Search customer group
						if ($order_assigned_agent === 0){
							$b2b_user = get_user_meta($customer_id,'b2bking_b2buser', true);
							if ($b2b_user === 'yes'){
								$b2b_group = get_user_meta($customer_id,'b2bking_customergroup', true);
								if (!empty($b2b_group)){
									$group_agent = get_post_meta($b2b_group,'salesking_assigned_agent', true);
									if (!empty($group_agent)){
										if ($this->is_agent($group_agent)){
											$order_assigned_agent = $group_agent;
										}
									}
								}
							}
						}
					}
				}


				// if the customer is an agent themselves
				if ($this->is_agent($customer_id)){

					// if agents earn commission on their own orders
					if (intval(get_option( 'salesking_agents_own_orders_commission_setting', 0 )) === 1){
						// assigned agent is self
						$order_assigned_agent = $customer_id;
					}
				}


				// COUPONS // if no agent yet, keep searching.
				if (apply_filters('salesking_commissions_use_coupons', true)){
					if ($order_assigned_agent === 0){
						foreach( $order->get_coupon_codes() as $coupon_code) {
					        $coupon = new WC_Coupon($coupon_code);
					        $coupon_id = $coupon->get_id();
					        // check agent
					        $coupon_agent = get_post_meta($coupon_id,'salesking_agent', true);

					        if (!empty($coupon_agent)){

					        	if ($this->is_agent($coupon_agent)){
					        		$order_assigned_agent = $coupon_agent;
					        		$assign_customer_to_agent = apply_filters('salesking_assign_customer_to_agent_coupon', $assign_customer_to_agent, $coupon_agent, $order);
					        	}
					        }
					    }
					}
				}

			    // AGENT USED SHOP AS CUSTOMER // if no agent yet, keep searching.
			    if (apply_filters('salesking_commissions_use_shop_as_customer', true)){
				    if ($order_assigned_agent === 0){
				    	if ($this->check_user_is_agent_with_access()){
							$agent_id = $this->get_current_agent_id();
							$order_assigned_agent = $agent_id;
							$assign_customer_to_agent = apply_filters('salesking_assign_customer_to_agent_shopping_as_customer', $assign_customer_to_agent, $order);

						}
				    }
				}

			    // SEARCH CART SHARING COOKIE OR AFFILIATE COOKIE
			    if (apply_filters('salesking_commissions_use_cookies', true)){
				    if ($order_assigned_agent === 0){
				    	if (isset($_COOKIE['salesking_affiliate_cookie'])){
				    		$affiliate_cookie = sanitize_text_field($_COOKIE['salesking_affiliate_cookie']);
				    		// search agentid
			    			$agent = get_users(array(
							    'meta_key'     => 'salesking_agentid',
							    'meta_value'   => $affiliate_cookie,
							    'meta_compare' => '=',
							    'fields' => 'ids',
							));
							if (count($agent) === 1){
								$order_assigned_agent = $agent[0];
							}
				    	}
				    }	
				}

			    if ($order_assigned_agent === 0){
				    if (intval(get_option( 'salesking_all_agents_shop_all_customers_setting', 0 ))=== 1 && apply_filters('salesking_agent_shop_customer_use_commission', true)){
				    	// CUSTOMER ALREADY ASSIGNED
				    	$customer_id = $order->get_customer_id();
				    	$customer_agent = get_user_meta($customer_id,'salesking_assigned_agent', true);
				    	if (!empty($customer_agent)){
				    		if ($this->is_agent($customer_agent)){
				    			$order_assigned_agent = $customer_agent;
				    		}
				    	}
				    	if ($order_assigned_agent === 0){
				    		$customer_agent = get_user_meta($customer_id,'salesking_agent', true);
				    		if (!empty($customer_agent)){
				    			if ($this->is_agent($customer_agent)){
				    				$order_assigned_agent = $customer_agent;
				    			}
				    		}
				    	}

				    	if (defined('B2BKING_DIR') || defined('B2BKINGCORE_DIR')){
				    		// Search customer group
				    		if ($order_assigned_agent === 0){
				    			$b2b_user = get_user_meta($customer_id,'b2bking_b2buser', true);
				    			if ($b2b_user === 'yes'){
				    				$b2b_group = get_user_meta($customer_id,'b2bking_customergroup', true);
				    				if (!empty($b2b_group)){
				    					$group_agent = get_post_meta($b2b_group,'salesking_assigned_agent', true);
				    					if (!empty($group_agent)){
				    						if ($this->is_agent($group_agent)){
				    							$order_assigned_agent = $group_agent;
				    						}
				    					}
				    				}
				    			}
				    		}
				    	}
				    }	
				}

				if (isset($_POST['customer_user'])){
					if (intval($order_assigned_agent) === 0){
						$order_assigned_agent = $_POST['customer_user'];

						// check if this user has an agent, and if so, set the user's agent
						$customer_agent = get_user_meta($order_assigned_agent,'salesking_assigned_agent', true);
						if (!empty($customer_agent)){
							if (intval($customer_agent) !== 0){
								$order_assigned_agent = $customer_agent;
							}
						}
					}
				}

				$order_assigned_agent = apply_filters('salesking_agent_assigned_order', $order_assigned_agent, $order);

				// check, must be agent
				if (!$this->is_agent($order_assigned_agent)){
					$order_assigned_agent = 0;
				}


			    // cancel function if this order does not have an agent
			    if ($order_assigned_agent !== 0 or intval(get_option( 'salesking_individual_agents_auto_commissions_setting', 0 )) === 1){

			    	// here let's have an option via FILTER to always set the assigned agent to 0 (so that individual agent rules are not affected by for example an agent giving a coupon or affilaite link)
			    	if (apply_filters('salesking_assigned_agent_order_never', false)){
			    		$order_assigned_agent = 0;
			    	}

			    	$agent_id = $order_assigned_agent;

				    // STEP 2: We check and set who placed the order
				    $placed_by = 0;
				    if ($this->check_user_is_agent_with_access()){
				    	$agent_id = $this->get_current_agent_id();
				    	if ($agent_id !== $order->get_customer_id()){
				    		$placed_by = 'placed_by_agent';
				    		$order->update_meta_data('salesking_order_placed_by', $agent_id);

				    	} else {
				    		$placed_by = 'placed_by_customer';
				    	}
				    } else {
				    	$placed_by = 'placed_by_customer';
				    }
				    $order->update_meta_data('salesking_order_placed_type', $placed_by);
				    $order->save();


				    // Step 3: Assign customer to agent if not already assigned + assign order to agent
				    // (only if we're not applying commission by product for individual agents)
				    if ($order_assigned_agent !== 0){

				    	if ($assign_customer_to_agent){
				    		if (apply_filters('salesking_assign_customer_to_agent', true)){
				    			update_user_meta($customer_id, 'salesking_assigned_agent', $order_assigned_agent);
				    		}
				    	}

				    	$order->update_meta_data('salesking_assigned_agent', $order_assigned_agent);


				    	$agent_obj = new WP_User($order_assigned_agent);
				    	$customer_obj = new WP_User($customer_id);

				    	$agent_name = $agent_obj->first_name.' '.$agent_obj->last_name;
				    	$customer_name = $customer_obj->first_name.' '.$customer_obj->last_name;

				    	if ($agent_name !== $customer_name){

				    		$order->update_meta_data('salesking_assigned_agent_name', $agent_name);

				    		$agent_id_code = get_user_meta($order_assigned_agent, 'salesking_agentid', true);
				    		
				    		$order->update_meta_data('salesking_assigned_agent_code', $agent_id_code);


				    		do_action('salesking_assign_agent_code_order', $order_id, $order_assigned_agent);


				    	} else {
				    		$agent_name_id = get_user_meta($customer_id,'salesking_assigned_agent', true);
				    		$agent_obj = new WP_User($agent_name_id);
				    		$agent_name = $agent_obj->first_name.' '.$agent_obj->last_name;
				    		$order->update_meta_data('salesking_assigned_agent_name', $agent_name);


				    		$agent_id_code = get_user_meta($agent_name_id, 'salesking_agentid', true);
				    		$order->update_meta_data('salesking_assigned_agent_code', $agent_id_code);


				    		do_action('salesking_assign_agent_code_order', $order_id, $agent_name_id);
				    	}

				    	$order->save();

				    }

				    // sanity check, user cannot be his own agent
				    if (intval(get_option( 'salesking_agents_own_orders_commission_setting', 0 )) === 0){
				    	if (intval($order_assigned_agent) === get_current_user_id()){
					    	$order_assigned_agent = 0;
							$agent_id = 0;
					    }
						if (intval($order_assigned_agent) === $customer_id or intval($agent_id) === $customer_id){
					    	$order_assigned_agent = 0;
							$agent_id = 0;
					    }
				    }
				    
				    if (empty($order_assigned_agent)){
				    	$order_assigned_agent = 0;
						$agent_id = 0;
				    }

				    if (intval($customer_id) === 0){
						if (isset($_POST['customer_user'])){
							$customer_id = sanitize_text_field($_POST['customer_user']);
						}
					}
					
				   
				    
				    // Step 4: Now that we have the agent of the order, we must calculate earnings
				    // We begin by getting all rules applicable to this agent
				    $agent_group_id = get_user_meta($agent_id,'salesking_group', true);

				    if ($order_assigned_agent !== 0){
				    	$rules = $this->get_all_agent_rules($agent_id);
				    } else {
				    	$rules = $this->get_all_agent_rules($agent_id, 'yes'); // all rules for all agents
				    }


				    $rules = $this->filter_which_rules_apply_to_customer($rules, $customer_id);
				    $rules = $this->filter_which_rules_apply_to_order($rules, $order_id, $customer_id, $agent_id);



				    // Step 5: Calculate earnings

				    // 5.1 check if there is a different commission for above price
				    // apply that commission indifferent of commission rules
				    $agent_id = $order_assigned_agent;
				    $above_original_price = 0;
				    $above_original_price_commission = 0;
				    $below_original_price = 0;

				    // check if discounts should be taken from agent's commission
			        if (intval(get_option( 'salesking_take_out_discount_agent_commission_setting', 1 )) === 1 && $order_assigned_agent !== 0){
			        	// if order is placed by agent on behalf of customer, calculate commission on edited increased price
			    		if ($this->check_user_is_agent_with_access() || $this->agent_can_edit_price_for_themselves()){
			        		$agent_id = $this->get_current_agent_id();
			        		if ($agent_id !== $order->get_customer_id() || $this->agent_can_edit_price_for_themselves()){
			        		
			        			// Iterating through each "line" items in the order
			        			foreach ($order->get_items() as $item_id => $item ) {
			        				$original_price = $item->get_meta('_salesking_original_price');
			        				$set_price = $item->get_meta('_salesking_set_price');
			        				$quantity = $item->get_quantity();
			        				if (!empty($original_price) && !empty($set_price)){
			        					$original_price = floatval($original_price);
			        					$set_price = floatval($set_price);
			        					if ($set_price < $original_price){
			        						// price difference
			        						$below_original_price += ($original_price-$set_price)*$quantity;
			        					}
			        				}
			        			}
			        		}
			        	}
			        }

				    if (intval(get_option( 'salesking_different_commission_price_increase_setting', 1 )) === 1 && $order_assigned_agent !== 0){
				    	// if order is placed by agent on behalf of customer, calculate commission on edited increased price
						if ($this->check_user_is_agent_with_access() || $this->agent_can_edit_price_for_themselves()){
				    		$agent_id = $this->get_current_agent_id();
				    		if ($agent_id !== $order->get_customer_id() || $this->agent_can_edit_price_for_themselves()){
				    		
				    			// Iterating through each "line" items in the order
				    			foreach ($order->get_items() as $item_id => $item ) {
				    				$original_price = $item->get_meta('_salesking_original_price');
				    				$set_price = $item->get_meta('_salesking_set_price');
				    				$quantity = $item->get_quantity();
				    				if (!empty($original_price) && !empty($set_price)){
				    					$original_price = floatval($original_price);
				    					$set_price = floatval($set_price);
				    					if ($set_price > $original_price){
				    						// price difference
				    						$above_original_price += ($set_price-$original_price)*$quantity;
				    						$above_original_price_commission += ($set_price-$original_price)*$quantity*get_option('salesking_different_commission_price_increase_number_setting', 100 )/100;
				    					}
				    				}
				    			}
				    		}
				    	}
				    }

				    // 5.2 now apply rules for the rest (item price < increased price by agent)
				    $commission_rules_total = 0;
				    $commission_log = array();
				    $rules_apply_log = array();
				    $commission_by_agent = array(); // here we hold agent ID and commission in the case of individual agent rules


					foreach ($order->get_items() as $item_id => $item ) {

						// Get the WC_Order_Item_Product object properties in an array
					    $item_data = $item->get_data();

					    if ($item['quantity'] > 0) {

					        // get the WC_Product object
					        $product_id = $item['product_id'];

					        if (isset($item['variation_id'])){
					        	if (intval($item['variation_id']) !== 0){
					        		$product_id = $item['variation_id'];
					        	}
					        }

							$rules_that_apply_to_product = $this->filter_which_rules_apply_to_product($rules, $order_id, $customer_id, $product_id);

							require_once ( SALESKING_DIR . 'includes/class-salesking-helper.php' );
							$helper = new Salesking_Helper();
							$rules_that_apply_to_product = $helper->get_rules_apply_priority($rules_that_apply_to_product);
							

							$rules_apply_log[]=array('Product ID: '.$product_id, 'All rules: '.serialize($rules), 'Rules that apply: '.serialize($rules_that_apply_to_product));

							if (!empty($rules_that_apply_to_product)){
								// get the calculation basis for the product (amount < increased price if setting is enabled)
								$original_price = $item->get_meta('_salesking_original_price');
								$set_price = $item->get_meta('_salesking_set_price');

								if (floatval($set_price) === floatval(0) && $set_price !== ''){
									continue; // no commission on this item, if item price is 0
								}

								$quantity = $item->get_quantity();
								if (!empty($original_price)){
									if (intval(get_option( 'salesking_commissions_calculated_including_tax_setting', 1 )) === 1){
										//$calculation_basis = floatval($original_price) * $quantity;
										// calculate price without tax based on original price
										$price_without_tax_edited_price = round($item->get_total(), 2) + round($item->get_total_tax(), 2);
										$ratio = $price_without_tax_edited_price / $set_price;
										$price_without_tax_original_price = $ratio * floatval($original_price) * $quantity;

										$calculation_basis = $price_without_tax_original_price;
									} else {
										// calculate price without tax based on original price
										$price_without_tax_edited_price = round($item->get_total(), 2);
										// change in v 1.5.03 it used to be $set_price only
										$ratio = $price_without_tax_edited_price / ($set_price*$quantity);
										$price_without_tax_original_price = $ratio * floatval($original_price) * $quantity;

										$calculation_basis = $price_without_tax_original_price;
									}

								} else {
									$item_total = round($item->get_total(), 2); // Get the item line total discounted
									$item_total_tax = round($item->get_total_tax(), 2); // Get the item line total  tax discounted

									if (intval(get_option( 'salesking_commissions_calculated_including_tax_setting', 1 )) === 1){
										$calculation_basis = $item_total + $item_total_tax;
									} else {
										$calculation_basis = $item_total;
									}
								}

								if (intval(get_option( 'salesking_commissions_calculated_based_profit_setting', 0 )) === 1){
									// overwrite completely, exclusively based on profit, tax irrelevant
									if ( class_exists( 'Alg_WC_Cost_of_Goods' ) ) {
										if (empty($original_price) or floatval($set_price) < floatval($original_price)){
											$price_without_tax = round($item->get_total(), 2);
										} else {
											$price_without_tax_edited_price = round($item->get_total(), 2);
											$ratio = $price_without_tax_edited_price / ($set_price*$quantity);
											$price_without_tax = $ratio * floatval($original_price) * $quantity;
										}

										$cost_id = $product_id;
										if (isset($item['variation_id'])){
											if (intval($item['variation_id']) !== 0){
												$cost_id = $item['variation_id'];
											}
										}

										$product_cost_temp = alg_wc_cog()->core->products->get_product_cost( $cost_id ) * $quantity;

										$product_cost = apply_filters('salesking_product_cost', $product_cost_temp, $cost_id, alg_wc_cog()->core->products->get_product_cost( $cost_id ), $quantity, $order);
		
										$profit = $price_without_tax - $product_cost;
										$calculation_basis = $profit;
									}
								}

								$fixed_commission_amount = $this->get_commission_amount($rules_that_apply_to_product, $calculation_basis, 'fixed', $quantity);
								$percentage_commission_amount = $this->get_commission_amount($rules_that_apply_to_product, $calculation_basis, 'percentage', $quantity);

								if (intval(get_option( 'salesking_individual_agents_auto_commissions_setting', 0 )) === 1){
									// who is the agent of the applied rule (for individual agent commission rules)
									$fixed_rules_agent = $this->get_commission_amount_rules_agent($rules_that_apply_to_product, $calculation_basis, 'fixed', $quantity);
									$percentage_rules_agent = $this->get_commission_amount_rules_agent($rules_that_apply_to_product, $calculation_basis, 'percentage', $quantity);

									if (!isset($commission_by_agent[$fixed_rules_agent])){
										$commission_by_agent[$fixed_rules_agent] = $fixed_commission_amount;
									} else {
										$commission_by_agent[$fixed_rules_agent] += $fixed_commission_amount;
									}

									if (!isset($commission_by_agent[$percentage_rules_agent])){
										$commission_by_agent[$percentage_rules_agent] = $percentage_commission_amount;
									} else {
										$commission_by_agent[$percentage_rules_agent] += $percentage_commission_amount;
									}
								}
				
						
								$item_commission = $fixed_commission_amount + $percentage_commission_amount;
								$commission_rules_total += $item_commission;

								// log into database for reference / debugging purposes
								$item_log = array('Product ID: '.$product_id, 'Fixed commission: '.$fixed_commission_amount, 'Percentage commission: '.$percentage_commission_amount, 'Total commission: '.$item_commission, 'Rules that apply: '.serialize($rules_that_apply_to_product), 'Calculation basis value: '.$calculation_basis);
								$commission_log[] = $item_log;

							}
						}
					}

					if ($order_assigned_agent !== 0){

						// 5.3 apply rules that apply once per order
						$rules_that_apply_once = $this->filter_which_rules_apply_once($rules, $order_id, $customer_id, $product_id);


						require_once ( SALESKING_DIR . 'includes/class-salesking-helper.php' );
						$helper = new Salesking_Helper();
						$rules_that_apply_once = $helper->get_rules_apply_priority($rules_that_apply_once);


						if (!empty($rules_that_apply_once)){
							// get order total calculation basis
							if (intval(get_option( 'salesking_commissions_calculated_including_tax_setting', 1 )) === 1){
								$calculation_basis = $order->get_total();
							} else {
								$calculation_basis = $order->get_total() - $order->get_total_tax();
							}

							// check if any items have increased price, and if they do, set the calculation basis to original price

							$original_total = 0;
							$items_increased_price = 'no';

							foreach ($order->get_items() as $item_id => $item ) {

								// Get the WC_Order_Item_Product object properties in an array
							    $item_data = $item->get_data();
							    if ($item['quantity'] > 0) {
									// get the calculation basis for the product (amount < increased price if setting is enabled)
									$original_price = $item->get_meta('_salesking_original_price');
									$quantity = $item->get_quantity();
									$set_price = $item->get_meta('_salesking_set_price');

									if (!empty($original_price) && $original_price !== $set_price && floatval($set_price) > floatval($original_price)){
										$items_increased_price = 'yes';

										if (intval(get_option( 'salesking_commissions_calculated_including_tax_setting', 1 )) === 1){
											$original_total += floatval($original_price) * $quantity;
										} else {
											// calculate price without tax based on original price
											$price_without_tax_edited_price = round($item->get_total(), 2);
											$ratio = $price_without_tax_edited_price / $set_price;
											$price_without_tax_original_price = $ratio * floatval($original_price) * $quantity;

											$original_total += $price_without_tax_original_price;
										}
									}
								}
							}

							if ($items_increased_price === 'yes'){
								// reset calculation basis depending on original total
								$calculation_basis = $original_total;
							}

							if (intval(get_option( 'salesking_commissions_calculated_based_profit_setting', 0 )) === 1){
								// overwrite completely, exclusively based on profit, tax irrelevant
								if ( class_exists( 'Alg_WC_Cost_of_Goods' ) ) {
									// ignore shipping and tax

									$total_cost = 0;
									$total_price = 0;
									// first calculate all products cost
									foreach ($order->get_items() as $item_id => $item ) {

									    if ($item['quantity'] > 0) {
									    	$product_id = $item['product_id'];

									    	$cost_id = $product_id;
									    	if (isset($item['variation_id'])){
									    		if (intval($item['variation_id']) !== 0){
									    			$cost_id = $item['variation_id'];
									    		}
									    	}
									    	
									    	$product_cost_temp = alg_wc_cog()->core->products->get_product_cost( $cost_id ) * $item['quantity'];
									    	$cost = apply_filters('salesking_product_cost', $product_cost_temp, $cost_id, alg_wc_cog()->core->products->get_product_cost( $cost_id ), $item['quantity'], $order);

									    	$total_cost += $cost;


									    	$original_price = $item->get_meta('_salesking_original_price');
									    	if (!empty($original_price) && $original_price !== $set_price && floatval($set_price) > floatval($original_price)){
									    		$total_price += floatval($original_price) * $quantity;
									    	} else {
									    		$total_price += round($item->get_total(), 2) * $quantity;
									    	}
									    }
									}

									$total_profit = $total_price - $total_cost;

									$calculation_basis = $total_profit;
								}
							}

							$calculation_basis = apply_filters('salesking_custom_calculation_basis', $calculation_basis, $order);

							$fixed_commission_amount = $this->get_commission_amount_once($rules_that_apply_once, $calculation_basis, 'fixed');
							$percentage_commission_amount = $this->get_commission_amount_once($rules_that_apply_once, $calculation_basis, 'percentage');

							$item_commission = $fixed_commission_amount + $percentage_commission_amount;
							$commission_rules_total += $item_commission;

						}
					}

					$commission_rules_total = round($commission_rules_total, 2);
					$above_original_price = round($above_original_price, 2);
					$below_original_price = round($below_original_price, 2);
					$above_original_price_commission = round($above_original_price_commission, 2);


					// Step 6: Finally create and set earnings
					$all_earnings_total = round( ($above_original_price_commission + $commission_rules_total - $below_original_price), 2); //calculate all here


					// reference / log
					$order->update_meta_data('commission_log_before', $commission_log);
					$order->update_meta_data('rules_apply_log_before', $rules_apply_log);



					if ($all_earnings_total > apply_filters('salesking_earnings_total_threshold', 0 )){

						// Create transaction
						$earning = array(
						    'post_title' => sanitize_text_field(esc_html__('Earning','salesking')),
						    'post_status' => 'publish',
						    'post_type' => 'salesking_earning',
						    'post_author' => 1,
						);
						$earning_post_id = wp_insert_post($earning);

						// reference / log
						update_post_meta($earning_post_id, 'commission_log', $commission_log);
						update_post_meta($earning_post_id, 'rules_apply_log', $rules_apply_log);

						// set meta
						update_post_meta($earning_post_id, 'time', time());
						update_post_meta($earning_post_id, 'order_id', $order_id);
						update_post_meta($earning_post_id, 'customer_id', $order->get_customer_id());
						update_post_meta($earning_post_id, 'order_status', $order->get_status());

						if ($agent_id !== 0){
							update_post_meta($earning_post_id, 'agent_id', $agent_id);
						} else {
							// get a first agent
							if ($order_assigned_agent === 0){
								unset($commission_by_agent[0]);
								
								$first_agent = array_key_first($commission_by_agent);
								update_option('earning_key_first', $first_agent);
								update_post_meta($earning_post_id,'agent_id', array_key_first($commission_by_agent)); // first agent is the one with the commissions
								update_post_meta($earning_post_id,'individual_agents_earnings', 'yes'); // first agent is the one with the commissions
							}
						}

						// create transaction as pending if the agent did collect extra over original price
						if ($above_original_price > 0){
							update_post_meta($earning_post_id, 'above_original_price', $above_original_price);
							update_post_meta($earning_post_id, 'above_original_price_commission', $above_original_price_commission);
						}

						if ($below_original_price > 0){
							update_post_meta($earning_post_id, 'below_original_price', $below_original_price);
						}

						if ($commission_rules_total > 0){
							update_post_meta($earning_post_id, 'commission_rules_total', $commission_rules_total);
						}

						$order->update_meta_data('salesking_earning_id', $earning_post_id);

						update_post_meta($earning_post_id, 'salesking_commission_total', $all_earnings_total);

						if ($order_assigned_agent === 0){

							// first agent in commission by agent var
							update_post_meta($earning_post_id, 'salesking_commission_total', $commission_by_agent[array_key_first($commission_by_agent)]);

							unset($commission_by_agent[array_key_first($commission_by_agent)]);

							$agents_of_earning = array();

							foreach ($commission_by_agent as $agent_id => $commission_value){
								update_post_meta($earning_post_id, 'parent_agent_id_'.$agent_id, $agent_id);
								update_post_meta($earning_post_id, 'parent_agent_id_'.$agent_id.'_earnings', $commission_value);
								array_push($agents_of_earning, $agent_id);

							}
						} else {

							// Step 7: We must check if current agent is subagent, -> if any of this should go to parent account
							// get all earnings rules that apply to subagent

							if (apply_filters('salesking_calculation_apply_step_7', true)){
								$rules = $this->filter_which_rules_are_earnings_rules($rules);

								$subagent_id = $agent_id;

								// if user is indeed a subagent (has a parent) // recursive, all parents up the chain
								$parent_agent = get_user_meta($subagent_id,'salesking_parent_agent', true);

								$agents_of_earning = array();

								$all_earnings_total_original = $all_earnings_total;

								$i = 1;
								$max_agents = apply_filters('salesking_max_parent_agents_commission', 1000000);

								$all_earnings_total = apply_filters('salesking_parent_agent_calculation_basis', $all_earnings_total, $order);

								while (!empty($parent_agent) && $i <= $max_agents){

									array_push($agents_of_earning, $parent_agent);

									/*
									CHANGE SALESKING 1.3.0
									Calculation now based on PARENT RULES
									START
									*/
									$parentrules = $this->get_all_agent_rules($parent_agent);
									$parentrules = $this->filter_which_rules_are_earnings_rules($parentrules);
									$parentrules = $this->filter_which_earnings_rules_apply($parentrules, $subagent_id);


									// replaced 	$parent_earnings = $this->get_parent_total_earnings($rules, $all_earnings_total);
									$parent_earnings = $this->get_parent_total_earnings($parentrules, $all_earnings_total);

									/* CHANGE 1.3.0 END */


									if (intval(get_option( 'salesking_substract_subagent_earnings_agent_setting', 0 )) === 1){
										/* example order was 20000, with 10% parent ag com
										Normally it would go to agent 1 = 2000, ag 2 = 200, ag 3 = 20
										here we must adjust so that for 3 agents we end up with agent 1 = 1800, agent 2 = 180, agent 3 = 20
										*/
										// if first agent, remove from original commission
										if ($i === 1){
											$substracted = $all_earnings_total_original - $parent_earnings;
											update_post_meta($earning_post_id, 'salesking_commission_total', $substracted);
										} else {
											// subsequent agents
											$substracted = $all_earnings_total - $parent_earnings;
											update_post_meta($earning_post_id, 'parent_agent_id_'.$subagent_id.'_earnings', $substracted);

										}
									}

									update_post_meta($earning_post_id, 'parent_agent_id_'.$parent_agent, $parent_agent);
									update_post_meta($earning_post_id, 'parent_agent_id_'.$parent_agent.'_earnings', $parent_earnings);

									// if there is any rule based on "single value", then always use all_earnings_total_original, do not cascade values
									if ($this->have_single_value_earnings_rules($parentrules)){
										// do not cascade values
									} else {
										$all_earnings_total = $parent_earnings;
									}


									$subagent_id = $parent_agent;
									$parent_agent = get_user_meta($subagent_id,'salesking_parent_agent', true);
									$i++;

								}
							}

							
						}

						
						update_post_meta($earning_post_id, 'created_in', 'frontend_register_order');

						update_post_meta($earning_post_id, 'agents_of_earning', $agents_of_earning);

						// Step 8: Apply TOTAL GROUP Rules (e.g. change agent group on threshold reached)
						// check if there are any group rules that apply to this agent's group

						$group_rules_applicable = $this->get_group_rules($agent_group_id);
						// foreach rule, check if the condition is met, and then apply it
						foreach ($group_rules_applicable as $group_rule_id){
							$howmuch = get_post_meta($group_rule_id,'salesking_rule_howmuch', true);
							$newgroup = get_post_meta($group_rule_id, 'salesking_rule_who', true);
							$newgroup_id = explode('_', $newgroup)[1];

							$condition = get_post_meta($group_rule_id, 'salesking_rule_applies', true);

							$total_orders_amount = $total_agent_commissions = 0;

							$group_rules_args = apply_filters('salesking_group_rules_args', array( 
							    'post_type' => 'salesking_earning',
							    'numberposts' => -1,
							    'post_status'    => 'any',
							    'fields'    => 'ids',
							    'meta_key'   => 'agent_id',
							    'meta_value' => $agent_id,
							), $agent_id);
							// get total agent commissions
							$earnings = get_posts( $group_rules_args );

							foreach ($earnings as $earning_id){
							    $order_id = get_post_meta($earning_id,'order_id', true);
							    $orderobj = wc_get_order($order_id);
							    if ($orderobj !== false){
								    $earnings_total = get_post_meta($earning_id,'salesking_commission_total', true);
								    if (!empty($earnings_total) && floatval($earnings_total) !== 0){
								        $status = $orderobj->get_status();
								        $order_total = $orderobj->get_total();
								        if (in_array($status,apply_filters('salesking_earning_completed_statuses', array('completed')))){
								        	$total_agent_commissions+=$earnings_total;
								        	$total_orders_amount += $order_total;
								        }
								        if (in_array($status, apply_filters('salesking_group_rules_allowed_statuses', array()))){
								        	$total_agent_commissions+=$earnings_total;
								        	$total_orders_amount += $order_total;
								        }

								    }
								}
							}

							$site_time = time()+(get_option('gmt_offset')*3600);
							$current_day = date_i18n( 'd', $site_time );
							

							// also get all earnings where this agent is parent
							$group_rules_args_parent = apply_filters('salesking_group_rules_args_parent', array( 
							    'post_type' => 'salesking_earning',
							    'numberposts' => -1,
							    'post_status'    => 'any',
							    'date_query' => array(
							            'after' => date('Y-m-d', strtotime('-'.$current_day.' days')) 
							        ),
							    'fields'    => 'ids',
							    'meta_key'   => 'parent_agent_id_'.$agent_id,
							    'meta_value' => $agent_id,
							), $agent_id);

							$earnings = get_posts( $group_rules_args_parent );

							foreach ($earnings as $earning_id){
							    $order_id = get_post_meta($earning_id,'order_id', true);
							    $orderobj = wc_get_order($order_id);
							    if ($orderobj !== false){
								    $status = $orderobj->get_status();
								    $earnings_total = get_post_meta($earning_id,'parent_agent_id_'.$agent_id.'_earnings', true);
								    // check if approved
								    if (in_array($status,apply_filters('salesking_earning_completed_statuses', array('completed')))){
								        $total_agent_commissions+=$earnings_total;
								    }
								    if (in_array($status, apply_filters('salesking_group_rules_allowed_statuses', array()))){
								    	$total_agent_commissions+=$earnings_total;
								    }
								}
							}

							$total_orders_amount = apply_filters('salesking_group_monthly_earnings', $total_orders_amount, $total_agent_commissions, $agent_id);

							
							if ($condition === 'earnings_total'){
								// calculate agent earnings total
								if ($total_agent_commissions >= $howmuch){
									// change group
									update_user_meta($agent_id,'salesking_group', $newgroup_id);
								}
							}

							if ($condition === 'order_value_total'){
								// calculate agent order value total
								if ($total_orders_amount >= $howmuch){
									// change group
									update_user_meta($agent_id,'salesking_group', $newgroup_id);
								}
							}
						}



					}
				}
				

				do_action('salesking_after_calculated_earnings', $order_id, get_current_user_id());

			}
			
		}

		if ($order){
			$order->save();
		}
	}
Leave a Comment