Wednesday, December 19, 2018

Adding new button with existing operation to the MPOS layout in Retail headquarters - Dynamics 365 Retail

Hi Guys,

Today I would like to show how we can add new button in the MPOS screen from AX and publish to MPOS in Dynamics 365 Retail

Please follow below steps to achieve the same and if you have any questions then feel free to post/comment.
  1. Go to Retail > Channel setup > POS setup > POS > Screen layouts
  2. Filter for 'F3CSH'. screen layout Id as its the screen which is assigned to my MPOS user/Register/Store
  3. Then select the screen size and then bottom grid select button grid "Welcome Screen 1" as I would like to add my new button in home screen.
  4. Select the Designer button, and then follow the instructions to install the designer. I you're prompted for credentials, enter the Retail user name and password.
  5. Right-click in the designer area, and then select Add new button.
  6. Right-click the new button, and then select Button properties as shown below., if you would like to add images then you can add as well for button.
  7. Set the Action property to Product search. Then select OK, and close the designer.
  8. Then button grid looks like below.
  9. To reflect the changes in POS we need to the 1090 job so for that Go to Retail and commerce > Retail IT > Distribution schedule.
  10. Select 1090, and then select Run now.

  11. Once job applied then verify the changes by logging in MPOS, here we can the button we added "Product search" then click on it to go to product search page.
  12. Here we can see Product search window, similar fashion we add our custom operations as well but we need to write business logic in Retail SDK to perform some operation when we click on it.
Tags:- D365, DFO 365 , Retail , MPOS , Cloud POS , CPOS, POS

Thanks/Jayaprakash 

Thursday, October 18, 2018

Real-time service profile is missing for Online Store / Store Front in Dynamics 365 Retail

Hi Guys,

I would like to share my experience with you all, as I had a issue while configuring new online store in dynamics 365 Retail but I end up with Realtime Service Profile issue  where profile was not set to online store.


Then I have searched for Real-Time Service Profile option and I didn't find on online store form, later I realized that its missing in standard form.

Resolution:-

To quickly solve this issue personalize the form and add the field called "Real-Time Service Profile" then set the value as "Default".


Now if you click on Configuration Status then it validates fine.

Hope this helps even though quick one, will come up with interesting blog post.




Friday, October 12, 2018

Steps To Configure TFS/VSTS workspace In Development Environment ( VM ) For Microsoft Dynamics 365 for Operations


Hi Guys,


I would like to describe steps to configure TFS/VSTS workspaces in Development environment in Local VM as Microsoft Dynamics 365 for Operations has changed the development model significantly and all the developments done in Visual studio now on.

This blog post will be useful the one who try to configure in house development environment VM with customer TFS.

It is very important to make sure we have the work space mapped correctly for everything to work properly.

Note:- We consider that Hyper V has been configured and you are able to login to D365 VM.

Steps to configure TFS/VSTS workspaces in Development environment

1. Firstly as soon as you setup change the system name with meaning full name then restart the VM to reflect the change.
2. You must be an administrator on the instance to start development, To provision your own credentials as an administrator, run the admin user provisioning tool that is provided on the desktop, and provide your email address (Azure AD credentials) in the tool.
From the desktop, run the admin user provisioning tool as an administrator (right-click the icon, and then click Run as administrator).
Enter your email address, and then click Submit
3. Then launch the Visual studio and make sure its licensed.
4. Click on Team > Manage Connections.
5. In Team Explorer Click on Manage connections > Connect to Team Project
6. In Connect to Team Foundation Server, click on Severs to Add new servers, then in Add/Remove Team foundation server form click on Add and enter TSF server name and click on Okay.

7. Once you close the form “Add/Remove Team foundation server” then click on connect as shown below.
8. Once you click on Connect then go Team Explorer click on “Configure workspace” then click on “Advanced”
9. In Edit workspace form, update source control folder and local folder, then click on okay.
One with VSTS location where projects will get save and another with Dev server metadata which will point to our Local server AOS metadata.
10. Once you click on connect then below pop up comes to download latest code from TSF server, click “Yes” to download the same. 
11. It will take some 30 -40 min of time to get all the latest codes.
12. We can also see the message saying “The workspace was mapped successfully“

Now System is ready to open Source Control Explorer and open solution in Solution Explore 

Hope this helps, I will come-up with another interesting blog.


Monday, September 24, 2018

Steps to configure retail when copying or restoring database between environments in Dynamics 365 Retail


Hi Guys,

The general business scenario we will be moving database from Production servers to Sandbox, UAT, DEV servers and after every restore there are few steps we need to follow to make system up and running.

I would like to list out the steps needs to be followed to configure retail when copying or restoring database between environments in Dynamics, please find the same below.

1. Run the Environment retargeting tool from LCS.

When you do any kind of copying between environments in Dynamics there are some settings related to Retail which are copied that are actually wrong for the destination environment.
To fix these you need to apply tool called Environment retargeting tool  and also its knowsn Retail Reprovisioning tool.

This tool needs to be run every time we do restore and all the environments. Irrespective if they use Retail components or not.

a.      Please make sure that we have the latest version of the tool.
b.      To check the same go to LCS – Asset Library. Go to Software Deployable Packages – Import  and Select the latest Environment Reprovisioning tool.


c.      Please select the latest tool and click on Apply.



d.      Once its applied then it will get Queued and start servicing, this operation will finish within 30 min (Please make sure to use latest version of tool).

      2. Once retargeting tool applied then you need to run these five steps.
a.      Navigate to the “Organization administration > Number sequences > Number sequences” and click on “Generate” 



b.      Open the "Retail Parameters" form, and press the "Initialize" link under the "General" tab. Answer "Yes" to the prompt. This will provide any new Retail seed data. 



c.      Open the "Initialize Retail Scheduler" form, and run it with "delete existing configuration" set to "yes". 



d.      Restart the "Microsoft Dynamics AX Batch Service" on all AOS VMs. This will update any cached connection credentials that may be used when running a CDX data sync. (done by DSE if PROD) 


e.      Navigate to the "Channel Database" form and run a CDX 9999 sync (full sync). This should succeed if everything is properly configured for retail. 



And also please have a look at blog to understand about Datawriting batch job

 Hope this helpful and Next post will be explain common issues we face when we run distribution scheduler job.

Thanks for reading!


Sunday, September 23, 2018

All about Data writing job "Default channel database batch job(RetailCdxChannelDbDirectAccess)" in Dynamics 365 Retail


Hi Guys,

Today I would like to discuss about the importance of  "Default channel database batch job(RetailCdxChannelDbDirectAccess)" in Dynamics 365 Retail and its role.

This job main duty is to check all Download sessions and Upload sessions with status “Available”, then it will apply the data to respective target DB's (AX or channel DB).
There will be few case we could see all distribution schedule jobs struck in executing state and not Applied, there could be following reasons for this issue.

1. Please check if the “Data writing job” assigned to channels

2. Make sure “Default channel database batch job(RetailCdxChannelDbDirectAccess)” is running



3. Restart the “Microsoft Dynamics AX Batch Service” on all AOS VMs. This will update any cached connection credentials that may be used when running a CDX data sync. (done by DSE if PROD => you need to raise a ticket)




How to setup Data writing batch job or recreate the same if existing have issues:- 

      The DataWritingBatchJob is automatically generated by the system when we run a full sync- 9999 job, it will create the batch job and update that field.
    
      Please run a Full Sync-9999 job and it will recreate the missing Retail DataWritingBatchjob.

      If the issue is still persists and the system thinks it already exists, then you need to reset DataWritingBatchJob in your UAT AX DB as shown below for RCSU channel database.   

      Restart the “Microsoft Dynamics AX Batch Management Service” under Services.msc on all AOS VMs.


      Now the next time when you run a Full sync-9999 job it should automatically recreate the the DataWritingBatchJob and update the field.

Hope this helps, I will come up with next blog post about Retail configuration and how to make distribution schedule jobs up and running when we do restore DB in D365 Retail.

Thank you!





User personal information like Favourites, Cues Personalization’s and User roles access in AX 2012 R3


Hi Guys ,

I would like to discuss today about "User personal information in AX", recently I was working for one of our customer and we are using AX 2012 R3 Retail with Store front.

They planned to move servers from one hosting partner to another hosting partner.

I am sure here many people could have done this for many customers earlier and  I would like to share one of the business criteria which customer requested, as we all know when customer is working in daily basis in our ERP system, it’s more important for them to save their personal information as well.

In the process of moving server from one hosting partner to another there is a chances to loose this info as we gonna import users from new active directory and there might be chances that users Id’s would be different compared to old system based of their user creation process.

So just to save user info we have dig into system and came across following tables which holds user personal info.

1.     Personalized Favourites
a.      SysPersonalization

2.     Personalized Cues on roles centre
a.      SysCue
b.     SysCueGroup
c.      SysCuePersonalization

3.     Form Personalization’s.
a.      SysLastValue

     4.     User security roles based on organization access
                  a.     SecurityUserRole
                  b.     SecurityUserRoleCondition
                  c.     OMUserRoleOrganization

These all tables has a User Id relation, so what I have done is , I have listed and matched the all users from Hosting partner A and B in CSV file. then written a script to update their Id's from Old to New

This applies for Dynamics 365 as well except Cues.

Hope this info helpful!

Your feedback is always welcome and meet you guys with new post!

Monday, August 13, 2018

Realtime service application pool goes down with error "ValueFactory attempted to access the Value property of this instance" in AX 2012 R3 Retail Online Channel

ISSUE:-
We are setting up new servers for our client and they are using AX 2012 R3 Retail Online store front. here we have issue with Realtime service where Realtime service pool automatically going down or not reachable. when ever you make Realtime service call from store front then it will not return any results and below error will be recorded in Realtime Service Server.
- <System>
<Provider Name="Microsoft Dynamics AX Retail : Real time Service RealTimeServices" />
<EventID Qualifiers="0">1</EventID>
<Level>2</Level>
<Task>0</Task>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2018-08-01T07:44:30.000000000Z" />
<EventRecordID>45284</EventRecordID>
<Channel>Application</Channel>
<Computer>dtxprodax03.int.deltaco.se</Computer>
<Security />
</System>
- <EventData>
<Data>Exception occured: [8/1/2018 7:44:30 AM][5246da1c-92ce-409e-9ab5-78ebbe96769a] ValueFactory attempted to access the Value property of this instance.</Data>
</EventData>
</Event>

I don’t see any issues with Realtime service and when you go and check Realtime service then it will be up and running. Again if you recycle or restart Realtime service then again it will start working.

Looking at the error message I don’t see any clue what is causing the issue and when it does down as the error logs only when you call Realtime service from storefront. Till that time no error will be logged in event viewer.
In a day it will go down once or twice remaining all the time it will just working fine.
Resolution:- 
After verifying all the settings, done following changes in RealTime service application pool then its working fine.
1. Idle timeout i have changed it to zero it was 20 min by default for RealTime service application pool 
2. Recycling I have unchecked , just to make sure it should not recycle anytime.

Hope this helps!


Sunday, March 11, 2018

Setup CDX sync for new custom table from AX to Channel (Download Job) in Dynamics 365 Retail


The post shows how to create a new custom table across both AX and the channel and setup sync(CDX) in Dynamics 365 Retail.

Changes are in AX tables, CDX, Channel DB

Setup steps:-
1. AX Customization:

- Create a new Table called ISVRetailStoreHoursTable
        - Enum field: Day,  enum type: WeekDays, mandatory,
        - Int field: OpenTime, extended data type: TimeOfDay, mandatory,
        - Int field: ClosingTime, extended data type: TimeOfDay, mandatory,
        - Int64 field: RetailStoreTable, extended data type: RefRecId, mandatory

- Create a Foreign Key Relation to RetailStoreTable
        - Name: RetailStoreTable
        - Cardinality: ZeroOne
        - RelatedTable: RetailStoreTable
        - Related table cardinality: ExactlyOne
        - Relationship type: Association
        - Contraint: Normal, name: RetailStoreTable, Field: RetailStoreTable, Related field: RecId

 

- Populate some data by running below job or manually enter some data.

class Temp_InsertData
{       
    /// <summary>
    /// Runs the class with the specified arguments.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>
    public static void main(Args _args)
    {       
        ISVRetailStoreHoursTable     storeDayHoursTable;
        RetailStoreTable                storeTable;
        Int64                           numberOfDeletedRows;
       
        // insert data for houston
        select * from storeTable
            where storeTable.StoreNumber == "HOUSTON";
       
        print storeTable.Recid;
       
       
        ttsBegin;
       
        delete_from storeDayHoursTable
            where storeDayHoursTable.RetailStoreTable == storeTable.RecId;
        numberOfDeletedRows = storeDayHoursTable.RowCount();
        print numberOfDeletedRows;
       
        // yyyy-mm-ddThh:mm:ss
       
        storeDayHoursTable.RetailStoreTable =  storeTable.RecId;
        storeDayHoursTable.Day = WeekDays::Monday;
        storeDayHoursTable.OpenTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T08:00:00"));
        storeDayHoursTable.ClosingTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T20:00:00"));
        storeDayHoursTable.insert();
       
        storeDayHoursTable.RetailStoreTable =  storeTable.RecId;
        storeDayHoursTable.Day = WeekDays::Tuesday;
        storeDayHoursTable.OpenTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T08:00:00"));
        storeDayHoursTable.ClosingTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T20:00:00"));
        storeDayHoursTable.insert();
       
        storeDayHoursTable.RetailStoreTable =  storeTable.RecId;
        storeDayHoursTable.Day = WeekDays::Wednesday;
        storeDayHoursTable.OpenTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T11:00:00"));
        storeDayHoursTable.ClosingTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T21:00:00"));
        storeDayHoursTable.insert();
       
        storeDayHoursTable.RetailStoreTable =  storeTable.RecId;
        storeDayHoursTable.Day = WeekDays::Thursday;
        storeDayHoursTable.OpenTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T09:00:00"));
        storeDayHoursTable.ClosingTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T20:00:00"));
        storeDayHoursTable.insert();
       
        storeDayHoursTable.RetailStoreTable =  storeTable.RecId;
        storeDayHoursTable.Day = WeekDays::Friday;
        storeDayHoursTable.OpenTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T08:00:00"));
        storeDayHoursTable.ClosingTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T20:00:00"));
        storeDayHoursTable.insert();
       
        storeDayHoursTable.RetailStoreTable =  storeTable.RecId;
        storeDayHoursTable.Day = WeekDays::Saturday;
        storeDayHoursTable.OpenTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T10:00:00"));
        storeDayHoursTable.ClosingTime = DateTimeUtil::time(DateTimeUtil::parse("2015-05-18T18:00:00"));
        storeDayHoursTable.insert();
        ttsCommit;
    }

}

2. CDX CHANGE:-

- -        Create a new resource file with all job, sub jobs and table information as below and save it as ISVRetailStoreHoursTable.xml file.

<RetailCdxSeedData ChannelDBMajorVersion="7" ChannelDBSchema="ext" Name="AX7">
<Jobs>
   <!-- <Job DescriptionLabelId="REX4520710" Description="Custom job" Id="1070"/> -->
</Jobs>
  <Subjobs>
    <Subjob Id="ISVRetailStoreHoursTable" TargetTableSchema="ext" AxTableName="ISVRetailStoreHoursTable">
      <ScheduledByJobs>
        <ScheduledByJob>1070</ScheduledByJob>
      </ScheduledByJobs>
      <AxFields>
        <Field Name="Day"/>
        <Field Name="RetailStoreTable"/>
        <Field Name="OpenTime"/>
        <Field Name="ClosingTime"/>
        <Field Name="RecId"/>
      </AxFields>
    </Subjob>
  </Subjobs>
</RetailCdxSeedData>


-        Right-click the project, and then select Add > New Item
-        In the Add New item dialog box, select Resources, name the resource file RetailCDXSeedDataAX7_Demo, and then select Add.


-        In the Select a Resource file dialog box, find the resource file that you created in step 2, and then select Open.



-        Add a new class that should be used to handle the registerCDXSeedDataExtension event. Search for the RetailCDXSeedDataBase class in AOT, and then open it in the designer. Right-click the registerCDXSeedDataExtension delegate, and then select Copy event handler.

-        Go to the event handler class that you created, and paste the following event handler code into it.



class RetailCDXSeedDataAX7EventHandler
{
   
    /// <summary>
    ///
    /// </summary>
    /// <param name="originalCDXSeedDataResource"></param>
    /// <param name="resources"></param>
    [SubscribesTo(classStr(RetailCDXSeedDataBase), delegateStr(RetailCDXSeedDataBase, registerCDXSeedDataExtension))]
    public static void RetailCDXSeedDataBase_registerCDXSeedDataExtension(str originalCDXSeedDataResource, List resources)
    {
        if (originalCDXSeedDataResource == resourceStr(RetailCDXSeedDataAX7))
        {
           resources.addEnd(resourceStr(RetailCDXSeedDataAX7_Demo));
        }
    }

}
-        Whenever the Retail initialization class runs, it looks for any extension that implements this handler. If an extension is found, the runtime will also initialize the custom information that is found in the resource file.
-        Before you add your custom resource to the list, you must verify that the originalCDXSeedDataResource resource that is being processed is RetailCDXSeedDataAX7. Otherwise, you might cause unintended results.

-        Navigate to Retail > Headquarters setup > Retail scheduler and click on Initialize retail scheduler.


-        In the dialog box that appears, select Delete existing configuration.
-        Select OK to start the initialization.


-        When the initialization is completed, the CDX scheduler jobs, subjob definitions, and distribution schedules are updated by using the original RetailCDXSeedDataAX7 resource and the customized RetailCDXSeedDataAX7_Demo resource.

    3. Verify Changes:

-        Navigate to Retail > Headquarters setup > Retail scheduler > Scheduler subjobs , here we can see ISVRetailStoreHoursTable is added under Scheduler subjobs and scheduled by 1070 as specified in resource file.


      4. Channel DB:
-        Run the below query to create table in Channel database, here we should create custom tables in ext schema as we are not allowed to override the standard.
-        The advantage of using ext schema , while DB upgrade we will not face any conflict .
 -- Create the extension table to store the custom fields.

IF (SELECT OBJECT_ID('[ext].[ISVRETAILSTOREHOURSTABLE]')) IS NULL
BEGIN
    CREATE TABLE [ext].[ISVRETAILSTOREHOURSTABLE](
        [RECID] [bigint] NOT NULL,
        [DAY] [int] NOT NULL DEFAULT ((0)),
        [OPENTIME] [int] NOT NULL DEFAULT ((0)),
        [CLOSINGTIME] [int] NOT NULL DEFAULT ((0)),
        [RETAILSTORETABLE] [bigint] NOT NULL DEFAULT ((0)),
    CONSTRAINT [I_ISVRETAILSTOREHOURSTABLE_RECID] PRIMARY KEY CLUSTERED
    (
        [RECID] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    ALTER TABLE [ext].[ISVRETAILSTOREHOURSTABLE]  WITH CHECK ADD CHECK  (([RECID]<>(0)))
END
GO

GRANT SELECT, INSERT, UPDATE, DELETE ON OBJECT::[ext].[ISVRETAILSTOREHOURSTABLE] TO [DataSyncUsersRole]

                  - Create view for the table we created that joins the original table on the channel side and                      the extension table on the channel side is created. This view is required so that CDX can                      correctly download and push the records from Retail HQ tables to the channel extension                      table back.


-- Create the customer extension view that is accessed by CRT to query the custom fields.

IF (SELECT OBJECT_ID('[ext].[ISVRETAILSTOREHOURSVIEW]')) IS NOT NULL
    DROP VIEW [ext].[ISVRETAILSTOREHOURSVIEW]
GO

CREATE VIEW [ext].[ISVRETAILSTOREHOURSVIEW] AS
(
    SELECT
        sdht.DAY,
        sdht.OPENTIME,
        sdht.CLOSINGTIME,
        sdht.RECID,
        rst.STORENUMBER
    FROM [ext].[ISVRETAILSTOREHOURSTABLE] sdht
    INNER JOIN [ax].RETAILSTORETABLE rst ON rst.RECID = sdht.RETAILSTORETABLE
)
GO

GRANT SELECT ON OBJECT::[ext].[ISVRETAILSTOREHOURSVIEW] TO [UsersRole];
GO

5. Verify CDX:

    - run 1070 job full sync (channel data group)
    - check Download sessions and channel DB that the data arrived