Stephen Smith's Blog

All things Sage 300…

Posts Tagged ‘Sage

Stateless Versus Stateful Sage 300c Web UIs

with one comment

Introduction

When two computers communicate they use a well-defined communications protocol. In Browser to Server communications these are often broadly categorized as either stateless or stateful. A stateless communications protocol doesn’t require that anything be remembered between calls. In web applications this is desirable for a number of reasons:

  • often calls are load balanced across multiple servers (perhaps even in different locations).
  • storing state in memory can be expensive and will limit how many users can be accessing a web server at once.

On the other hand, maintaining server state has some advantages:

  • less information needs to be transferred between the client and server since the server knows what has gone before.
  • having things handy in memory can make operations faster and more context aware.

Often in the real world these components are combined or stacked on each other, for instance the TCP protocol is stateful and then the HTTP stateless protocol is layered on top of TCP.

The Sage 300c Web UIs use both stateless and stateful technology. This article will talk about when we use each, how to program either case and what are the advantages and disadvantages of each method. Like many things in programming the lines between these two things can become quite blurred.

Since we do have stateful UIs, this does require that if you scale out to multiple web servers then the load balancer must use sticky sessions as we explained in this blog posting. Basically guarantee that all the requests from a given client go to the same web server in case they are running a stateful UI.

Stateless Sage 300 Web UIs

Most of the Sage 300c setup UIs, processing UIs and report UIs are all stateless. This means IIS could be reset between requests and things would still work. It would just be quite slow since it would need to re-open a Sage 300 session and re-open the Views to process the next request. To avoid this we keep a cache of open sessions along with their open Views. This way when a stateless request comes in we match up a session for the right company, user and with the right Views from the session pool and use that to handle the request. If a session in the pool hasn’t been used for a while we will release it and if too many sessions are in use, we will release the oldest if we need another one. This way practically speaking you usually open a session for your first stateless request and then keep using it from the cache of the duration of your work.

schedules

A Typical Stateless UI

Every Sage 300c business logic entity (View) will have a stateless repository defined for it. This is because only the document entry UI needs stateful operation, everything else like finders, export and other UIs will want to use the stateless version. You get all the default behavior for your stateless repository by having your specific repository inherit from one of the stateless base repositories in Sage.CA.SBS.ERP.Sage300.Common.BusinessRepository.Base like FlatRepository, ProcessingRepository or InquiryRepository.

Generally stateless operation fits very well with ASP.Net MVC since this is the natural way that it works. There is a lot of infrastructure to pass the data model back and forth between the client and server in a stateless manner. Add to that our use of knockout data binding and this makes most basic CRUD operations all handled by the framework.

This doesn’t mean that a stateless UI can’t dynamically interact with the user. By default, you have the CRUD operation off the basic navigation and save/delete buttons. But you can certainly add your own custom AJAX calls to dynamically update areas of your form. We provide support in the framework to update things like descriptions of external keys, but in fact you have a lot of power to make your UI very interactive and polished.

Stateful Sage 300 Web UIs

Most of the main Accounting document entry UIs are stateful. This includes UIs like Order Entry, Purchase Orders, G/L Journal Entry and A/R Invoice Entry. These UIs have a lot of sophistication in building up the Accounting document and the size of these documents can be quite large. Sending this entire document back and forth between the browser and the server as a JSON object is quite impractical. When one of these UIs is started, a session and set of Views are assigned to it for the duration that it runs. As changes are made to the UIs they are sent to the server to make the attendant changes to the server model.

oe1100new

A Typical Stateful UI

To create a stateful business repository, just inherit from one of the stateful base repositories in Sage.CA.SBS.ERP.Sage300.Common.BusinessRepository.Base.Statefull like BatchHeaderDetailRepository or SequencedHeaderDetailRepository.

When you exchange information between the server and browser rather than send the entire document back and forth, you tend to send one component back and forth like one order detail line or the order header. This then reduces the amount of data transmitted, but more importantly greatly reduces the size of the JSON object that JavaScript needs to process. If the transferred document gets too large then JavaScript processing speed can become a real bottleneck.

You don’t need to send something to the server every time every field changes, only the fields that cause some business logic to execute. So you don’t need to do anything say when the user changes a description field. When a field changes that causes business logic on the server to execute then you need to send that to the server and get back all the fields that changed as a result. We tend to mostly do this using the default ASP.Net MVC mechanisms along with the knockout data binding. But only doing it for the component record. So say the item number in a detail record is changed, then we would refresh that record by sending it to the server, which would set the changed fields, do the Sage 300 business logic operations (puts and gets) and return the newly updated record where a number of fields have changed.

This works for most cases, but there is room for optimization. If something is rather a major operation, you might want a more tailored AJAX call for the processing. Similarly, if multiple records are affected you might want to denormalize a bit to reduce the dataflow. For instance, when dealing with details, often header totals change, but you might want to associate these with the detail, rather than also refreshing the header.

Summary

This was a quick overview of the main modes or how our Sage 300 Web UIs operation. Stateless operation reduces server overhead, while stateful operation lets us fully leverage our existing business logic, while reducing our bandwidth requirements.

Written by smist08

February 9, 2016 at 8:44 pm

Adding a Grid to Your Sage 300 Web UI

with one comment

Introduction

The grid or table control is a key element for data entry in any Accounting application. With Sage 300 we use the grid control to enter things like Order or Invoice details. Interactions with a grid control tend to be quite complex. The data has to be managed so it is loaded only a page at a time (often called virtual scrolling), since there could be thousands of detail lines and loading them all at once would be quite slow. There is the ability to edit, delete and add lines. Tabbing has to be handled well to enhance data entry. People also have the ability to re-arrange the grid columns, hide columns and then expect these changes to be remembered.

icreceipts

This blog article will talk about the key elements to adding a grid control to your Sage 300 Web UI and what sort of support you need in your UI to support all the desired functionality. A fair bit is handled for you in the Sage 300 Web UI Framework, however you have to handle various events and there is a lot of power to add your own programming.

Configuration

There is a lot of support for standard grid operations in the Sage 300 Web UI framework. Much of this is controlled by a config JSON object which is passed to our @Html.KoKendoGrid function that defines the grid in the Razor View. This file defines a number of properties of the grid along with a number of standard callout functions you can define to add your custom processing. The good news is we have a utility to generate much of this from the ASP.Net MVC Model.

JavaScript Generation Utility

To generate this code we provide a utility which will generate the Razor View code and a lot of the standard JavaScript code that you need. So for instance the code for the Razor View might be:

jsgen1

And then some of the JavaScript code for the config object might be:

jsgen2

Server Side Pagination

In our VB UIs, we had virtual scrolling in our grids, which would basically bring in a page or two at a time. It supported scrolling one page ahead or one page back, go to the top or bottom but you couldn’t go to an arbitrary point in the file without searching (in fact the scroll bar would always be at the top, bottom or right in the middle). In the Web UIs we use the Kendo UI Grid control and try to keep the scrolling mechanism standard for the Web, which means the control tells you how many pages there are and lets you go to any page you like as well as going to the next or previous one.

We provide a lot of the support for doing this in our business repository base classes which expose a get method which takes the page number, page size, filter and order as parameters. Then as long as you match and set the configuration data in the grid’s JavaScript config JSON object, you get the pagination support. There are a couple of things to keep in mind, one is that we rely on our filterCount API call, which translates directly to a SQL statement, which means it can only count based on database fields and not calculated fields, so you can’t restrict the records in your grid based on any calculated fields or the count will be wrong (if you really need this then you need to disable the ability to go to a specific page). You also need to have a hidden SerialNumber column in the grid which contains the record number.

ViewListControl vs AccpacGrid

In our VB UIs, we actually had two grid controls. One was the ViewListControl which would show a separate View record in each line and supported virtual scrolling. Then we had the AccpacGrid control which would usually show an array of fields from a single record (like tax information, or perhaps item structure information).

In the Web UIs we only have one Grid control. It naturally works more like VB’s ViewListControl. So how do we handle the other case of the AccpacGrid? We do this in our controller by translating the array of fields into what looks like a list of details. This way to the Grid control, it doesn’t really see a difference. Usually you don’t need to enable virtual scrolling in this case since there is typically 5 or 10 records and you just provide them all at once. So typically your ViewModel will have a list of records which the controller will populate and then this is set as the Grid’s data source.

Editing

Like VB, the intent of editing cells is to place the correct edit control over the grid cell to perform the edit. There is a lot of framework support for this as well as lots of callouts for you to do your own custom processing. The same is true for adding a new line and deleting a set of lines (note that the Web UI grid supports multiple selection). Also note that the add line, delete line, edit columns buttons aren’t part of the Grid, these are separate buttons styled to look like part of the grid in a region just above the Grid. This means you can easily add your own buttons and controls to this area if you wish.

Saving Preferences

We have API support to help with loading and saving grid column preferences. In VB these are stored in the *_p.ism files, in the Web UIs these are stored in the SQL database in the new USRPROP table. So emptying USRPROP is the Web UI equivalent of deleting the *_p.ism files. Generally, we want to move everything into the database and remove our reliance on the shared data folder over time.

Summary

This article was just a quick introduction to adding a Grid control to a Web UI. Similar to the VB UIs, the grid control is potentially quite complicated as it supports a lot of diverse functionality. But, if you are doing fairly standard functionality, look for a lot of support in the Web UI framework to help you get the job done.

Written by smist08

February 3, 2016 at 6:29 pm

Adding Your Application to the Home Page

with 6 comments

Introduction

We’ve been talking about how to develop Web UIs using our beta SDK. But so far we’ve only been running these in Visual Studio, we haven’t talked about how to deploy them in a production system. With this article we’ll discuss how to add your menus to the home page. Which files need to be installed where and a few configuration notes to observe.

We’ll continue playing with Project and Job Costing, so first we’ll add PJC on to the end of the More menu in the Home Page:

pjc1

As part of this we’ll build and deploy the PJC application so that we can run its UIs in a deployed environment, rather than just running the screens individually in Visual Studio like we have been.

pjc2

The Code Generation Wizard

When you create your solution, you get a starting skeleton Sage.PM.BusinessRepository/Menu/PMMenuModuleHelper.cs. I’m using PM since I’m playing at creating PJC Web UIs, but instead of PM you will get whatever your application’s two letter prefix is. If you don’t have such a prefix, remember to register one with Sage to avoid conflicts with other Sage 300 SDK developers. Similarly, I use Sage as my company, but in reality this will be whatever company name you specified when you created the solution. This MenuModuleHelper.cs file specifies the name of the XML file that specifies your application’s Sage 300 Home Page menu structure. This C# source file is also where you put code to dynamically hide and show your program menu items, so for instance if you have some multi-currency only UIs then this is where you would put the code to hide them in the case of a single currency database (or application).

The solution wizard creates a starting PMMenuDetails.xml file in the root of the Sage.Web project. Then each time you run the code generation wizard it will add another item for the UI just generated. This will produce rather a flat structure so you need to polish this a bit as well as fix up the strings in the generated MenuResx.resx file in the Sage.PM.Resources project. This resource file contains all the strings that are displayed in the menu. Further you can optionally update all the generated files for the other supported languages.

One caveat on the MenuDetails.xml file is that you must give a security resource that the user has rights to or nothing will display. Leaving this out or putting N/A won’t work. One good comparison is that since these are XML files you can see all of Sage’s MenuDetails.xml files by looking in the Sage 300\Online\Web\App_Data\MenuDetail folder. Note that the way the customize screen works, it removes items and puts them in a company folder under these. It will regenerate them if the file changes, but if you have troubles you might try clearing these folders to force them to be regenerated.

Below is a sample XML element for a single UI to give a bit of flavor of what the MenuDetails.xml file contains.

 

  <item>
    <MenuID>PM4001</MenuID>
    <MenuName>PM4001</MenuName>
    <ResourceKey>PMCostType</ResourceKey>
    <ParentMenuID>PM2000</ParentMenuID>
    <IsGroupHeader>false</IsGroupHeader>
    <ScreenURL>PM/CostType</ScreenURL>
    <MenuItemLevel>4</MenuItemLevel>
    <MenuItemOrder>2</MenuItemOrder>
    <ColOrder>1</ColOrder>
    <SecurityResourceKey>PMCostType</SecurityResourceKey>
    <IsReport>false</IsReport>
    <IsActive>true</IsActive>
    <IsGroupEnd>false</IsGroupEnd>
    <IsWidget>false</IsWidget>
    <Isintelligence>false</Isintelligence>
    <ModuleName>PM</ModuleName>
  </item>

Post Build Utility

Now that we have our menu defined and our application screens running individually in debug mode inside Visual Studio, how do we deploy it to run inside IIS as a part of the Sage 300 system? Which DLLs need to be copied, which configuration files need to be copied and where do they all go? To try these steps, make sure you have the latest version of the Sage 300 SDK Wizards and the matching newest beta build.

The Wizard adds a post build event to the Web project that will deploy all the right files to the local Sage 300 running in IIS. The MergeISVProject.exe utility can also be run standalone outside of VS, its a handy mechanism to copy your files. Its usually a good idea to restart IIS before testing this way to ensure all the new files are loaded.

postbuild1

This utility basically copies the following files to places under the Sage300\online\web folder:

  • xml is the configuration file which defines your application to Sage 300. Think of this as like roto.dat for the Web. It defines which are your DLLs to load using unity dependency injection when we start up.
  • App_Data\MenuDetail\PMMenuDetails.xml is your menu definition that we talked about earlier.
  • Areas\PM\*.* area all your Razor Views and their accompanying JavaScript. Basically anything that needs to go to the Browser.
  • Bin\Sage.PM.*.dll and Bin\Sage.Web.DLL are the DLLs that you need to run. (Keep in mind that I’m using Sage for my company name, you will get whatever your company is instead of Sage in these).

With these in place your application is ready to roll.

Update 2016/01/20: This tool was updated to support compiled razor view and the command line is now:

Call "$(ProjectDir)MergeISVProject.exe" "$(SolutionPath)"  "$(ProjectDir)\"
     {ModuleName}MenuDetails.xml $(ConfigurationName) $(FrameworkDir)

Plus it is only run when the solution (not an individual project) is set for a “Release” build.

Compiled Views

When we ship Sage 300, all our Razor Views are pre-compiled. This means the screens start much faster. If you don’t compile them, the when first accessed, IIS needs to invoke the C# compiler to compile them and we’ve found that this process can take ten seconds or so. Plus, the results are cached and the cache is reset every few days causing this to have to happen over again. Another plus is that when pre-compiled the Views can’t easily be edited, which means people can’t arbitrarily change these causing a problem for future upgrades.

Strangely Visual Studio doesn’t have a dialog where you can set whether you want your Views pre-compiled, you have to edit the Sage.Web.csproj file directly. And you need to change the XML value:

<MvcBuildViews>false</MvcBuildViews>

Between true and false yourself in a text editor.

The Sage 300 system is set so that it only runs compiled Razor Views. If you do want to run un-compiled Razor Views, then you need to edit Sage300\online\web\precompiledapp.config and change updatable from false to true.

Beta note: As I write this the MergeISVProject utility doesn’t copy compiled Views properly. This will be fixed shortly, but in the meantime if you want to test with compiled Views you need to copy these over by hand.

New Beta note: This tool now fully supports compiled razor views.

Beta note: The previous beta wouldn’t successfully compile if you were set to use compiled Views, this has been fixed and the solution wizard now includes all the references necessary to do this.

Summary

This article was meant to give a quick overview of the steps to take once you have a screen working in Visual Studio debug mode, to being able to test it running in the Sage 300 Home Page as part of a proper deployment. Generally, the tools help a lot and hopefully you don’t find this process too difficult.

 

Written by smist08

December 29, 2015 at 4:26 pm

Sage 300 Web UI SDK – Adding JavaScript

with one comment

Introduction

Last week we talked about adding UI controls to our Web UI project. In the early days of the Web, this would be all you needed to do. The user would just enter the data and hit save (or submit). However modern Web applications are expected to be more responsive and interactive. This is achieved by adding JavaScript code which can perform local processing or make calls to the server for additional data or to perform additional actions. Most modern Web applications contain quite a bit of JavaScript and achieve quite a high degree of user interaction.

jscalm

In our source code for the new Web UIs, it turns out that 80% of the application code is C# and 20% is JavaScript. Although it is only 20%, this is still a lot of code and care needs to be taken with it. Some programmers really love JavaScript, some really hate it. JavaScript is more of a free form interpreted language that is very forgiving. This allows a lot more freedom in how you structure your programs. Debugging and writing JavaScript is quick and easy since there is no big build/compile step. On the other hand if you capitalize or spell something wrong, there is no compiler to catch the mistake and debugging these errors can be quite frustrating.

We use JQuery to isolate ourselves from Browser differences, for the most part with newer versions of all the Browsers the differences in dialects of JavaScript is much smaller than it used to be. But it still has to be taken into account. Usually the differences manifest themselves in error handling and security concerns. Sometimes one Browser might ignore an error and keep on going whereas another Browser will throw an exception. Similarly, as some practices that lead to security problems are tightened, the implementation can be a bit uneven across the Browsers. Fortunately, most of our application programming doesn’t hit these cases, but it does highlight one the importance of testing in all the supported Browsers.

Another good thing about JavaScript is that tools have all gotten better. You can debug your code in Visual Studio while it runs in Internet Explorer quite seamlessly with debugging you C# code. Further the other Browser all have great debugging tools that can really help. A lot of times you can get several views on something to see what is going wrong. Plus there are compilers for JavaScript to help find some common typos and to enforce programming standards you might want to adopt.

Frameworks

We provide a global framework for doing things like popping up Finders. We also have lots of routines to handle our standard data like dates and numbers. We use a number of open source libraries like JQuery and Knockout.js as well as the (partly commercial) Kendo UI library. Generally, if you know our framework, you don’t need to know that much from the other libraries, but as you get more sophisticated, you will want to leverage them as well. There is also nothing stopping you including further libraries, just that we won’t be able to support you in their use.

Server Independent

We don’t use any libraries with matching client and server components. Hence all communications are handled by our JavaScript code, which means we have full control over all communications. This means it’s our responsibility to not be chatty. It also means we write all the code to handle any Ajax calls from the Browser. ASP.Net MVC makes this pretty easy. It also means that if you want to add your own components (say another UI control) then you can do so as long as you follow this same basic approach.

Example Code

The Web UI code generation wizard creates three JavaScript files for each UI. These are:

  1. screennameKoExtn.js – This is an extension to the knockout data binding where you can add some JavaScript generated calculated fields to the model.
  2. screennameRepository.js – This file contains a method for each RPC call that can be made. We start with the basic CRUD operations, but you would add your screen specific ones here.
  3. screennameBehaviour.js – This is all the other JavaScript code. You may want to break this file up for larger UIs. But for smaller UIs this is a handy place to contain all the JavaScript for working with the controls on your form.

The Behaviour.js file contains a large object for the screen with functions to bind controls to methods and to do various processing when that control is activated. For instance, for our sample PJC CostType UI, in the init routine it will call initButtons which will bind all the buttons to code including the Save button:

       // Save Button
       $("#btnSave").bind('click', function () {
              sg.utls.SyncExecute(costTypeUI.saveCostType);
       });

Then the saveCostType routine is:

saveCostType: function () {
     if ($("#frmCostType").valid()) {
         var data = sg.utls.ko.toJS(modelData, costTypeUI.computedProperties);
         if (modelData.UIMode() === sg.utls.OperationMode.SAVE) {
              costTypeRepository.update(data, costTypeUISuccess.update);
         } else {
         costTypeRepository.add(data, costTypeUISuccess.update);
      }
   }
},

The costTypeRepository.update routine is in the Repository.js file and performs the Ajax call to do the save:

       // Update
       update: function(data, callbackMethod) {
              costTypeAjax.call("Save", data, callbackMethod);
       }

This Ajax.call routine will actually transmit the data model to the server where it is picked up by a controller and processed. We talk about the server side of things in a later article. The entire file is a bit on the long side to include in the blog, but hopefully this give a bit of flavour of what it contains.

The dataModel.UIMode is a predefined calculated field in the screennameKoExtn.js file and keeps track of whether the UI is in Add or Save mode.

Summary

This was a quick glimpse of the JavaScript that is always running behind the scenes in our new Sage 300 Web UIs. Once we cover the server side, we’ll have to consider a lot of cases that go from the HTML to the JavaScript to the C# to the Sage 300 Business Logic to the SQL database and then all the way back. This is just the second step on this journey after last week’s article.

 

Written by smist08

December 12, 2015 at 8:22 pm

Sage 300 Web UI SDK – Adding UI Controls

with 9 comments

Introduction

In my last posting I showed how to quickly create an empty Sage 300 Web UI by running our two new wizards from Visual Studio. In this article we’ll look at how to add some visual controls to this project and talk a bit about some of the issues with doing this, namely about using our provided HTML helper functions and CSS styling.

We’re basically going to continue on and add the visual elements for the PJC Cost Types setup screen. We won’t write any JavaScript yet, so the only functionality will be that provided by the code generator and the default data binding support. This still give quite a bit as you can navigate, use the finder, delete records and save updates.

The UI Wizard discussed last week produces a simple starting page with the standard heading controls, the key field and the Save and Delete buttons. These are all wired up to Javascript and working. This makes our life much easier when adding the rest of the controls.

The only thing you need to do manually is change the Starting Page to: “/OnPremise/PM/CostType” on the Web tab of the Web project’s properties. Then it will compile and run yielding:

costtype1

Adding the Parts

ASP.Net MVC Razor Views are a technique to dynamically generate our HTML by embedding C# code in an HTML template. When the HTML needs to go to the browser the C# code is executed and it usually generates more HTML into the template, so that pure dynamically generated HTML is transmitted to the Browser. The Razor View system is very extensible and it allows a lot of extensibility which we do by adding a large set of helper functions.

Below is the screen once we add some more controls. I showed with a record loaded since that part works with the generated code. The dates and bottom combo box aren’t working yet since we need to add some JavaScript code to help them out.

costtype2

The source code for this screens Razor View (the partial view part) is:

(That didn’t work so well. Apparently WordPress ate all the div’s, I’ll do a bit of research to see if I can fix this, so a bit is missing from the below code. I also added some line breaks so the code doesn’t go off the right of the page).

@* Copyright © 2015 Sage *@
@model Sage.Web.Areas.PM.Models.CostTypeViewModel<Sage.PM.Models.CostType>
@using Sage.PM.Resources.Forms

@using Sage.CA.SBS.ERP.Sage300.Common.Web.AreaConstants
@using Sage.CA.SBS.ERP.Sage300.Common.Resources
@using Sage.CA.SBS.ERP.Sage300.Common.Web.HtmlHelperExtension
@using Sage.CA.SBS.ERP.Sage300.Common.Models.Enums
@using AnnotationsResx = Sage.CA.SBS.ERP.Sage300.Common.Resources.AnnotationsResx

@Html.ConvertToJsVariableUsingNewtonSoft("CostTypeViewModel", Model)

@Html.Partial("~/Areas/PM/Views/CostType/Partials/_Localization.cshtml")
<section class="header-group">
    @Html.SageHeader3Label("CostTypeHeader", CostTypeResx.Entity)
    @if (Model.UserAccess.SecurityType.HasFlag(SecurityType.Modify))
    {
        @Html.KoSageButton("btnNew", null, new { @value = CommonResx.CreateNew, @id = "btnNew",
             @class = "btn-primary" })
    }
    @Html.Partial(Core.Menu, Model.UserAccess)
</section>

<section class="required-group">
    @Html.SageLabel(CommonResx.RequiredLegend, new { @class = "required" })
</section>


  @Html.SageLabel("CostTypeCode", CostTypeResx.CostTypeCode, new { @class = "required" })
  @Html.KoSageTextBoxFor(model => model.Data.CostTypeCode, new { @sagevalue = "Data.CostTypeCode",
      @valueUpdate = "'input'" }, new { @id = "txtCostTypeCode", @class = "default txt-upper",
      @formatTextbox = "alphaNumeric" })
  @Html.KoSageButton("btnLoadCostTypeCode", null, new { @id = "btnLoad", @class = "icon btn-go",
      @tabindex = "-1" })
  @Html.KoSageButton("btnFinderCostTypeCode", null, new { @class = "icon btn-search",
      @id = "btnFinderCostTypeCode", @tabindex = "-1" })
  @Html.ValidationMessageFor(model => model.Data.CostTypeCode)
            
</div>

@* End of generated header, next is code I wrote. *@



    @Html.SageLabelFor(model => model.Data.Description)
    @Html.KoSageTextBoxFor(model => model.Data.Description, new { @value = "Data.Description",
        @valueUpdate = "'input'" }, new { @id = "tbDescription", @class = "large" })
    @Html.ValidationMessageFor(model => model.Data.Description, null)
            
 </div>



   @Html.SageLabelFor(model => model.Data.LastMaintained)
   @Html.KoSageTextBoxFor(model => model.Data.LastMaintained, new {
       @value = "Data.ComputedLastMaintainedDate" }, new { @disabled = "true", @class = "default" })
            


    @Html.KoSageCheckBox("chkStatus", false, new { @sagechecked = "Data.Status" },
         new { @id = "chkStatus" })
    @Html.SageLabel(CommonResx.InactiveAsOfDate, null, new { @for = "chkStatus", @class = "" })
                
    @Html.KoSageTextBox("txInactiveDate", new { @value = "Data.ComputedInactiveDate" },
         new { @disabled = true, @class = "default " })
   </div>
</div>



    @Html.SageLabelFor(m => m.Data.CostClass, new { @id = "lblCostClass", @class = "" })
    @Html.KoSageDropDownList("Data_CostClass", new { @options = "CostClass", @sagevalue =
          "Data.CostClass", @optionsText = "'Text'", @optionsValue = "'Value'" },
          new { @class = "w188" })
            
</div>

@* End of my code, next is the generated footer. *@


<section class="footer-group">
   @if (Model.UserAccess.SecurityType.HasFlag(SecurityType.Modify))
   {
      @Html.KoSageButton("btnSave", new { }, new { @value = CommonResx.Save, @id = "btnSave",
            @class = "btn-primary" })
      @Html.KoSageButton("btnDelete", new { }, new { @value = CommonResx.Delete, @id = "btnDelete",
            @class = "btn-primary" })
   }
</section>
</div>

 

I put comments around the code I wrote so you can see what is generated by the code generation wizard versus the code you add later. Basically this is a mixture of C# code (each line starts with @) and HTML which is in the angle brackets.

There isn’t much layout in this file because this is handled by the CSS. For simple screens like this one there are sufficient styles in the provided Sage standard CSS file that we don’t need to add any CSS. As a result, the HTML is actually fairly simple and really just used to logically group things.

Notice that we use Sage provided extension functions to create all the controls. This provides us with the hooks to provide quite a bit of standard functionality. For instance, we don’t want any hard coded strings in our HTML, otherwise we would force our translators to produce a different copy of the HTML for each language and then we would have to maintain all these files. Here we just use the helper function and it will look up the correct string from the language resource appropriate for the user’s language setting. This also gives us the ability to change the underlying control without changing all the HTMLs. So we can use a different date picker control for instance by changing the code our helper function emits rather than editing each HTML individually. Basically giving us a lot of global control over the behavior of the product.

These helper functions also can setup databinding. Any helper that start with ko will bind the data to the model (more precisely the viewmodel). We used ko since we use knockout.js for databinding which perhaps isn’t the best choice of function naming since again we can change the mechanism in the background without effecting the application code.

Notice there is a partial view called _Localization.cshtml that is included. This provides any localized strings that are needed by JavaScript. So anything referenced in here will be generated in the correct language when the page is loaded.

There is a strange call to “ConvertToJsVariableUsingNewtonSoft” near the top of the file. This is to load a copy of the model into JavaScript during page loading. This means we don’t need to do an initialization RPC call to get the model (Sage 300 View) meta data. Basically the usual empty screen then has the default data and meta data as a starting point.

Summary

This was a quick look at the Razor View part of our Web UIs. This is where the controls and layout are specified. Layout is handled by CSS and data binding is provided to greatly reduce required coding. Next we’ll start to look at the JavaScript that runs behind the scenes in the Browser.

 

Written by smist08

December 5, 2015 at 12:11 am

Introducing the SDK for the Sage 300 Web UIs

with 12 comments

Introduction

Sage 300 has always provided an SDK to allow ISVs to create accounting applications in the same way that we create our own applications like General Ledger or Order Entry. In the past our internal application developers have usually only had the SDK installed for doing their own work.

Further these ISVs can install their applications into a working Sage 300 installation by just copying a specific set of folders. We then will see these folders and allow that module to be activated and used.

The new Web Screens will have the same ability to create custom accounting applications and to easily add them to one of our installations.

We will be starting the beta program for this SDK shortly, so this should start to give people a preview of what is coming.

This overview assumes you have an existing SDK program. That you have Sage 300 Views and VB UIs. That you have an activation UI and can activate your module, making it known to Sage 300. This is just how to create the actual Web UI components.

The Module Creation Wizard

We are first going to create a Visual Studio solution for your Accounting module. Then we will use another wizard to add the screens to this solution. The solution will contain several projects that correspond to the parts of a UI screen. This is different than each screen having its own project. This stays in tune with how the ASP.Net MVC tools create solutions and allows us to leverage everything built into Visual Studio.

Create a Visual Studio project. We provide a project wizard to create your solution. Let’s pretend we are going to create the Project and Job Costing module:

solnwizard1

The wizard will then ask you some questions about your module.

solnwizard2

And then create a solution with the correct project structure for your application.

solnwizard3

This solution now has the correct structure to add screens to, plus it has all the module level compents and references. This will compile, but there isn’t anything to run yet.

The UI Wizard

Now you create your separate UIs by running our Code Generation Wizard. You get this by right clicking on the solution and choosing it from the context menu.

uiwiz1

This then brings up a wizard that you can step through.

uiwiz2

Depending on what you choose for the Code Type, you will get a relevant screen for the details. If you choose Flat you will get the following:

uiwiz25

The View ID will be used to generate the model and business repository for this screen. Basically it will use the View meta-data to generate C# classes that will provide most of the functionality to perform standard CRUD type operations.

Next you get a screen to specify which resource file to use for your stirngs:

uiwiz3

Like all our previous SDKs there is full support for producing a multi-language product. Of course as in the past its up to you whether you leverage this or not.

Now you get to select some options of features to include:

uiwiz4

With in the Sage accounting modules the I/C, O/E and P/O Views contain more functionality for determining if a fields is editable or not than do the G/L, A/R or A/P screens. The “Generate Dynamic Enablement” indicates whether all the checking editbable is done by your UIs or by your Views.

Now its time to confirm to generate the code:

uiwiz45

And finally you get the list of files that it generated for you:

uiwiz5

The wizard has used the meta-data from the Sage 300 Business Logic View, in this case the PJC Cost Types view to generate the code for a Business Reposity to use and an empty HTML screen.

Real Work

Running these wizards is quite quick and hopefully they give you a good start. The solution will compile and run, but all you get is a blank screen, since the generated Razor View just contains a TODO to add some controls. Now the real work begins adding controls to your Razor Views, adding custom processing logic and generally wiring things up.

You can now use the code-debug-fix cycle within Visual Studio and hopefully find it a productive way to create your Sage 300 screens.

In future articles I’ll talk about creating the Razor Views, using the extension functions we supply to help make this process easier and the CSS that is used to give the screens a standard look and feel. Then we will need to go into how to wire up finders, perform custom processing and all the other things required to make a Sage 300 screen.

Summary

This was a very quick look at the SDK for our Web Screens. We haven’t covered any coding yet, but we will. All the functionality used is built into the DLLs installed with Sage 300, so the actual SDK component is quite small. Besides the wizard, there is a lot of framework support to help you with common components and abstractions to hide some of the details.

Written by smist08

November 27, 2015 at 6:19 pm

Sage 300 2016 Operations Beta

with 3 comments

Introduction

We recently released Sage 300 2016 with Web UIs for C/S, Bank, Tax, G/L, A/R and A/P. Now we have released our first beta of the operations modules I/C, O/E and P/O. Internally we are calling this our February 2016 release, I’m not sure what it will be officially called externally yet. This release will be packaged as a Service Pack to the Sage 300 2016 version, so this will need to be installed first. This will be a pretty major Service Pack with a lot of new functionality added. But as a Service Pack, the actual internal program versions won’t change and the upgrade procedures will be the same as for a regular Service Pack.

Due to various dependencies, we needed to produce the Financial Accounting screens for the Web first. Even though most users who can really benefit from Web/Mobile access need the Operations screens. So hopefully having all these Operations screens available should open up a great many possibilities for our customers. Of course you can still use the existing Windows Desktop VB screens, and you can even use a combination of both.

You need to run the “Portal…” dialog from Database Setup again to seed some data for the operations modules into the Portal database.

New KPIs

We have new KPIs for I/C, O/E and P/O. They are in the screen shot below, namely “Top Salespersons”, “Inventory Item Performance” and “Activity Trend”. Also notice the menus for I/C, O/E and P/O have been added to the main menu bar.

operationkpis

Order Entry

We are really pleased to have moved Order Entry to the Web. This is a module where there are often a great many users that are located in different geographic locations, or need to use the module while on the road. This module also integrates with Sage Payment Solutions (SPS) for processing credit cards. Below is a sample showing the main Order Entry UI.

oe1100new

Purchase Order

Purchase Order is a pretty major module that is now in the Web. Perhaps we don’t get as many users running P/O screens as O/E screens, but for a lot of companies, the P/O process is very important. Below is a screen shot of the main P/O Purchase Order Entry screen.

poentry

Inventory Control

I/C is a large module with lots of UIs that now have Web UI versions. We haven’t moved Lot Tracking or Serialized Inventory yet, but most of the other I/C functionality is now available in the Web. Below is a screen shot of the I/C Receipts screen, which is one of the major I/C document entry screens.

icreceipts

Other Screens

A number of the lesser used C/S, G/L, A/P and A/R screens were omitted from the first release. Quite a few of these are now in. For instance C/S Schedules has been added along with the various recurring entry screens that use Schedule Codes.

schedules

We added a number of other screens like the G/L Fiscal Set Comparison screen.

fiscalsetcomp

Another thing you might notice is that the Web UIs are available in Chinese now in addition to English and French.

There will be More

This is just beta 1. It is focused on the new parts of the Web Screens. It doesn’t include the new features that will be included in the Windows Desktop version, these will be appearing in a later Beta.

Summary

With the addition of the I/C, O/E and P/O screens, Sage 300 now has a very large footprint of its functionality in the Web. Hopefully we can get lots of feedback from this Beta release and have a successful launch in February.

It may seem like we are releasing the February version pretty quickly after just releasing the main Sage 300 2016 version, but we are now looking to release three fairly major updates to the product each year. This is the result of our adoption of Agile methodologies and the use of continuous delivery techniques (to release frequently, reliably and easily). Even though this isn’t a cloud release, we can still use the techniques of cloud delivery for our on-premise customers.

 

Written by smist08

November 14, 2015 at 5:51 pm

Follow

Get every new post delivered to your Inbox.

Join 340 other followers