/** * Main execute function for Refresh Inventory * * @throws Exception */ public function main() { $this->stdout->styles('backorder', ['text' => 'red']); $this->_now = date("Y-m-d H:i:s"); $this->NsProductCount->useDbConfig = 'default'; $this->NsLowItem->useDbConfig = 'default'; // block until RefreshLowItemsShell releases the write lock $this->_waitForLock(); // Because our join has a failover, it's not really a join on policy $productCounts = $this->NsProductCount->find('all', ['fields' => ["NsProductCount.*", "MAX(ItemAvailabilityTimes.start_date) AS LatestTime", "ItemAvailabilityTimes.item_availability_id", '(select count(*) from ns_low_items WHERE sku = NsBackorderPolicy.sku AND ns_warehouse_id = NsBackorderPolicy.ns_warehouse_id) as low_count'], 'group' => ["ItemAvailabilityTimes.item_id HAVING low_count < 1"], 'joins' => [['table' => 'ns_backorder_policies', 'alias' => 'NsBackorderPolicy', 'type' => 'INNER', 'conditions' => ['NsProductCount.sku = NsBackorderPolicy.sku', 'NsProductCount.ns_warehouse_id = NsBackorderPolicy.ns_warehouse_id']], ["table" => "items", "alias" => "Item", "type" => "INNER", "conditions" => ["NsProductCount.sku = Item.sku"]], ["table" => "item_availability_times", "alias" => "ItemAvailabilityTimes", "type" => "INNER", "conditions" => ["Item.id = ItemAvailabilityTimes.item_id", "ItemAvailabilityTimes.ns_warehouse_id = NsBackorderPolicy.ns_warehouse_id"]]], 'conditions' => ['NsProductCount.inventory_count - NsBackorderPolicy.unorderable_threshold < NsBackorderPolicy.backorder_threshold', 'ItemAvailabilityTimes.end_date IS NULL', 'ItemAvailabilityTimes.item_availability_id IN (2, 3)']]); $this->out('Processing ' . count($productCounts) . ' products.', 1, Shell::VERBOSE); // Add to the ns_low_items table foreach ($productCounts as $aProductCount) { $this->out("Working sku: {$aProductCount['NsProductCount']['sku']}...", 1, Shell::NORMAL); $policy = []; // Try to find an explicit policy $NsBackorderPolicy = $this->NsBackorderPolicy->find('first', ["conditions" => ["sku" => $aProductCount['NsProductCount']['sku'], "ns_warehouse_id" => $aProductCount['NsProductCount']['ns_warehouse_id']]]); if ($NsBackorderPolicy) { $policy = $NsBackorderPolicy['NsBackorderPolicy']; } if (!$policy) { throw new Exception("Failed to find policy for {$aProductCount['NsProductCount']['sku']}"); } $this->NsLowItem->create(); $this->NsLowItem->save(["sku" => $aProductCount['NsProductCount']['sku'], "ns_warehouse_id" => $aProductCount['NsProductCount']['ns_warehouse_id'], "inventory_count" => $aProductCount['NsProductCount']['inventory_count'], "item_availability_id" => $policy['backorder_item_availability_id'], "restock_date" => $policy['backorder_restock_date'], "threshold" => $policy['unorderable_threshold']]); $this->out("<backorder>I am notifying you of a low item!</backorder>", 1, Shell::NORMAL); $subject = "Low Inventory Alert"; $word = $this->_iatToWord($policy['item_availability_id']); $message = "An item (SKU {$aProductCount['NsProductCount']['sku']}) is at risk of going into {$word} status.\n\n" . "To set this item's backorder policy, visit the following URL:\n" . "http://admin.youniqueproducts.com/admin3/warehouse.php#/warehouse/backorder\n\n" . "Message: {$policy['message']}\n\n" . "If you are not logged in, please first visit:\n" . "https://admin.youniqueproducts.com/admin3/index.php"; SNS::sendSNS("Shipping_Issues", $subject, $message); } $this->_releaseLock(); }
/** * Execute DataFlowFour * @return bool */ public function execute() { $this->out('Sending sns test.'); try { SNS::sendSNS("Payment_Declines", 'Test', 'test message'); } catch (Exception $e) { print $e->getCode() . "\n"; print $e->getMessage() . "\n"; } $this->out('Sent sns test.'); return true; }
public function main() { $this->__populateNsProductsCount(); // We're looking for products that are in ns_product_counts but not in ns_backorder_defaults // Those rows won't be flagged when they run low on inventory $NsProductCount = $this->NsProductCount->find('all', ['fields' => ["NsProductCount.*", "NsBackorderDefault.*"], 'joins' => [['table' => 'ns_backorder_defaults', 'alias' => 'NsBackorderDefault', 'type' => 'LEFT', 'conditions' => ['NsProductCount.ns_warehouse_id = NsBackorderDefault.ns_warehouse_id', 'NsProductCount.sku = NsBackorderDefault.sku']]]]); var_export($NsProductCount); $orphanList = []; foreach ($NsProductCount as $aNsProductCount) { if (!$aNsProductCount['NsBackorderDefault']['id']) { $orphanList[] = ["sku" => $aNsProductCount['NsProductCount']['sku'], "ns_warehouse_id" => $aNsProductCount['NsProductCount']['ns_warehouse_id']]; } } if ($orphanList) { $subject = "Missing Backorder Default Alert"; $message = "At least one item is missing a backorder default policy.\n" . "Contact Don; we're sure he's just the one to fix this for you.\n\n"; foreach ($orphanList as $orphan) { $message .= "SKU: {$orphan['sku']},\twarehouse id: {$orphan['ns_warehouse_id']}\n"; } SNS::sendSNS("Shipping_Issues", $subject, $message); } }
/** * Process Payments * @param string $referenceId * @param array $paymentMethods * @param bool $test_mode * @return array */ public function processOrderPayments($referenceId, $paymentMethods, $test_mode = false) { syslog(LOG_DEBUG, "Order Payments {$referenceId} " . count($paymentMethods)); $creditCards = []; $oxxoPayments = []; $giroPayments = []; $sofortPayments = []; $paypalPayments = []; $ledgerMethods = []; foreach ($paymentMethods as $payment) { switch ($payment['type']) { case OrderPayment::TYPE_LEDGER_NAME: $ledgerMethods[] = $payment; break; case OrderPayment::TYPE_CREDITCARD_NAME: $creditCards[] = $payment; break; case OrderPayment::TYPE_PAYPAL_NAME: $paypalPayments[] = $payment; break; case OrderPayment::TYPE_OXXO_NAME: $oxxoPayments[] = $payment; break; case OrderPayment::TYPE_GIRO_NAME: $giroPayments[] = $payment; break; case OrderPayment::TYPE_SOFORT_NAME: $sofortPayments[] = $payment; break; } } $processedPayments = []; try { if (count($ledgerMethods) > 0) { $this->ProductCredit = ClassRegistry::init('ProductCredit'); foreach ($ledgerMethods as $payment) { $result = $this->ProductCredit->authorize(ProductCredit::METHOD_SYSTEM, ProductCredit::TYPE_PURCHASE, Configure::read("market_id"), $payment['presenter_id'], $payment['user_id'], $payment['amount'], "System", $referenceId); $payment['identifier'] = $payment['user_id']; if ($result !== false) { $payment['transaction_id'] = $result; $payment['status'] = "authorized"; $processedPayments[] = $payment; } else { $payment['status'] = "failed"; $payment['transaction_id'] = "0"; return $this->voidTransactions($processedPayments, "Insufficient Product Credits"); } } } if (count($giroPayments) > 0) { foreach ($giroPayments as $payment) { $mid = Configure::read('market_id'); $agent = $_SERVER['HTTP_USER_AGENT']; // unset($payment['processor']); // unset($payment['type']); try { $p = $payment; $p['amount'] = $payment['amount']->amount; $result = $this->WorldPayGiro->purchase($mid, $p, $agent, $test_mode); } catch (WorldPayError $e) { if ($e->getMessage() == WorldPay::$RESPONSE_ERROR) { if ($this->WorldPayGiro->api->reply->hasError()) { $response = $this->WorldPayGiro->api->reply; $result = ['success' => false, 'error' => ['errno' => $response->err_code, 'errmsg' => $response->err_msgs]]; } else { $result = ['success' => false, 'error' => ['errno' => '500', 'errmsg' => 'Server Error']]; } } else { $result = ['success' => false, 'error' => ['errno' => '401', 'errmsg' => 'Authentication Failed']]; } } if (!$result['success']) { $payment['status'] = 'failed'; $error = " Code: " . $result['error']['errno'] . " Message: " . $result['error']['errmsg']; if (!empty($result['error']['errno'])) { // log to api log table $this->ApiAudit = ClassRegistry::init('ApiAudit'); $api_data = ['reference_name' => get_class(), 'reference_id' => 0, 'source' => __FILE__ . ' ' . __LINE__, 'destination' => 'worldpay api', 'sent' => json_encode($payment), 'received' => $error, 'notes' => 'World Pay Giro fail']; $this->ApiAudit->clear(); $this->ApiAudit->create($api_data); $this->ApiAudit->save(); } $error = __('There was a payment error. Please contact support.'); return $this->voidTransactions($processedPayments, $error); } else { // For giro save reference and redirect $payment['status'] = "success"; $payment['redirect'] = true; $payment['identifier'] = 0; $payment['processor'] = PaymentComponent::GATEWAY_WORLDPAY_GIRO; $payment['transaction_id'] = $result['reply']->response->reply->orderStatus->reference; $processedPayments[] = $payment; } } } if (count($sofortPayments) > 0) { foreach ($sofortPayments as $payment) { $mid = Configure::read('market_id'); $agent = $_SERVER['HTTP_USER_AGENT']; // unset($payment['processor']); // unset($payment['type']); try { $p = $payment; $p['amount'] = $payment['amount']->amount; $result = $this->WorldPaySofort->purchase($mid, $p, $agent, $test_mode); } catch (WorldPayError $e) { if ($e->getMessage() == WorldPay::$RESPONSE_ERROR) { if ($this->WorldPaySofort->api->reply->hasError()) { $response = $this->WorldPaySofort->api->reply; $result = ['success' => false, 'error' => ['errno' => $response->err_code, 'errmsg' => $response->err_msgs]]; } else { $result = ['success' => false, 'error' => ['errno' => '500', 'errmsg' => 'Server Error']]; } } else { $result = ['success' => false, 'error' => ['errno' => '401', 'errmsg' => 'Authentication Failed']]; } } if (!$result['success']) { $payment['status'] = 'failed'; $error = " Code: " . $result['error']['errno'] . " Message: " . $result['error']['errmsg']; if (!empty($result['error']['errno'])) { // log to api log table $this->ApiAudit = ClassRegistry::init('ApiAudit'); $api_data = ['reference_name' => get_class(), 'reference_id' => 0, 'source' => __FILE__ . ' ' . __LINE__, 'destination' => 'worldpay api', 'sent' => json_encode($payment), 'received' => $error, 'notes' => 'World Pay Sofort fail']; $this->ApiAudit->clear(); $this->ApiAudit->create($api_data); $this->ApiAudit->save(); } $error = __('There was a payment error. Please contact support.'); return $this->voidTransactions($processedPayments, $error); } else { // For sofort save reference and redirect $payment['status'] = "success"; $payment['redirect'] = true; $payment['identifier'] = 0; $payment['processor'] = PaymentComponent::GATEWAY_WORLDPAY_SOFORT; $payment['transaction_id'] = $result['reply']->response->reply->orderStatus->reference; $processedPayments[] = $payment; } } } if (count($oxxoPayments) > 0) { foreach ($oxxoPayments as $payment) { $mid = Configure::read('market_id'); $agent = $_SERVER['HTTP_USER_AGENT']; // unset($payment['processor']); // unset($payment['type']); try { $p = $payment; $p['amount'] = $payment['amount']->amount; $result = $this->WorldPayOxxo->purchase($mid, $p, $agent, $test_mode); } catch (WorldPayError $e) { if ($e->getMessage() == WorldPay::$RESPONSE_ERROR) { if ($this->WorldPayOxxo->api->reply->hasError()) { $response = $this->WorldPayOxxo->api->reply; $result = ['success' => false, 'error' => ['errno' => $response->err_code, 'errmsg' => $response->err_msgs]]; } else { $result = ['success' => false, 'error' => ['errno' => '500', 'errmsg' => 'Server Error']]; } } else { $result = ['success' => false, 'error' => ['errno' => '401', 'errmsg' => 'Authentication Failed']]; } } if (!$result['success']) { $payment['status'] = 'failed'; $error = " Code: " . $result['error']['errno'] . " Message: " . $result['error']['errmsg']; if (!empty($result['error']['errno'])) { // log to api log table $this->ApiAudit = ClassRegistry::init('ApiAudit'); $api_data = ['reference_name' => get_class(), 'reference_id' => 0, 'source' => __FILE__ . ' ' . __LINE__, 'destination' => 'worldpay api', 'sent' => json_encode($payment), 'received' => $error, 'notes' => 'World Pay fail']; $this->ApiAudit->clear(); $this->ApiAudit->create($api_data); $this->ApiAudit->save(); } $error = __('There was a payment error. Please contact support.'); return $this->voidTransactions($processedPayments, $error); } else { // For oxxo save reference and redirect $payment['status'] = "success"; $payment['redirect'] = true; $payment['identifier'] = 0; $payment['processor'] = PaymentComponent::GATEWAY_WORLDPAY_OXXO; $payment['transaction_id'] = $result['reply']->response->reply->orderStatus->reference; $processedPayments[] = $payment; } } } if (count($creditCards) > 0) { foreach ($creditCards as $payment) { $payment['identifier'] = substr($payment['cardnum'], -4); switch ($payment['processor']) { case self::GATEWAY_WORLDPAY: $currency = $this->WorldPay->getCurrency(Configure::read("market_id")); $mid = Configure::read('market_id'); $agent = $_SERVER['HTTP_USER_AGENT']; $data = ['amount' => $payment['amount']->amount, 'currency' => $currency, 'ip_address' => $payment['ip_address'], 'email' => $payment['email'], 'session_id' => $payment['session_id'], 'id' => $payment['orderId'], 'address' => $payment['billing'], 'card' => ['accountNumber' => $payment['cardnum'], 'expirationMonth' => $payment['cardExpMonth'], 'expirationYear' => $payment['cardExpYear'], 'cvv' => $payment['cardcode'], 'firstName' => $payment['firstName'], 'lastName' => $payment['lastName']]]; try { $result = $this->WorldPay->purchase($mid, $data, $agent, $test_mode); } catch (WorldPayError $e) { if ($e->getMessage() == WorldPay::$RESPONSE_ERROR) { if ($this->WorldPay->api->reply->hasError()) { $response = $this->WorldPay->api->reply; $result = ['success' => false, 'error' => ['errno' => $response->err_code, 'errmsg' => $response->err_msgs]]; } else { $result = ['success' => false, 'error' => ['errno' => '500', 'errmsg' => 'Server Error']]; } } else { $result = ['success' => false, 'error' => ['errno' => '401', 'errmsg' => 'Authentication Failed']]; } } if (!$result['success']) { $payment['status'] = 'failed'; $error = " Code: " . $result['error']['errno'] . " Message: " . $result['error']['errmsg']; if (!empty($result['error']['errno'])) { // log to api log table $this->ApiAudit = ClassRegistry::init('ApiAudit'); unset($data['card']); $api_data = ['reference_name' => get_class(), 'reference_id' => 0, 'source' => __FILE__ . ' ' . __LINE__, 'destination' => 'worldpay api', 'sent' => json_encode($data), 'received' => $error, 'notes' => 'World Pay fail']; $this->ApiAudit->clear(); $this->ApiAudit->create($api_data); $this->ApiAudit->save(); } $error = __('There was a payment error. Please contact support.'); return $this->voidTransactions($processedPayments, $error); } else { $payment['status'] = "success"; $card_num = substr($result['reply']->response->reply->orderStatus->payment->cardNumber, -4); $payment['identifier'] = $card_num; $payment['transaction_id'] = $result['reply']->response->reply->orderStatus['orderCode']; //World Pay : Credit Cards Only if (substr($result['reply']->response->reply->orderStatus->payment->cardNumber, 0, 1) == '4') { //All Visa cards start with 4 $payment['paid_with'] = 'visa'; } elseif (in_array(substr($result['reply']->response->reply->orderStatus->payment->cardNumber, 0, 2), ['51', '52', '53', '54', '55'])) { //All MasterCard cards start with either 51,52,53,54,55 $payment['paid_with'] = 'mastercard'; } $processedPayments[] = $payment; } break; case self::GATEWAY_PAYPAL: $result = $this->Paypal->process($referenceId, (string) $payment['amount'], $payment['firstName'], $payment['lastName'], $payment['billingpostalcode'], $payment['cardnum'], $payment['carexp'], $payment['cardcode']); if ($result->Ack != "Success") { $payment['status'] = "failed"; $payment['transaction_id'] = $result->TransactionID; return $this->voidTransactions($processedPayments, $result->Errors->LongMessage); } else { $payment['transaction_id'] = $result->TransactionID; $payment['status'] = "success"; $processedPayments[] = $payment; } break; case self::GATEWAY_CYBERSOURCE: $ip = array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']; try { if (strlen($payment['billingpostalcode']) > 10) { throw new Exception("billing postal code not valid."); } } catch (Exception $e) { return false; } $billTo = array("email" => $payment['billingemail'], "city" => $payment['billingcity'], "firstName" => $payment['firstName'], "lastName" => $payment['lastName'], "postalCode" => $payment['billingpostalcode'], "state" => $payment['billingstate'], "street1" => $payment['billingaddress1'], "street2" => $payment['billingaddress2'], "country" => $payment['billingcountry'], "ipAddress" => $ip); //format exp for cybersource $exp_month = substr($payment['carexp'], 0, 2); $exp_year = substr($payment['carexp'], 3, 4); $card = array("accountNumber" => $payment['cardnum'], "expirationMonth" => $exp_month, "expirationYear" => $exp_year, "cvv" => $payment['cardcode']); $purchaseTotals = array("grandTotalAmount" => (string) $payment['amount']); $result = $this->Cybersource->purchase($billTo, $card, $purchaseTotals); $payment['transaction_id'] = $result->requestID; $payment['processor'] = OrderPaymentProcessor::PROCESSOR_CYBERSOURCE; if ($result->reasonCode != 100) { $payment['status'] = "failed"; return $this->voidTransactions($processedPayments, $this->Cybersource->reasonDescriptions[$result->reasonCode]); } else { $payment['status'] = "success"; $processedPayments[] = $payment; } break; case self::GATEWAY_BRAINTREE: $result = $this->Braintree->purchase($payment, $_POST['device_data']); if (YOUNIQUE_TESTSERVER) { CakeLog::debug(var_export($result, true)); } if ($result->success) { $payment['status'] = "success"; $payment['paid_with'] = ''; if (!empty($result->transaction->creditCardDetails->last4)) { $payment['identifier'] = $result->transaction->creditCardDetails->last4; if (substr($result->transaction->creditCardDetails->maskedNumber, 0, 1) == '4') { //All Visa cards start with 4 $payment['paid_with'] = 'visa'; } elseif (in_array(substr($result->transaction->creditCardDetails->maskedNumber, 0, 2), ['51', '52', '53', '54', '55'])) { //All MasterCard cards start with either 51,52,53,54,55 $payment['paid_with'] = 'mastercard'; } } else { if (!empty($result->transaction->paypalDetails->paymentId)) { $payment['identifier'] = $result->transaction->paypalDetails->payerEmail; $payment['paid_with'] = 'paypal'; } else { $payment['identifier'] = $result->transaction->id; } } $payment['transaction_id'] = $result->transaction->id; $processedPayments[] = $payment; } else { if (isset($result->errors)) { $errors = $result->errors->deepAll(); } if (!empty($errors)) { // errors can be referenced here: // https://developers.braintreepayments.com/javascript+php/sdk/server/transaction-processing/validations $api_errors = $result->errors->deepAll(); $errors = []; foreach ($api_errors as $key => $value) { $errors[] = $value->message; } $internal_use_error = implode(" ", $errors); $error = __('There was an error. Please contact support.'); // log to api log table $this->ApiAudit = ClassRegistry::init('ApiAudit'); $api_data = ['reference_name' => get_class(), 'reference_id' => 0, 'source' => __FILE__ . ' ' . __LINE__, 'destination' => 'braintree api', 'sent' => json_encode($this->Braintree->payment_data), 'received' => $internal_use_error, 'notes' => 'Braintree validation fail']; $this->ApiAudit->clear(); $this->ApiAudit->create($api_data); $this->ApiAudit->save(); } else { // decline /** * Error overwrites as per Michael Gulbrandsen */ switch ($result->transaction->processorResponseCode) { case 1000: $error = "We are unable to process your transaction given the " . "information provided. Please provide an alternate form of " . "payment or reach out to your bank for more information."; break; case 3000: $error = "We're sorry, we cannot process your transaction " . "at this time. Please try again."; break; default: $subject = "BrainTree Payment Decline"; $error = "We are unable to process your transaction given the " . "information provided. Please provide an alternate form of " . "payment or reach out to your bank for more information."; $message = "Status: " . $result->transaction->status . " Code: " . $result->transaction->processorResponseCode . " Message: " . $result->transaction->processorResponseText . "\n"; $message .= var_export($result, true); SNS::sendSNS("Payment_Declines", $subject, $message); break; } } return $this->voidTransactions($processedPayments, $error); } break; default: return FALSE; break; } } } if (count($paypalPayments) > 0) { foreach ($paypalPayments as $payment) { $expressPayment = $this->Paypal->getExpressCheckout($payment['token']); //need to return token, paypal user id, amount, and currency $token = $expressPayment->GetExpressCheckoutDetailsResponseDetails->Token; $payerId = $expressPayment->GetExpressCheckoutDetailsResponseDetails->PayerInfo->PayerID; $amount = $expressPayment->GetExpressCheckoutDetailsResponseDetails->PaymentDetails->OrderTotal->value; $currency = $expressPayment->GetExpressCheckoutDetailsResponseDetails->PaymentDetails->OrderTotal->currencyID; //can compare payer userid, amount, currency to validate transaction here if needed //also could make sure the receiving acct is correct $result = $this->Paypal->doExpressCheckout($token, $payerId, $amount, $currency); $payment['identifier'] = $payment['user_id']; if ($result->Ack != "Success") { $payment['status'] = "failed"; if (isset($result->TransactionID)) { $payment['transaction_id'] = $result->TransactionID; } return $this->voidTransactions($processedPayments, $result->Errors->LongMessage); } else { $payment['transaction_id'] = $result->DoExpressCheckoutPaymentResponseDetails->PaymentInfo->TransactionID; $payment['status'] = "success"; $processedPayments[] = $payment; } } } foreach ($processedPayments as $key => $payment) { if ($processedPayments[$key]['type'] == OrderPayment::TYPE_LEDGER_NAME) { $this->ProductCredit->capture($processedPayments[$key]['presenter_id'], $processedPayments[$key]['user_id'], $processedPayments[$key]['transaction_id']); $processedPayments[$key]['status'] = "success"; } } } catch (Exception $e) { if (YOUNIQUE_TESTSERVER != true) { YouniqueEmail::queueEmail(['date' => date('Y-m-d H:i:s'), 'reference_id' => $referenceId, 'message' => $e->getMessage(), 'trace' => $e->getTraceAsString()], 'admin/paymentfailure', '*****@*****.**', 'Payment failure', 'paymentFailure', 'en_US'); } return ["success" => false]; } return ["success" => true, "payments" => $processedPayments]; }
/** * Send Sns Alert * * @param $message * @param null $subject */ protected function sendSnsAlert($message, $subject = null) { if (empty($subject)) { $subject = "{$this->sqs_name} SQS Alert"; } $message = "An alert has been triggered for {$this->sqs_name}.\n\n" . "{$message}\n\n" . "SQS message available in queue: \n" . $this->primarySqsUrl() . "\n" . "https://younique.signin.aws.amazon.com/console"; try { SNS::sendSNS($this->sns_topic, $subject, $message); } catch (Exception $e) { $this->logMsg("SNS Topic {$this->sns_topic} not configured correctly.", false, true); } }
/** * Send Sns Error message * * @param $message */ private function sendErrorMessage($message) { $subject = "Foundation Donation Cron Failed"; $message = ".\n" . $message . "\n"; SNS::sendSNS("crons", $subject, $message); }
/** * Invoked when a 400 response is received from Snap due to a missing SKU */ private function _nonExistentItemProcessing() { //Delete order from Snap $this->deleteShipment($this->snap_order['ShipmentId']); //Send to Amazon SNS Service (email, SMS, Slack) $subject = "Snap API Missing Sku Alert ORD# {$this->snap_order['CustomerRef']}"; $message = "Failed to update Snap, API responded with 400 - bad SKUid item missing\n" . "View Order: https://admin.youniqueproducts.com/admin3/orders.php?order_id={$this->snap_order['CustomerRef']}"; SNS::sendSNS("Logistics_Alert", $subject, $message); //Put order in new 'Order Shipment Status' (9) called "Incomplete order in WMS" $this->OrderShipment->clear(); $this->OrderShipment->id = $this->snap_order['ShipmentId']; $this->OrderShipment->saveField("order_shipment_status_id", OrderShipmentStatus::INCOMPLETE_ORDER_WMS); $this->OrderShipment->saveField("order_id", $this->snap_order['CustomerRef']); //Add to order log $this->UserNote->clear(); $this->UserNote->save(['user_id' => $this->user_id, 'note' => "Removed shipment from Snap, sent error to Logistics team, set shipment to 'WMS Incomplete'", 'reference_type' => 'order', 'reference_id' => $this->snap_order['CustomerRef'], 'user_note_status' => 'normal']); }
/** * Main execute function of Refresh Low Items Shell */ public function main() { $this->stdout->styles('backorder', ['text' => 'red']); $this->_waitForLock(); $this->_startDateTime = date("Y-m-d H:i:s", strtotime('-30 minutes')); $now = date("Y-m-d H:i:s"); $this->ItemAvailabilityTimes->useDbConfig = 'default'; /** * This sets availability to be true (Just send email) * or false item availability gets set to backorder. */ $this->_disableSetAvailability = $this->args['0'] == "enable" ? false : true; if ($this->_disableSetAvailability) { $this->out('Setting Item Availability is disabled. Emails only.', 1, Shell::VERBOSE); } else { $this->out('Setting Item Availability is enabled.', 1, Shell::VERBOSE); } // read data from low_items $NsLowItem = $this->NsLowItem->find('all', []); $this->out("Processing " . count($NsLowItem) . " Low Items.", 1, Shell::VERBOSE); foreach ($NsLowItem as $aNsLowItem) { // get the number of order items since startDateTime $OrderItem = $this->OrderItem->find('all', ['fields' => ['SUM(OrderItem.quantity) AS BBQ', 'OrderItem.item_id'], 'joins' => [['table' => 'items', 'alias' => 'Item', 'type' => 'INNER', 'conditions' => ['OrderItem.item_id = Item.id']]], 'conditions' => ['Item.sku' => $aNsLowItem['NsLowItem']['sku'], 'OrderItem.date_created >=' => $this->_startDateTime, 'OrderItem.ns_warehouse_id' => $aNsLowItem['NsLowItem']['ns_warehouse_id']], 'group' => ['OrderItem.item_id']]); $this->out("SKU: " . $aNsLowItem['NsLowItem']['sku'], 1, Shell::NORMAL); $this->out("Inv Count: " . $aNsLowItem['NsLowItem']['inventory_count'], 1, Shell::NORMAL); $this->out("Agg Quant: " . (int) $OrderItem[0][0]['BBQ'], 1, Shell::NORMAL); $this->out("Threshold: " . $aNsLowItem['NsLowItem']['threshold'], 1, Shell::NORMAL); $this->out('Order item count: ' . (int) $OrderItem[0][0]['BBQ']); $this->NsLowItem->updateAll(['NsLowItem.order_count' => $OrderItem[0][0]['BBQ']], ['NsLowItem.id' => $aNsLowItem['NsLowItem']['id']]); if ($aNsLowItem['NsLowItem']['inventory_count'] - (int) $OrderItem[0][0]['BBQ'] < $aNsLowItem['NsLowItem']['threshold']) { // implement back order policy // See if the item is already unavailable $redundantItem = $this->Item->find('first', ['conditions' => ['Item.sku' => $aNsLowItem['NsLowItem']['sku']]]); $isAvailable = $this->Item->getIsAvailableById($redundantItem['Item']['id']); if (!$isAvailable) { continue; } if (!$this->_disableSetAvailability) { $this->ItemAvailabilityTimes->updateAll(['end_date' => '"' . trim($now) . '"'], ['ItemAvailabilityTimes.item_id' => $redundantItem['Item']['id'], 'ItemAvailabilityTimes.ns_warehouse_id' => $aNsLowItem['NsLowItem']['ns_warehouse_id'], 'ItemAvailabilityTimes.end_date IS NULL']); $this->ItemAvailabilityTimes->clear(); $this->ItemAvailabilityTimes->create(); $this->ItemAvailabilityTimes->save(['item_id' => $redundantItem['Item']['id'], 'item_availability_id' => $aNsLowItem['NsLowItem']['item_availability_id'], 'ns_warehouse_id' => $aNsLowItem['NsLowItem']['ns_warehouse_id'], 'estimated_date' => $aNsLowItem['NsLowItem']['restock_date'], 'start_date' => $now]); $setAvailabilityMessage = 'Set Availability is enabled the product: ' . $aNsLowItem['NsLowItem']['sku'] . ' has been set to backorder.'; /** * Clean up product count */ $this->NsLowItem->clear(); $this->NsLowItem->delete($aNsLowItem['NsLowItem']['id']); } else { $setAvailabilityMessage = "Set Availability is disabled only notification was sent no action was taken.\n\n"; } // tell an adult $this->out("<backorder>I am notifying you of a back-order policy implementation!</backorder>", 1, Shell::NORMAL); $subject = "Backorder Policy Implementation Alert"; $word = $this->_iatToWord($aNsLowItem['NsLowItem']['item_availability_id']); $message = "An item (SKU {$aNsLowItem['NsLowItem']['sku']}) has gone into {$word} status.\n\n" . $setAvailabilityMessage . "\n" . "To look at backorder policies, visit the following URL:\n" . "https://admin.youniqueproducts.com/admin3/warehouse.php#/warehouse/backorder\n\n" . "If you are not logged in, please first visit:\n" . "https://admin.youniqueproducts.com/admin3/index.php"; SNS::sendSNS("Shipping_Issues", $subject, $message); } } $this->_releaseLock(); }
/** * Send Error SNS * @param $order_id * @param $error_data */ private function sendError($order_id, $error_data) { $subject = "Shipment Method Error Alert"; $message = "Setting shipment method failed [order_id: {$order_id}].\n" . "Message: \n" . var_export($error_data, true); SNS::sendSNS("Order_Queue_Issues", $subject, $message); }
public function natesSns() { $subject = "Snap API Missing Sku Alert ORD# xxxxxx"; $message = "Failed to update Snap, API responded with 400 - bad SKUid item missing\n" . "https://admin.youniqueproducts.com/admin3/orders.php?order_id=xxxxx"; SNS::sendSNS("Logistics_Alert", $subject, $message); $this->out("<error> sending out test </error>"); }
public function sendSnsEmail() { if ($_SERVER['REMOTE_ADDR'] == "127.0.0.1") { $data = $this->request->data; if (empty($data['resource']) || empty($data['subject']) || empty($data['message'])) { $result = 'Please supply a resource, subject and message.'; } else { $response = SNS::sendSNS($data['resource'], $data['$subject'], $data['message']); $result = $response; } $this->set(array('result' => $result, '_serialize' => ['result'])); } }
/** * Pay Retail Commission * * Used by Commission Sqs Queue to pay commissions * * @param $commission * @param null $queue_message * @see PayCommissionTask * @see CommissionSqsShell * @see QueueCommissionsTask * @return bool|mixed|stdClass */ public function payRetailCommission($commission, &$queue_message = null) { $config = array(); $config_file = parse_ini_file("/etc/younique/payquicker.ini", true); $address = $this->Presenter->loadAddressDetails($commission['presenter_id']); $state_code = $address['User']['Address']['State']['abbrev']; $country_code = $address['User']['Address']['Country']['country_code']; $us_domestic = FALSE; switch ($commission['currency']) { case 'USD': if (in_array($state_code, $this->us_territories)) { $config['payquicker'] = $config_file['USD_INT']; } else { $config['payquicker'] = $config_file['USD_DOM']; } $us_domestic = TRUE; break; case 'CAD': $config['payquicker'] = $config_file['CAD']; break; case 'AUD': $config['payquicker'] = $config_file['AUD']; break; case 'NZD': //NZD Gets paid from the USD international account $config['payquicker'] = $config_file['NZD']; break; case 'GBP': $config['payquicker'] = $config_file['GBP']; break; case 'EUR': $config['payquicker'] = $config_file['EUR']; break; case 'MXN': $config['payquicker'] = $config_file['MXN']; break; default: // this should never happen $this->apiLog("royalties_earned.id", $commission['id'], "RoyaltiesEarned->payRetailCommission", "PayQuicker API", var_export($commission, true), "", "Could not load config for this currency", 1); error_log("Could not load config for this currency"); return FALSE; break; } $this->Presenter->RoyaltiesEarned->id = $commission['id']; //Withhold appropriate taxes: switch ($commission['market_id']) { case 6: //Mexico $commission = $this->withholdMexicoTaxes($commission); break; case 8: //France $payFr = $this->payFranceCommissions($commission['presenter_id']); if (strtoupper($payFr) == 'VDI') { $commission = $this->withholdFranceTaxes($commission); } break; default: break; } App::uses("PayquickerAPI", "Lib"); $royalties_withheld = $this->Presenter->getDynamicData($commission['presenter_id'], 'royalties_withheld'); if (isset($royalties_withheld[0]) && $royalties_withheld[0]['value'] == 1) { $this->Presenter->RoyaltiesEarned->saveField("reference_id", 'Royalties_Withheld'); return 'Royalties_Withheld'; } $dateEarned = $commission['date_earned']; $dateExpires = date("m/d/Y", strtotime("next year", strtotime($dateEarned))); $orderId = $commission['order_id']; $payeeName = $commission['first_name']; $recipientEmail = $commission['payquickeremail']; $paymentObject = array("authorizedKey" => $config['payquicker']['authorizedKey'], "senderEmail" => $config['payquicker']["senderEmail"], "recipientEmail" => $recipientEmail, "amount" => $commission['amount'], "comment" => "Hi {$payeeName}, This is your retail royalty for order #{$orderId}. Congratulations! We are proud of your online success.", "expirationDate" => $dateExpires, "forceDebitCard" => $commission['forceCard'], "accountingId" => $orderId, "currency" => $commission['currency'], "countryCode" => $country_code); if ($us_domestic === TRUE) { $paymentObject['stateCode'] = $state_code; } $this->Presenter->RoyaltiesEarned->saveField("date_attempted", date("Y-m-d H:i:s")); /** * Empty amounts should not be tried against payquicker * and are set to paid status */ if (empty($paymentObject['amount'])) { $this->Presenter->RoyaltiesEarned->saveField("date_paid", date("Y-m-d H:i:s")); $this->Presenter->RoyaltiesEarned->saveField("royalty_status_id", RoyaltiesEarned::STATUS_IS_PAID); return true; } if (YOUNIQUE_TESTSERVER === true) { $response = new stdClass(); $response->success = true; $response->reference = 'QATesting:' . $commission['order_id']; } else { $response = PayquickerAPI::call("instantPayment", $paymentObject); } if ($response->success == true) { $this->Presenter->RoyaltiesEarned->saveField("date_paid", date("Y-m-d H:i:s")); $this->Presenter->RoyaltiesEarned->saveField("reference_id", $response->reference); $this->Presenter->RoyaltiesEarned->saveField("royalty_status_id", RoyaltiesEarned::STATUS_IS_PAID); } else { /** * If error is duplicate update royalties earned data * if it is not already set. */ if (!empty($response) && isset($response->status)) { if ($response->status == 'Duplicate') { $duplicate = $this->find('first', ['conditions' => ['RoyaltiesEarned.id' => $commission['id']]]); if (empty($duplicate['RoyaltiesEarned']['date_paid'])) { $this->Presenter->RoyaltiesEarned->saveField("date_paid", date("Y-m-d H:i:s")); } if (empty($duplicate['RoyaltiesEarned']['reference_id'])) { $this->Presenter->RoyaltiesEarned->saveField("reference_id", $response->reference); } if (empty($duplicate['RoyaltiesEarned']['royalty_status_id'])) { $this->Presenter->RoyaltiesEarned->saveField("royalty_status_id", RoyaltiesEarned::STATUS_IS_PAID); } return true; } } /** * Send pay quicker error only once */ if (!empty($queue_message) && empty($queue_message['failure'])) { $queue_message['failure'] = $response; // Remove the key since this is going into an email unset($paymentObject['authorizedKey']); $message_body = "There was an error posting a retail commission, here are the details:\n\n" . var_export($paymentObject, true) . "\n\nHere is the response we got:\n\n" . var_export($response, true); SNS::sendSNS('PayQuicker_Issues', "Failure to Pay Retail Commission [{$recipientEmail}]", $message_body); } /** * Return true status on state code failure * so queue will not retry it. */ if (!empty($response) && isset($response->errorMessage)) { if ($response->errorMessage == 'stateCode is Required.') { return true; } } return false; } return $response; }
/** * Send Sns Error message * * @param $message_id * @param $receipt * @param $err */ private function sendErrorMessage($message_id, $receipt, $err) { $subject = "{$this->queue_name} Queue Alert"; $message = "A {$this->queue_name} Task has failed [message_id: {$message_id}].\n" . "Message: \n" . "{$err}\n" . "Queue message available in queue: " . AWS_ORDERS_SQS_URL . "\n" . "[\n" . " message_id: {$message_id}\n" . " receipt: {$receipt} \n" . "]\n" . "https://younique.signin.aws.amazon.com/console"; SNS::sendSNS($this->sns_name, $subject, $message); }
/** * Send Sns Error message * * @param $message_id * @param $receipt * @param $err */ private function sendErrorMessage($message_id, $receipt, $err) { $subject = "Email Queue Alert"; $message = "An Email Queue Task has failed [message_id: {$message_id}].\n" . "Message: \n" . "{$err}\n" . "Message data available in table: " . $this->table . "\n" . "Queue message available in queue: " . $this->queue . "\n" . "[\n" . " message_id: {$message_id}\n" . " receipt: {$receipt} \n" . "]\n" . "https://younique.signin.aws.amazon.com/console"; SNS::sendSNS("Order_Queue_Issues", $subject, $message); }