phpclassic / php-shopify

PHP SDK for Shopify API
Apache License 2.0
568 stars 211 forks source link

Fulfilled an order by creating new fulfillment #285

Open AntoineLHF opened 1 year ago

AntoineLHF commented 1 year ago

Hello,

I try to develop a Symfony app in wich I would like to change the value of fulfillment_status for an order, from null to fulfilled. First of all, I tried :

$updateInfo = array (
        "fulfillment_status" => "fulfilled",
        "email"=>"test@test.fr"
);
$res = $shopify->Order($orderId)->put($updateInfo);

But, even if the email field is updated as expected, the value of fulfillment_status doesn't changed.

I finally find that I have to manage fulfillment object to change the fulfillment_status of an order. I found some posts (#283 and #268 ) about how to update an existing fulfillment, but, in my case, fulfillment is null : "fulfillments" => []

So I tried to create one by this way :

$newFulfillment = [
    "order_id" => $orderId
];
$shopify->Fulfillment->post($newFulfillment);

But I get this error : The required line_items_by_fulfillment_order field is missing. And when I try :

$newFulfillment = array (
        "order_id" =>$orderId,
        "line_items_by_fulfillment_order" => [
            "fulfillment_order_id" => $orderId
          ],
       );

I get : line_items_by_fulfillment_order - expected Hash to be a Array

I suppose something wrong in the content-type, but I don't know hom to deal with this.

My init :

 $config = array(
      'ShopUrl' => $_ENV['SHOPIFY_APP_HOST_NAME'],
      'ApiKey' => $_ENV['SHOPIFY_API_KEY'],
      'AccessToken' => $_ENV['SHOPIFY_ACCESS_TOKEN'],
      'ApiVersion' => "2023-01",
);
ShopifySDK::config($config);
$shopify = new ShopifySDK($config);
zamliyconsulting commented 1 year ago
function postFulfillment($locid,$trackingnumber,$trackingcompany,$trackingurl,$config){
    global $config;
    $postdata = array (
        "location_id" => $locid,
        "tracking_number" => $trackingnumber,
        "tracking_company" => $trackingcompany,
        "tracking_url" => $trackingurl
    );
    fulfillOrder($orderid,$postdata,$config);
}

function fulfillOrder($orderid,$postdata,$config){
    $shopify = new PHPShopify\ShopifySDK($config);
    return $shopify->Order($orderid)->Fulfillment->post($postdata);
}
AntoineLHF commented 1 year ago

Hi @zamliyconsulting Thank you for your reply, but I already get the message "The required line_items_by_fulfillment_order field is missing"

tareqtms commented 1 year ago

Please check the latest release.

PHPism commented 1 year ago

@zamliyconsulting As I see in your postFulfillment function. fulfillOrder($orderid,$postdata,$config); But you don't have $orderid in your code. The way I do it is get the original order data, then create $fulfillment_order_line_items array and include it with the post data.

$params = array(
    'name' => $order_number,
);
$shopifyOrders = $shopify->Order->get($params);
if(isset($shopifyOrders[0]['id']))
{
    $shopifyOrder = $shopifyOrders[0];

    $fulfillment_order_line_items = array();

    foreach($shopifyOrder['line_items'] as $line_item)
    {
        $fulfillment_order_line_item = array();
        $fulfillment_order_line_item['id'] = $line_item['id'];
        $fulfillment_order_line_item['quantity'] = $line_item['quantity'];

        $fulfillment_order_line_items[] = $fulfillment_order_line_item;
    }

    $postInfo = array(
        "location_id" => $shopify_location_id,
        "tracking_number" => null,
        "tracking_urls" => [],
        "notify_customer" => true,
        "line_items_by_fulfillment_order" => array(
            "fulfillment_order_id" => $shopifyOrder['id'],
            "fulfillment_order_line_items" => $fulfillment_order_line_items,
        ),
    );

    $shopify->Order($shopifyOrder['id'])->Fulfillment->post($postInfo);
}

Hope this will help.

tonytoms commented 1 year ago

return $shopify->Order($orderid)->Fulfillment->post($postdata); $shopify->Order($orderid)->Fulfillment->post($postdata); Isn't this one Deprecated?

folz14 commented 1 year ago

The "line_items_by_fulfillment_order - expected Hash to be a Array" is due to how $newFulfillment is formatted. Try the below - where $item is the line_item in the FulfillmentOrder;

$newFulfillment = array(
    'location_id' => $item['assigned_location_id'],
    'tracking_number' => null,
    'notify_customer' => false,
    'line_items_by_fulfillment_order' => [
        array(
            'fulfillment_order_id' => $item['fulfillment_order_id'],
            'fulfillment_order_line_items' => [
                array(
                    'id' => $item['id'],
                    'quantity' => $item['quantity']
                )
            ]
        )
    ]
);

Here is a working code assuming you have your $order and $shopify objects. Note that you have to use the fulfillment_order_id as of API version 2022-07

if ($order['id']){
    //Get FulfillmentOrder
    $FulfillmentOrders = $shopify->Order($order['id'])->FulfillmentOrder()->get();
    if(!empty($FulfillmentOrders)){
        foreach($FulfillmentOrders as $FulfillmentOrder){
            foreach($FulfillmentOrder['line_items'] as $item){
                //Fulfill only items not yet fulfilled
                if($item['fulfillable_quantity'] > 0){
                    try{
                        $data = array(
                            'location_id' => $item['assigned_location_id'],
                            'tracking_number' => null,
                            'notify_customer' => false,
                            'line_items_by_fulfillment_order' => [
                                array(
                                    'fulfillment_order_id' => $item['fulfillment_order_id'],
                                    'fulfillment_order_line_items' => [
                                        array(
                                            'id' => $item['id'],
                                            'quantity' => $item['quantity']
                                        )
                                    ]
                                )
                            ]
                        );
                        $Fulfillment = $shopify->Fulfillment->post($data);
                    } catch(Exception $e) {
                        echo 'Caught exception - Fulfillment Items: ' . $order['id'] . ' - ',  $e->getMessage(), "\n";
                        continue;
                    }
                }
            }
        }
    }
}