Developer forum

Forum » Ecommerce - Standard features » Importing discounts

Importing discounts

Stephen Anthony Jackson
Reply

Hello. I am trying to import discounts from en ERP system, where I want the discounts to be applied for all users that have an account within the customer group

I have defined groups with the customer number from the ERP as the name of the group, but when I try to import to the EcomDiscounts table, only the ID of the user group is available, not the name

I guess this makes sense as its the foreign key. So how then can I retrieve the system ID (foreign key), of the user object, so I can set it to DiscountAccessUserGroupId ?

I am starting to think that the cloud based solution is very limiting for integrations, as I am totally at the mercy of what data integration actually allows me to do


Replies

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

Hi Stephen

You have 2 options.

BR Nicolai

 
Stephen Anthony Jackson
Reply

Hi Nicolai. Thanks for the suggestions. The user-based solution will however not work, as the discount will not be applied if a new user is created in that group (I have mapped a customer in the ERP to a group in DW as the invididual users are not present in the ERP system, only the customer organization, so the "customer group" has to the be the root object of which I connect to the discounts). The idea is that the primary customer user will be able to login and have permissions only on their own group, and have access to add users under that group (which would then inherit the discounts)... so I think that solution two is really the only way this can be implemented. 

I guess live integration for prices would also work, but thats a huge amount of development for something that could be solved with a table script?, and I think Live Pricecheck only works when adding articles to the basket or completing order, not when viewing price lists?

 
Stephen Anthony Jackson
Reply

If I use the tablescript option, do you have any examples on how the database is interacted with? The only example on the docs page just changes a productprice to an arbritrary value 

I need to do a lookup on accessuser (accessuserid) by name (customer group name), and set that value for the DISCOUNTACCESSUSERGROUPID in the import row

 
Stephen Anthony Jackson
Reply

Posting my code. Havent tested this yet, I dont know if I am using the right classes for database access

 

using System.Linq;
using System.Collections.Generic;
using Dynamicweb.DataIntegration.Integration;
using System.Data.SqlTypes;
using Dynamicweb.Data;

namespace T3
{
    public class GetAccessUserIDByName : TableScript
    {
        public override string ScriptingName
        {
            get
            {
                return "Get the AccessUserId by AccessUserName and set DiscountAccessUserGroupId  ";
            }
        }

        public override void ProcessInputRow(Mapping mapping, Dictionary<string, object> row)
        {
          
            if (mapping.SourceTable != null)
            {
                var accessUserNameCol = mapping.SourceTable.Columns.FirstOrDefault(c => c != null && c.Name.ToLower() == "DiscountAccessUserGroupName".ToLower());

                if (accessUserNameCol != null && row.ContainsKey(accessUserNameCol.Name))
                {
                    var accessUserName = row[accessUserNameCol.Name].ToString();

                    string SQL = $"SELECT AccessUserId FROM AccessUser where accessusername = '{accessUserName}' ";

                    var accessUserId = Database.CreateDataReader(SQL).GetValue(0).ToString();
                    
                    if (accessUserId != null)
                    {
                        var col = mapping.SourceTable.Columns.FirstOrDefault(c => c != null && c.Name.ToLower() == "DISCOUNTACCESSUSERGROUPID".ToLower());

                        if (col != null && row.ContainsKey(col.Name))
                        {
                            row[col.Name] = accessUserId;
                        }

                    }
                
                }
                
            }
        }
    }
}

 
Lars Hejgaard Sørensen Dynamicweb Employee
Lars Hejgaard Sørensen
Reply

Hi Stephen,

There are three interesting topics in this thread. Let's start with the simples one first :-)

1) You can actually make this work by using the customer number approach as suggested by Nicolai. The Extranet app has a nifty feature in that it listens to a lot of the properties on the user, including custom fiels, when users are created in the frontend. The properties must be prefixed with UserManagement_Form, So you can add a hidden field in the Create Account form with the customer number of the current user, i.e., the primary user:

<input type="hidden" name="UserManagement_Form_CustomerNumber" value="@GetString("UserManagement:User.Address")" />

And then the new user will have the same customer number as the primary user who created the user.

2) For your tablescript, I would consider, do I have a lot of customer groups or just a few. If you have just a few, I would use the API to look up the group:

var group = new Dynamicweb.Security.UserManagement.Group(accessUserName);
if (group != null)
{
    var col = mapping.SourceTable.Columns.FirstOrDefault(c => c != null && c.Name.ToLower() == "DISCOUNTACCESSUSERGROUPID".ToLower());

    if (col != null && row.ContainsKey(col.Name))
    {
        row[col.Name] = group.ID;
    }
}

Then, the API handles the cache, and this could reduce the number of database calls and speed up performance.

if you have a lot of groups, i would cache all the groups in a dictionary in the httpcontext.items collection, when the first row is processed, and the use that cache for the subsequent records. I've attached and example of, how this could be done with products, but it can easily be transformed to user groups.

3) Then you make an interesting statement about cloud based solution, and I aknowledge your point. You don't have on-prem tool-kit at hand, so it can feel like losing control. But in the case you are discribing, we do have very useful tool, the SQL Firehose, which I would use in the folloing way to solve your case. In fact, I would favor this over table script any day, because it keeps the platform standard, and it is so much easier to debug data in a database rather than debuggin a table script from your local machine.

1: Create a staging table for the raw data from ERP. We will load the data into this e.g. from an OData endpoint before loading in into the EcomDiscounts table. It could be something like this, and, yes, you can create this through the SQL Firehose too:

create table Staging_Discounts(
ItemNumber nvarchar(25) not null,
 CustomerNumber nvarchar(25) not null,
Discount float not null
)

Very simplified, of cause. Just add your own fields and keys.
 
2: The I'd add an SQL view that joins the staing tabel with AccessUser to get group id for the customer gorup. This, you can also do through the firehose:
create view Staging_DiscountGroup as SELECT ItemNumber, Discount, AccessUserId from Staging_Discounts inner join accessuser on AccessUserUserName = CustomerNumber WHERE AccessUserType = '2'
 

3: Finally, I'd set up a Data Integration activity with the Dynamciweb source provider pointing to the Staging_DiscountGroup view, and with Dynamicweb destination provider pointing the EcomDiscounts table.

Then, you have a code-free solution to the challenge, which you can easily apply to both cloud and on-prem solutions. I added an article about this approach some time ago, which you might find interesting to have a look at:

https://doc.dynamicweb.com/community/devblog/blog/alternatives-to-applying-code-in-you-integration-flow?PID=8967

Br.
Lars

 
Stephen Anthony Jackson
Reply

Hi Lars.

Thanks for the answer!

I never even considered using views. I guess I didnt think it was advisable to alter the database schema in anyway - just the data.  There will be quite a few of these cases, so I am not sure if I want a heavily altered database, but it is also a solution which doesnt require me to have to get support to deploy a dll each time.

And thanks for the solution to the lookup issue. Its only 20-30 groups, so the API would probably work fine there yes.

I almost feel spoiled for choice now, but I have to get the tablescript working anyway, and I will have to think about what the most maintainable solution is, going forward.

 
Lars Hejgaard Sørensen Dynamicweb Employee
Lars Hejgaard Sørensen
Reply

Hi Stephen,

Glad you could make some use for it. Don't worry about adding to the scema as long as you dont remove anything standard, don't make constraints to standard tables and keep naming to something that we wouldn't think of naming something in the standard product, and ;-) Prefixing wih "custom_" or something will probably keep you safe.

If you are concerned about the scema anyway, consider placing your staging table in an Azure database and having it added as a linked server in the DW database. That would enable you to join tables across servers - however, performance would not be impressive :-)

Br.

Lars

 
Stephen Anthony Jackson
Reply

Thanks Lars.

I think the tablescript option is anyway a good solution as it doesnt touch the schema, and it is reusable to a certain degree. Getting a foreign key id for a certain value in a certain table, is most likely a common requirement during import, so having scripts that handle this will make for a good deal of reusable code.

It could be argued however, that these should be a standard part of the dw data integration features, such that it is easier to use it out-of-the-box, but thats another type of discussion.

 

You must be logged in to post in the forum