/** * Update the status of an order. * * @param mixed Either an array of order IDs to update, or an integer for a single order ID. * @param int The new status of the order. * @param boolean Should emails be sent out if the email on status change feature is enabled? * @param boolean Set to true if this status update is in a pingback from a payment module and payment modules should not be notified of the change. * @return boolean True if successful. */ function UpdateOrderStatus($orderIds, $status, $email=true, $preventModuleUpdateCallback=false) { if(!is_array($orderIds)) { $orderIds = array($orderIds); } foreach($orderIds as $orderId) { $order = GetOrder($orderId, false); if (!$order || !$order['orderid']) { return false; } // Start transaction $GLOBALS['ISC_CLASS_DB']->Query("START TRANSACTION"); $existing_status = $order['ordstatus']; // If the order is incomplete, it needs to be completed first if($existing_status == 0) { CompletePendingOrder($order['ordtoken'], $status, $email); } $updatedOrder = array( "ordstatus" => (int)$status, "ordlastmodified" => time(), ); // If the order status is 2 or 10 (completed, shipped) then set the orddateshipped timestamp if (OrderIsComplete($status)) { $updatedOrder['orddateshipped'] = time(); } // Update the status for this order if ($GLOBALS['ISC_CLASS_DB']->UpdateQuery("orders", $updatedOrder, "orderid=" . (int)$orderId)) { // Fetch the name of the status this order was changed to $query = sprintf("SELECT statusdesc FROM [|PREFIX|]order_status WHERE statusid='%d'", $GLOBALS['ISC_CLASS_DB']->Quote($status)); $result2 = $GLOBALS['ISC_CLASS_DB']->Query($query); $statusName = $GLOBALS['ISC_CLASS_DB']->FetchOne($result2); // Log this action if we are in the control panel if (defined('ISC_ADMIN_CP')) { $GLOBALS['ISC_CLASS_LOG']->LogAdminAction($orderId, $statusName); } // This order was marked as refunded or cancelled if ($status == ORDER_STATUS_REFUNDED || $status == ORDER_STATUS_CANCELLED) { // If the inventory levels for products in this order have previously been changed, we need to // return the inventory too if ($order['ordinventoryupdated'] == 1) { UpdateInventoryOnReturn($orderId); } // Marked as refunded or cancelled, need to cancel the gift certificates in this order too if there are any $updatedCertificates = array( "giftcertstatus" => 3 ); $GLOBALS['ISC_CLASS_DB']->UpdateQuery("gift_certificates", $updatedCertificates, "giftcertorderid='" . $GLOBALS['ISC_CLASS_DB']->Quote($orderId) . "'"); } // This order was marked as completed/shipped as long as the inventory hasn't been adjusted previously else if (OrderIsComplete($status)) { if ($order['ordinventoryupdated'] == 0) { DecreaseInventoryFromOrder($orderId); } // Send out gift certificates if the order wasn't already complete if (!OrderIsComplete($existing_status)) { $GLOBALS['ISC_CLASS_GIFT_CERTIFICATES'] = GetClass('ISC_GIFTCERTIFICATES'); $GLOBALS['ISC_CLASS_GIFT_CERTIFICATES']->ActivateGiftCertificates($orderId); } } } // Was there an error? If not, commit if ($GLOBALS['ISC_CLASS_DB']->Error() == "") { $GLOBALS['ISC_CLASS_DB']->Query("COMMIT"); // Does the customer now need to be notified for this status change? $statuses = explode(",", GetConfig('OrderStatusNotifications')); if (in_array($status, $statuses) && $email == true) { foreach($orderIds as $orderId) { EmailOnStatusChange($orderId, $status); } } // If the checkout module that was used for an order is still enabled and has a function // to handle a status change, then call that function if($preventModuleUpdateCallback == false) { $valid_checkout_modules = GetAvailableModules('checkout', true, true); $valid_checkout_module_ids = array(); foreach ($valid_checkout_modules as $valid_module) { $valid_checkout_module_ids[] = $valid_module['id']; } foreach($orderIds as $orderId) { $order = GetOrder($orderId, false); if (in_array($order['orderpaymentmodule'], $valid_checkout_module_ids)) { GetModuleById('checkout', $checkout_module, $order['orderpaymentmodule']); if (method_exists($checkout_module, 'HandleStatusChange')) { call_user_func(array($checkout_module, 'HandleStatusChange'), $orderId, $existing_status, $status, 0); } } } } return true; } else { return false; } } return false; }
public function UpdateReturnStatus(&$return, $status, $crediting = false) { // Start a transaction $GLOBALS['ISC_CLASS_DB']->Query("START TRANSACTION"); if ($status == 5 && $return['retstatus'] != 5) { // Changing the status of this return to "Refunded", so we need to perform some additional things $refundAmount = $return['retprodcost'] * $return['retprodqty']; // Grab the order if it still exists to provide a refund on the tax as well $order = GetOrder($return['retorderid']); if ($order['ordtotalincludestax'] == 0 && $order['ordtaxrate'] > 0) { $taxCharged = number_format($refundAmount / 100 * $order['ordtaxrate'], GetConfig('DecimalPlaces'), '.', ''); $refundAmount += $taxCharged; } $updatedProduct = array("ordprodrefundamount" => $return['retprodcost'], "ordprodrefunded" => $return['retprodqty'], "ordprodreturnid" => $return['returnid']); $GLOBALS['ISC_CLASS_DB']->UpdateQuery("order_products", $updatedProduct, "orderprodid='" . $GLOBALS['ISC_CLASS_DB']->Quote($return['retordprodid']) . "'"); // Fetch the total for this order $query = sprintf("SELECT ordsubtotal, ordtotalamount FROM [|PREFIX|]orders WHERE orderid='%s'", $return['retorderid']); $result = $GLOBALS['ISC_CLASS_DB']->Query($query); $orderTotal = $GLOBALS['ISC_CLASS_DB']->Fetch($result); // Reduce the order total by retprodcost x retprodqty (the price we paid x the quantity being returned) $orderSubTotal = $orderTotal['ordsubtotal'] - $refundAmount; if ($orderSubTotal <= 0) { $orderSubTotal = 0; } $orderTotalAmount = $orderTotal['ordtotalamount'] - $orderTotal['ordsubtotal'] + $orderSubTotal; if ($orderTotalAmount <= 0) { $orderTotalAmount = 0; } $updatedOrder = array("ordsubtotal" => $orderSubTotal, "ordtotalamount" => $orderTotalAmount); // If the amount of tax has changed, need to update that total too if (isset($taxCharged)) { $updatedOrder['ordtaxtotal'] = $order['ordtaxtotal'] - $taxCharged; } else { if ($order['ordtotalincludestax']) { $taxCharged = $refundAmount / (100 + $order['ordtaxrate']) * $order['ordtaxrate']; $taxCharged = number_format($taxCharged, GetConfig('DecimalPlaces'), '.', ''); $updatedOrder['ordtaxtotal'] = $order['ordtaxtotal'] - $taxCharged; } } if ($orderTotalAmount == 0) { $updatedOrder['ordtaxtotal'] = 0; } // Have all items in this order been refunded? Mark the order as refunded. $query = sprintf("SELECT SUM(ordprodqty-ordprodrefunded) FROM [|PREFIX|]order_products WHERE orderorderid=%d", $return['retorderid']); $result = $GLOBALS['ISC_CLASS_DB']->Query($query); $remainingItems = $GLOBALS['ISC_CLASS_DB']->FetchOne($result); if ($remainingItems == 0) { $updatedOrder['ordstatus'] = 4; } $GLOBALS['ISC_CLASS_DB']->UpdateQuery("orders", $updatedOrder, "orderid='" . $GLOBALS['ISC_CLASS_DB']->Quote($return['retorderid']) . "'"); // Update the status of this return $updatedReturn = array("retstatus" => 5, "retuserid" => $GLOBALS['ISC_CLASS_ADMIN_AUTH']->GetUserId()); $GLOBALS['ISC_CLASS_DB']->UpdateQuery("returns", $updatedReturn, "returnid='" . $GLOBALS['ISC_CLASS_DB']->Quote($return['returnid']) . "'"); // Update the product inventory for this returned item $query = sprintf("SELECT * FROM [|PREFIX|]order_products WHERE ordprodid='%d'", $return['retordprodid']); $result = $GLOBALS['ISC_CLASS_DB']->Query($query); $row = $GLOBALS['ISC_CLASS_DB']->Fetch($result); UpdateInventoryOnReturn($return['retordprodid']); // dont send a refund through the checkout module if a store credit was issued if (!$crediting) { // If the checkout module that was used for an order is still enabled and has a function // to handle a status change, then call that function $valid_checkout_modules = GetAvailableModules('checkout', true, true); $valid_checkout_module_ids = array(); foreach ($valid_checkout_modules as $valid_module) { $valid_checkout_module_ids[] = $valid_module['id']; } $newStatus = $order['ordstatus']; if (isset($updatedOrder['ordstatus'])) { $newStatus = $updatedOrder['ordstatus']; } // attempt to refund this amount with the checkout provider $order = GetOrder($return['retorderid'], false); if (in_array($order['orderpaymentmodule'], $valid_checkout_module_ids)) { GetModuleById('checkout', $checkout_module, $order['orderpaymentmodule']); if (method_exists($checkout_module, 'HandleStatusChange')) { call_user_func(array($checkout_module, 'HandleStatusChange'), $return['retorderid'], $order['ordstatus'], $newStatus, $refundAmount); } } } } else { // Update the status of this return $updatedReturn = array("retstatus" => $status); $GLOBALS['ISC_CLASS_DB']->UpdateQuery("returns", $updatedReturn, "returnid='" . $GLOBALS['ISC_CLASS_DB']->Quote($return['returnid']) . "'"); } $return['retstatus'] = $status; if (GetConfig('NotifyOnReturnStatusChange') == 1) { $this->EmailReturnStatusChange($return); } if ($GLOBALS['ISC_CLASS_DB']->GetErrorMsg() == "") { $GLOBALS['ISC_CLASS_DB']->Query("COMMIT"); return true; } else { return false; } }
public function UpdateReturnStatus(&$return, $status, $crediting = false) { // Start a transaction $GLOBALS['ISC_CLASS_DB']->Query("START TRANSACTION"); // Changing the status of this return to "Refunded", so we need to perform some additional things if($status == 5 && $return['retstatus'] != 5) { $refundAmount = $return['retprodcost'] * $return['retprodqty']; $updatedProduct = array( "ordprodrefundamount" => $return['retprodcost'], "ordprodrefunded" => $return['retprodqty'], "ordprodreturnid" => $return['returnid'] ); $order = getOrder($return['retorderid']); if (!$order) { return false; } $GLOBALS['ISC_CLASS_DB']->UpdateQuery("order_products", $updatedProduct, "orderprodid='".$GLOBALS['ISC_CLASS_DB']->Quote($return['retordprodid'])."'"); $query = " UPDATE [|PREFIX|]orders SET ordrefundedamount = ordrefundedamount + ".$refundAmount." WHERE orderid='".$return['retorderid']."' "; $this->db->query($query); // Have all items in this order been refunded? Mark the order as refunded. $query = sprintf("SELECT SUM(ordprodqty-ordprodrefunded) FROM [|PREFIX|]order_products WHERE orderorderid=%d", $return['retorderid']); $result = $GLOBALS['ISC_CLASS_DB']->Query($query); $remainingItems = $GLOBALS['ISC_CLASS_DB']->FetchOne($result); if($remainingItems == 0) { $updatedOrder = array( 'ordstatus' => 4 ); $GLOBALS['ISC_CLASS_DB']->UpdateQuery("orders", $updatedOrder, "orderid='".$GLOBALS['ISC_CLASS_DB']->Quote($return['retorderid'])."'"); } // Update the status of this return $updatedReturn = array( "retstatus" => 5, "retuserid" => $GLOBALS['ISC_CLASS_ADMIN_AUTH']->GetUserId() ); $GLOBALS['ISC_CLASS_DB']->UpdateQuery("returns", $updatedReturn, "returnid='".$GLOBALS['ISC_CLASS_DB']->Quote($return['returnid'])."'"); // Update the product inventory for this returned item $query = sprintf("SELECT * FROM [|PREFIX|]order_products WHERE ordprodid='%d'", $return['retordprodid']); $result = $GLOBALS['ISC_CLASS_DB']->Query($query); $row = $GLOBALS['ISC_CLASS_DB']->Fetch($result); UpdateInventoryOnReturn($return['retordprodid']); // dont send a refund through the checkout module if a store credit was issued if (!$crediting) { // If the checkout module that was used for an order is still enabled and has a function // to handle a status change, then call that function $valid_checkout_modules = GetAvailableModules('checkout', true, true); $valid_checkout_module_ids = array(); foreach ($valid_checkout_modules as $valid_module) { $valid_checkout_module_ids[] = $valid_module['id']; } $newStatus = $order['ordstatus']; if (isset($updatedOrder['ordstatus'])) { $newStatus = $updatedOrder['ordstatus']; } // attempt to refund this amount with the checkout provider $order = GetOrder($return['retorderid'], false); if (in_array($order['orderpaymentmodule'], $valid_checkout_module_ids)) { GetModuleById('checkout', $checkout_module, $order['orderpaymentmodule']); if (method_exists($checkout_module, 'HandleStatusChange')) { call_user_func(array($checkout_module, 'HandleStatusChange'), $return['retorderid'], $order['ordstatus'], $newStatus, $refundAmount); } } } } else { // Update the status of this return $updatedReturn = array( "retstatus" => $status ); $GLOBALS['ISC_CLASS_DB']->UpdateQuery("returns", $updatedReturn, "returnid='".$GLOBALS['ISC_CLASS_DB']->Quote($return['returnid'])."'"); } $return['retstatus'] = $status; if(GetConfig('NotifyOnReturnStatusChange') == 1) { $this->EmailReturnStatusChange($return); } if($GLOBALS['ISC_CLASS_DB']->GetErrorMsg() == "") { $GLOBALS['ISC_CLASS_DB']->Query("COMMIT"); return true; } else { return false; } }
/** * Insert/Update the node with the response record * * Method will insert/update the node with the response record * * @access protected * @param array $responseData The reponse data from QB * @param array $nodeData The optional node data array. If set then update, else insert * @return int The new or updtaed node ID on success, FALSE on error */ protected function syncResponseRecord2Store($responseData, $nodeData=false) { if (!is_array($responseData)) { $xargs = func_get_args(); throw new QBException("Invalid arguments when syncing order record from QB", $xargs); } /** * Get our stored customer ID if we have one */ $customerId = $this->getCustomer4Order($responseData["TxnID"]); /** * Get the customer ListID and find the matching customer ID if we can. We need to have a customer ListID */ if (is_null($customerId)) { if (!isset($responseData["CustomerRef"]["ListID"])) { throw new QBException("Unable to find customer ListID when syncing orders", $responseData); } $customerRef = $this->accounting->getReference("customer", '', $responseData["CustomerRef"]["ListID"], '', false); /** * If we don't have a reference then use the existing customer ID if we have one */ if (!is_array($customerRef)) { if (is_array($nodeData) && array_key_exists("ordcustid", $nodeData) && isId($nodeData["ordcustid"])) { $customerId = $nodeData["ordcustid"]; /** * Else if we do have a nodeData but no customer ID then its a guest checkout */ } else if (is_array($nodeData) && (!array_key_exists("ordcustid", $nodeData) || !isId($nodeData["ordcustid"]))) { $customerId = ''; /** * Else it is a new customer which we do not have a record for */ } else { $lastKid = end($this->spool["children"]); if ($lastKid["nodeType"] == "customer" && $lastKid["service"] == "query") { /** * If we couldn't find the record then error out */ if ($lastKid["errNo"] > 0) { throw new QBException("Unable to find customer when syncing orders from QB", $responseData["CustomerRef"]["ListID"]); } /** * Check to see if this is an anonymous customer (guest checkout). If so then don't create a customer record */ if ($this->accounting->isCustomerGuestCheckout($lastKid["response"])) { $customerId = ''; /** * Else it is a real customer so create it */ } else { $customerId = $this->customerSyncAPI->syncResponseRecord2Store($lastKid["response"]); if (!isId($customerId)) { throw new QBException("Unable to create customer record when syncing orders from QB", $lastKid["response"]); } $referenceDataSetup = $this->customerSyncAPI->referenceDataSetup; $referenceDataExternalKey = $this->customerSyncAPI->referenceDataExternalKey; $referenceReturn = $this->setReferenceDataStatically("customer", $customerId, $lastKid["response"], '', $referenceDataSetup, $referenceDataExternalKey); if (isId($referenceReturn)) { $customerRef = $this->accounting->getReference("customer", $referenceReturn, '', '', false); } } } else { $childRequestData = array( "ListID" => $responseData["CustomerRef"]["ListID"] ); return $this->execChildService("customer", "query", $childRequestData); } } /** * Else we have the customer but not the order yet */ } else if (is_array($customerRef)) { $customerId = $customerRef["accountingrefnodeid"]; /** * Else we got no customer */ } else { $customerId = ''; } /** * Save the customer ID for this order */ $this->setCustomer2Order($responseData["TxnID"], $customerId); } /** * If we have a custom ID then get the customer record as we'll need it later on */ $customerNodeData = ''; if (isId($customerId)) { $customerNodeData = $this->customerAPI->get($customerId); } if ($this->accounting->getValue("orderoption") == "order") { $salesLineRetTag = "SalesOrderLineRet"; } else { $salesLineRetTag = "SalesReceiptLineRet"; } /** * OK, we got the customer, now we need to get all the products */ if (!isset($responseData[$salesLineRetTag]) || !is_array($responseData[$salesLineRetTag]) || empty($responseData[$salesLineRetTag])) { throw new QBException("Missing/Invalid product array when syncing orders", array("tag" => $salesLineRetTag, "response" => $responseData)); } /** * Set aside some vars for shipping costs and the tax component */ $productSubTotal = 0; $shippingCost = 0; $taxCost = 0; /** * Sanatize it */ if (!isset($responseData[$salesLineRetTag][0])) { $responseData[$salesLineRetTag] = array($responseData[$salesLineRetTag]); } foreach ($responseData[$salesLineRetTag] as $product) { /** * Check to see if we have already recorded this product */ if ($this->checkProductListId4Order($responseData["TxnID"], $product["ItemRef"]["ListID"])) { continue; } /** * OK, we haven't done this one yet so lets do it. If we have any kids then deal with them first */ $lastKid = end($this->spool["children"]); if ($lastKid["service"] == "query" && ($lastKid["nodeType"] == "product" || $lastKid["nodeType"] == "productvariation")) { /** * If we couldn't find the record then error out */ if ($lastKid["errNo"] > 0) { throw new QBException("Unable to find product when syncing orders from QB", $product["ItemRef"]["ListID"]); } /** * Else try to add in this product/variation */ if ($lastKid["nodeType"] == "productvariation") { $productFatcory =& $this->productVariationSyncAPI; } else { $productFatcory =& $this->productSyncAPI; } $productData = $productFatcory->searchNodeByDB($lastKid["response"]); $productId = $productFatcory->syncResponseRecord2Store($lastKid["response"], $productData); /** * Dam! We can't add it. Error out of here as we really needed that product for the order */ if (!isId($productId)) { throw new QBException("Unable to create product/variation record when syncing orders from QB", $lastKid["response"]); } /** * Set the reference for this product */ $referenceDataSetup = $productFatcory->referenceDataSetup; $referenceDataExternalKey = $productFatcory->referenceDataExternalKey; $this->setReferenceDataStatically($lastKid["nodeType"], $productId, $lastKid["response"], '', $referenceDataSetup, $referenceDataExternalKey); } /** * There aren't any query kids so try and find the reference for this product/variation/other product */ $checkTypes = array("product", "productvariation", "prerequisite"); $productRef = ""; $productType = ""; foreach ($checkTypes as $checkType) { $productRef = $this->accounting->getReference($checkType, '', $product["ItemRef"]["ListID"], '', false); if (is_array($productRef)) { $productType = $checkType; break; } } /** * Check to see if this is a prerequisite (shipping & tax costs) */ if ($productType == "prerequisite") { switch (isc_strtolower(trim($productRef["accountingrefvalue"]["Type"]))) { case "shipping": $cost = ($product["Quantity"] * $product["Rate"]); break; case "tax": $cost = ($product["Quantity"] * $product["Rate"]); break; } $productNodeData = array( "Type" => isc_strtolower(trim($productRef["accountingrefvalue"]["Type"])), "Cost" => $cost ); $this->setProductListId2Order($responseData["TxnID"], $product["ItemRef"]["ListID"], $productType, $productNodeData, $product); /** * We don't want to insert this in the order_products table */ continue; } /** * OK, prerequisites are done, now for the rest. If no reference then send out a query child */ if (!is_array($productRef)) { if ($this->accounting->isProductVariationShortName($product["ItemRef"]["FullName"])) { $productType = "productvariation"; } else { $productType = "product"; } $childRequestData = array( "ListID" => $product["ItemRef"]["ListID"] ); return $this->execChildService($productType, "query", $childRequestData); } /** * Must have a reference by now */ if (!is_array($productRef)) { throw new QBException("Unable to find product reference when syncing order ID: " . $this->spool["nodeId"], $responseData); } $prodNodeData = ''; if ($productType == "productvariation") { $prodNodeData = $this->productVariationAPI->get($productRef["accountingrefnodeid"]); } else { $prodNodeData = $this->productAPI->get($productRef["accountingrefnodeid"]); } /** * If no prodNodeData then no go */ if (!is_array($prodNodeData)) { throw new QBException("Unable to find " . $productType . " node data when syncing order ID: " . $this->spool["nodeId"], array("order" => $responseData, "prodNodeId" => $productRef["accountingrefnodeid"])); } /** * Lastly, save this product to our tmp cache */ $this->setProductListId2Order($responseData["TxnID"], $product["ItemRef"]["ListID"], $productType, $prodNodeData, $product); } /** * OK, now retrieve all our product from our tmp cache to build the products for this order */ $products = array(); $taxCost = $shippingCost = 0; $cacheProducts = $this->getProductListIds4Order($responseData["TxnID"]); if (!is_array($cacheProducts) || empty($cacheProducts)) { throw new QBException("Empty product cache array when syncing order ID: " . $this->spool["nodeId"], $responseData); } foreach ($cacheProducts as $productListId => $product) { /** * Add up our stored shipping and tax costs if we have any */ if ($product["productType"] == "prerequisite") { switch (isc_strtolower(trim($product["productNodeData"]["Type"]))) { case "shipping": $shippingCost = $product["productNodeData"]["Cost"]; break; case "tax": $taxCost = $product["productNodeData"]["Cost"]; break; } continue; } $prodCode = ''; $prodVariationId = 0; $prodOptions = array(); if ($product["productType"] == "productvariation") { $prodCode = $product["productNodeData"]["vcsku"]; $prodVariationId = $product["productNodeData"]["combinationid"]; $prodOptions = $product["productNodeData"]["prodvariationarray"]; } if (trim($prodCode) == '') { $prodCode = $product["productNodeData"]["prodcode"]; } $products[] = array( "product_id" => $product["productNodeData"]["productid"], "product_name" => $product["productNodeData"]["prodname"], "product_code" => $prodCode, "quantity" => max(1, $product["productResponse"]["Quantity"]), "product_price" => $product["productResponse"]["Rate"], "original_price" => $product["productResponse"]["Rate"], "variation_id" => $prodVariationId, "options" => $prodOptions ); /** * Check to see if this is an existing product in an already existing order */ if (is_array($nodeData) && isset($nodeData["products"]) && is_array($nodeData["products"])) { foreach ($nodeData["products"] as $existingProduct) { if ($existingProduct["productid"] == $product["productNodeData"]["productid"] && isset($existingProduct["prodorderid"])) { $products[count($products)-1]["existing_order_product"] = $existingProduct["prodorderid"]; } } } /** * Add up our sub total */ $productSubTotal += $product["productResponse"]["Amount"]; } /** * OK, we have all the products and the customer details. Now for the actual order details */ $savedata = array( "ordcustid" => $customerId, "subtotal_ex_tax" => $productSubTotal, "total_tax" => $taxCost, "shipping_cost_ex_tax" => $shippingCost, "total_inc_tax" => ($productSubTotal + $taxCost + $shippingCost), "products" => $products ); if (isset($responseData["Memo"])) { $savedata["ordnotes"] = $responseData["Memo"]; } /** * Add in the addresses */ $addressMap = array( "shipaddress1" => "Addr1", "shipaddress2" => "Addr2", "shipcity" => "City", "shipstate" => "State", "shipzip" => "PostalCode", "shipcountry" => "Country" ); foreach (array("BillAddress", "ShipAddress") as $addressType) { if (!array_key_exists($addressType, $responseData) || !is_array($responseData[$addressType])) { $responseData[$addressType] = array(); } if ($addressType == "BillAddress") { $addressKey = "billingaddress"; } else { $addressKey = "shippingaddress"; } $savedata[$addressKey] = array(); foreach ($addressMap as $columnName => $refKey) { if (!isset($responseData[$addressType][$refKey]) && !is_array($nodeData)) { $responseData[$addressType][$refKey] = ''; } if (isset($responseData[$addressType][$refKey])) { $savedata[$addressKey][$columnName] = $responseData[$addressType][$refKey]; } } /** * Find the country and state IDs */ $countryId = $this->getCountryId(@$savedata[$addressKey]["shipcountry"], $properCountryName); $stateId = ''; if (isId($countryId) && trim(@$savedata[$addressKey]["shipstate"]) !== '') { $savedata[$addressKey]["shipcountry"] = $properCountryName; $stateId = $this->getStateId($savedata[$addressKey]["shipstate"], $countryId, $properStateName); if (!isId($stateId)) { $stateId = ''; } else if (trim($properStateName) !== '') { $savedata[$addressKey]["shipstate"] = $properStateName; } } else { $countryId = ''; } if (is_array($nodeData) || !isId($stateId)) { $savedata[$addressKey]["shipstateid"] = $stateId; } if (is_array($nodeData) || !isId($countryId)) { $savedata[$addressKey]["shipcountryid"] = $countryId; } /** * Fill in the name. Use whatever QB gave us regardless */ $customerName = @$responseData["CustomerRef"]["FullName"]; if ($this->accounting->isCustomerShortName($customerName)) { $tmpName = $this->accounting->qbCustomerShortName2CustomerNameId($customerName); if (is_array($tmpName) && array_key_exists("customername", $tmpName)) { $customerName = $tmpName["customername"]; } } else if ($this->accounting->isCustomerGuestShortName($customerName)) { $tmpName = $this->accounting->qbCustomerGuestShortName2CustomerGuestNameId($customerName); if (is_array($tmpName) && array_key_exists("customerguestname", $tmpName)) { $customerName = $tmpName["customerguestname"]; } } $nameParts = explode(" ", $customerName); if (count($nameParts) > 2) { $firstName = implode(" ", array_slice($nameParts, 0, count($nameParts)-1)); $lastName = $nameParts[count($nameParts)-1]; } else if (count($nameParts) == 1) { $firstName = $nameParts[0]; $lastName = ""; } else { $firstName = $nameParts[0]; $lastName = $nameParts[1]; } $savedata[$addressKey]["shipfirstname"] = $firstName; $savedata[$addressKey]["shiplastname"] = $lastName; /** * Set something to each field if it is NULL as the database can't handle NULL values for this schema */ foreach ($savedata[$addressKey] as $addKey => $addVal) { if (is_null($addVal)) { $savedata[$addressKey][$addKey] = ''; } } } /** * If we don't have a $nodeData then we can still fill in some blanks */ if (!is_array($nodeData)) { $savedata["ordtoken"] = GenerateOrderToken(); $savedata["ordstatus"] = ORDER_STATUS_COMPLETED; $savedata["orderpaymentmodule"] = "manual"; $savedata["orderpaymentmethod"] = GetLang("QuickBooksDefaultPaymentName"); $savedata["total_inc_tax"] = $savedata["totalcost"]; $savedata["handling_cost_ex_tax"] = 0; $savedata["handling_cost_inc_tax"] = 0; if (isset($savedata["billingaddress"]["shipcountry"])) { $savedata["ordgeoipcountry"] = $savedata["billingaddress"]["shipcountry"]; $savedata["ordgeoipcountrycode"] = GetCountryISO2ByName($savedata["billingaddress"]["shipcountry"]); } if (is_array($customerNodeData)) { $savedata["ordbillemail"] = $customerNodeData["custconemail"]; $savedata["ordbillphone"] = $customerNodeData["custconphone"]; $savedata["ordshipemail"] = $customerNodeData["custconemail"]; $savedata["ordshipphone"] = $customerNodeData["custconphone"]; } } else { $savedata["orderid"] = $nodeData["orderid"]; } /** * Alright, we have EVERYTHING, now create/update EVERYTHING */ $orderId = false; if (is_array($nodeData)) { /** * Reset the inventory levels before we update it */ if ($this->accounting->getValue("invlevels") !== ACCOUNTING_QUICKBOOKS_TYPE_QUICKBOOKS) { UpdateInventoryOnReturn($savedata["orderid"]); /* /lib/orders.php */ } if ($this->entityAPI->edit($savedata) !== false) { $orderId = $savedata["orderid"]; } /** * Now sync back the inventory levels */ if ($this->accounting->getValue("invlevels") !== ACCOUNTING_QUICKBOOKS_TYPE_QUICKBOOKS) { DecreaseInventoryFromOrder($orderId); } } else { $orderId = $this->entityAPI->add($savedata); /** * Sync up the inventory levels as each order is marked as completed */ if ($this->accounting->getValue("invlevels") !== ACCOUNTING_QUICKBOOKS_TYPE_QUICKBOOKS) { DecreaseInventoryFromOrder($orderId); } } if (!isId($orderId)) { $this->accounting->logError("ORDER DATA", array("SaveData" => $savedata, "NodeData" => $nodeData, "DB" => $GLOBALS["ISC_CLASS_DB"]->GetError())); throw new QBException("Cannot save order record with data from QB", array("SaveData" => $savedata, "NodeData" => $nodeData, "DB" => $GLOBALS["ISC_CLASS_DB"]->GetError())); } return $orderId; }