From orders, it appears that you are calculating the sales tax on an order before the application of a coupon. Customers should be charged sales tax based on the subtotal after coupon application. Either there needs to be a setting where you can say whether to charge before or after coupon application, or this needs to be fixed. I believe the problem is in the: administrator\components\com_easystore\src\Traits\Order.php You're pulling 'discount_type' and 'discount_reason' from the coupon table, but you're not applying them to the sales tax calculation.:
public function updateOrders()
{
$response = (object) [
'status' => false,
'message' => '',
];
$canDo = ContentHelper::getActions('com_easystore');
$hasPermission = $canDo->get('core.create');
if (!$hasPermission) {
$this->sendResponse(['message' => Text::_("COM_EASYSTORE_PERMISSION_ERROR_MSG")], 403);
}
$id = $this->getInput('id', 0, 'INT');
$orderStatus = $this->getInput('order_status', 'draft', 'STRING');
if (empty($id)) {
$response->status = false;
$response->message = Text::_("COM_EASYSTORE_FAILED_TO_UPDATE_ORDER");
$this->sendResponse($response);
}
$model = new OrderModel();
$response = new stdClass();
$response->id = null;
$orderInformation = new stdClass();
$orderInformation->id = $id;
$orderInformation->order_status = $orderStatus;
$orderInformation->creation_date = null;
$isActivated = false;
if (!$model->checkCreationDateExists($id) && $orderStatus === 'active') {
$orderInformation->creation_date = Factory::getDate('now');
$isActivated = true;
}
$orderInformation->customer_id = $this->getInput('customer_id', 0, 'INT');
$orderInformation->customer_note = $this->getInput('customer_note', '', 'RAW');
$orderInformation->payment_status = $this->getInput('payment_status', 'unpaid', 'STRING');
$orderInformation->fulfilment = $this->getInput('fulfilment', 'unfulfilled', 'STRING');
$orderInformation->discount_type = $this->getInput('discount_type', 'percent', 'STRING');
$orderInformation->discount_value = $this->formatToNumeric($this->getInput('discount_value'), 'decimal');
$orderInformation->discount_reason = $this->getInput('discount_reason', '', 'STRING');
$orderInformation->shipping = $this->getInput('shipping', '', 'STRING');
$orderInformation->access = $this->formatToNumeric($this->getInput('access'));
$orderInformation->ordering = $this->formatToNumeric($this->getInput('ordering'));
$orderInformation->shipping_address = null;
$orderInformation->billing_address = null;
if (!empty($orderInformation->customer_id)) {
$customerInfo = EasyStoreHelper::getCustomerById($orderInformation->customer_id);
$orderInformation->shipping_address = $customerInfo->shipping_address ?? null;
$orderInformation->billing_address = $customerInfo->billing_address ?? null;
}
$updateStatus = $model->update($orderInformation);
if ($updateStatus) {
$orderProducts = $this->getInput('order_products', '', 'ARRAY');
$orderProducts = array_map(function ($product) {
return \json_decode($product, true);
}, $orderProducts);
$model->storeMultipleOrderedProducts($orderProducts, $id);
if (!is_null($orderInformation->shipping_address)) {
$shippingAddress = json_decode($orderInformation->shipping_address);
$country = $shippingAddress->country;
$state = $shippingAddress->state;
$settingsModel = new SettingsModel();
$tax = $settingsModel->getTaxRate($country, $state);
$taxRate = !empty($tax) ? $tax->rate : 0;
$isTaxOnShipping = !empty($tax) ? $tax->applyOnShipping : false;
$saleTax = 0.0;
$subTotal = 0.0;
$calculatedPrice = [];
foreach ($orderProducts as $product) {
$calculatedPrice[] = ($product['discounted_price'] > 0 ? $product['discounted_price'] * $product['quantity'] : $product['price'] * $product['quantity']);
}
$subTotal = array_sum($calculatedPrice);
$saleTax = ($subTotal * $taxRate) / 100;
$orderInformation->sale_tax = $saleTax;
$model->update($orderInformation);
}
if ($isActivated) {
$model->addOrderActivity($id, 'order_created');
}
$response->status = true;
$response->message = Text::_("COM_EASYSTORE_ORDER_UPDATED");
$response->id = $id;
} else {
$response->status = false;
$response->message = Text::_("COM_EASYSTORE_FAILED_TO_UPDATE_ORDER");
}
$this->sendResponse($response);
}
I've altered mine as follows:
foreach ($orderProducts as $product) {
$calculatedPrice[] = $product['quantity'] * ($product['discounted_price'] > 0 ? $product['discounted_price'] : $product['price']);
}
//foreach ($orderProducts as $product) {
// $calculatedPrice[] = ($product['discounted_price'] > 0 ? $product['discounted_price'] * $product['quantity'] : $product['price'] * $product['quantity']);
//}
$subTotal = array_sum($calculatedPrice);
if ($orderInformation->discount_value) {
switch ($orderInformation->discount_type) {
case 'percent':
$subTotal = $subTotal * (100 - $orderInformation->discount_value)/100;
case 'amount':
$subTotal -= (($subTotal > $orderInformation->discount_value) ? $orderInformation->discount_value : $subTotal);
default:
}
}
$saleTax = ($subTotal * $taxRate) / 100;
$orderInformation->sale_tax = $saleTax;
$model->update($orderInformation);