From 04b91dd63982c4c29ca9ef5dd72d60b9090ffeac Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Wed, 19 Apr 2023 07:21:20 -0400 Subject: [PATCH 01/14] Update nugetpackages --- ShipEngine.Tests/ShipEngine.Tests.csproj | 12 ++++++------ ShipEngine/ShipEngine.csproj | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ShipEngine.Tests/ShipEngine.Tests.csproj b/ShipEngine.Tests/ShipEngine.Tests.csproj index 64e2bcfd..312bd0c1 100644 --- a/ShipEngine.Tests/ShipEngine.Tests.csproj +++ b/ShipEngine.Tests/ShipEngine.Tests.csproj @@ -1,21 +1,21 @@ - net5.0;netcoreapp3.1;netcoreapp2.1;net461 + netcoreapp3.1;netcoreapp2.1;net462 false - - + + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/ShipEngine/ShipEngine.csproj b/ShipEngine/ShipEngine.csproj index 30e01862..d47b5be6 100644 --- a/ShipEngine/ShipEngine.csproj +++ b/ShipEngine/ShipEngine.csproj @@ -22,8 +22,8 @@ - - + + From 4c01bbc39be86278b85eed187edc42ac0b629282 Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Wed, 19 Apr 2023 08:23:40 -0400 Subject: [PATCH 02/14] Add Update Shipment method, Move Shipment class to common models --- .../UpdateShipmentByID200Response.json | 150 +++++++++++++ ShipEngine.Tests/ShipEngine.Tests.csproj | 2 +- .../UpdateShipmentByIDTest.cs | 198 ++++++++++++++++++ .../Models/Dto/Common/Enums/ShipmentStatus.cs | 20 ++ ShipEngine/Models/Dto/Common/Shipment.cs | 124 +++++++++++ .../CreateLabelFromShipmentDetails/Params.cs | 100 --------- .../Dto/GetRatesFromShipmentDetails/Enums.cs | 13 -- .../Dto/GetRatesFromShipmentDetails/Params.cs | 118 ----------- .../Models/Dto/UpdateShipmentByID/Params.cs | 22 ++ .../Models/Dto/UpdateShipmentByID/Result.cs | 138 ++++++++++++ ShipEngine/ShipEngine.cs | 39 ++++ ShipEngine/ShipEngine.csproj | 2 +- 12 files changed, 693 insertions(+), 233 deletions(-) create mode 100644 ShipEngine.Tests/HttpResponseMocks/UpdateShipmentByID200Response.json create mode 100644 ShipEngine.Tests/ShipEngineMethodTests/UpdateShipmentByIDTest.cs create mode 100644 ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs create mode 100644 ShipEngine/Models/Dto/Common/Shipment.cs create mode 100644 ShipEngine/Models/Dto/UpdateShipmentByID/Params.cs create mode 100644 ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs diff --git a/ShipEngine.Tests/HttpResponseMocks/UpdateShipmentByID200Response.json b/ShipEngine.Tests/HttpResponseMocks/UpdateShipmentByID200Response.json new file mode 100644 index 00000000..5b1a6304 --- /dev/null +++ b/ShipEngine.Tests/HttpResponseMocks/UpdateShipmentByID200Response.json @@ -0,0 +1,150 @@ +{ + "shipment_id": "se-153814671", + "carrier_id": "se-423888", + "service_code": "ups_ground", + "external_shipment_id": null, + "ship_date": "2021-08-27T00:00:00Z", + "created_at": "2021-08-27T16:29:25.257Z", + "modified_at": "2021-08-27T16:29:25.24Z", + "shipment_status": "pending", + "ship_to": { + "name": "Amanda Miller", + "phone": null, + "company_name": null, + "address_line1": "525 S Winchester Blvd", + "address_line2": null, + "address_line3": null, + "city_locality": "San Jose", + "state_province": "CA", + "postal_code": "95128", + "country_code": "US", + "address_residential_indicator": "unknown" + }, + "ship_from": { + "name": "John Doe", + "phone": "512-555-5555", + "company_name": "", + "address_line1": "4009 Marathon Blvd", + "address_line2": null, + "address_line3": null, + "city_locality": "Austin", + "state_province": "TX", + "postal_code": "78756", + "country_code": "US", + "address_residential_indicator": "unknown" + }, + "warehouse_id": null, + "return_to": { + "name": "John Doe", + "phone": "512-555-5555", + "company_name": "", + "address_line1": "4009 Marathon Blvd", + "address_line2": null, + "address_line3": null, + "city_locality": "Austin", + "state_province": "TX", + "postal_code": "78756", + "country_code": "US", + "address_residential_indicator": "unknown" + }, + "confirmation": "none", + "customs": { + "contents": "merchandise", + "customs_items": [ + { + "customs_item_id": "se-65172544", + "description": "Prescription", + "quantity": 1, + "value": 100.00, + "harmonized_tariff_code": null, + "country_of_origin": null, + "unit_of_measure": null + } + ], + "non_delivery": "return_to_sender", + "buyer_shipping_amount_paid": null, + "duties_paid": null + }, + "external_order_id": null, + "order_source_code": null, + "advanced_options": { + "bill_to_account": null, + "bill_to_country_code": null, + "bill_to_party": null, + "bill_to_postal_code": null, + "contains_alcohol": false, + "delivered_duty_paid": false, + "non_machinable": false, + "saturday_delivery": false, + "dry_ice": false, + "dry_ice_weight": null, + "fedex_freight": null, + "freight_class": null, + "custom_field1": null, + "custom_field2": null, + "custom_field3": null, + "collect_on_delivery": null + }, + "insurance_provider": "none", + "tags": [], + "packages": [ + { + "package_code": "package", + "weight": { + "value": 17.0, + "unit": "pound" + }, + "dimensions": { + "unit": "inch", + "length": 36.0, + "width": 12.0, + "height": 24.0 + }, + "insured_value": { + "currency": "usd", + "amount": 0.0 + }, + "label_messages": { + "reference1": null, + "reference2": null, + "reference3": null + }, + "external_package_id": null + } + ], + "total_weight": { + "value": 17.0, + "unit": "pound" + }, + "items": [], + "address_validation": { + "status": "verified", + "original_address": { + "name": "John Smith", + "phone": null, + "company_name": "ShipStation", + "address_line1": "3800 N Lamar Blvd", + "address_line2": "#220", + "address_line3": null, + "city_locality": "Austin", + "state_province": "TX", + "postal_code": "78756", + "country_code": "US", + "address_residential_indicator": "no" + }, + "matched_address": { + "name": "JOHN SMITH", + "phone": null, + "company_name": "SHIPSTATION", + "address_line1": "3800 N LAMAR BLVD STE 220", + "address_line2": null, + "address_line3": null, + "city_locality": "AUSTIN", + "state_province": "TX", + "postal_code": "78756-0003", + "country_code": "US", + "address_residential_indicator": "no" + }, + "messages": [] + } +} diff --git a/ShipEngine.Tests/ShipEngine.Tests.csproj b/ShipEngine.Tests/ShipEngine.Tests.csproj index 312bd0c1..1e0da776 100644 --- a/ShipEngine.Tests/ShipEngine.Tests.csproj +++ b/ShipEngine.Tests/ShipEngine.Tests.csproj @@ -25,6 +25,6 @@ - + diff --git a/ShipEngine.Tests/ShipEngineMethodTests/UpdateShipmentByIDTest.cs b/ShipEngine.Tests/ShipEngineMethodTests/UpdateShipmentByIDTest.cs new file mode 100644 index 00000000..9ecdef18 --- /dev/null +++ b/ShipEngine.Tests/ShipEngineMethodTests/UpdateShipmentByIDTest.cs @@ -0,0 +1,198 @@ +using Moq; +using Newtonsoft.Json; +using ShipEngineSDK; +using ShipEngineSDK.Common; +using ShipEngineSDK.Common.Enums; +using ShipEngineSDK.UpdateShipmentByID; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace ShipEngineTest +{ + public class UpdateShipmentByIDTest + { + public Params ShipmentParameters; + public TestUtils TestUtils; + + public UpdateShipmentByIDTest() + { + TestUtils = new TestUtils(); + ShipmentParameters = new Params() + { + Shipment = new Shipment() + { + ServiceCode = "usps_priority_mail", + ShipFrom = new Address() + { + Name = "John Doe", + AddressLine1 = "4009 Marathon Blvd", + CityLocality = "Austin", + StateProvince = "TX", + PostalCode = "78756", + CountryCode = Country.US, + Phone = "512-555-5555" + }, + ShipTo = new Address() + { + Name = "Amanda Miller", + AddressLine1 = "525 S Winchester Blvd", + CityLocality = "San Jose", + StateProvince = "CA", + PostalCode = "95128", + CountryCode = Country.US, + Phone = "512-555-5555" + }, + Customs = new Customs() + { + NonDelivery = NonDelivery.ReturnToSender, + Contents = PackageContents.Merchandise, + CustomsItems = new List() + { + new CustomsItem() + { + Description = "Merchandise", + CountryOfOrigin = Country.US, + Quantity = 1, + UnitOfMeasure = "each", + Value = new MonetaryValue() + { + Amount = 100D, + Currency = Currency.USD + } + } + } + }, + Packages = new List() { + new ShipmentPackage() { + Weight = new Weight() { + Value = 17, + Unit = WeightUnit.Pound + }, + Dimensions = new Dimensions() { + Length = 36, + Width = 12, + Height = 24, + Unit = DimensionUnit.Inch, + } + } + }, + ValidateAddress = ValidateAddress.ValidateAndClean + }, + }; + } + + [Fact] + public async void ValidUpdateShipmentByIDTest() + { + + var config = new Config("TEST_bTYAskEX6tD7vv6u/cZ/M4LaUSWBJ219+8S1jgFcnkk"); + var mockShipEngineFixture = new MockShipEngineFixture(config); + + string json = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "../../../HttpResponseMocks/UpdateShipmentByID200Response.json")); + + mockShipEngineFixture.StubRequest(HttpMethod.Put, "/v1/shipments/se-153814671", System.Net.HttpStatusCode.OK, json); + + var result = await mockShipEngineFixture.ShipEngine.UpdateShipmentFromShipmentDetails(ShipmentParameters, "se-153814671"); + + Assert.Equal("se-153814671", result.ShipmentId); + Assert.Equal("se-423888", result.CarrierId); + Assert.Equal("ups_ground", result.ServiceCode); + Assert.Null(result.ExternalShipmentId); + Assert.Equal("2021-08-27T00:00:00Z", result.ShipDate); + Assert.Equal("2021-08-27T16:29:25.257Z", result.CreatedAt); + Assert.Equal("2021-08-27T16:29:25.24Z", result.ModifiedAt); + Assert.Equal(ShipmentStatus.Pending, result.ShipmentStatus); + + Assert.Equal("Amanda Miller", result.ShipTo.Name); + Assert.Null(result.ShipTo.Phone); + Assert.Null(result.ShipTo.CompanyName); + Assert.Equal("525 S Winchester Blvd", result.ShipTo.AddressLine1); + Assert.Null(result.ShipTo.AddressLine2); + Assert.Null(result.ShipTo.AddressLine3); + Assert.Equal("San Jose", result.ShipTo.CityLocality); + Assert.Equal("CA", result.ShipTo.StateProvince); + Assert.Equal("95128", result.ShipTo.PostalCode); + Assert.Equal(Country.US, result.ShipTo.CountryCode); + Assert.Equal(AddressResidentialIndicator.Unknown, result.ShipTo.AddressResidentialIndicator); + + Assert.Equal("John Doe", result.ShipFrom.Name); + Assert.Equal("512-555-5555", result.ShipFrom.Phone); + Assert.Empty(result.ShipFrom.CompanyName); + Assert.Equal("4009 Marathon Blvd", result.ShipFrom.AddressLine1); + Assert.Null(result.ShipFrom.AddressLine2); + Assert.Null(result.ShipFrom.AddressLine3); + Assert.Equal("Austin", result.ShipFrom.CityLocality); + Assert.Equal("TX", result.ShipFrom.StateProvince); + Assert.Equal(AddressResidentialIndicator.Unknown, result.ShipFrom.AddressResidentialIndicator); + + Assert.Null(result.WarehouseId); + + Assert.Equal("John Doe", result.ReturnTo.Name); + Assert.Equal("512-555-5555", result.ReturnTo.Phone); + Assert.Empty(result.ReturnTo.CompanyName); + Assert.Equal("4009 Marathon Blvd", result.ReturnTo.AddressLine1); + Assert.Null(result.ReturnTo.AddressLine2); + Assert.Null(result.ReturnTo.AddressLine3); + Assert.Equal("Austin", result.ReturnTo.CityLocality); + Assert.Equal("TX", result.ReturnTo.StateProvince); + Assert.Equal(AddressResidentialIndicator.Unknown, result.ReturnTo.AddressResidentialIndicator); + + Assert.Equal(DeliveryConfirmation.None, result.Confirmation); + + Assert.Equal(PackageContents.Merchandise, result.Customs.Contents); + Assert.NotEmpty(result.Customs.CustomsItems); + Assert.Equal(100D, result.Customs.CustomsItems.First().Value.Amount); + Assert.Equal(NonDelivery.ReturnToSender, result.Customs.NonDelivery); + + Assert.Null(result.ExternalOrderId); + Assert.Null(result.OrderSourceCode); + + Assert.Null(result.AdvancedOptions.BillToAccount); + Assert.Null(result.AdvancedOptions.BillToCountryCode); + Assert.Null(result.AdvancedOptions.BillToParty); + Assert.Null(result.AdvancedOptions.BillToPostalCode); + Assert.False(result.AdvancedOptions.ContainsAlcohol); + Assert.False(result.AdvancedOptions.DeliveredDutyPaid); + Assert.False(result.AdvancedOptions.NonMachinable); + Assert.False(result.AdvancedOptions.SaturdayDelivery); + Assert.False(result.AdvancedOptions.DryIce); + Assert.Null(result.AdvancedOptions.DryIceWeight); + Assert.Null(result.AdvancedOptions.FedexFreight); + Assert.Null(result.AdvancedOptions.FreightClass); + Assert.Null(result.AdvancedOptions.CustomField1); + Assert.Null(result.AdvancedOptions.CustomField2); + Assert.Null(result.AdvancedOptions.CustomField3); + Assert.Null(result.AdvancedOptions.CollectOnDelivery); + + Assert.Equal(InsuranceProvider.None, result.InsuranceProvider); + Assert.Empty(result.Tags); + + Assert.Equal("package", result.Packages[0].PackageCode); + Assert.Equal(17.0, result.Packages[0].Weight.Value); + Assert.Equal(WeightUnit.Pound, result.Packages[0].Weight.Unit); + Assert.Equal(DimensionUnit.Inch, result.Packages[0].Dimensions.Unit); + Assert.Equal(12, result.Packages[0].Dimensions.Width); + Assert.Equal(36, result.Packages[0].Dimensions.Length); + Assert.Equal(24, result.Packages[0].Dimensions.Height); + + Assert.Equal(Currency.USD, result.Packages[0].InsuredValue.Currency); + Assert.Equal(0, result.Packages[0].InsuredValue.Amount); + + Assert.Null(result.Packages[0].LabelMessages.Reference1); + Assert.Null(result.Packages[0].LabelMessages.Reference2); + Assert.Null(result.Packages[0].LabelMessages.Reference3); + + Assert.Null(result.Packages[0].ExternalPackageId); + + Assert.Equal(17.0, result.TotalWeight.Value); + Assert.Equal(WeightUnit.Pound, result.TotalWeight.Unit); + Assert.Empty(result.Items); + + } + } +} diff --git a/ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs b/ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs new file mode 100644 index 00000000..0de4c9b6 --- /dev/null +++ b/ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs @@ -0,0 +1,20 @@ +#pragma warning disable 1591 + +using System.Runtime.Serialization; + +namespace ShipEngineSDK.Common.Enums +{ + + /// + /// The possible shipment status values + /// + public enum ShipmentStatus + { + Pending, + Processing, + + [EnumMember(Value = "label_purchased")] + LabelPurchased, + Cancelled + } +} diff --git a/ShipEngine/Models/Dto/Common/Shipment.cs b/ShipEngine/Models/Dto/Common/Shipment.cs new file mode 100644 index 00000000..f3f0ca45 --- /dev/null +++ b/ShipEngine/Models/Dto/Common/Shipment.cs @@ -0,0 +1,124 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using ShipEngineSDK.Common.Enums; +using System.Collections.Generic; + +namespace ShipEngineSDK.Common +{ + /// + /// Shipment information + /// + public class Shipment + { + /// + /// The possible validate address values + /// + [JsonConverter(typeof(StringEnumConverter))] + public ValidateAddress ValidateAddress { get; set; } + + /// + /// The carrier account that is billed for the shipping charges + /// + public string CarrierId { get; set; } + + /// + /// The carrier service used to ship the package + /// + public string ServiceCode { get; set; } + + /// + /// ID that the Order Source assigned + /// + public string ExternalOrderId { get; set; } + + /// + /// Describe the packages included in this shipment as related to potential metadata that was imported from external order sources + /// + public List Items { get; set; } + + /// + /// Tax identifiers + /// + public List TaxIdentifiers { get; set; } + + /// + /// You can optionally use this field to store your own identifier for this shipment. + /// + public string ExternalShipmentId { get; set; } + + /// + /// The date that the shipment was (or will be) shippped. ShipEngine will take the day of week into consideration. + /// For example, if the carrier does not operate on Sundays, then a package that would have shipped on Sunday will ship on Monday instead. + /// + public string ShipDate { get; set; } + + /// + /// The recipient's mailing address + /// + public Address ShipTo { get; set; } + + /// + /// The shipment's origin address. If you frequently ship from the same location, consider creating a warehouse. + /// Then you can simply specify the warehouse_id rather than the complete address each time. + /// + public Address ShipFrom { get; set; } + + /// + /// The warehouse that the shipment is being shipped from. Either warehouse_id or ship_from must be specified. + /// + public string WarehouseId { get; set; } + + /// + /// The return address for this shipment. Defaults to the ship_from address. + /// + public Address ReturnTo { get; set; } + + /// + /// The type of delivery confirmation that is required for this shipment. + /// + [JsonConverter(typeof(StringEnumConverter))] + public DeliveryConfirmation Confirmation { get; set; } + + /// + /// Customs information. This is usually only needed for international shipments. + /// + public Customs Customs { get; set; } + + /// + /// Advanced shipment options. These are entirely optional. + /// + public AdvancedShipmentOptions AdvancedOptions { get; set; } + + /// + /// Indicates if the package will be picked up or dropped off by the carrier + /// + public OriginType OriginType { get; set; } + + /// + /// The insurance provider to use for any insured packages in the shipment. + /// + [JsonConverter(typeof(StringEnumConverter))] + public InsuranceProvider InsuranceProvider { get; set; } + + /// + /// Arbitrary tags associated with this shipment. Tags can be used to categorize shipments, and shipments can be queried by their tags. + /// + public List Tags { get; set; } + + /// + /// The order sources that are supported by ShipEngine + /// + [JsonConverter(typeof(StringEnumConverter))] + public OrderSourceCode OrderSourceCode { get; set; } + + /// + /// The packages in the shipment. + /// + public List Packages { get; set; } + + /// + /// The combined weight of all packages in the shipment + /// + public Weight Weight { get; set; } + } +} diff --git a/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs b/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs index 007ee76a..e24e59ef 100644 --- a/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs +++ b/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs @@ -75,106 +75,6 @@ public class Params public string LabelImageId { get; set; } } - /// - /// Shipment information - /// - public class Shipment - { - /// - /// The carrier account that is billed for the shipping charges - /// - public string CarrierId { get; set; } - - /// - /// The carrier service used to ship the package, such as fedexGround, uspsFirstClassMail, flatRateEnvelope, etc. - /// - public string ServiceCode { get; set; } - - /// - /// ID that the Order Source assigned - /// - public string ExternalOrderId { get; set; } - - /// - /// Describe the packages included in this shipment as related to potential metadata that was imported from external order sources - /// - public List Items { get; set; } - - /// - /// Array of tax identifiers - /// - public List TaxIdentifiers { get; set; } - - /// - /// You can optionally use this field to store your own identifier for this shipment. - /// - public string ExternalShipmentId { get; set; } - - /// - /// The date that the shipment was(or will be) shipped. ShipEngine will take the day of week into consideration.For example, if the carrier does not operate on Sundays, then a package that would have shipped on Sunday will ship on Monday instead. - /// - public string ShipDate { get; set; } - - /// - /// The recipient's mailing address - /// - public Address ShipTo { get; set; } - - /// - /// The shipment's origin address. If you frequently ship from the same location, consider creating a warehouse. Then you can simply specify the warehouseId rather than the complete address each time. - /// - public Address ShipFrom { get; set; } - - /// - /// The warehouse that the shipment is being shipped from. Either warehouseId or shipFrom must be specified. - /// - public string WarehouseId { get; set; } - - /// - /// The return address for this shipment. Defaults to the shipFrom address. - /// - public Address ReturnTo { get; set; } - - /// - /// The type of delivery confirmation that is required for this shipment. - /// - [JsonConverter(typeof(StringEnumConverter))] - public DeliveryConfirmation Confirmation { get; set; } - - /// - /// Customs information. This is usually only needed for international shipments. - /// - public InternationalShipmentOptions Customs { get; set; } - - /// - /// Advanced shipment options. These are entirely optional. - /// - public AdvancedShipmentOptions AdvancedOptions { get; set; } - - /// - /// Indicates if the package will be picked up or dropped off by the carrier - /// - [JsonConverter(typeof(StringEnumConverter))] - public OriginType OriginType { get; set; } - - /// - /// The insurance provider to use for any insured packages in the shipment - /// - [JsonConverter(typeof(StringEnumConverter))] - public InsuranceProvider InsuranceProvider { get; set; } - - /// - /// The order sources that are supported by ShipEngine - /// - [JsonConverter(typeof(StringEnumConverter))] - public OrderSourceCode OrderSourceCode { get; set; } - - /// - /// The packages in the shipment. - /// - public List Packages { get; set; } - } - /// /// Package information /// diff --git a/ShipEngine/Models/Dto/GetRatesFromShipmentDetails/Enums.cs b/ShipEngine/Models/Dto/GetRatesFromShipmentDetails/Enums.cs index 008a9f8b..20069c2f 100644 --- a/ShipEngine/Models/Dto/GetRatesFromShipmentDetails/Enums.cs +++ b/ShipEngine/Models/Dto/GetRatesFromShipmentDetails/Enums.cs @@ -3,19 +3,6 @@ namespace ShipEngineSDK.GetRatesWithShipmentDetails { - /// - /// The possible shipment status values - /// - public enum ShipmentStatus - { - Pending, - Processing, - - [EnumMember(Value = "label_purchased")] - LabelPurchased, - Cancelled - } - /// /// The possible rate type values /// diff --git a/ShipEngine/Models/Dto/GetRatesFromShipmentDetails/Params.cs b/ShipEngine/Models/Dto/GetRatesFromShipmentDetails/Params.cs index b40e5d25..c6657037 100644 --- a/ShipEngine/Models/Dto/GetRatesFromShipmentDetails/Params.cs +++ b/ShipEngine/Models/Dto/GetRatesFromShipmentDetails/Params.cs @@ -29,124 +29,6 @@ public class Params /// public RateOptions RateOptions { get; set; } } - - /// - /// Shipment information - /// - public class Shipment - { - /// - /// The possible validate address values - /// - [JsonConverter(typeof(StringEnumConverter))] - public ValidateAddress ValidateAddress { get; set; } - - /// - /// The carrier account that is billed for the shipping charges - /// - public string CarrierId { get; set; } - - /// - /// The carrier service used to ship the package - /// - public string ServiceCode { get; set; } - - /// - /// ID that the Order Source assigned - /// - public string ExternalOrderId { get; set; } - - /// - /// Describe the packages included in this shipment as related to potential metadata that was imported from external order sources - /// - public List Items { get; set; } - - /// - /// Tax identifiers - /// - public List TaxIdentifiers { get; set; } - - /// - /// You can optionally use this field to store your own identifier for this shipment. - /// - public string ExternalShipmentId { get; set; } - - /// - /// The date that the shipment was (or will be) shippped. ShipEngine will take the day of week into consideration. - /// For example, if the carrier does not operate on Sundays, then a package that would have shipped on Sunday will ship on Monday instead. - /// - public string ShipDate { get; set; } - - /// - /// The recipient's mailing address - /// - public Address ShipTo { get; set; } - - /// - /// The shipment's origin address. If you frequently ship from the same location, consider creating a warehouse. - /// Then you can simply specify the warehouse_id rather than the complete address each time. - /// - public Address ShipFrom { get; set; } - - /// - /// The warehouse that the shipment is being shipped from. Either warehouse_id or ship_from must be specified. - /// - public string WarehouseId { get; set; } - - /// - /// The return address for this shipment. Defaults to the ship_from address. - /// - public Address ReturnTo { get; set; } - - /// - /// The type of delivery confirmation that is required for this shipment. - /// - [JsonConverter(typeof(StringEnumConverter))] - public DeliveryConfirmation Confirmation { get; set; } - - /// - /// Customs information. This is usually only needed for international shipments. - /// - public Customs Customs { get; set; } - - /// - /// Advanced shipment options. These are entirely optional. - /// - public AdvancedShipmentOptions AdvancedOptions { get; set; } - - /// - /// Indicates if the package will be picked up or dropped off by the carrier - /// - public OriginType OriginType { get; set; } - - /// - /// The insurance provider to use for any insured packages in the shipment. - /// - [JsonConverter(typeof(StringEnumConverter))] - public InsuranceProvider InsuranceProvider { get; set; } - - /// - /// Arbitrary tags associated with this shipment. Tags can be used to categorize shipments, and shipments can be queried by their tags. - /// - public List Tags { get; set; } - - /// - /// The order sources that are supported by ShipEngine - /// - [JsonConverter(typeof(StringEnumConverter))] - public OrderSourceCode OrderSourceCode { get; set; } - - /// - /// The packages in the shipment. - /// - public List Packages { get; set; } - - /// - /// The combined weight of all packages in the shipment - /// - public Weight Weight { get; set; } - } - /// /// Rate options for specifying the type of rate estimates /// diff --git a/ShipEngine/Models/Dto/UpdateShipmentByID/Params.cs b/ShipEngine/Models/Dto/UpdateShipmentByID/Params.cs new file mode 100644 index 00000000..2b5c6a9d --- /dev/null +++ b/ShipEngine/Models/Dto/UpdateShipmentByID/Params.cs @@ -0,0 +1,22 @@ +#nullable disable + +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using ShipEngineSDK.Common; +using ShipEngineSDK.Common.Enums; +using System.Collections.Generic; + +namespace ShipEngineSDK.UpdateShipmentByID +{ + + /// + /// Paramters needed for updating a shipment. + /// + public class Params + { + /// + /// The shipment information used to update a shipment + /// + public Shipment Shipment { get; set; } + } +} diff --git a/ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs b/ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs new file mode 100644 index 00000000..e78a9242 --- /dev/null +++ b/ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs @@ -0,0 +1,138 @@ +using ShipEngineSDK.Common; +using ShipEngineSDK.Common.Enums; +using System.Collections.Generic; + +namespace ShipEngineSDK.UpdateShipmentByID +{ + + + public class Result + { + /// + /// A string that uniquely identifies the shipment + /// + public string? ShipmentId { get; set; } + + /// + /// The carrier account that is billed for the shipping charges + /// + public string? CarrierId { get; set; } + + /// + /// The carrier service used to ship the package + /// + public string? ServiceCode { get; set; } + + /// + /// ID that the Order Source assigned + /// + public string? ExternalOrderId { get; set; } + + /// + /// Describe the packages included in this shipment as related to potential metadata that was imported from external order sources + /// + public List Items { get; set; } + + /// + /// Tax identifiers + /// + public List TaxIdentifiers { get; set; } + + /// + /// You can optionally use this field to store your own identifier for this shipment. + /// + public string? ExternalShipmentId { get; set; } + + /// + /// The date that the shipment was (or will be) shippped. ShipEngine will take the day of week into consideration. + /// For example, if the carrier does not operate on Sundays, then a package that would have shipped on Sunday will ship on Monday instead. + /// + public string? ShipDate { get; set; } + + /// + /// The date and time that the shipment was created in ShipEngine. + /// + public string? CreatedAt { get; set; } + /// + /// The date and time that the shipment was created or last modified. + /// + public string? ModifiedAt { get; set; } + + /// + /// The current status of the shipment + /// + public ShipmentStatus ShipmentStatus { get; set; } + + /// + /// The recipient's mailing address + /// + public Address ShipTo { get; set; } + + /// + /// The shipment's origin address. If you frequently ship from the same location, consider creating a warehouse. + /// Then you can simply specify the warehouse_id rather than the complete address each time. + /// + public Address ShipFrom { get; set; } + + /// + /// The warehouse that the shipment is being shipped from. Either warehouse_id or ship_from must be specified. + /// + public string? WarehouseId { get; set; } + + /// + /// The return address for this shipment. Defaults to the ship_from address. + /// + public Address ReturnTo { get; set; } + + /// + /// The type of delivery confirmation that is required for this shipment. + /// + public DeliveryConfirmation Confirmation { get; set; } + + /// + /// Customs information. This is usually only needed for international shipments. + /// + public Customs Customs { get; set; } + + /// + /// Advanced shipment options. These are entirely optional. + /// + public AdvancedShipmentOptions AdvancedOptions { get; set; } + + /// + /// Indicates if the package will be picked up or dropped off by the carrier + /// + public OriginType OriginType { get; set; } + + /// + /// The insurance provider to use for any insured packages in the shipment. + /// + public InsuranceProvider InsuranceProvider { get; set; } + + /// + /// Arbitrary tags associated with this shipment. Tags can be used to categorize shipments, and shipments can be queried by their tags. + /// + public List Tags { get; set; } + + + /// + /// Total Weight of the Shipment + /// + public Weight TotalWeight { get; set; } + + /// + /// The order sources that are supported by ShipEngine + /// + public OrderSourceCode? OrderSourceCode { get; set; } + + /// + /// The packages in the shipment. + /// + public List Packages { get; set; } + + /// + /// The address validation. + /// + public ValidateAddresses.Result AddressValidation { get; set; } + } +} diff --git a/ShipEngine/ShipEngine.cs b/ShipEngine/ShipEngine.cs index cbdcf2f8..78448c6e 100644 --- a/ShipEngine/ShipEngine.cs +++ b/ShipEngine/ShipEngine.cs @@ -363,5 +363,44 @@ public ShipEngine(Config config) : base() return labelResult; } + + /// + /// Update a shipment from shipment details + /// + /// Details of the shipment that you want to update + /// Object containing the updated shipment information + public async Task UpdateShipmentFromShipmentDetails(UpdateShipmentByID.Params shipmentParams, string shipmentID) + { + + string shipmentParamsString = JsonConvert.SerializeObject(shipmentParams, JsonSerializerSettings); + + var path = $"/v1/shipments/{shipmentID}"; + + var labelResult = await SendHttpRequestAsync(HttpMethod.Put, path, shipmentParamsString, _client, _config); + + return labelResult; + } + + /// + /// Update a shipment from shipment details + /// + /// Details of the shipment that you want to update + /// Configuration object that overrides the global config for this method call + /// Object containing the updated shipment information + public async Task UpdateShipmentFromShipmentDetails(UpdateShipmentByID.Params shipmentParams, string shipmentID, Config methodConfig) + { + + var client = ConfigureHttpClient(methodConfig, new HttpClient()); + + string shipmentParamsString = JsonConvert.SerializeObject(shipmentParams, JsonSerializerSettings); + + var path = $"/v1/shipments/{shipmentID}"; + + var labelResult = await SendHttpRequestAsync(HttpMethod.Put, path, shipmentParamsString, client, methodConfig); + + client.Dispose(); + + return labelResult; + } } } \ No newline at end of file diff --git a/ShipEngine/ShipEngine.csproj b/ShipEngine/ShipEngine.csproj index d47b5be6..28c6e531 100644 --- a/ShipEngine/ShipEngine.csproj +++ b/ShipEngine/ShipEngine.csproj @@ -4,7 +4,7 @@ ShipEngine sdk;rest;api;shipping;rates;label;tracking;cost;address;validation;normalization;fedex;ups;usps; - 1.1.0 + 1.1.1 ShipEngine ShipEngine The official ShipEngine C# SDK for .NET From 51bac4a2a35b34a1acb4021e35aae3dea5caf89e Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Wed, 19 Apr 2023 08:27:20 -0400 Subject: [PATCH 03/14] Update Package To ShipmentPackage --- .../CreateLabelFromShipmentDetailsTest.cs | 4 +- .../CreateLabelFromShipmentDetails/Params.cs | 39 ------------------- 2 files changed, 2 insertions(+), 41 deletions(-) diff --git a/ShipEngine.Tests/ShipEngineMethodTests/CreateLabelFromShipmentDetailsTest.cs b/ShipEngine.Tests/ShipEngineMethodTests/CreateLabelFromShipmentDetailsTest.cs index 4930c29d..c35bd7e6 100644 --- a/ShipEngine.Tests/ShipEngineMethodTests/CreateLabelFromShipmentDetailsTest.cs +++ b/ShipEngine.Tests/ShipEngineMethodTests/CreateLabelFromShipmentDetailsTest.cs @@ -52,8 +52,8 @@ public CreateLabelFromShipmentDetailsTest() Phone = "512-555-5555" }, Confirmation = DeliveryConfirmation.DeliveryMailed, - Packages = new List() { - new Package() { + Packages = new List() { + new ShipmentPackage() { Weight = new Weight() { Value = 17, Unit = WeightUnit.Pound diff --git a/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs b/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs index e24e59ef..0c2248dd 100644 --- a/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs +++ b/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs @@ -74,45 +74,6 @@ public class Params /// public string LabelImageId { get; set; } } - - /// - /// Package information - /// - public class Package - { - /// - /// The package type, such as thick_envelope, small_flat_rate_box, large_package, etc. The code package indicates a custom or unknown package type - /// - public string PackageCode { get; set; } - - /// - /// The package weight - /// - public Weight Weight { get; set; } - - /// - /// The package dimensions - /// - public Dimensions Dimensions { get; set; } - - /// - /// The insured value of the package. Requires the InsuranceProvider property of the shipment to be set. - /// - public MonetaryValue InsuredValue { get; set; } - - /// - /// Custom messages to print on the shipping label for the package. - /// These are typically used to print invoice numbers, product numbers, or other internal reference numbers. - /// Not all carriers support label messages. The number of lines and the maximum length of each line also varies by carrier. - /// - public LabelMessages LabelMessages { get; set; } - - /// - /// An external package id. - /// - public string ExternalPackageId { get; set; } - } - /// /// Options associated with international shipments /// From 3c8e26d6132a7e6c64f5b5e96de549a304368995 Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Wed, 19 Apr 2023 12:16:58 -0400 Subject: [PATCH 04/14] Create Publish Profiles --- ShipEngine/Properties/PublishProfiles/Debug.pubxml | 13 +++++++++++++ .../Properties/PublishProfiles/Release.pubxml | 12 ++++++++++++ ShipEngine/ShipEngine.cs | 4 ++-- 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 ShipEngine/Properties/PublishProfiles/Debug.pubxml create mode 100644 ShipEngine/Properties/PublishProfiles/Release.pubxml diff --git a/ShipEngine/Properties/PublishProfiles/Debug.pubxml b/ShipEngine/Properties/PublishProfiles/Debug.pubxml new file mode 100644 index 00000000..26c8e9c5 --- /dev/null +++ b/ShipEngine/Properties/PublishProfiles/Debug.pubxml @@ -0,0 +1,13 @@ + + + + + Debug + Any CPU + bin\Debug\netstandard2.0\publish\ + FileSystem + netstandard2.0 + + \ No newline at end of file diff --git a/ShipEngine/Properties/PublishProfiles/Release.pubxml b/ShipEngine/Properties/PublishProfiles/Release.pubxml new file mode 100644 index 00000000..31cd7494 --- /dev/null +++ b/ShipEngine/Properties/PublishProfiles/Release.pubxml @@ -0,0 +1,12 @@ + + + + + Release + Any CPU + bin\Release\netstandard2.0\publish\ + FileSystem + + \ No newline at end of file diff --git a/ShipEngine/ShipEngine.cs b/ShipEngine/ShipEngine.cs index 78448c6e..9f083ca6 100644 --- a/ShipEngine/ShipEngine.cs +++ b/ShipEngine/ShipEngine.cs @@ -372,7 +372,7 @@ public ShipEngine(Config config) : base() public async Task UpdateShipmentFromShipmentDetails(UpdateShipmentByID.Params shipmentParams, string shipmentID) { - string shipmentParamsString = JsonConvert.SerializeObject(shipmentParams, JsonSerializerSettings); + string shipmentParamsString = JsonConvert.SerializeObject(shipmentParams.Shipment, JsonSerializerSettings); var path = $"/v1/shipments/{shipmentID}"; @@ -392,7 +392,7 @@ public ShipEngine(Config config) : base() var client = ConfigureHttpClient(methodConfig, new HttpClient()); - string shipmentParamsString = JsonConvert.SerializeObject(shipmentParams, JsonSerializerSettings); + string shipmentParamsString = JsonConvert.SerializeObject(shipmentParams.Shipment, JsonSerializerSettings); var path = $"/v1/shipments/{shipmentID}"; From 4442ed4fe5b7e29038ebb91d95f21a01e970e5b7 Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Wed, 19 Apr 2023 12:18:54 -0400 Subject: [PATCH 05/14] Update version --- ShipEngine/ShipEngine.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ShipEngine/ShipEngine.csproj b/ShipEngine/ShipEngine.csproj index 28c6e531..0dbef948 100644 --- a/ShipEngine/ShipEngine.csproj +++ b/ShipEngine/ShipEngine.csproj @@ -4,7 +4,7 @@ ShipEngine sdk;rest;api;shipping;rates;label;tracking;cost;address;validation;normalization;fedex;ups;usps; - 1.1.1 + 1.2.0 ShipEngine ShipEngine The official ShipEngine C# SDK for .NET From 2c83f5698ca675c69e8cfe2578cead6ea07cec55 Mon Sep 17 00:00:00 2001 From: pats721 Date: Wed, 19 Apr 2023 12:23:12 -0400 Subject: [PATCH 06/14] 1.2.0 1.2.0 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b72a97..bfcac65b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,3 +37,14 @@ Rename LabelDownload method to the more generic Download ### Fixed Some documentation linking errors and minor typos + +## 1.2.0 + +### Added + +Method to Update Shipment By Shipment ID + +### Changed + +Moved Shipment Class to the common models, as it is used in multiple requests. +Updated package class to use the Shipment Package class in Rate Requests. From 56abef4f53ad8a39b2472778133cd86c346c8f0e Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Wed, 19 Apr 2023 12:25:08 -0400 Subject: [PATCH 07/14] dotnet format --- .../ShipEngineMethodTests/UpdateShipmentByIDTest.cs | 2 +- ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs | 2 +- ShipEngine/Models/Dto/Common/Shipment.cs | 2 +- ShipEngine/Models/Dto/UpdateShipmentByID/Params.cs | 2 +- ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ShipEngine.Tests/ShipEngineMethodTests/UpdateShipmentByIDTest.cs b/ShipEngine.Tests/ShipEngineMethodTests/UpdateShipmentByIDTest.cs index 9ecdef18..c94a6268 100644 --- a/ShipEngine.Tests/ShipEngineMethodTests/UpdateShipmentByIDTest.cs +++ b/ShipEngine.Tests/ShipEngineMethodTests/UpdateShipmentByIDTest.cs @@ -195,4 +195,4 @@ public async void ValidUpdateShipmentByIDTest() } } -} +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs b/ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs index 0de4c9b6..d9b2c2e9 100644 --- a/ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs +++ b/ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs @@ -17,4 +17,4 @@ public enum ShipmentStatus LabelPurchased, Cancelled } -} +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/Common/Shipment.cs b/ShipEngine/Models/Dto/Common/Shipment.cs index f3f0ca45..fa458486 100644 --- a/ShipEngine/Models/Dto/Common/Shipment.cs +++ b/ShipEngine/Models/Dto/Common/Shipment.cs @@ -121,4 +121,4 @@ public class Shipment /// public Weight Weight { get; set; } } -} +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/UpdateShipmentByID/Params.cs b/ShipEngine/Models/Dto/UpdateShipmentByID/Params.cs index 2b5c6a9d..bd8e4010 100644 --- a/ShipEngine/Models/Dto/UpdateShipmentByID/Params.cs +++ b/ShipEngine/Models/Dto/UpdateShipmentByID/Params.cs @@ -19,4 +19,4 @@ public class Params /// public Shipment Shipment { get; set; } } -} +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs b/ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs index e78a9242..c9ab9c8e 100644 --- a/ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs +++ b/ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs @@ -135,4 +135,4 @@ public class Result /// public ValidateAddresses.Result AddressValidation { get; set; } } -} +} \ No newline at end of file From 0571a70cb5b6502dc6a9c43b35feaf5acf613036 Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Fri, 28 Apr 2023 09:12:09 -0400 Subject: [PATCH 08/14] Added CreateShipment Functionality --- .../CreateShipmentsTest.cs | 201 ++++++++++++++++++ .../Models/Dto/CreateShipments/Params.cs | 21 ++ .../Models/Dto/CreateShipments/Result.cs | 151 +++++++++++++ .../Properties/PublishProfiles/Release.pubxml | 1 + ShipEngine/ShipEngine.cs | 39 ++++ ShipEngine/ShipEngine.csproj | 6 +- 6 files changed, 416 insertions(+), 3 deletions(-) create mode 100644 ShipEngine.Tests/ShipEngineMethodTests/CreateShipmentsTest.cs create mode 100644 ShipEngine/Models/Dto/CreateShipments/Params.cs create mode 100644 ShipEngine/Models/Dto/CreateShipments/Result.cs diff --git a/ShipEngine.Tests/ShipEngineMethodTests/CreateShipmentsTest.cs b/ShipEngine.Tests/ShipEngineMethodTests/CreateShipmentsTest.cs new file mode 100644 index 00000000..b8214de0 --- /dev/null +++ b/ShipEngine.Tests/ShipEngineMethodTests/CreateShipmentsTest.cs @@ -0,0 +1,201 @@ +using Moq; +using Newtonsoft.Json; +using ShipEngineSDK; +using ShipEngineSDK.Common; +using ShipEngineSDK.Common.Enums; +using ShipEngineSDK.CreateShipments; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace ShipEngineTest +{ + public class CreateShipmentsTest + { + public Params ShipmentParameters; + public TestUtils TestUtils; + + public CreateShipmentsTest() + { + TestUtils = new TestUtils(); + var Shipments = new List(); + Shipment shipment = new Shipment() + { + ServiceCode = "usps_priority_mail", + ShipFrom = new Address() + { + Name = "John Doe", + AddressLine1 = "4009 Marathon Blvd", + CityLocality = "Austin", + StateProvince = "TX", + PostalCode = "78756", + CountryCode = Country.US, + Phone = "512-555-5555" + }, + ShipTo = new Address() + { + Name = "Amanda Miller", + AddressLine1 = "525 S Winchester Blvd", + CityLocality = "San Jose", + StateProvince = "CA", + PostalCode = "95128", + CountryCode = Country.US, + Phone = "512-555-5555" + }, + Customs = new Customs() + { + NonDelivery = NonDelivery.ReturnToSender, + Contents = PackageContents.Merchandise, + CustomsItems = new List() + { + new CustomsItem() + { + Description = "Merchandise", + CountryOfOrigin = Country.US, + Quantity = 1, + UnitOfMeasure = "each", + Value = new MonetaryValue() + { + Amount = 100D, + Currency = Currency.USD + } + } + } + }, + Packages = new List() { + new ShipmentPackage() { + Weight = new Weight() { + Value = 17, + Unit = WeightUnit.Pound + }, + Dimensions = new Dimensions() { + Length = 36, + Width = 12, + Height = 24, + Unit = DimensionUnit.Inch, + } + } + }, + ValidateAddress = ValidateAddress.ValidateAndClean + }; + Shipments.Add(shipment); + ShipmentParameters = new Params() + { + Shipments = Shipments, + }; + } + + [Fact] + public async void ValidCreateShipmentsTestTest() + { + + var config = new Config("TEST_bTYAskEX6tD7vv6u/cZ/M4LaUSWBJ219+8S1jgFcnkk"); + var mockShipEngineFixture = new MockShipEngineFixture(config); + + string json = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "../../../HttpResponseMocks/UpdateShipmentByID200Response.json")); + + mockShipEngineFixture.StubRequest(HttpMethod.Put, "/v1/shipments/se-153814671", System.Net.HttpStatusCode.OK, json); + + var resultCreate = await mockShipEngineFixture.ShipEngine.CreateShipments(ShipmentParameters); + var result = resultCreate.Shipments.First(); + Assert.Equal("se-153814671", result.ShipmentId); + Assert.Equal("se-423888", result.CarrierId); + Assert.Equal("ups_ground", result.ServiceCode); + Assert.Null(result.ExternalShipmentId); + Assert.Equal("2021-08-27T00:00:00Z", result.ShipDate); + Assert.Equal("2021-08-27T16:29:25.257Z", result.CreatedAt); + Assert.Equal("2021-08-27T16:29:25.24Z", result.ModifiedAt); + Assert.Equal(ShipmentStatus.Pending, result.ShipmentStatus); + + Assert.Equal("Amanda Miller", result.ShipTo.Name); + Assert.Null(result.ShipTo.Phone); + Assert.Null(result.ShipTo.CompanyName); + Assert.Equal("525 S Winchester Blvd", result.ShipTo.AddressLine1); + Assert.Null(result.ShipTo.AddressLine2); + Assert.Null(result.ShipTo.AddressLine3); + Assert.Equal("San Jose", result.ShipTo.CityLocality); + Assert.Equal("CA", result.ShipTo.StateProvince); + Assert.Equal("95128", result.ShipTo.PostalCode); + Assert.Equal(Country.US, result.ShipTo.CountryCode); + Assert.Equal(AddressResidentialIndicator.Unknown, result.ShipTo.AddressResidentialIndicator); + + Assert.Equal("John Doe", result.ShipFrom.Name); + Assert.Equal("512-555-5555", result.ShipFrom.Phone); + Assert.Empty(result.ShipFrom.CompanyName); + Assert.Equal("4009 Marathon Blvd", result.ShipFrom.AddressLine1); + Assert.Null(result.ShipFrom.AddressLine2); + Assert.Null(result.ShipFrom.AddressLine3); + Assert.Equal("Austin", result.ShipFrom.CityLocality); + Assert.Equal("TX", result.ShipFrom.StateProvince); + Assert.Equal(AddressResidentialIndicator.Unknown, result.ShipFrom.AddressResidentialIndicator); + + Assert.Null(result.WarehouseId); + + Assert.Equal("John Doe", result.ReturnTo.Name); + Assert.Equal("512-555-5555", result.ReturnTo.Phone); + Assert.Empty(result.ReturnTo.CompanyName); + Assert.Equal("4009 Marathon Blvd", result.ReturnTo.AddressLine1); + Assert.Null(result.ReturnTo.AddressLine2); + Assert.Null(result.ReturnTo.AddressLine3); + Assert.Equal("Austin", result.ReturnTo.CityLocality); + Assert.Equal("TX", result.ReturnTo.StateProvince); + Assert.Equal(AddressResidentialIndicator.Unknown, result.ReturnTo.AddressResidentialIndicator); + + Assert.Equal(DeliveryConfirmation.None, result.Confirmation); + + Assert.Equal(PackageContents.Merchandise, result.Customs.Contents); + Assert.NotEmpty(result.Customs.CustomsItems); + Assert.Equal(100D, result.Customs.CustomsItems.First().Value.Amount); + Assert.Equal(NonDelivery.ReturnToSender, result.Customs.NonDelivery); + + Assert.Null(result.ExternalOrderId); + Assert.Null(result.OrderSourceCode); + + Assert.Null(result.AdvancedOptions.BillToAccount); + Assert.Null(result.AdvancedOptions.BillToCountryCode); + Assert.Null(result.AdvancedOptions.BillToParty); + Assert.Null(result.AdvancedOptions.BillToPostalCode); + Assert.False(result.AdvancedOptions.ContainsAlcohol); + Assert.False(result.AdvancedOptions.DeliveredDutyPaid); + Assert.False(result.AdvancedOptions.NonMachinable); + Assert.False(result.AdvancedOptions.SaturdayDelivery); + Assert.False(result.AdvancedOptions.DryIce); + Assert.Null(result.AdvancedOptions.DryIceWeight); + Assert.Null(result.AdvancedOptions.FedexFreight); + Assert.Null(result.AdvancedOptions.FreightClass); + Assert.Null(result.AdvancedOptions.CustomField1); + Assert.Null(result.AdvancedOptions.CustomField2); + Assert.Null(result.AdvancedOptions.CustomField3); + Assert.Null(result.AdvancedOptions.CollectOnDelivery); + + Assert.Equal(InsuranceProvider.None, result.InsuranceProvider); + Assert.Empty(result.Tags); + + Assert.Equal("package", result.Packages[0].PackageCode); + Assert.Equal(17.0, result.Packages[0].Weight.Value); + Assert.Equal(WeightUnit.Pound, result.Packages[0].Weight.Unit); + Assert.Equal(DimensionUnit.Inch, result.Packages[0].Dimensions.Unit); + Assert.Equal(12, result.Packages[0].Dimensions.Width); + Assert.Equal(36, result.Packages[0].Dimensions.Length); + Assert.Equal(24, result.Packages[0].Dimensions.Height); + + Assert.Equal(Currency.USD, result.Packages[0].InsuredValue.Currency); + Assert.Equal(0, result.Packages[0].InsuredValue.Amount); + + Assert.Null(result.Packages[0].LabelMessages.Reference1); + Assert.Null(result.Packages[0].LabelMessages.Reference2); + Assert.Null(result.Packages[0].LabelMessages.Reference3); + + Assert.Null(result.Packages[0].ExternalPackageId); + + Assert.Equal(17.0, result.TotalWeight.Value); + Assert.Equal(WeightUnit.Pound, result.TotalWeight.Unit); + Assert.Empty(result.Items); + + } + } +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/CreateShipments/Params.cs b/ShipEngine/Models/Dto/CreateShipments/Params.cs new file mode 100644 index 00000000..49d6943d --- /dev/null +++ b/ShipEngine/Models/Dto/CreateShipments/Params.cs @@ -0,0 +1,21 @@ + +#nullable disable + +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using ShipEngineSDK.Common; +using ShipEngineSDK.Common.Enums; +using System.Collections.Generic; + +namespace ShipEngineSDK.CreateShipments +{ + + + public class Params + { + /// + /// An array of shipments to be created + /// + public List Shipments { get; set; } + } +} diff --git a/ShipEngine/Models/Dto/CreateShipments/Result.cs b/ShipEngine/Models/Dto/CreateShipments/Result.cs new file mode 100644 index 00000000..064dcd62 --- /dev/null +++ b/ShipEngine/Models/Dto/CreateShipments/Result.cs @@ -0,0 +1,151 @@ +using ShipEngineSDK.Common; +using ShipEngineSDK.Common.Enums; +using System; +using System.Collections.Generic; + +namespace ShipEngineSDK.CreateShipments +{ + + public class Result + { + /// + /// Indicates if errors occured while creating the shipments + /// + public Boolean? HasErrors { get; set; } + + /// + /// An array of shipments that were created + /// + public List Shipments { get; set; } + } + + public class ShipmentResult + { + /// + /// A string that uniquely identifies the shipment + /// + public string? ShipmentId { get; set; } + + /// + /// The carrier account that is billed for the shipping charges + /// + public string? CarrierId { get; set; } + + /// + /// The carrier service used to ship the package + /// + public string? ServiceCode { get; set; } + + /// + /// ID that the Order Source assigned + /// + public string? ExternalOrderId { get; set; } + + /// + /// Describe the packages included in this shipment as related to potential metadata that was imported from external order sources + /// + public List Items { get; set; } + + /// + /// Tax identifiers + /// + public List TaxIdentifiers { get; set; } + + /// + /// You can optionally use this field to store your own identifier for this shipment. + /// + public string? ExternalShipmentId { get; set; } + + /// + /// The date that the shipment was (or will be) shippped. ShipEngine will take the day of week into consideration. + /// For example, if the carrier does not operate on Sundays, then a package that would have shipped on Sunday will ship on Monday instead. + /// + public string? ShipDate { get; set; } + + /// + /// The date and time that the shipment was created in ShipEngine. + /// + public string? CreatedAt { get; set; } + /// + /// The date and time that the shipment was created or last modified. + /// + public string? ModifiedAt { get; set; } + + /// + /// The current status of the shipment + /// + public ShipmentStatus ShipmentStatus { get; set; } + + /// + /// The recipient's mailing address + /// + public Address ShipTo { get; set; } + + /// + /// The shipment's origin address. If you frequently ship from the same location, consider creating a warehouse. + /// Then you can simply specify the warehouse_id rather than the complete address each time. + /// + public Address ShipFrom { get; set; } + + /// + /// The warehouse that the shipment is being shipped from. Either warehouse_id or ship_from must be specified. + /// + public string? WarehouseId { get; set; } + + /// + /// The return address for this shipment. Defaults to the ship_from address. + /// + public Address ReturnTo { get; set; } + + /// + /// The type of delivery confirmation that is required for this shipment. + /// + public DeliveryConfirmation Confirmation { get; set; } + + /// + /// Customs information. This is usually only needed for international shipments. + /// + public Customs Customs { get; set; } + + /// + /// Advanced shipment options. These are entirely optional. + /// + public AdvancedShipmentOptions AdvancedOptions { get; set; } + + /// + /// Indicates if the package will be picked up or dropped off by the carrier + /// + public OriginType OriginType { get; set; } + + /// + /// The insurance provider to use for any insured packages in the shipment. + /// + public InsuranceProvider InsuranceProvider { get; set; } + + /// + /// Arbitrary tags associated with this shipment. Tags can be used to categorize shipments, and shipments can be queried by their tags. + /// + public List Tags { get; set; } + + + /// + /// Total Weight of the Shipment + /// + public Weight TotalWeight { get; set; } + + /// + /// The order sources that are supported by ShipEngine + /// + public OrderSourceCode? OrderSourceCode { get; set; } + + /// + /// The packages in the shipment. + /// + public List Packages { get; set; } + + /// + /// The address validation. + /// + public ValidateAddresses.Result AddressValidation { get; set; } + } +} diff --git a/ShipEngine/Properties/PublishProfiles/Release.pubxml b/ShipEngine/Properties/PublishProfiles/Release.pubxml index 31cd7494..284f1ec6 100644 --- a/ShipEngine/Properties/PublishProfiles/Release.pubxml +++ b/ShipEngine/Properties/PublishProfiles/Release.pubxml @@ -8,5 +8,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121. Any CPU bin\Release\netstandard2.0\publish\ FileSystem + netstandard2.0 \ No newline at end of file diff --git a/ShipEngine/ShipEngine.cs b/ShipEngine/ShipEngine.cs index 9f083ca6..242296ab 100644 --- a/ShipEngine/ShipEngine.cs +++ b/ShipEngine/ShipEngine.cs @@ -402,5 +402,44 @@ public ShipEngine(Config config) : base() return labelResult; } + + /// + /// Create one or multiple shipments + /// + /// List of details of the shipments that you want to create + /// Object containing the created shipments information + public async Task CreateShipments(CreateShipments.Params shipmentParams) + { + + string shipmentParamsString = JsonConvert.SerializeObject(shipmentParams.Shipments, JsonSerializerSettings); + + var path = $"/v1/shipments"; + + var shipmentResult = await SendHttpRequestAsync(HttpMethod.Post, path, shipmentParamsString, _client, _config); + + return shipmentResult; + } + + /// + /// Create one or multiple shipments + /// + /// List of details of the shipments that you want to create + /// Configuration object that overrides the global config for this method call + /// Object containing the created shipments information + public async Task CreateShipments(CreateShipments.Params shipmentParams, Config methodConfig) + { + + var client = ConfigureHttpClient(methodConfig, new HttpClient()); + + string shipmentParamsString = JsonConvert.SerializeObject(shipmentParams.Shipments, JsonSerializerSettings); + + var path = $"/v1/shipments"; + + var shipmentResult = await SendHttpRequestAsync(HttpMethod.Post, path, shipmentParamsString, _client, _config); + + client.Dispose(); + + return shipmentResult; + } } } \ No newline at end of file diff --git a/ShipEngine/ShipEngine.csproj b/ShipEngine/ShipEngine.csproj index 0dbef948..7908bd7c 100644 --- a/ShipEngine/ShipEngine.csproj +++ b/ShipEngine/ShipEngine.csproj @@ -4,7 +4,7 @@ ShipEngine sdk;rest;api;shipping;rates;label;tracking;cost;address;validation;normalization;fedex;ups;usps; - 1.2.0 + 1.3.0 ShipEngine ShipEngine The official ShipEngine C# SDK for .NET @@ -22,8 +22,8 @@ - - + + From 6e9f7bad70080a912793b688afa40e355d69a05a Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Fri, 28 Apr 2023 09:16:44 -0400 Subject: [PATCH 09/14] Fix Params --- ShipEngine/ShipEngine.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ShipEngine/ShipEngine.cs b/ShipEngine/ShipEngine.cs index 242296ab..e073ca96 100644 --- a/ShipEngine/ShipEngine.cs +++ b/ShipEngine/ShipEngine.cs @@ -368,6 +368,7 @@ public ShipEngine(Config config) : base() /// Update a shipment from shipment details /// /// Details of the shipment that you want to update + /// Shipment ID to update /// Object containing the updated shipment information public async Task UpdateShipmentFromShipmentDetails(UpdateShipmentByID.Params shipmentParams, string shipmentID) { @@ -385,6 +386,7 @@ public ShipEngine(Config config) : base() /// Update a shipment from shipment details /// /// Details of the shipment that you want to update + /// Shipment ID to update /// Configuration object that overrides the global config for this method call /// Object containing the updated shipment information public async Task UpdateShipmentFromShipmentDetails(UpdateShipmentByID.Params shipmentParams, string shipmentID, Config methodConfig) From 8eecaf8ea0ffbd21398f92aa16d4fffce1fe03f2 Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Fri, 28 Apr 2023 09:26:54 -0400 Subject: [PATCH 10/14] Change nuget setting --- ShipEngine/ShipEngine.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ShipEngine/ShipEngine.csproj b/ShipEngine/ShipEngine.csproj index 7908bd7c..76ea7977 100644 --- a/ShipEngine/ShipEngine.csproj +++ b/ShipEngine/ShipEngine.csproj @@ -1,4 +1,4 @@ - + ShipEngine @@ -19,6 +19,7 @@ netstandard2.0 latest enable + True From ae7cc76aa8a5c913986f98740eca480afd345211 Mon Sep 17 00:00:00 2001 From: pats721 Date: Fri, 28 Apr 2023 09:28:22 -0400 Subject: [PATCH 11/14] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfcac65b..711527d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,3 +48,9 @@ Method to Update Shipment By Shipment ID Moved Shipment Class to the common models, as it is used in multiple requests. Updated package class to use the Shipment Package class in Rate Requests. + +## 1.3.0 + +### Added + +Create Shipments request From 648be96d37a330be02cb4f91645af23a11a424b9 Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Fri, 28 Apr 2023 09:40:25 -0400 Subject: [PATCH 12/14] CreateLabelFromShipmentID --- .../CreateLabelFromShipmentIDTest.cs | 177 +++++++++++++ .../Dto/CreateLabelFromShipmentID/Enums.cs | 63 +++++ .../Dto/CreateLabelFromShipmentID/Params.cs | 48 ++++ .../Dto/CreateLabelFromShipmentID/Result.cs | 233 ++++++++++++++++++ ShipEngine/ShipEngine.cs | 38 +++ ShipEngine/ShipEngine.csproj | 7 +- 6 files changed, 562 insertions(+), 4 deletions(-) create mode 100644 ShipEngine.Tests/ShipEngineMethodTests/CreateLabelFromShipmentIDTest.cs create mode 100644 ShipEngine/Models/Dto/CreateLabelFromShipmentID/Enums.cs create mode 100644 ShipEngine/Models/Dto/CreateLabelFromShipmentID/Params.cs create mode 100644 ShipEngine/Models/Dto/CreateLabelFromShipmentID/Result.cs diff --git a/ShipEngine.Tests/ShipEngineMethodTests/CreateLabelFromShipmentIDTest.cs b/ShipEngine.Tests/ShipEngineMethodTests/CreateLabelFromShipmentIDTest.cs new file mode 100644 index 00000000..39f74792 --- /dev/null +++ b/ShipEngine.Tests/ShipEngineMethodTests/CreateLabelFromShipmentIDTest.cs @@ -0,0 +1,177 @@ +using Moq; +using Newtonsoft.Json; +using ShipEngineSDK; +using ShipEngineSDK.Common.Enums; +using ShipEngineSDK.CreateLabelFromShipmentID; +using System; +using System.IO; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace ShipEngineTest +{ + using Moq; + using Newtonsoft.Json; + using ShipEngineSDK.Common.Enums; + using ShipEngineSDK; + using System.IO; + using System.Net.Http; + using System.Threading.Tasks; + using System; + using Xunit; + + public class CreateLabelFromShipmentIDTest + { + + public TestUtils TestUtils; + + public Params Params; + + public CreateLabelFromShipmentIDTest() + { + + Params = new Params() + { + ShipmentID = "se-153814671", + ValidateAddress = ValidateAddress.NoValidation, + LabelLayout = LabelLayout.Letter, + LabelFormat = LabelFormat.PDF, + LabelDownloadType = LabelDownloadType.Url + }; + + TestUtils = new TestUtils(); + } + + [Fact] + public async void ValidCreateLabelFromRateTest() + { + var config = new Config("TEST_bTYAskEX6tD7vv6u/cZ/M4LaUSWBJ219+8S1jgFcnkk"); + var mockShipEngineFixture = new MockShipEngineFixture(config); + + string json = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "../../../HttpResponseMocks/CreateLabelFromRate200Response.json")); + + mockShipEngineFixture.StubRequest(HttpMethod.Post, "/v1/labels/rates/se-1234", System.Net.HttpStatusCode.OK, json); + + var result = await mockShipEngineFixture.ShipEngine.CreateLabelFromShipmentID(Params); + + Assert.Equal("se-80255646", result.LabelId); + Assert.Equal(LabelStatus.Completed, result.Status); + Assert.Equal("se-153814671", result.ShipmentId); + Assert.Equal("2021-08-27T00:00:00Z", result.ShipDate); + Assert.Equal("2021-08-27T16:29:56.8779097Z", result.CreatedAt); + + Assert.Equal(Currency.USD, result.ShipmentCost.Currency); + Assert.Equal(93.21, result.ShipmentCost.Amount); + + Assert.Equal(0.0, result.InsuranceCost.Amount); + Assert.Equal(Currency.USD, result.InsuranceCost.Currency); + + Assert.Equal("1Z63R0960332529481", result.TrackingNumber); + Assert.False(result.IsReturnLabel); + Assert.Null(result.RmaNumber); + Assert.False(result.IsInternational); + + Assert.Equal("", result.BatchId); + Assert.Equal("se-423888", result.CarrierId); + Assert.Equal("ups_ground", result.ServiceCode); + Assert.Equal("package", result.PackageCode); + Assert.False(result.Voided); + Assert.Null(result.VoidedAt); + Assert.Equal(LabelFormat.PDF, result.LabelFormat); + Assert.Equal(DisplayScheme.Label, result.DisplayScheme); + Assert.Equal(LabelLayout.FourBySix, result.LabelLayout); + Assert.True(result.Trackable); + Assert.Null(result.LabelImageId); + Assert.Equal("ups", result.CarrierCode); + Assert.Equal(TrackingStatus.InTransit, result.TrackingStatus); + + Assert.Equal("https://api.shipengine.com/v1/downloads/10/xJi-OIh8UU-_RBVmfA6dDw/label-80255646.pdf", result.LabelDownload.Pdf); + Assert.Equal("https://api.shipengine.com/v1/downloads/10/xJi-OIh8UU-_RBVmfA6dDw/label-80255646.png", result.LabelDownload.Png); + Assert.Equal("https://api.shipengine.com/v1/downloads/10/xJi-OIh8UU-_RBVmfA6dDw/label-80255646.zpl", result.LabelDownload.Zpl); + Assert.Equal("https://api.shipengine.com/v1/downloads/10/xJi-OIh8UU-_RBVmfA6dDw/label-80255646.pdf", result.LabelDownload.Href); + + Assert.Null(result.FormDownload); + Assert.Null(result.InsuranceClaim); + + var package = result.Packages[0]; + Assert.Equal(85151459, package.PackageId); + + Assert.Equal("package", package.PackageCode); + Assert.Equal(17.0, package.Weight.Value); + Assert.Equal(WeightUnit.Pound, package.Weight.Unit); + + Assert.Equal(DimensionUnit.Inch, package.Dimensions.Unit); + Assert.Equal(36.0, package.Dimensions.Length); + Assert.Equal(12.0, package.Dimensions.Width); + Assert.Equal(24.0, package.Dimensions.Height); + + Assert.Equal(Currency.USD, package.InsuredValue.Currency); + Assert.Equal(0.0, package.InsuredValue.Amount); + + Assert.Equal("1Z63R0960332529481", package.TrackingNumber); + + Assert.Null(package.LabelMessages.Reference1); + Assert.Null(package.LabelMessages.Reference2); + Assert.Null(package.LabelMessages.Reference3); + + Assert.Null(package.ExternalPackageId); + Assert.Equal(1, package.Sequence); + + Assert.Equal(ChargeEvent.CarrierDefault, result.ChargeEvent); + } + + [Fact] + public async void ValidateCustomSettingsAtMethodLevel() + { + var apiKeyString = "TEST_bTYAskEX6tD7vv6u/cZ/M4LaUSWBJ219+8S1jgFcnkk"; + + var config = new Config(apiKey: apiKeyString, timeout: TimeSpan.FromSeconds(1)); + + var mockHandler = new Mock(config); + + var shipEngine = mockHandler.Object; + string json = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "../../../HttpResponseMocks/CreateLabelFromRate200Response.json")); + + var voidLabelResult = JsonConvert.DeserializeObject(json); + var request = new HttpRequestMessage(HttpMethod.Post, "v1/labels/shipment/se-153814671"); + + // Verify that the client has a custom timeout of 1 second when called. + mockHandler + .Setup(x => x.SendHttpRequestAsync + ( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.Is(client => + client.Timeout == TimeSpan.FromSeconds(1) && + client.DefaultRequestHeaders.ToString().Contains("12345")), + It.IsAny() + )) + .Returns(Task.FromResult(voidLabelResult)); + + var customConfig = new Config(apiKey: "12345", timeout: TimeSpan.FromSeconds(1)); + + await shipEngine.CreateLabelFromShipmentID(Params, methodConfig: customConfig); + + mockHandler.VerifyAll(); + } + + [Fact] + public async void InvalidRetriesInMethodCall() + { + var apiKeyString = "TEST_bTYAskEX6tD7vv6u/cZ/M4LaUSWBJ219+8S1jgFcnkk"; + + var config = new Config(apiKey: apiKeyString); + var mockHandler = new Mock(config); + var shipEngine = mockHandler.Object; + + var ex = await Assert.ThrowsAsync(async () => await shipEngine.CreateLabelFromShipmentID(Params, methodConfig: new Config(apiKey: "12345", retries: -1))); + Assert.Equal(ErrorSource.Shipengine, ex.ErrorSource); + Assert.Equal(ErrorType.Validation, ex.ErrorType); + Assert.Equal(ErrorCode.InvalidFieldValue, ex.ErrorCode); + Assert.Equal("Retries must be greater than zero.", ex.Message); + Assert.Null(ex.RequestId); + } + } +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/CreateLabelFromShipmentID/Enums.cs b/ShipEngine/Models/Dto/CreateLabelFromShipmentID/Enums.cs new file mode 100644 index 00000000..b4803363 --- /dev/null +++ b/ShipEngine/Models/Dto/CreateLabelFromShipmentID/Enums.cs @@ -0,0 +1,63 @@ +#pragma warning disable 1591 + +using System.Runtime.Serialization; + +namespace ShipEngineSDK.CreateLabelFromShipmentID +{ + /// + /// The label charge event. + /// + public enum ChargeEvent + { + [EnumMember(Value = "carrier_default")] + CarrierDefault, + + [EnumMember(Value = "on_creation")] + OnCreation, + + [EnumMember(Value = "on_carrier_acceptance")] + OnCarrierAcceptance + } + + /// + /// The possible statuses that a shipping label can be in. + /// + public enum LabelStatus + { + Processing, + Completed, + Error, + Voided + } + + /// + /// The current status of the package. + /// + public enum TrackingStatus + { + Unknown, + + [EnumMember(Value = "in_transit")] + InTransit, + Error, + Delivered + } + + /// + /// The available label download types. + /// + public enum LabelDownloadType + { + /// + /// You will receive a URL, which you can use to download the label in a separate request. + /// The URL will remain valid for 90 days. + /// + Url, + + /// + /// You will receive the Base64-encoded label as part of the response. + /// No need for a second request to download the label. + /// + Inline, + } +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/CreateLabelFromShipmentID/Params.cs b/ShipEngine/Models/Dto/CreateLabelFromShipmentID/Params.cs new file mode 100644 index 00000000..27ff81f2 --- /dev/null +++ b/ShipEngine/Models/Dto/CreateLabelFromShipmentID/Params.cs @@ -0,0 +1,48 @@ +#nullable disable +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using ShipEngineSDK.Common.Enums; + +namespace ShipEngineSDK.CreateLabelFromShipmentID +{ + /// + /// Params for creating a label from a rate id. + /// / + public class Params + { + /// + /// The Shipment ID used to purchase the label. + /// + public string ShipmentID { get; set; } + + /// + /// Address validation to perform while purchasing the label. + /// + [JsonConverter(typeof(StringEnumConverter))] + public ValidateAddress ValidateAddress { get; set; } + + /// + /// The layout (size) that you want the label to be in. + /// + [JsonConverter(typeof(StringEnumConverter))] + public LabelLayout LabelLayout { get; set; } + + /// + /// The file format that you want the label to be in. + /// + [JsonConverter(typeof(StringEnumConverter))] + public LabelFormat LabelFormat { get; set; } + + /// + /// Download the label via url or a base64 encoded string. + /// + [JsonConverter(typeof(StringEnumConverter))] + public LabelDownloadType LabelDownloadType { get; set; } + + /// + /// The display format that the label should be shown in. + /// + [JsonConverter(typeof(StringEnumConverter))] + public DisplayScheme DisplayScheme { get; set; } + } +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/CreateLabelFromShipmentID/Result.cs b/ShipEngine/Models/Dto/CreateLabelFromShipmentID/Result.cs new file mode 100644 index 00000000..cc05ac95 --- /dev/null +++ b/ShipEngine/Models/Dto/CreateLabelFromShipmentID/Result.cs @@ -0,0 +1,233 @@ +using ShipEngineSDK.Common; +using ShipEngineSDK.Common.Enums; +using System.Collections.Generic; + +namespace ShipEngineSDK.CreateLabelFromShipmentID +{ + /// + /// Purchased label information + /// + public class Result + { + /// + /// A string that uniquely identifies the label. This ID is generated by ShipEngine when the label is created. + /// + public string? LabelId { get; set; } + + /// + /// The possible statuses that a shipping label can be in. + /// + public LabelStatus? Status { get; set; } + + /// + /// The shipment that this label is for. ShipEngine can create a shipment for you automatically when you create a label, + /// or you can create your own shipment and then use it to print a label + /// + public string? ShipmentId { get; set; } + + /// + /// The date that the package was (or will be) shippped. ShipEngine will take the day of week into consideration. + /// For example, if the carrier does not operate on Sundays, then a package that would have shipped on Sunday will ship on Monday instead. + /// + public string? ShipDate { get; set; } + + /// + /// The date and time that the label was created in ShipEngine. + /// + public string? CreatedAt { get; set; } + + /// + /// The cost of shipping, delivery confirmation, and other carrier charges. This amount does not include insurance costs. + /// + public MonetaryValue? ShipmentCost { get; set; } + + /// + /// The insurance cost for this package. Add this to the shipment_cost field to get the total cost. + /// + public MonetaryValue? InsuranceCost { get; set; } + + /// + /// The tracking number for the package. Tracking number formats vary across carriers. + /// + public string? TrackingNumber { get; set; } + + /// + /// Indicates whether this is a return label. You may also want to set the rma_number so you know what is being returned. + /// + public bool? IsReturnLabel { get; set; } + + /// + /// An optional Return Merchandise Authorization number. This field is useful for return labels. You can set it to any string value. + /// + public string? RmaNumber { get; set; } + + /// + /// Indicates whether this is an international shipment. That is, the originating country and destination country are different. + /// + public bool? IsInternational { get; set; } + + /// + /// If this label was created as part of a batch, then this is the unique ID of that batch. + /// + public string? BatchId { get; set; } + + /// + /// The unique ID of the carrier account that was used to create this label + /// + public string? CarrierId { get; set; } + + /// + /// The label charge event. + /// + public ChargeEvent? ChargeEvent { get; set; } + + /// + /// The carrier service used to ship the package, such as fedex_ground, usps_first_class_mail, flat_rate_envelope, etc. + /// + public string? ServiceCode { get; set; } + + /// + /// The package type, such as thick_envelope, small_flat_rate_box, large_package, etc. The code package indicates a custom or unknown package type. + /// + public string? PackageCode { get; set; } + + /// + /// Indicates whether the label has been voided + /// + public bool? Voided { get; set; } + + /// + /// The date and time that the label was voided, or null if the label has not been voided + /// + public string? VoidedAt { get; set; } + + /// + /// The file format that you want the label to be in. We recommend pdf format because it is supported by all carriers, + /// whereas some carriers do not support the png or zpl formats. + /// + public LabelFormat? LabelFormat { get; set; } + + /// + /// The display format that the label should be shown in. + /// + public DisplayScheme? DisplayScheme { get; set; } + + /// + /// The layout (size) that you want the label to be in. The label_format determines which sizes are allowed. + /// 4x6 is supported for all label formats, whereas letter (8.5" x 11") is only supported for pdf format. + /// + public LabelLayout? LabelLayout { get; set; } + + /// + /// Indicates whether the shipment is trackable, in which case the tracking_status field will reflect the current status and each package will have a tracking_number. + /// + public bool? Trackable { get; set; } + + /// + /// The label image resource that was used to create a custom label image. + /// + public string? LabelImageId { get; set; } + + /// + /// The shipping carrier who will ship the package, such as fedex, dhl_express, stamps_com, etc. + /// + public string? CarrierCode { get; set; } + + /// + /// Reference to the various downloadable file formats for the generated label + /// + public Download? LabelDownload { get; set; } + + /// + /// The current status of the package, such as in_transit or delivered + /// + public TrackingStatus? TrackingStatus { get; set; } + + /// + /// The link to download the customs form (a.k.a. commercial invoice) for this shipment, if any. + /// Forms are in PDF format. This field is null if the shipment does not require a customs form, or if the carrier does not support it. + /// + public Link? FormDownload { get; set; } + + /// + /// The link to submit an insurance claim for the shipment. + /// This field is null if the shipment is not insured or if the insurance provider does not support online claim submission. + /// + public Link? InsuranceClaim { get; set; } + + /// + /// The label's package(s). + /// + public List Packages { get; set; } + } + + /// + /// Link information + /// + public class Link + { + /// + /// The URL of the linked resource, if any + /// + public string? Href { get; set; } + + /// + /// The type of resource, or the type of relationship to the parent resource + /// + public string? Type { get; set; } + } + + /// + /// Package information + /// + public class Package + { + /// + /// Id supported by the package + /// + public int? PackageId { get; set; } + + /// + /// The package type, such as thick_envelope, small_flat_rate_box, large_package, etc. + /// The code package indicates a custom or unknown package type. + /// + public string? PackageCode { get; set; } + + /// + /// The package weight + /// + public Weight? Weight { get; set; } + + /// + /// The package dimensions + /// + public Dimensions? Dimensions { get; set; } + + /// + /// The insured value of the package. Requires the insurance_provider field of the shipment to be set. + /// + public MonetaryValue? InsuredValue { get; set; } + + /// + /// The tracking number for the package. The format depends on the carrier. + /// + public string? TrackingNumber { get; set; } + + /// + /// Custom messages to print on the shipping label for the package. + /// These are typically used to print invoice numbers, product numbers, or other internal reference numbers. + /// Not all carriers support label messages. The number of lines and the maximum length of each line also varies by carrier. + /// + public LabelMessages? LabelMessages { get; set; } + + /// + /// An external package id. + /// + public string? ExternalPackageId { get; set; } + + /// + /// Package sequence + /// + public int? Sequence { get; set; } + } +} \ No newline at end of file diff --git a/ShipEngine/ShipEngine.cs b/ShipEngine/ShipEngine.cs index e073ca96..edf28960 100644 --- a/ShipEngine/ShipEngine.cs +++ b/ShipEngine/ShipEngine.cs @@ -443,5 +443,43 @@ public ShipEngine(Config config) : base() return shipmentResult; } + + /// + /// Create a label from a rate id + /// + /// The details of the shipment that you want to use to purchase a label + /// Object containing the created label information + public async Task CreateLabelFromShipmentID(CreateLabelFromShipmentID.Params createLabelFromShipmentIDParams) + { + var path = $"/v1/labels/shipment/{createLabelFromShipmentIDParams.ShipmentID}"; + + string createLabelFromShipmentIDParamsString = JsonConvert.SerializeObject(createLabelFromShipmentIDParams, JsonSerializerSettings); + + var labelResult = await SendHttpRequestAsync(HttpMethod.Post, path, createLabelFromShipmentIDParamsString, _client, _config); + + return labelResult; + } + + /// + /// Create a label from a rate id + /// + /// The details of the shipment that you want to use to purchase a label + /// Configuration object that overrides the global config for this method call + /// Object containing the created label information + public async Task CreateLabelFromShipmentID(CreateLabelFromShipmentID.Params createLabelFromShipmentIDParams, Config methodConfig) + { + + var client = ConfigureHttpClient(methodConfig, new HttpClient()); + + var path = $"/v1/labels/shipment/{createLabelFromShipmentIDParams.ShipmentID}"; + + string createLabelFromShipmentIDParamsString = JsonConvert.SerializeObject(createLabelFromShipmentIDParams, JsonSerializerSettings); + + var labelResult = await SendHttpRequestAsync(HttpMethod.Post, path, createLabelFromShipmentIDParamsString, client, methodConfig); + + client.Dispose(); + + return labelResult; + } } } \ No newline at end of file diff --git a/ShipEngine/ShipEngine.csproj b/ShipEngine/ShipEngine.csproj index 76ea7977..f95f0e58 100644 --- a/ShipEngine/ShipEngine.csproj +++ b/ShipEngine/ShipEngine.csproj @@ -4,7 +4,7 @@ ShipEngine sdk;rest;api;shipping;rates;label;tracking;cost;address;validation;normalization;fedex;ups;usps; - 1.3.0 + 1.4.0 ShipEngine ShipEngine The official ShipEngine C# SDK for .NET @@ -19,12 +19,11 @@ netstandard2.0 latest enable - True - - + + From fa911618bc9a26db3cd15603acff28a02565bca7 Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Fri, 28 Apr 2023 10:01:49 -0400 Subject: [PATCH 13/14] Update Settings --- ShipEngine/ShipEngine.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/ShipEngine/ShipEngine.csproj b/ShipEngine/ShipEngine.csproj index f95f0e58..1c95e1fa 100644 --- a/ShipEngine/ShipEngine.csproj +++ b/ShipEngine/ShipEngine.csproj @@ -19,6 +19,7 @@ netstandard2.0 latest enable + True From 1e85abcc3ecd26b9145edfd598c10d46302102be Mon Sep 17 00:00:00 2001 From: pats721 Date: Fri, 28 Apr 2023 10:02:53 -0400 Subject: [PATCH 14/14] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 711527d3..3976ef5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,3 +54,9 @@ Updated package class to use the Shipment Package class in Rate Requests. ### Added Create Shipments request + +## 1.4.0 + +### Added + +Create Label from Shipment ID