Skip to content

Commit 4130f34

Browse files
Setup TaxCalculationMethods + updates to TaxClasses
1 parent 6d92eee commit 4130f34

9 files changed

+186
-20
lines changed

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<GlobalPackageReference Include="Umbraco.JsonSchema.Extensions" Version="0.3.0" PrivateAssets="all" />
1111
</ItemGroup>
1212
<ItemGroup>
13-
<PackageVersion Include="Umbraco.Commerce.Cms.Startup" Version="[14.0.0, 15)" />
13+
<PackageVersion Include="Umbraco.Commerce.Cms.Startup" Version="[14.1.0--preview.30, 15)" />
1414
<PackageVersion Include="Umbraco.Deploy.Infrastructure" Version="[14.1.0, 15)" />
1515
</ItemGroup>
1616
</Project>

NuGet.config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@
99
<packageSource key="nuget.org">
1010
<package pattern="*" />
1111
</packageSource>
12+
<packageSource key="Umbraco Nightly">
13+
<package pattern="Umbraco.Commerce.*" />
14+
</packageSource>
1215
</packageSourceMapping>
1316
</configuration>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System.Collections.Generic;
2+
using Umbraco.Cms.Core;
3+
using Umbraco.Cms.Core.Deploy;
4+
using Umbraco.Deploy.Infrastructure.Serialization;
5+
6+
namespace Umbraco.Commerce.Deploy.Artifacts
7+
{
8+
public class TaxCalculationMethodArtifact(GuidUdi? udi, GuidUdi storeUdi, IEnumerable<ArtifactDependency> dependencies = null)
9+
: StoreEntityArtifactBase(udi, storeUdi, dependencies)
10+
{
11+
public string SalesTaxProviderAlias { get; set; }
12+
public SortedDictionary<string, string> SalesTaxProviderSettings { get; set; }
13+
public int SortOrder { get; set; }
14+
}
15+
}

src/Umbraco.Commerce.Deploy/Artifacts/TaxClassArtifact.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,22 @@ public class TaxClassArtifact(GuidUdi? udi, GuidUdi storeUdi, IEnumerable<Artifa
1111
[RoundingDecimalConverter(3)]
1212
public decimal DefaultTaxRate { get; set; }
1313

14-
public IEnumerable<CountryRegionTaxRateArtifact>? CountryRegionTaxRates { get; set; }
14+
public string DefaultTaxCode { get; set; }
15+
16+
public IEnumerable<CountryRegionTaxClassArtifact>? CountryRegionTaxClasses { get; set; }
1517

1618
public int SortOrder { get; set; }
1719
}
1820

19-
public class CountryRegionTaxRateArtifact
21+
public class CountryRegionTaxClassArtifact
2022
{
2123
public GuidUdi CountryUdi { get; set; }
2224

2325
public GuidUdi? RegionUdi { get; set; }
2426

2527
[RoundingDecimalConverter(3)]
2628
public decimal TaxRate { get; set; }
29+
30+
public string TaxCode { get; set; }
2731
}
2832
}

src/Umbraco.Commerce.Deploy/Composing/UmbracoCommerceDeployComponent.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ private static void RegisterUdiTypes()
4444
UdiParser.RegisterUdiType(UmbracoCommerceConstants.UdiEntityType.Region, UdiType.GuidUdi);
4545
UdiParser.RegisterUdiType(UmbracoCommerceConstants.UdiEntityType.Currency, UdiType.GuidUdi);
4646
UdiParser.RegisterUdiType(UmbracoCommerceConstants.UdiEntityType.TaxClass, UdiType.GuidUdi);
47+
UdiParser.RegisterUdiType(UmbracoCommerceConstants.UdiEntityType.TaxCalculationMethod, UdiType.GuidUdi);
4748
UdiParser.RegisterUdiType(UmbracoCommerceConstants.UdiEntityType.EmailTemplate, UdiType.GuidUdi);
4849
UdiParser.RegisterUdiType(UmbracoCommerceConstants.UdiEntityType.PrintTemplate, UdiType.GuidUdi);
4950
UdiParser.RegisterUdiType(UmbracoCommerceConstants.UdiEntityType.ExportTemplate, UdiType.GuidUdi);
@@ -172,6 +173,7 @@ private void InitializeDiskRefreshers()
172173
diskEntityService.RegisterDiskEntityType(UmbracoCommerceConstants.UdiEntityType.Region);
173174
diskEntityService.RegisterDiskEntityType(UmbracoCommerceConstants.UdiEntityType.Currency);
174175
diskEntityService.RegisterDiskEntityType(UmbracoCommerceConstants.UdiEntityType.TaxClass);
176+
diskEntityService.RegisterDiskEntityType(UmbracoCommerceConstants.UdiEntityType.TaxCalculationMethod);
175177
diskEntityService.RegisterDiskEntityType(UmbracoCommerceConstants.UdiEntityType.EmailTemplate);
176178
diskEntityService.RegisterDiskEntityType(UmbracoCommerceConstants.UdiEntityType.PrintTemplate);
177179
diskEntityService.RegisterDiskEntityType(UmbracoCommerceConstants.UdiEntityType.ExportTemplate);
@@ -214,6 +216,10 @@ private void InitializeDiskRefreshers()
214216
EventHub.NotificationEvents.OnTaxClassSaved((e) => WriteEntityArtifact(e.TaxClass));
215217
EventHub.NotificationEvents.OnTaxClassDeleted((e) => DeleteEntityArtifact(e.TaxClass));
216218

219+
// TaxCalculationMethod
220+
EventHub.NotificationEvents.OnTaxCalculationMethodSaved((e) => WriteEntityArtifact(e.TaxCalculationMethod));
221+
EventHub.NotificationEvents.OnTaxCalculationMethodDeleted((e) => DeleteEntityArtifact(e.TaxCalculationMethod));
222+
217223
// EmailTemplate
218224
EventHub.NotificationEvents.OnEmailTemplateSaved((e) => WriteEntityArtifact(e.EmailTemplate));
219225
EventHub.NotificationEvents.OnEmailTemplateDeleted((e) => DeleteEntityArtifact(e.EmailTemplate));

src/Umbraco.Commerce.Deploy/Configuration/UmbracoCommerceDeploySettings.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ namespace Umbraco.Commerce.Deploy.Configuration
22
{
33
public class UmbracoCommerceDeploySettings
44
{
5+
public UmbracoCommerceDeployTaxCalculationMethodSettings TaxCalculationMethods { get; set; } = new();
56
public UmbracoCommerceDeployPaymentMethodSettings PaymentMethods { get; set; } = new();
67
public UmbracoCommerceDeployShippingMethodSettings ShippingMethods { get; set; } = new();
78
}
@@ -15,4 +16,9 @@ public class UmbracoCommerceDeployShippingMethodSettings
1516
{
1617
public string[] IgnoreSettings { get; set; } = [];
1718
}
19+
20+
public class UmbracoCommerceDeployTaxCalculationMethodSettings
21+
{
22+
public string[] IgnoreSettings { get; set; } = [];
23+
}
1824
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using Umbraco.Commerce.Core.Api;
7+
using Umbraco.Commerce.Core.Models;
8+
using Umbraco.Commerce.Deploy.Artifacts;
9+
using Umbraco.Commerce.Deploy.Configuration;
10+
11+
using Umbraco.Cms.Core;
12+
using Umbraco.Cms.Core.Deploy;
13+
14+
using StringExtensions = Umbraco.Commerce.Extensions.StringExtensions;
15+
16+
namespace Umbraco.Commerce.Deploy.Connectors.ServiceConnectors
17+
{
18+
[UdiDefinition(UmbracoCommerceConstants.UdiEntityType.TaxCalculationMethod, UdiType.GuidUdi)]
19+
public class UmbracoCommerceTaxCalculationMethodServiceConnector : UmbracoCommerceStoreEntityServiceConnectorBase<TaxCalculationMethodArtifact, TaxCalculationMethodReadOnly, TaxCalculationMethod, TaxCalculationMethodState>
20+
{
21+
protected override int[] ProcessPasses => new[]
22+
{
23+
2
24+
};
25+
26+
protected override string[] ValidOpenSelectors => new[]
27+
{
28+
"this",
29+
"this-and-descendants",
30+
"descendants"
31+
};
32+
33+
protected override string OpenUdiName => "All Umbraco Commerce Tax Classes";
34+
35+
public override string UdiEntityType => UmbracoCommerceConstants.UdiEntityType.TaxCalculationMethod;
36+
37+
public UmbracoCommerceTaxCalculationMethodServiceConnector(IUmbracoCommerceApi umbracoCommerceApi, UmbracoCommerceDeploySettingsAccessor settingsAccessor)
38+
: base(umbracoCommerceApi, settingsAccessor)
39+
{ }
40+
41+
public override string GetEntityName(TaxCalculationMethodReadOnly entity)
42+
=> entity.Name;
43+
44+
public override Task<TaxCalculationMethodReadOnly?> GetEntityAsync(Guid id, CancellationToken cancellationToken = default)
45+
=> Task.FromResult((TaxCalculationMethodReadOnly?)_umbracoCommerceApi.GetTaxCalculationMethod(id));
46+
47+
public override IAsyncEnumerable<TaxCalculationMethodReadOnly> GetEntitiesAsync(Guid storeId, CancellationToken cancellationToken = default)
48+
=> _umbracoCommerceApi.GetTaxCalculationMethods(storeId).ToAsyncEnumerable();
49+
50+
public override Task<TaxCalculationMethodArtifact?> GetArtifactAsync(GuidUdi? udi, TaxCalculationMethodReadOnly? entity, CancellationToken cancellationToken = default)
51+
{
52+
if (entity == null)
53+
{
54+
return Task.FromResult<TaxCalculationMethodArtifact?>(null);
55+
}
56+
57+
var storeUdi = new GuidUdi(UmbracoCommerceConstants.UdiEntityType.Store, entity.StoreId);
58+
59+
var dependencies = new ArtifactDependencyCollection
60+
{
61+
new UmbracoCommerceArtifactDependency(storeUdi)
62+
};
63+
64+
var artifact = new TaxCalculationMethodArtifact(udi, storeUdi, dependencies)
65+
{
66+
Name = entity.Name,
67+
Alias = entity.Alias,
68+
SalesTaxProviderAlias = entity.SalesTaxProviderAlias,
69+
SalesTaxProviderSettings = new SortedDictionary<string, string>(entity.SalesTaxProviderSettings
70+
.Where(x => !StringExtensions.InvariantContains(_settingsAccessor.Settings.TaxCalculationMethods.IgnoreSettings, x.Key)) // Ignore any settings that shouldn't be transfered
71+
.ToDictionary(x => x.Key, x => x.Value)), // Could contain UDIs?
72+
SortOrder = entity.SortOrder
73+
};
74+
75+
return Task.FromResult<TaxCalculationMethodArtifact?>(artifact);
76+
}
77+
78+
public override async Task ProcessAsync(ArtifactDeployState<TaxCalculationMethodArtifact, TaxCalculationMethodReadOnly> state, IDeployContext context, int pass, CancellationToken cancellationToken = default)
79+
{
80+
state.NextPass = GetNextPass(pass);
81+
82+
switch (pass)
83+
{
84+
case 2:
85+
await Pass2Async(state, context, cancellationToken).ConfigureAwait(false);
86+
break;
87+
default:
88+
throw new ArgumentOutOfRangeException(nameof(pass));
89+
}
90+
}
91+
92+
private Task Pass2Async(ArtifactDeployState<TaxCalculationMethodArtifact, TaxCalculationMethodReadOnly> state, IDeployContext context, CancellationToken cancellationToken = default) =>
93+
_umbracoCommerceApi.Uow.ExecuteAsync(
94+
(uow, ct) =>
95+
{
96+
TaxCalculationMethodArtifact artifact = state.Artifact;
97+
98+
artifact.Udi.EnsureType(UmbracoCommerceConstants.UdiEntityType.TaxCalculationMethod);
99+
artifact.StoreUdi.EnsureType(UmbracoCommerceConstants.UdiEntityType.Store);
100+
101+
TaxCalculationMethod? entity = state.Entity?.AsWritable(uow) ?? TaxCalculationMethod.Create(
102+
uow,
103+
artifact.Udi.Guid,
104+
artifact.StoreUdi.Guid,
105+
artifact.Alias,
106+
artifact.Name,
107+
artifact.SalesTaxProviderAlias);
108+
109+
var settings = artifact.SalesTaxProviderSettings
110+
.Where(x => !StringExtensions.InvariantContains(_settingsAccessor.Settings.TaxCalculationMethods.IgnoreSettings, x.Key)) // Ignore any settings that shouldn't be transferred
111+
.ToDictionary(x => x.Key, x => x.Value);
112+
113+
entity.SetName(artifact.Name, artifact.Alias)
114+
.SetSettings(settings, SetBehavior.Merge)
115+
.SetSortOrder(artifact.SortOrder);
116+
117+
_umbracoCommerceApi.SaveTaxCalculationMethod(entity);
118+
119+
state.Entity = entity;
120+
121+
uow.Complete();
122+
123+
return Task.CompletedTask;
124+
},
125+
cancellationToken);
126+
}
127+
}

src/Umbraco.Commerce.Deploy/Connectors/ServiceConnectors/UmbracoCommerceTaxClassServiceConnector.cs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,28 +64,30 @@ public override IAsyncEnumerable<TaxClassReadOnly> GetEntitiesAsync(Guid storeId
6464
Name = entity.Name,
6565
Alias = entity.Alias,
6666
DefaultTaxRate = entity.DefaultTaxRate,
67+
DefaultTaxCode = entity.DefaultTaxCode,
6768
SortOrder = entity.SortOrder
6869
};
6970

7071
// Country region tax rates
71-
var countryRegionTaxRateArtifacts = new List<CountryRegionTaxRateArtifact>();
72+
var countryRegionTaxRateArtifacts = new List<CountryRegionTaxClassArtifact>();
7273

73-
foreach (var countryRegionTaxRate in entity.CountryRegionTaxRates.OrderBy(x => x.CountryId).ThenBy(x => x.RegionId))
74+
foreach (var countryRegionTaxClass in entity.CountryRegionTaxClasses.OrderBy(x => x.CountryId).ThenBy(x => x.RegionId))
7475
{
75-
var crtrArtifact = new CountryRegionTaxRateArtifact
76+
var crtrArtifact = new CountryRegionTaxClassArtifact
7677
{
77-
TaxRate = countryRegionTaxRate.TaxRate
78+
TaxRate = countryRegionTaxClass.TaxRate,
79+
TaxCode = countryRegionTaxClass.TaxCode
7880
};
7981

80-
var countryDepUdi = new GuidUdi(UmbracoCommerceConstants.UdiEntityType.Country, countryRegionTaxRate.CountryId);
82+
var countryDepUdi = new GuidUdi(UmbracoCommerceConstants.UdiEntityType.Country, countryRegionTaxClass.CountryId);
8183
var countryDep = new UmbracoCommerceArtifactDependency(countryDepUdi);
8284
dependencies.Add(countryDep);
8385

8486
crtrArtifact.CountryUdi = countryDepUdi;
8587

86-
if (countryRegionTaxRate.RegionId.HasValue)
88+
if (countryRegionTaxClass.RegionId.HasValue)
8789
{
88-
var regionDepUdi = new GuidUdi(UmbracoCommerceConstants.UdiEntityType.Country, countryRegionTaxRate.CountryId);
90+
var regionDepUdi = new GuidUdi(UmbracoCommerceConstants.UdiEntityType.Country, countryRegionTaxClass.CountryId);
8991
var regionDep = new UmbracoCommerceArtifactDependency(regionDepUdi);
9092
dependencies.Add(regionDep);
9193

@@ -95,7 +97,7 @@ public override IAsyncEnumerable<TaxClassReadOnly> GetEntitiesAsync(Guid storeId
9597
countryRegionTaxRateArtifacts.Add(crtrArtifact);
9698
}
9799

98-
artifact.CountryRegionTaxRates = countryRegionTaxRateArtifacts;
100+
artifact.CountryRegionTaxClasses = countryRegionTaxRateArtifacts;
99101

100102
return Task.FromResult<TaxClassArtifact?>(artifact);
101103
}
@@ -136,6 +138,7 @@ private Task Pass2Async(ArtifactDeployState<TaxClassArtifact, TaxClassReadOnly>
136138

137139
entity.SetName(artifact.Name, artifact.Alias)
138140
.SetDefaultTaxRate(artifact.DefaultTaxRate)
141+
.SetDefaultTaxCode(artifact.DefaultTaxCode)
139142
.SetSortOrder(artifact.SortOrder);
140143

141144
_umbracoCommerceApi.SaveTaxClass(entity);
@@ -161,38 +164,38 @@ private Task Pass4Async(ArtifactDeployState<TaxClassArtifact, TaxClassReadOnly>
161164
// Should probably validate the entity type here too, but really
162165
// given we are using guids, the likelyhood of a matching guid
163166
// being for a different entity type are pretty slim
164-
var countryRegionTaxRatesToRemove = entity.CountryRegionTaxRates
165-
.Where(x => artifact.CountryRegionTaxRates == null || !artifact.CountryRegionTaxRates.Any(y => y.CountryUdi.Guid == x.CountryId && y.RegionUdi?.Guid == x.RegionId))
167+
var countryRegionTaxClassesToRemove = entity.CountryRegionTaxClasses
168+
.Where(x => artifact.CountryRegionTaxClasses == null || !artifact.CountryRegionTaxClasses.Any(y => y.CountryUdi.Guid == x.CountryId && y.RegionUdi?.Guid == x.RegionId))
166169
.ToList();
167170

168-
if (artifact.CountryRegionTaxRates != null)
171+
if (artifact.CountryRegionTaxClasses != null)
169172
{
170-
foreach (CountryRegionTaxRateArtifact crtr in artifact.CountryRegionTaxRates)
173+
foreach (CountryRegionTaxClassArtifact crtr in artifact.CountryRegionTaxClasses)
171174
{
172175
crtr.CountryUdi.EnsureType(UmbracoCommerceConstants.UdiEntityType.Country);
173176

174177
if (crtr.RegionUdi == null)
175178
{
176-
entity.SetCountryTaxRate(crtr.CountryUdi.Guid, crtr.TaxRate);
179+
entity.SetCountryTaxClass(crtr.CountryUdi.Guid, crtr.TaxRate, crtr.TaxCode);
177180
}
178181
else
179182
{
180183
crtr.RegionUdi.EnsureType(UmbracoCommerceConstants.UdiEntityType.Region);
181184

182-
entity.SetRegionTaxRate(crtr.CountryUdi.Guid, crtr.RegionUdi.Guid, crtr.TaxRate);
185+
entity.SetRegionTaxClass(crtr.CountryUdi.Guid, crtr.RegionUdi.Guid, crtr.TaxRate, crtr.TaxCode);
183186
}
184187
}
185188
}
186189

187-
foreach (CountryRegionTaxRate? crtr in countryRegionTaxRatesToRemove)
190+
foreach (CountryRegionTaxClass? crtr in countryRegionTaxClassesToRemove)
188191
{
189192
if (crtr.RegionId == null)
190193
{
191-
entity.ClearCountryTaxRate(crtr.CountryId);
194+
entity.ClearCountryTaxClass(crtr.CountryId);
192195
}
193196
else
194197
{
195-
entity.ClearRegionTaxRate(crtr.CountryId, crtr.RegionId.Value);
198+
entity.ClearRegionTaxClass(crtr.CountryId, crtr.RegionId.Value);
196199
}
197200
}
198201

src/Umbraco.Commerce.Deploy/UmbracoCommerceConstants.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public static class UdiEntityType
2222

2323
public const string TaxClass = "umbraco-commerce-tax-class";
2424

25+
public const string TaxCalculationMethod = "umbraco-commerce-tax-calculation-method";
26+
2527
public const string EmailTemplate = "umbraco-commerce-email-template";
2628

2729
public const string PrintTemplate = "umbraco-commerce-print-template";

0 commit comments

Comments
 (0)