diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b72a97..3976ef5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,3 +37,26 @@ 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. + +## 1.3.0 + +### Added + +Create Shipments request + +## 1.4.0 + +### Added + +Create Label from Shipment ID 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 64e2bcfd..1e0da776 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 @@ -25,6 +25,6 @@ - + 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.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.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.Tests/ShipEngineMethodTests/UpdateShipmentByIDTest.cs b/ShipEngine.Tests/ShipEngineMethodTests/UpdateShipmentByIDTest.cs new file mode 100644 index 00000000..c94a6268 --- /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); + + } + } +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs b/ShipEngine/Models/Dto/Common/Enums/ShipmentStatus.cs new file mode 100644 index 00000000..d9b2c2e9 --- /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 + } +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/Common/Shipment.cs b/ShipEngine/Models/Dto/Common/Shipment.cs new file mode 100644 index 00000000..fa458486 --- /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; } + } +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs b/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs index 007ee76a..0c2248dd 100644 --- a/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs +++ b/ShipEngine/Models/Dto/CreateLabelFromShipmentDetails/Params.cs @@ -74,145 +74,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 - /// - 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 /// 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/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/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..bd8e4010 --- /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; } + } +} \ No newline at end of file diff --git a/ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs b/ShipEngine/Models/Dto/UpdateShipmentByID/Result.cs new file mode 100644 index 00000000..c9ab9c8e --- /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; } + } +} \ No newline at end of file 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..284f1ec6 --- /dev/null +++ b/ShipEngine/Properties/PublishProfiles/Release.pubxml @@ -0,0 +1,13 @@ + + + + + Release + 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 cbdcf2f8..edf28960 100644 --- a/ShipEngine/ShipEngine.cs +++ b/ShipEngine/ShipEngine.cs @@ -363,5 +363,123 @@ public ShipEngine(Config config) : base() return labelResult; } + + /// + /// 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) + { + + string shipmentParamsString = JsonConvert.SerializeObject(shipmentParams.Shipment, 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 + /// 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) + { + + var client = ConfigureHttpClient(methodConfig, new HttpClient()); + + string shipmentParamsString = JsonConvert.SerializeObject(shipmentParams.Shipment, JsonSerializerSettings); + + var path = $"/v1/shipments/{shipmentID}"; + + var labelResult = await SendHttpRequestAsync(HttpMethod.Put, path, shipmentParamsString, client, methodConfig); + + client.Dispose(); + + 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; + } + + /// + /// 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 30e01862..1c95e1fa 100644 --- a/ShipEngine/ShipEngine.csproj +++ b/ShipEngine/ShipEngine.csproj @@ -1,10 +1,10 @@ - + ShipEngine sdk;rest;api;shipping;rates;label;tracking;cost;address;validation;normalization;fedex;ups;usps; - 1.1.0 + 1.4.0 ShipEngine ShipEngine The official ShipEngine C# SDK for .NET @@ -19,11 +19,12 @@ netstandard2.0 latest enable + True - - + +