Sage 300 Optional Resource Files

Introduction

The Sage 300 Web Screens use Resource Files (Resx files) to localize strings, text, captions, messages, etc. that are presented in the screens. Behind the scene, these Resx files are supported by Microsoft’s Resource Manager class and framework.

So, what happens if a Resx file for a language is not provided or blank values exist in a Resx file?

Supported Languages

Before we begin, let’s identify the languages that are currently supported in the Sage 300 Web Screens:

  • English (en-US) (i.e. MenuResx.resx)
  • Chinese Simplified (zh-Hans) (i.e. MenuResx.zh-Hans.resx)
  • Chinese Traditional (zh-Hant) (i.e. MenuResx.zh-Hant.resx)
  • Spanish (es) (i.e. MenuResx.es.resx)
  • French (fr-CA) (i.e. MenuResx.fr-CA.resx)

English is considered the default language and all Resx files without a locale extension are to be considered the English Resx files.

The Sage 300 PDX Group takes the completed English Resx files and translates the values into the other supported non-English languages.

How Does It Work?

The Sage 300 Web Screen implementation is to place the Resx files for the same screen into the same folder.

This is a requirement for the Resource Manager magic!

These resource files are referenced with a standard Object.Property notation and do not specify a locale. The magic is performed by the Resource Manager to understand the current locale and retrieve the string (property) from the correct Resx file based upon the locale.

This is very convenient from a code perspective in that the application code does not have to determine which Resx file to access.

Non-existent Resx File for a Locale

If a specified locale’s Resx file does not exist, the English Resx file is used instead. Since the code does not specify a locale, this default behavior by the Resource Manager is perfect and the resulting English resource allows the application to function without error.

Blank Values in a Resx File and Resulting Issue

A blank value is a value. It is just blank. But, this can cause issues in the application when a value is retrieved from any Resx file, not just non-English Resx files, and then the value is displayed on the screen. Where is my caption? Where is my menu item? Where is my message?

As mentioned in the previous section, a missing non-English Resx file will default to the English Resx file so there is no loss in functionality or behavior.

But, it was recently observed by a partner, that the Solution Wizard and Code Generation Wizard will generate the Menu Resx files and any screen Resx files for all supported languages. But, the values in these non-English Resx files will contain keys, but blank values, which is perfect for Sage internal developers, but in many cases not ideal for external developers.

Example 1: English Resx File

blob10example1

Example 2: French Resx File

blog10example2

External developers must also fill out these files to avoid having a Sage 300 supported locale selected by the customer, but now the screens and menus will display blank or key values (in the case of the menu system, it has explicit logic that states “if the localized menu value is blank, display the keys instead”). This behavior then places the burden on the partner to delete these non-English Resx files IF the partner does not intend to support the translation of a particular language.

Resolution to Blank Values in a Non-English Resx File

Blank values in an English Resx file must be resolved to contain a value. This is plain and simple in order to avoid any issues in the display.

Blank values in a non-English Resx file can be resolved in one of two ways:

  • If the partner is intending to support their screen in a Sage 300 supported locale, the locale’s Resx file must be translated with proper values
  • If the partner is not intending to support their screen in a Sage 300 supported locale, the locale’s non-English Resx file can simply be deleted from the project while in the Visual Studio IDE.

But, regarding the deletion of the non-English Resx file, what if it was never created in the first place? Yes, this is a better option!

Sage 300 Solution Wizard’s New Feature

If the partner is able to determine when creating the solution and projects that a Sage 300 supported language will not be supported by their screens (i.e. a partner in Asia may not want to provide Spanish and/or French for their screen), the Wizards should not create the non-English Resx files in the first place.

Therefore, an enhancement has been made to the 2017.2 version of the Sage 300 UI Wizards (Solution Wizard and Code Generation Wizard) to prompt the developer for the language Resx files to be included/created in the projects of the solution.

blog10newstep

This new step has been added to the Solution Wizard in order to allow the developer to decide which language Resx files to include/create.

English is defaulted as it is a requirement.

Sage internal developers will select all of the languages.

The Code Generation Wizard will not prompt again for this, but instead will look at the Menu Resx files that exist and when creating Resx files for the specific screen, will create the language files based upon this discovery.

If a new solution is being generated starting with release 2017.2, this ability to limit or restrict what is created is a welcome new feature.

For partners with solutions and projects created prior to release 2017.2, the Code Generation Wizard will discover the Menu Resx files and create the non-English Resx files accordingly. Therefore, if a particular locale’s Resx files exist and they are not required to be translated, deleting the MenuResx.{locale}.resx file(s) from the Resources project will need to be performed.

Summary

This article presented how the Sage 300 Web Screens implement the Microsoft Resource Manager, what happens when a locale’s Resx file is missing, what happens when a locale’s Resx file has blank values and the steps required to avoid “blank value” issues.

The Sage 300 Solution and Code Generation Wizards have been enhanced for the 2017.2 release (April 2017) to present a new step which allows for the selection of which non-English Resx files are to be included/generated. This new step is a proactive approach to not creating locale Resx files that are not used by the partner and therefore preventing display issues if a customer selects a Sage 300 supported language that is not supported by a partner screen.

As a standard disclaimer, any topic in this article is subject to review and doesn’t represent a commitment as to when it will be available.

Sage 300 JavaScript Bundle Names

Introduction

JavaScript Bundling is a technique that can be used to improve request load times. The Sage 300 Web Screens use this technique to bundle the required JavaScript files on a per screen basis.

Known Issue

There is a known issue that bundle names with a dot will generate a 404 error condition in certain situations. While the Sage 300 bundle names do not have a dot in the bundle name, it was recently discovered that the code generated by partners by the Code Generation Wizard might include a dot.

Remember that the bundle name is separate from the JavaScript file name which can contain a dot.

Manual Resolution

For any existing projects, the change is quite simple and must be performed in two locations: The Bundle Registration class where the bundle is registered and in the Index Razor View where the bundle is referenced.

Example 1: BundleRegistration.cs (Before and After)

blog8example1before

Blog8Example1After.png

Example 2: Index.cshtml (Before and After)

Blog8Example2Before.png

Blog8Example2After.png

Summary

This article presented a known issue with a dot being in the name of a JavaScript bundle, the potential existence of this issue in code generated by the Sage 300 Web Code Generation Wizard, and the steps required to resolve this issue.

The Sage 300 Code Generation Wizard has been modified for the 2017.2 release (April 2017) of the Web SDK to prevent this issue from being present in any newly generated code.

As a standard disclaimer, any topic in this article is subject to review and doesn’t represent a commitment as to when it will be available.

Sage 300 Date Utility

Introduction

Microsoft’s DateTime Structure is an object that represents an instant in time, typically expressed as a date and time of day.

In Sage 300’s Web Screens, we use this object for dates and times in our C-Sharp code. However, we do not use its numerous properties and methods directly. Instead, we have encapsulated this functionality in our DateUtil class.

Let’s me explain why we came to the decision to encapsulate this functionality.

Encapsulation and Technical Debt

But, first let’s cover some concepts that were at the core of our decision.

What is encapsulation?

Encapsulation is the ability to provide users with a well-defined interface to a set of functions in a way which hides their internal workings.

Benefits of encapsulation

One of the principles of encapsulation is that the internal representation of an object should not concern its consumers. It also hides complex mechanisms and provides code reduction.

What is technical debt?

Technical debt is the set of problems in a development effort that make progress on customer value inefficient.

What does technical debt look like?

Technical debt are problems found through code analysis, duplicate code patterns, code complexity, spaghetti code, …

Encapsulation Decision

We analyzed the code and determined that individual usage of the DateTime properties numbered in excess of ten thousand lines of code. Yikes.

Sage 300 Web Screens can be localized and therefore these lines of code had to specify a locale along with the necessary conditional logic.

And, unfortunately we had different patterns being implemented in those individual lines of code.

So, the decision to encapsulate and to create a single design pattern for the developers to access a date and time was the best choice.

Date Utility Class

Thus, the DateUtil class was created and is available in the Sage.CA.SBS.ERP.Sage300.Common.Utilities assembly.

dateutil

Why should I use this class?

  • Sage 300 Web Screen Date and Time Pattern
    • Let this class do the date validations, acquire a new date, perform conditional checks, etc. for you
    • It’s the standard for Sage 300 Web Screen developers
  • Minimum Date logic is centralized
    • The DateTime structure has different values for the minimum date value based upon how the object was instantiated
    • The DateUtil class has the ability to standardize on a single minimum date value and therefore the application will not have multiple minimum date possibilities
  • Formatting based upon Current Culture
    • The encapsulation allows for the DateUtil class to perform the culture specific logic
    • This eliminates the developer from having to specify this where required
  • It’s easy and does the work for you
    • Enough said on this!

Before and After Examples

In this section, I will show some examples where we replaced code in our application with usage of the DateUtil class.

Example 1: Before

before1

Example 1: After

after1

Example 2: Before

before2

Example 2: After

after2

Example 3: Before

before3

Example 3: After

After3.png

Example 4: Before

Before4.png

Example 4: After

after4

Summary

This article presented the DateUtil class for dealing with dates and times in the Sage 300 Web Screens (C-Sharp code) along with the benefits of using a single pattern by developers.

By encapsulating the date and time functions, we are able to provide a consistent and simple pattern while reducing the potential for technical debt.

When this class was implemented, we removed over 6,500 lines of code from the application.

The DateUtil class is available in the Sage.CA.SBS.ERP.Sage300.Common.Utilities assembly which is referenced in most if not all projects.

As a standard disclaimer, any topic in this article is subject to review and doesn’t represent a commitment as to when it will be available.

Implementing an External Finder

Introduction

The following question was recently asked:

I am a developer working in my Sage assigned module and I need to invoke a finder from one of the standard Sage modules (i.e. AR, AP, GL, etc.). How do I do this?

This article will illustrate the steps required to invoke a finder from a module other than what is currently being developed.

Example

To illustrate the steps involved in adding a finder from another module, I have run the solution and code generation wizards and have created the TU Payment Codes setup screen. This screen is based upon the AR Payment Codes business view (AR0012) and only contains the key field and finder as generated from the wizards. For this example, I am going to want a finder for a vendor (just because it’s from another module).

Blog2Figure1

Step One

In this step, I need to locate the name for the Vendor Finder. The finder name is a descriptive field used to register the finder with Unity for dependency injection. The name is found in the Sage.CA.SBS.ERP.Sage300.Common.Plugin.Finder.js file. This file is located in the Areas\Core\Scripts folder of the Web project:

Blog2Figure2

This JavaScript file contains sg.finder object with the name definitions:

Blog2Figure3

The value “vendor” as this will be used later in the setFinder method.

Step Two

In this step, I need to add the required references to the AP binaries in the Web project in order for the finder to be invoked.

Finders for all modules have already been registered with Unity.

The AP binaries are located in your Sage 300 Online\Web\bin folder.

The following binaries will be added if they do not exist or have not been previously added:

Blog2Figure4

Step Three

In this step, I will add the controls to the razor view.

This example will not be bound to the data model as it is only being added to demonstrate invoking another finder and not data binding

Blog2Figure5

Step Four

In this step, I will add the required localization variables to the _Localization.cshtml partial view.

Blog2Figure6Untitled.png

Step Five

In this step, I will add the code to the JavaScript Behaviour file for this screen in order to setup and invoke the finder:

InitFinders:

Blog2Figure7finderSuccessVendor:

Blog2Figure8.pnggetFilterVendor:

Blog2Figure9.png

Step Six

Mission accomplished!

Blog2Figure10.png

 

Blog2Figure11.png

Summary

This article was meant to present the steps required to display a finder from another module not currently being developed. Since the finders are already registered via Unity in the Sage 300 application, the work involved is simply to locate the finder name, ensure the binaries for the finder’s module is added to the Web project and to hookup the plumbing in the JavaScript file.

As we begin to implement the customization framework, we will investigate the notion of externalizing the Unity Registrations into external XML files and therefore the discovery performed in Step One of this article will be simplified.