-
-
Notifications
You must be signed in to change notification settings - Fork 312
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check here for common issues with fulfilling line items and orders #828
Comments
In particular, this code in my app is not working anymore since switching to the latest release (I was a bit behind in releases, so this might as well have been caused by a breaking change in a previous update). var fulfillment = new Fulfillment()
{
TrackingCompany = "DPD",
TrackingUrl = String.Format(Settings.Default.ShopifyDPDTrackingUrl, mTrackingNr),
TrackingNumber = mTrackingNr,
LocationId = mShopconfig.FulfillmentLocationId,
NotifyCustomer = true
};
fulfillment = await mFulfillmentService.CreateAsync(mOrder.Id.Value, fulfillment); Can anyone please give a hint on how this code should look like nowadays? I am aware that I can create Thanks for the awsome work in this project btw! |
Thanks for the heads up! That definitely needs to be updated. Fulfillments are slightly more complicated now, you need to work with the You can find our tests for the var fulfillments = new FulfillmentService(domain, accessToken);
var fulfillmentOrders = new FulfillmentOrderService(domain, accessToken);
var orderId = 123456;
// Find open fulfillment orders for this order
var openFulfillmentOrders = await fulfillmentOrders.ListAsync(orderId);
openFulfillmentOrders = openFulfillmentOrders.Where(f => f.Status == "open").ToList();
// Fulfill the line items
var lineItems = openFulfillmentOrders.Select(o => new LineItemsByFulfillmentOrder
{
FulfillmentOrderId = o.Id.Value
// Optionally specify a list of line items if you're doing a partial fulfillment
// FulfillmentRequestOrderLineItems = ...
});
var fulfillment = await fulfillments.CreateAsync(new FulfillmentShipping
{
Message = "items are shipping!",
FulfillmentRequestOrderLineItems = lineItems,
NotifyCustomer = true,
TrackingInfo = new TrackingInfo
{
Company = "UPS",
Url = "...",
Number = "..."
}
}); Let me know if that answers your question! Edit A note on partially fulfilling line items. The Yes, it's confusing. Here's an example that I'm using in a guide I'm writing for using ShopifySharp to do fulfillments. In the example, the user will be able to select which line items in a single fulfillment order (not an order, a fulfillment order) will be fulfilled. Here's how we'd do that: var fulfillmentService = new FulfillmentService(domain, accessToken);
var fulfillmentOrderService = new FulfillmentOrderService(domain, accessToken);
var fulfillmentOrderId = 123456789L;
// Get this fulfillment order
var fulfillmentOrder = await fulfillmentOrderService.GetAsync(fulfillmentOrderId);
// In this example, we let the user choose which line items in this particular fulfillment order will be fulfilled
// Where request = some kind of form post or json model
long[] itemIds = request.ItemsToFulfill;
// Wrap the desired line items together with the fulfillment order id
var fulfillmentOrderLineItems = new LineItemsByFulfillmentOrder
{
FulfillmentOrderId = fulfillmentOrderId,
// This is where you do a partial fulfillment. Using this property means you're telling Shopify "only fulfill these parts of the fulfillment order".
FulfillmentRequestOrderLineItems = itemIds.Select(itemId => new FulfillmentRequestOrderLineItem
{
// NOTE: This Id property is not the same as a `FulfillmentOrderLineItem.LineItemId` value!
// You want to use `FulfillmentOrderLineItem.Id` instead.
Id = itemId,
// You need to tell Shopify how much of this single item to fulfill. You must ensure that
// you are not fulfilling more than the fulfillable quantity, or else Shopify will throw an error.
// In this example, we just want to fulfill all of the available line item, so we pass in the
// entire fulfillable quantity.
Quantity = fulfillmentOrder.FulfillmentOrderLineItems
.First(li => li.Id == itemId)
.FulfillableQuantity
})
};
// Create a new fulfillment using that fulfillment order with partial line items
var fulfillment = await fulfillments.CreateAsync(new FulfillmentShipping
{
Message = "items are shipping!",
FulfillmentRequestOrderLineItems = new [] { lineItem },
NotifyCustomer = true,
TrackingInfo = new TrackingInfo
{
Company = "UPS",
Url = "...",
Number = "..."
}
}); Thanks to @ajvanlaningham below for pointing out the |
Thank you so much, that's exactly what I was looking for! |
Great! I'll keep this open as a reminder for me to get the fulfillment example code updated. |
Thanks for the update, What is the practice when we have multipe TrackingNumbers/Urls? before we could send them as an array. Now the FulfillmentShipping only supports a single "TrackingInfo". I could create multiple fulfillments for each tracking number, but this is a problem for many of my customers, because this will trigger some payment providers to create multiple invoices. |
For anyone who might stumble across this issue after ugrading to the 2022-07 API-version: If It's weird that the call just succeeds and returns an empty array, instead of giving a permission error, but that's exactly what happens. (I know this is the Shopify API's fault, ShopifySharp has nothing to do with this). Hope this will save someone the hassle of figuring this out the hard way. 😉 |
I noticed in the fulfillment example code, there is a ToDo list which is still incomplete. For example as of writing this, 'Mark fulfillment order as open' is not checked as complete. Does that mean the code still needs working on, or just the documentation? |
@nozzlegear, my app uses the current But today, I was notified by Shopify, that...
Is it possible that the This is the code I'm using: private async Task FulfillOrder()
{
var openFulfillmentOrders = await mFulfillmentOrderService.ListAsync(mOrder.Id.Value);
openFulfillmentOrders = openFulfillmentOrders.Where(f => f.Status == "open").ToList();
var lineItems = openFulfillmentOrders.Select(o => new LineItemsByFulfillmentOrder()
{
FulfillmentOrderId = o.Id.Value
});
var fulfillmentShipping = new FulfillmentShipping()
{
NotifyCustomer = true,
Message = "Ihre Bestellung wird nun versendet!",
FulfillmentRequestOrderLineItems = lineItems,
TrackingInfo = new TrackingInfo()
{
Company = "DPD",
Url = String.Format(Settings.Default.ShopifyDPDTrackingUrl, mTrackingNr),
Number = mTrackingNr
}
};
var fulfillment = await mFulfillmentService.CreateAsync(fulfillmentShipping);
} Thanks in advance for your input! |
Hi @nozzlegear , according to you "once an order is created Shopify will create one or more fulfillment orders automatically for the order" if i call "ListAsync" function from FulfillmentOrderService i must receive some response, but my response list is empty; maybe it's because i don't use 2022-07 api? where i can see the API version i'm using? EDIT: Sorry didn't see this response "If fulfillmentOrders.ListAsync(orderId) comes back empty and returns no FulfillmentOrders, the problem for me was that I had not granted my app access to some of the newly added fulfillment-related API-permissions like read_merchant_managed_fulfillment_orders or write_merchant_managed_fulfillment_orders." after setting this permissions correctly work |
Am I missing how/where to set the Fulfillment Location with the new objects? |
same here |
A NOTE ABOUT PARTIAL FULFILLMENT: var fulfillments = new FulfillmentService(domain, accessToken);
var fulfillmentOrders = new FulfillmentOrderService(domain, accessToken);
var orderId = 123456;
//*** NEW CODE ***
var lineItemId = 654321; //the long? ShopifySharp.LineItem.Id of the item that you want to partially fulfill
// Find open fulfillment orders for this order
var openFulfillmentOrders = await fulfillmentOrders.ListAsync(orderId);
openFulfillmentOrders = openFulfillmentOrders.Where(f => f.Status == "open").ToList();
//***NEW CODE ***
//grab the open fulfullment order list of line items
var fulfullmentLineItems = openFulfillments.FirstOrDefault().FulfillmentOrderLineItems.ToList();
var fulfillmentLineItem = fulfillmentLineItems.Find(li => li.lineItemId == lineItemId); //pick the correct line item
// Fulfill the line items
var lineItems = openFulfillmentOrders.Select(o => new LineItemsByFulfillmentOrder
{
FulfillmentOrderId = o.Id.Value,
//***NEW CODE***
//Specify a list of line items if you're doing a partial fulfillment for
FulfillmentRequestOrderLineItems = new List<FulfullmentRequestOrderLineItems>
{
new ShopifySharp.FulfillmentRequestOrderLineItem
{
Id = fulfillmentLineItem.Id, //NOTE: this is not fulfillmentLineItem.LineItemId!!
Quantity = ... // The quantity you want to partially fulfill.
}
}
});
var fulfillment = await fulfillments.CreateAsync(new FulfillmentShipping
{
Message = "items are shipping!",
FulfillmentRequestOrderLineItems = lineItems,
NotifyCustomer = true,
TrackingInfo = new TrackingInfo
{
Company = "UPS",
Url = "...",
Number = "..."
}
}); It took me a fair amount of time to figure out why I was getting an error, and ultimately it was because I was using the "FulfillmentOrderLineItem.LineItemId" instead of the "FulfillmentOrderLineItem.Id"... both of which are different from the actual ShopifySharp.LineItem.Id. I can't see anything wrong with using the above code always, especially if you are doing work for a shopify store front in which partial fulfillments are a regular occurance. If it's a full fulfillment, just loop through all the items in the fulfillmentLineItems list and fill the full quantity. I'd love to hear from a more experienced developer if I'm wrong though! |
Thanks Alex! I actually ran into that issue myself recently, I'll update the readme soon with a note about the line item ids specifically.
…--
Joshua Harms
On Tue, Apr 25, 2023, at 09:01, Alex VanLaningham wrote:
A NOTE ABOUT PARTIAL FULFILLMENT:
It took a day for me to figure out so I wanted to expand on this thread for anyone who might find it helpful.
`var fulfillments = new FulfillmentService(domain, accessToken);
var fulfillmentOrders = new FulfillmentOrderService(domain, accessToken);
var orderId = 123456;
//*** NEW CODE ***
var lineItemId = 654321; //the long? ShopifySharp.LineItemId of the item that you want to partially fulfill
// Find open fulfillment orders for this order
var openFulfillmentOrders = await fulfillmentOrders.ListAsync(orderId);
openFulfillmentOrders = openFulfillmentOrders.Where(f => f.Status == "open").ToList();
//grab the open fulfullment order
var fulfullmentLineItems = openFulfillments.FirstOrDefault().FulfillmentOrderLineItems.ToList();
var fulfillmentLineItem = fulfillmentLineItems.Find(li => li.lineItemId == lineItem.Id); //pick the correct line item
// Fulfill the line items
var lineItems = openFulfillmentOrders.Select(o => new LineItemsByFulfillmentOrder
{
FulfillmentOrderId = o.Id.Value
//**NEW CODE**
//Specify a list of line items if you're doing a partial fulfillment for
FulfillmentRequestOrderLineItems = new List
{
new ShopifySharp.FulfillmentRequestOrderLineItem
{
Id = fulfillmentLineItem.Id, //NOTE: this is not fulfillmentLineItem.LineItemId!!
Quantity = ... // The quantity you want to partially fulfill.
}
};
});
var fulfillment = await fulfillments.CreateAsync(new FulfillmentShipping
{
Message = "items are shipping!",
FulfillmentRequestOrderLineItems = lineItems,
NotifyCustomer = true,
TrackingInfo = new TrackingInfo
{
Company = "UPS",
Url = "...",
Number = "..."
}
});`
It took me a fair amount of time to figure out why I was getting an error, and ultimately it was because I was using the "FulfillmentOrderLineItem.LineItemId" instead of the "FulfillmentOrderLineItem.Id".
I can't see anything wrong with using the above code always, especially if you are doing work for a shopify store front in which partial fulfillments are a regular occurance. If it's a full fulfillment, just loop through all the items in the fulfillmentLineItems list and fill the full quantity. I'd love to hear from a more experienced developer if I'm wrong though!
—
Reply to this email directly, view it on GitHub <#828 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AASOE7C5WIRVRPOQLJB72VTXC7KK7ANCNFSM6AAAAAATXYXVYI>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
If you're like me, and you commonly had multiple tracking #'s, my version of the code ended up looking like this:
|
I am having 404 error while executing the following code.
|
@z0ha1b That looks correct I think. One thing I'd investigate is that |
thanks, it worked fine :) |
Hi there :) I'm sitting here for hours to get the initial sample from @nozzlegear to work (see here: #828 (comment)). I'm using the basic version of the code (the first one) but I'm always getting a 404 from the API without any error message. I don't have any clue what I'm doing wrong. I also tried to enable all scopes but it simply doesn't work. I also tried the code from the tests right here: https://github.com/nozzlegear/ShopifySharp/blob/6169078e4c2452e54ee0fef08d4f727fa78fea69/ShopifySharp.Tests/Fulfillment_Tests.cs Is there a chance to get a more detailed error message since I'm desperatly trying for hours now and all I see is this 404? I receive the correct line items and everything works as expected until I want to create the fulfillment itself :/ Thanks so much in advance :) This is my current version: var orderService = new ShopifySharp.OrderService(domain, accessToken);
var fulfillmentService = new ShopifySharp.FulfillmentService(domain, accessToken);
var fulfillmentOrderService = new FulfillmentOrderService(domain, accessToken);
// find order id for order number
var order = await orderService.ListAsync(new OrderFilterWithName { Name = orderIdString });
var orderId = order.Items.First().Id.Value;
var fulfillmentOrders = await fulfillmentOrderService.ListAsync(orderId);
var openFulfillmentOrders = fulfillmentOrders.Where(f => f.Status == "open").ToList();
var lineItems = openFulfillmentOrders.Select(o => new LineItemsByFulfillmentOrder
{
FulfillmentOrderId = o.Id.Value,
});
try
{
var fulfillment = await fulfillmentService.CreateAsync(new FulfillmentShipping
{
Message = "Items are shipping now!",
FulfillmentRequestOrderLineItems = lineItems,
NotifyCustomer = notifyCustomer
});
}
catch (ShopifyException e)
{
telemetryData.Add("Error message", e.Message);
telemetryClient.TrackEvent("OrderFulfillment", telemetryData);
return req.CreateResponse(HttpStatusCode.BadRequest);
} |
Hey @PendelinP! Sorry to hear you're having trouble. If the code from the tests didn't work, I think my first suspicion would be to check the shop domain that you're using. Shopify will redirect requests and potentially cause 404s if you're not using the right myshopify domain. Make sure the domain you're passing in to the service constructors looks like |
Wow - that was super fast and this was exactly my problem (example.com instead of example.myshopify.com). I'm soooooo thankful! I would have never found this issue :D Again, thank you so, so much! |
Awesome, glad it's working now @PendelinP! |
Hello, would anyone know why all my fulfillment orders return as closed? |
Hey @lcost0323, I think I've run into this before. If I recall correctly, there's a setting that new Shopify stores have where Shopify will automatically fulfill all fulfillment orders as soon as an order is placed. The store owner can turn this setting off in the store by going to the store's Settings Page -> Checkout -> Order Processing and selecting the option that says "Don't fulfill any of the order's line items automatically". Alternatively, if you don't control the store (i.e. you're building an app for the Shopify App Store), you'll need to create a Fulfillment Service using the Fulfillment Service API instead. With the fulfillment service you can assign the store's products/inventory to your new fulfillment service's location, and after that Shopify should no longer fulfill them for you. That's kind of a simple overview of a fulfillment service, there's a lot more setup to it than that, but that's the gist of it. Let me know if that solves the problem for you or if you have any questions about fulfillment services. Happy to help! |
Hi @nozzlegear , thank you for getting back to me so quickly. It looks like we have it set to the gift card option and the order itself says unfulfilled. When these closed fulfillment orders come over, they also say unsubmitted. What I really want to do is fulfill, and then mark the order shipped/add tracking information so it gets closed out, but it seems like I have to create some kind of fulfilment order prior to updating the tracking information. I am very new to shopify. |
This turned out to be a "me" issue.. I was using the wrong orderID, it is working now. |
@lcost0323 Awesome, glad you got it working! Sorry I didn't reply to your follow up yesterday, I set a reminder to do so this morning but it looks like it's not necessary! Let me know if you have any other questions or problems getting it working. You can email me at the email address in my GitHub profile. |
The fulfillment example code in the
readme.md
does not compile any more, since it does not incorporate the breaking changes introduced with the switch to the2022-07
API.https://github.com/nozzlegear/ShopifySharp#fulfillments
The text was updated successfully, but these errors were encountered: