Skip to content

Instantly share code, notes, and snippets.

@shanerbaner82
Created September 9, 2019 17:55
Show Gist options
  • Save shanerbaner82/2e9f42bfcc74e31692c2ae05fd556c8a to your computer and use it in GitHub Desktop.
Save shanerbaner82/2e9f42bfcc74e31692c2ae05fd556c8a to your computer and use it in GitHub Desktop.
Modified to retroactively fulfill orders
<?php
namespace App\Console\Commands;
use App\Models\Order;
use App\Models\xcart\ShopifyAPI;
use Carbon\Carbon;
use Exception;
use GuzzleHttp\RequestOptions;
use Illuminate\Console\Command;
use stdClass;
class ShopifyFulfillmentCatchAll extends Command
{
protected $signature = 'fulfillment:shopify-catchall';
public function handle()
{
$start = Carbon::today()->startOfDay()->subDays(20);
$end = Carbon::today()->endOfDay();
$od = collect(\DB::connection('se')->table('Order Details')
->whereBetween('DateShipped', [$start, $end])
->whereNull('FulfillmentStatus')
->groupBy('OrderNumber')
->get(['OrderNumber']))
->map(function ($i, $t) {
return ($i->OrderNumber);
});
$orders = Order::with([
'tracking' => function ($q) use ($start, $end) {
$q->whereBetween('DateAdded', [$start, $end]);
$q->whereIn('fulfillment_uploaded', [null, 0]);
}
])
->whereIn('OrderNumber', $od)
->whereIn('CartID', [22, 23, 24, 27, 26])
->get()
->filter(function ($order) {
return $order->tracking->count() > 0;
})->pluck('OrderNumber');
$fulfillable_orders = $this->getOrders($orders, $start, $end);
if (count($fulfillable_orders)) {
//CREATE STATUS BAR
$bar = $this->output->createProgressBar(count($fulfillable_orders));
$bar->setFormat(' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%');
//CREATE AN ARRAY OF METADATA SO WE CAN MAKE SOME CALCULATIONS AND FILTER TRACKING AND SKUS
foreach ($fulfillable_orders as $order) {
$meta = collect([
'totalDetails' => ($order->order_details), //ALL ORDER ITEMS INCLUDING TAX AND SHIPPING
'fulfillable' => ($order->order_details()//ALL FULFILLABLE ITEMS (HAS AN EXPECTED SHIPDATE OR IS OVERSIZED HANDLING FEE WHICH NEEDS TO BE FULFILLED IN SHOPIFY)
->where(function ($q) {
$q->where('ExpectedShipDate', '!=', null)->orWhere('SKU', 'Surcharge');
})),
'printed_today' => ($order->order_details()//PRINTED TODAY
->where(function ($q) use($start, $end) {
$q->whereBetween('DateShipped', [$start, $end])->orWhere('SKU', 'Surcharge');
})),
'already_shipped' => ($order->order_details()//ITEMS THAT HAVE SHIPPED ON A PREVIOUS DAY
->where(function ($q) use($start, $end){
$q->where('DateShipped', '<', $start);
})),
'todays_tracking_numbers' => $order->tracking()//TRACKING NUMBERS FOR THIS ORDER THAT WERE CREATED TODAY
->where(function ($q) use($start, $end){
$q->where('DateAdded', '>=', $start);
})
]);
$order->fulfillment_meta = $meta->map(function ($i) {
return ($i->count());
});
//GET THE CART
switch ($order->CartID) {
case 23:
case 24:
case 27:
case 26:
$location_id = env('BB_SHOPIFY_LOCATIONID');
$s = new ShopifyAPI('bb');
break;
case 22:
$location_id = env('FGT_SHOPIFY_LOCATIONID');
$s = new ShopifyAPI('fgt');
break;
}
$tracking_array = [];
$todays_tracking = $meta['todays_tracking_numbers']->get()->groupBy('Carrier');
foreach ($todays_tracking as $carrier => $tracking) {
foreach ($tracking as $track) {
$tracking_array[$carrier][] = $track->TrackingID;
}
}
$todays_fulfillable_items = $meta['printed_today']
->get(['OrderNumber', 'Product', 'SKU', 'DateShipped', 'ExpectedShipDate', 'MarketLineID', 'FulfillmentStatus', 'QuantityOrdered'])
->filter(function ($od) {
return $od->FulfillmentStatus == null && $od->MarketLineID != null;
});
if (count($todays_fulfillable_items) && count($tracking_array)) {
$items_array = array();
foreach ($todays_fulfillable_items as $item) {
if ($item->MarketLineID != null) {
array_push($items_array, ['id' => $item->MarketLineID]);
}
}
$shopify_fulfillments = [];
if (count($todays_tracking) > 1) {
if (count($items_array) === 1) {
$shopify_fulfillments = $this->createQuantitySplitFulfillmentObject($order, $todays_fulfillable_items->toArray(), $tracking_array, true, $location_id);
} else {
$shopify_fulfillments = $this->handleMultipleCarrierFulfillments($order, $items_array, $tracking_array, $location_id);
}
} else {
$shopify_fulfillments[] = $this->createFulfillmentObject($order, $items_array, collect(array_values($tracking_array))->flatten()->toArray(), key($tracking_array), true, $location_id);
}
foreach ($shopify_fulfillments as $fulfillment) {
$this->sendFulfillment($s, $order, $fulfillment, $todays_tracking);
}
}
$bar->advance();
}
$bar->finish();
} else {
$this->comment('No orders to fulfill!');
}
}
private function createFulfillmentObject($order, $items, $tracking, $carrier, $notify = false, $location_id)
{
$f = new stdClass();
$f->fulfillment = [
'location_id' => $location_id,
'tracking_numbers' => $tracking,
'tracking_company' => $carrier,
'line_items' => $items,
'status' => 'pending',
'shipment_status' => 'label_printed',
'notify_customer' => false
];
return $f;
}
private function createQuantitySplitFulfillmentObject($order, $items, $tracking, $notify = false, $location_id)
{
$first_tracking = (array_slice($tracking, 0, 1));
$rest_of_tracking = (array_slice($tracking, 1));
$first_carrier = array_keys($first_tracking)[0];
$second_carrier = array_keys($rest_of_tracking)[0];
$totalQuantity = collect($items)->first()['QuantityOrdered'];
$remainder = $totalQuantity - 1;
$line_item = collect($items)->first()['MarketLineID'];
$firstItem = [[
'id' => $line_item,
'quantity' => 1
]];
$remainingItems = [[
'id' => $line_item,
'quantity' => $remainder
]];
$f = new stdClass();
$f->fulfillment = [
'location_id' => $location_id,
'tracking_numbers' => array_values($first_tracking)[0],
'tracking_company' => $first_carrier,
'line_items' => $firstItem,
'status' => 'pending',
'shipment_status' => 'label_printed',
'notify_customer' => false
];
$f2 = new stdClass();
$f2->fulfillment = [
'location_id' => $location_id,
'tracking_numbers' => array_values($rest_of_tracking)[0],
'tracking_company' => $second_carrier,
'line_items' => $remainingItems,
'status' => 'pending',
'shipment_status' => 'label_printed',
'notify_customer' => false
];
$fulfillments = [];
$fulfillments[] = $f;
$fulfillments[] = $f2;
return $fulfillments;
}
private function handleMultipleCarrierFulfillments($order, $items_array, $tracking_array, $location_id)
{
$first_item = (array_slice($items_array, 0, 1));
$first_tracking = (array_slice($tracking_array, 0, 1));
$rest_of_items = (array_slice($items_array, 1));
$rest_of_tracking = (array_slice($tracking_array, 1));
$fulfillments = [];
$fulfillments[] = $this->createFulfillmentObject($order, $first_item, collect(array_values($first_tracking))->flatten()->toArray(), key($first_tracking), false, $location_id);
if (count($rest_of_items) > 0) {
$fulfillments[] = $this->createFulfillmentObject($order, $rest_of_items, collect(array_values($rest_of_tracking))->flatten()->toArray(), key($rest_of_tracking), false, $location_id);
}
return $fulfillments;
}
private function sendFulfillment($api_object, $order, $fulfillment_object, $tracking)
{
// dd($api_object, $order, $fulfillment_object);
// dd($order->SourceOrderID, $order->CartID);
// dd(json_encode($fulfillment_object));
// dd($order->OrderNumber);
try {
$api_object->makeRequest('POST', 'orders/' . $order->SourceOrderID . '/fulfillments.json', [RequestOptions::JSON => $fulfillment_object]);
$items = array_values(collect($fulfillment_object->fulfillment['line_items'])->flatten()->toArray());
$order->order_details()->whereIn('MarketLineID', $items)->get()->each(function (&$item) use ($fulfillment_object) {
$item->FulfillmentStatus = true;
$item->FulfillmentTime = Carbon::now();
$item->FulfillmentCenter = $fulfillment_object->fulfillment['tracking_company'];
$item->save();
});
$tracking->each(function ($carrier) {
$carrier->each(function ($track) {
try {
$track->fulfillment_uploaded = 1;
$track->save();
} catch (Exception $m) {
$this->warn($m->getMessage());
}
});
});
// die();
} catch (Exception $e) {
$this->info($e->getMessage());
$this->info($order->OrderNumber);
// die();
}
}
private function getOrders($ids, $start, $end)
{
return Order::with([
'tracking' => function ($q) use ($start, $end) {
$q->whereBetween('DateAdded', [$start, $end]);
},
'order_details'
])
->whereIn('OrderNumber', $ids)
->get(['OrderNumber', 'SourceOrderID', 'CartID']);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment