Skip to content

Commit

Permalink
Merge pull request #25 from nozzlegear/master
Browse files Browse the repository at this point in the history
Merging nozzlegear/master
  • Loading branch information
clement911 committed Jun 14, 2019
2 parents 0551821 + e43b6a9 commit dc8f806
Show file tree
Hide file tree
Showing 8 changed files with 293 additions and 31 deletions.
79 changes: 79 additions & 0 deletions ShopifySharp.Tests/DateTime_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace ShopifySharp.Tests
{
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

using Newtonsoft.Json;

using Xunit;

public class DateTime_Tests : IClassFixture<Order_Tests_Fixture>
{
public DateTime_Tests(Order_Tests_Fixture orderTestsFixture)
{
this.OrderTestsFixture = orderTestsFixture;
}

public Order_Tests_Fixture OrderTestsFixture { get; }

[Fact]
public async Task GraphQL_CompareOrderDates()
{
var orderId = this.OrderTestsFixture.Created.First().Id.Value;

var order = await this.OrderTestsFixture.Service.GetAsync(orderId);
Assert.NotNull(order.UpdatedAt);

// Shopify seems to take approx. 10 seconds to propagate new orders into the GraphQL API
await Task.Delay(TimeSpan.FromSeconds(11));

var graphService = new GraphService(Utils.MyShopifyUrl, Utils.AccessToken);
var graphQlOrder = await graphService.PostAsync(
@"
{
orders(first:1,query:""id:" + orderId + @""") {
edges{
node{
updatedAt
}
}
}
}
");

var jtokenOrder = graphQlOrder["orders"]["edges"].First["node"];

var testOrder = jtokenOrder.ToObject<TestGraphQLOrderWithString>();
var testOrderDateTime = DateTimeOffset.Parse(testOrder.UpdatedAt, CultureInfo.InvariantCulture);
Assert.Equal(order.UpdatedAt.Value, testOrderDateTime);

var testOrderWithDateTimeOffset = jtokenOrder.ToObject<TestGraphQLOrderWithDateTimeOffset>();
Assert.Equal(order.UpdatedAt.Value, testOrderWithDateTimeOffset.UpdatedAt);

var testOrderWithDateTime = jtokenOrder.ToObject<TestGraphQLOrderWithDateTime>();
Assert.Equal(order.UpdatedAt.Value, testOrderWithDateTime.UpdatedAt);
}

public class TestGraphQLOrderWithString
{
public string UpdatedAt { get; set; }
}

public class TestGraphQLOrderWithDateTime
{
public DateTime UpdatedAt { get; set; }
}

public class TestGraphQLOrderWithDateTimeOffset
{
public DateTimeOffset UpdatedAt { get; set; }
}
}
}
6 changes: 6 additions & 0 deletions ShopifySharp/Entities/Order.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,12 @@ public class Order : ShopifyObject
[JsonProperty("taxes_included")]
public bool? TaxesIncluded { get; set; }

/// <summary>
/// States whether this is a test order.
/// </summary>
[JsonProperty("test")]
public bool? Test { get; set; }

/// <summary>
/// Unique identifier for a particular order.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions ShopifySharp/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace ShopifySharp
{
public static class StringExtensions
{
/// <summary>
/// Checks if a string starts with another string, ignoring case.
/// </summary>
public static bool StartsWithIgnoreCase(this string str, string a) => str.ToLower().StartsWith(a.ToLower());

/// <summary>
/// Checks if a string ends with another string, ignoring case.
/// </summary>
public static bool EndsWithIgnoreCase(this string str, string a) => str.ToLower().EndsWith(a.ToLower());

/// <summary>
/// Checks if a string contains another string, ignorning case.
/// </summary>
public static bool ContainsIgnoreCase(this string str, string a) => str.ToLower().Contains(a.ToLower());
}
}
87 changes: 85 additions & 2 deletions ShopifySharp/Filters/ArticleFilter.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,99 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace ShopifySharp.Filters
{
/// <summary>
/// Options for filtering the results of <see cref="ArticleService.ListAsync(long, ArticleFilter)"/>.
/// </summary>
public class ArticleFilter : PublishableListFilter
public class ArticleFilter : Parameterizable
{
/// <summary>
/// Filter the results to this article handle.
/// </summary>
[JsonProperty("handle")]
public string Handle { get; set; }

/// <summary>
/// Restricts results to those created after date (format: 2008-12-31 03:00).
/// </summary>
[JsonProperty("created_at_min")]
public DateTimeOffset? CreatedAtMin { get; set; }

/// <summary>
/// Restricts results to those created before date (format: 2008-12-31 03:00).
/// </summary>
[JsonProperty("created_at_max")]
public DateTimeOffset? CreatedAtMax { get; set; }

/// <summary>
/// Restricts results to those last updated after date (format: 2008-12-31 03:00).
/// </summary>
[JsonProperty("updated_at_min")]
public DateTimeOffset? UpdatedAtMin { get; set; }

/// <summary>
/// Restricts results to those last updated before date (format: 2008-12-31 03:00).
/// </summary>
[JsonProperty("updated_at_max")]
public DateTimeOffset? UpdatedAtMax { get; set; }

/// <summary>
/// Restrict results to after the specified ID. Note: this field may not have an effect on certain resources.
/// </summary>
[JsonProperty("since_id")]
public long? SinceId { get; set; }

/// <summary>
/// An optional array of order ids to retrieve.
/// </summary>
[JsonProperty("ids"), Obsolete("The Ids property is ignored for articles. Using this property to list or count articles is a noop, and the property will be removed in the future.", false)]
public IEnumerable<long> Ids { get; set; }

/// <summary>
/// Limit the amount of results. Default is 50, max is 250.
/// </summary>
[JsonProperty("limit")]
public int? Limit { get; set; }

/// <summary>
/// Page of results to be returned. Default is 1.
/// </summary>
[JsonProperty("page")]
public int? Page { get; set; }

/// <summary>
/// An optional, comma-separated list of fields to include in the response.
/// </summary>
[JsonProperty("fields")]
public string Fields { get; set; }

/// <summary>
/// An optional field name to order by, followed by either ' asc' or ' desc'.
/// For example, 'created_at asc'
/// Not all fields are supported...
/// </summary>
[JsonProperty("order")]
public string Order { get; set; }

/// <summary>
/// Show objects published after date (format: 2008-12-31 03:00).
/// </summary>
[JsonProperty("published_at_min")]
public DateTimeOffset? PublishedAtMin { get; set; } = null;

/// <summary>
/// Show objects published before date (format: 2008-12-31 03:00).
/// </summary>
[JsonProperty("published_at_max")]
public DateTimeOffset? PublishedAtMax { get; set; } = null;

/// <summary>
/// Published Status.
/// published - Show only published objects, unpublished - Show only unpublished objects, any - Show all objects(default)
/// </summary>
[JsonProperty("published_status")]
public string PublishedStatus { get; set; } = null;
}
}
5 changes: 1 addition & 4 deletions ShopifySharp/Infrastructure/JsonContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ public JsonContent(object data) : base(ToBytes(data))

private static byte[] ToBytes(object data)
{
var rawData = JsonConvert.SerializeObject(data, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore
});
var rawData = Serializer.Serialize(data);

return Encoding.UTF8.GetBytes(rawData);
}
Expand Down
24 changes: 24 additions & 0 deletions ShopifySharp/Infrastructure/Serializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Newtonsoft.Json;

namespace ShopifySharp.Infrastructure
{
/// <summary>
/// Contains JSON serialization settings and methods used by the rest of the ShopifySharp package.
/// </summary>
public static class Serializer
{
public static JsonSerializerSettings Settings { get; } = new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore
};

public static JsonSerializer JsonSerializer { get; } = new JsonSerializer
{
DateParseHandling = DateParseHandling.DateTimeOffset
};

public static string Serialize(object data) => JsonConvert.SerializeObject(data, Settings);

public static T Deserialize<T>(string json) => JsonConvert.DeserializeObject<T>(json, Settings);
}
}
46 changes: 37 additions & 9 deletions ShopifySharp/Services/Fulfillment/FulfillmentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using ShopifySharp.Infrastructure;
using System;

namespace ShopifySharp
{
Expand Down Expand Up @@ -79,14 +80,11 @@ public virtual async Task<Fulfillment> GetAsync(long orderId, long fulfillmentId
/// </summary>
/// <param name="orderId">The order id to which the fulfillments belong.</param>
/// <param name="fulfillment">A new <see cref="Fulfillment"/>. Id should be set to null.</param>
/// <param name="notifyCustomer">Whether the customer should be notified that the fulfillment
/// has been created.</param>
/// <returns>The new <see cref="Fulfillment"/>.</returns>
public virtual async Task<Fulfillment> CreateAsync(long orderId, Fulfillment fulfillment, bool notifyCustomer)
public virtual async Task<Fulfillment> CreateAsync(long orderId, Fulfillment fulfillment)
{
var req = PrepareRequest($"orders/{orderId}/fulfillments.json");
var body = fulfillment.ToDictionary();
body.Add("notify_customer", notifyCustomer);

var content = new JsonContent(new
{
Expand All @@ -96,20 +94,34 @@ public virtual async Task<Fulfillment> CreateAsync(long orderId, Fulfillment ful
return await ExecuteRequestAsync<Fulfillment>(req, HttpMethod.Post, content, "fulfillment");
}

/// <summary>
/// Creates a new <see cref="Fulfillment"/> on the order.
/// </summary>
/// <param name="orderId">The order id to which the fulfillments belong.</param>
/// <param name="fulfillment">A new <see cref="Fulfillment"/>. Id should be set to null.</param>
/// <param name="notifyCustomer">Whether the customer should be notified that the fulfillment
/// has been created.</param>
/// <returns>The new <see cref="Fulfillment"/>.</returns>
[Obsolete("The notifyCustomer parameter can already be found on the Fulfillment object. This extra parameter will be removed from FulfillmentService.UpdateAsync in a future release.", false)]
public virtual async Task<Fulfillment> CreateAsync(long orderId, Fulfillment fulfillment, bool notifyCustomer)
{
// Set the notifyCustomer property on the fulfillment
fulfillment.NotifyCustomer = notifyCustomer;

return await CreateAsync(orderId, fulfillment);
}

/// <summary>
/// Updates the given <see cref="Fulfillment"/>.
/// </summary>
/// <param name="orderId">The order id to which the fulfillments belong.</param>
/// <param name="">Id of the object being updated.</param>
/// <param name="fulfillmentId">Id of the object being updated.</param>
/// <param name="fulfillment">The <see cref="Fulfillment"/> to update.</param>
/// <returns>The updated <see cref="Fulfillment"/>.</returns>
public virtual async Task<Fulfillment> UpdateAsync(long orderId, long fulfillmentId, Fulfillment fulfillment, bool notifyCustomer=false)
public virtual async Task<Fulfillment> UpdateAsync(long orderId, long fulfillmentId, Fulfillment fulfillment)
{
var req = PrepareRequest($"orders/{orderId}/fulfillments/{fulfillmentId}.json");

var body = fulfillment.ToDictionary();
body.Add("notify_customer", notifyCustomer);

var content = new JsonContent(new
{
fulfillment = body
Expand All @@ -118,6 +130,22 @@ public virtual async Task<Fulfillment> UpdateAsync(long orderId, long fulfillmen
return await ExecuteRequestAsync<Fulfillment>(req, HttpMethod.Put, content, "fulfillment");
}

/// <summary>
/// Updates the given <see cref="Fulfillment"/>.
/// </summary>
/// <param name="orderId">The order id to which the fulfillments belong.</param>
/// <param name="fulfillmentId">Id of the object being updated.</param>
/// <param name="fulfillment">The <see cref="Fulfillment"/> to update.</param>
/// <returns>The updated <see cref="Fulfillment"/>.</returns>
[Obsolete("The notifyCustomer parameter can already be found on the Fulfillment object. This extra parameter will be removed from FulfillmentService.UpdateAsync in a future release.", false)]
public virtual async Task<Fulfillment> UpdateAsync(long orderId, long fulfillmentId, Fulfillment fulfillment, bool notifyCustomer = false)
{
// Set the notifyCustomer property on the fulfillment
fulfillment.NotifyCustomer = notifyCustomer;

return await UpdateAsync(orderId, fulfillmentId, fulfillment);
}

/// <summary>
/// Completes a pending fulfillment with the given id.
/// </summary>
Expand Down

0 comments on commit dc8f806

Please sign in to comment.