6

I have installed the Sitecore.StoreFront solution by following the official deployment's guide. I have also got from github the latest source code's version which I'm using as base for my commerce project.

I'm trying to calculate cart's VAT. By design the storefront solution uses a GlobalTaxPolicy which is not suitable for what I need to do (in Italy VAT calc is item based) so I changed the tax's policy in my Environment from Sitecore.Commerce.Plugin.Tax.GlobalTaxPolicy to Sitecore.Commerce.Plugin.Tax.ItemTaxPolicy.

The problem now is that there is not any documentation on how to use or extend the ItemTaxPolicy, so I though to calculate taxes by using a cartline adjustments, but when I add a new CartAdjustment to the CommerceCartLine.Adjustments, it is ignored and my adjustments is lost.

Any idea to solve these problems?

UPDATE 2

After read the Creating your first plugin guide in the SiteCore Commerce Developer's Guide, I made a banal tax plugin just do try how the engine works. Now the problem is that my Run method never runs. This is my banal class's code:

[PipelineDisplayName("VAT.CalculateCartLinesTaxBlock")]
public class VATBlock : CalculateCartLinesTaxBlock
{
    public override Task<Cart> Run(Cart arg, CommercePipelineExecutionContext context)
    {
        Condition.Requires(arg).IsNotNull("The argument can not be null");
        return Task.FromResult<Cart>(arg);
    }
}

This is the registration block in ConfigureSitecore.cs:

public void ConfigureServices(IServiceCollection services)
    {
        var assembly = Assembly.GetExecutingAssembly();
        services.RegisterAllPipelineBlocks(assembly);
        services.RegisterAllCommands(assembly);

        services.Sitecore().Pipelines(
            config => config
            .ConfigurePipeline<ICalculateCartLinesPipeline>(c =>
            {
                c.Add<VATBlock>().Before<CalculateCartLinesTotalsBlock>();
            })
            );

    }

I tried also to:

  1. Insert it after the Plugin.Tax.CalculateCartLinesTaxBlock
  2. Insert it and then remove the Plugin.Tax.CalculateCartLinesTaxBlock

but in the NodeConfiguration file, my plugin is never added in the pipeline (before or after) so my function never run.

What am I doing wrong?

0

2 Answers 2

5

As you can see a policy defines some configuration in Sitecore Commerce. By removing the GlobalTaxPolicy from the json file, you don't change how the tax is calculated, you just change the parameters used to calculate it. In this case the default parameters are used.

The components that actually do the tax calculation are called CalculateCartLinesTaxBlock and CalculateCartTaxBlock. They are blocks that are used in a pipeline. You can find out which pipeline by using the Postman examples included in the Commerce SDK and calling GetPipelines().

You will see that these blocks are used in ICalculateCartPipeline and ICalculateCartLinesPipeline.

Now to know how CalculateCartLinesTaxBlock works and get some inspiration for your own blocks, it is best to use dotPeek or another reflector tool that will show you a decompiled version of the source code.

Hope this helps.

1
  • I did a block inspired to CalculateCartLinesTaxBlock, but it not being added to the pipeline so it never runs. I registered it before CalculateCartLinesTotalsBlock but it seemes that the engine commerce ignores my pipeline configuration. Nov 10, 2017 at 14:52
2

We had the same problem with our tax calculation. We saw, that the ConfigureServices method was called successfully, but the pipeline block just wasn't added to the pipeline.

After a lot of trying and debugging, we figured out, that our plugin was loaded too early. So it looks like it is depending on another plugin to add the CalculateCartTaxBlock, but this plugin was loaded after our plugin. Sadly, it looks like there is no way to manipulate the order, in which the plugins are loaded.

To fix this, we had to do a pretty dirty hack. We implemented our plugin as part of the Customer.Sample.Solution.sln that ships with the SDK. In this solution you find the a couple of sample plugin like Plugin.Sample.AdventureWorks. Inside of the Plugin.Sample.AdventureWorks plugin we updated the ConfigureSitecore class to call our plugin. The final code of the ConfigureServices method inside of the sample plugin looks like this:

public void ConfigureServices(IServiceCollection services)
{
    var assembly = Assembly.GetExecutingAssembly();
    services.RegisterAllPipelineBlocks(assembly);

    services.Sitecore().Pipelines(config => config
     .ConfigurePipeline<IInitializeEnvironmentPipeline>(d =>
        {
            d.Add<InitializeCatalogBlock>()
                .Add<InitializeInventoryBlock>()
                .Add<InitializeEnvironmentRegionsBlock>()
                .Add<InitializeEnvironmentShopsBlock>()
                .Add<InitializeEnvironmentPricingBlock>()
                .Add<InitializeEnvironmentPromotionsBlock>()
                .Add<InitializeEnvironmentGiftCardsBlock>();
        })
     .ConfigurePipeline<IRunningPluginsPipeline>(c => { c.Add<RegisteredPluginBlock>().After<RunningPluginsBlock>(); }));

    services.ConfigureCartPipelines();
    services.ConfigureOrdersPipelines();


    new MyPlugin.ConfigureSitecore().ConfigureServices(services);
}

So we just added new MyPlugin.ConfigureSitecore().ConfigureServices(services); at the end to call our ConfigureServices of our plugin again.

To avoid, that all the commands and other services are loaded twice, we added a static variable to check if the plugin is already initialized. If so, we just replace our pipeline block (again).

public class ConfigureSitecore : IConfigureSitecore
{
    private static bool _isInitialized = false;

    public void ConfigureServices(IServiceCollection services)
    {
        if (_isInitialized)
        {
            services.Sitecore().Pipelines(cfg =>
                cfg.ConfigurePipeline<ICalculateCartPipeline>(d => d.Replace<CalculateCartTaxBlock, MyCalculateCartTaxBlock>()));

            Log.Information("Plugin already initialized. Skipping.");
            return;
        }

        Log.Information("Configure my plugin");
        var assembly = Assembly.GetExecutingAssembly();
        services.RegisterAllPipelineBlocks(assembly);

        services.Sitecore().Pipelines(cfg =>
            cfg.ConfigurePipeline<ICalculateCartPipeline>(d => d.Replace<CalculateCartTaxBlock, MyCalculateCartTaxBlock>()));

        services.RegisterAllCommands(assembly);

        _isInitialized = true;
    }
}

It's pretty hacky, but it works for us.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.