Infor M3 Smart Office Customization: Mashup Development, Event Handling, and XAML-Based UI Extensions

Sanjay Kulkarni
Sanjay Kulkarni
Practice Lead, Infor M3 and GHR
25 min read

If your organisation runs Infor M3, you already know the system is capable. What frustrates most operations teams is not what M3 can do – it is how long it takes users to get there. Standard M3 screens require multiple navigation steps to complete workflows that, from a business perspective, belong on a single screen. Data that a warehouse supervisor or a production planner needs is spread across four or five M3 programs, requiring constant context-switching that slows down decision-making and increases the risk of errors.

Smart Office is Infor’s answer to that problem. It is the .NET-based client layer for M3 that gives you the tools to rebuild user experiences without touching the M3 application itself. Mashups, event handlers, and XAML-based UI extensions are the three technical building blocks that make it possible. This post is a practical guide to all three. It covers what each capability does, how to implement it correctly, where the common mistakes are made, and how to approach customisation in a way that survives M3 upgrades.

What Smart Office Actually Is and Why It Matters for M3 Customization

Smart Office is not a skinning tool and it is not a separate application. It is the presentation layer that sits on top of M3, replacing the older Java-based Thin Client with a Windows desktop client built on Windows Presentation Foundation (WPF) and .NET. Because it uses WPF, the entire UI is rendered using XAML, which means every element of the interface – panels, grids, buttons, input fields, labels – can be defined, extended, and restructured using standard .NET tooling.

The significance of this for customisation is considerable. You are not working with a proprietary UI framework or a closed widget library. You are working with WPF, which is a mature, well-documented Microsoft technology with a large developer community and extensive tooling support. If you have .NET development experience, the learning curve for Smart Office customisation is manageable. If your team does not have that background, the concepts in this post will help you understand what a skilled developer needs to build, evaluate the quality of what is delivered, and make informed decisions about scope.

According to Infor’s own platform documentation, Smart Office is the primary customisation and integration framework for M3, supporting mashup development, scripting, and event-driven UI extension as first-class capabilities. It is not a workaround. It is the intended path for organisations that need to adapt M3 to their specific business processes.

For manufacturers and complex enterprises running M3 as part of their Infor ecosystem, Smart Office customisation is often what makes the difference between a system that users actually adopt and one they work around. The broader Infor LN and M3 consulting capabilities at Sama’s Infor LN service practice reflect exactly this kind of operational challenge across manufacturing environments.

Still navigating multiple M3 screens to complete a single workflow?

Sama builds Smart Office mashups and event-driven UI extensions that consolidate your M3 processes into purpose-built screens your team will actually use.

Part One: Mashup Development

A mashup in Smart Office is a composite user interface that combines content from one or more M3 programs into a single, purpose-built screen. Instead of a user navigating to MMS001 to look up item details, then to MMS002 to check stock, then to MWS410 to review warehouse locations, a mashup brings all of that together in one view – laid out according to how that specific user role actually works.

Understanding the Mashup Architecture

Every mashup is an XML file that defines a WPF-based panel layout. That XML file describes the visual structure of the mashup: which M3 programs are included, how they are arranged, which fields are visible, and how they communicate with each other. The Smart Office client reads this file at runtime and renders the mashup as a native WPF window within the Smart Office shell.

Mashups are stored in the Smart Office LifeCycle Manager (LCM) repository, which means they are version-controlled and can be deployed to specific user groups without touching the M3 application configuration. A mashup built for a warehouse receiving team can be deployed to that team’s Smart Office profiles without affecting any other user group. Deployment is managed through the Smart Office Administration tool, and access to mashups is controlled through Smart Office’s profile and role assignment system.

There are two ways to build mashups. The Smart Office Mashup Designer, which ships with the Smart Office SDK, provides a drag-and-drop visual interface for assembling mashup panels from M3 program sources. The second approach is editing the XML directly, which gives more precise control over layout and behaviour but requires familiarity with the mashup schema. In practice, experienced developers use the Mashup Designer for the initial layout and structural work, then edit the XML directly for refinements that the designer does not expose through its interface.

Building Your First Mashup: A Step-by-Step Walkthrough

Before opening the Mashup Designer, define the use case clearly. Answer three questions: which M3 programs are the data sources for this mashup, what is the primary user task the mashup is designed to support, and which user role will use it. Building a mashup without this definition produces a technically functional screen that does not solve the actual user problem.

For this walkthrough, the use case is a receiving supervisor who needs to view open purchase orders, confirm receipt against those orders, and check current stock levels for received items – all without leaving a single screen. The M3 programs involved are PPS200 (Purchase Order Lines), MWS420 (Receiving), and MMS002 (Stock On Hand).

Step 1: Create a new mashup project in the Mashup Designer. Open the Smart Office SDK, launch the Mashup Designer, and create a new mashup. Give it a meaningful name that reflects the user role and task – ReceivingSupervisor_POReceipt is preferable to Mashup001. Naming conventions matter because mashups accumulate quickly in LCM and become difficult to manage without a clear naming system.

Step 2: Add M3 program panels. In the Mashup Designer, each M3 program is added as a panel source. Drag the PPS200 panel onto the design canvas. The designer will prompt you to configure which list view or detail view of PPS200 you are including, and which fields should be visible. Select the list view first, showing open purchase order lines filtered to the current user’s assigned warehouse. Add MWS420 as a second panel, positioned below or alongside PPS200. Add MMS002 as a third panel.

Step 3: Configure panel size and layout. WPF’s layout engine uses a grid-based system. Define row and column proportions in the mashup XML to control how space is allocated across the three panels. A common layout for a receiving mashup puts the PO list in the upper half of the screen and the receiving confirmation and stock check panels side by side in the lower half.

Step 4: Set up inter-panel communication using data bindings. This is the step that makes a mashup genuinely useful rather than just a visual aggregation of three separate screens. Data bindings connect a field value in one panel to a filter or input in another. When the user selects a purchase order line in the PPS200 panel, the binding automatically sends the item number from that line to the MMS002 panel, which updates to show current stock for that specific item. Without this connection, the panels operate independently and the user still has to manually enter values across screens.

Data bindings are defined in the mashup XML using a source-target syntax. The source is the field in the origin panel (the item number field in PPS200’s list view), and the target is the filter parameter in the destination panel (the item number filter in MMS002). Multiple bindings can be defined on a single panel interaction, so selecting a PO line can simultaneously update both the receiving panel and the stock panel.

XML

<Binding>      <Source PanelId="PPS200_List" Field="ITNO" />      <Target PanelId="MMS002_List" Parameter="WITNO" />    </Binding>    <Binding>      <Source PanelId="PPS200_List" Field="SUNO" />      <Target PanelId="MWS420_Detail" Parameter="WSUNO" />    </Binding>    

Step 5: Test in the Smart Office client. Deploy the mashup to a test profile in Smart Office LCM and open it in the client. Verify that the panel layout renders correctly, that data bindings fire when a PO line is selected, and that the receiving panel is pre-populated with the correct supplier and item values. Test with representative data from your M3 environment, not sample records that may not reflect the field lengths and formatting of your actual data.

Mashup Design Principles That Hold Up Over Time

The most common mistake in mashup development is building screens that try to replicate entire M3 programs rather than serving a specific task. A mashup that includes fifteen fields from six programs in a single view is not more useful than the standard M3 navigation – it is more confusing. Design each mashup for a single workflow, with only the fields and actions that workflow requires.

Keep the number of M3 program panels per mashup to three or fewer where possible. Each additional panel increases the complexity of data binding logic and the potential for performance issues when the mashup loads. If a user role genuinely needs data from five or six programs simultaneously, consider whether the use case is actually two separate workflows that each deserve their own focused mashup.

Document the data binding configuration for every mashup in a separate reference document. When M3 is upgraded or a program panel changes its field structure, the binding configuration is the first thing that breaks and the documentation is what allows it to be fixed quickly.

Still navigating multiple M3 screens to complete a single workflow?

Sama builds Smart Office mashups and event-driven UI extensions that consolidate your M3 processes into purpose-built screens your team will actually use.

Part Two: Event Handling

Event handling in Smart Office allows you to define actions that execute in response to user interactions or M3 program events. Where mashup development is about restructuring the visual layout, event handling is about making the interface respond intelligently to what the user does.

What Events Are Available

Smart Office exposes three categories of events that can be handled in customisations.

UI events are triggered by user interactions with Smart Office controls: button clicks, list row selections, field value changes, and panel focus changes. These are the most commonly used events in mashup-based customisations, and the data binding mechanism described above is one form of UI event handling. More complex UI event handling involves executing scripts or calling external services in response to a user interaction.

M3 program events are triggered when specific actions occur within an M3 program: a transaction is posted, a record is created or updated, a batch job completes. These events can be used to trigger follow-on actions in Smart Office, such as refreshing a related panel, displaying a notification, or logging the event to an external system.

Lifecycle events fire during the mashup or panel lifecycle: on load, on close, on refresh. These are used to initialise field values, pre-populate filters, or perform cleanup when a mashup is closed.

Implementing Event Handlers in Mashup XML

Event handlers are defined in the mashup XML alongside the panel and binding configuration. A handler specifies the event type, the source element that triggers it, and the action to execute. The action can be a built-in Smart Office command, a JavaScript function, or a call to a .NET assembly registered with the Smart Office extension framework.

The following example shows a handler that refreshes the MMS002 stock panel whenever a new item is selected in the PPS200 list, ensuring the stock view is always current without requiring the user to manually trigger a refresh:

XML

<EventHandler>      <Event Source="PPS200_List" Type="RowSelected" />      <Action Type="RefreshPanel" Target="MMS002_List" />    </EventHandler>    

A more complex example uses an event handler to validate a field value before allowing a transaction to proceed. When the user enters a quantity in the receiving confirmation panel, a handler fires to compare the entered quantity against the ordered quantity from the PO line and display a warning if the received quantity exceeds the ordered quantity by more than a defined tolerance:

XML

<EventHandler>      <Event Source="MWS420_Detail"           Type="FieldChanged"           Field="RVQA" />      <Action Type="ExecuteScript"            Script="ValidateReceiptQuantity" />    </EventHandler>    

The ValidateReceiptQuantity script accesses the ordered quantity field from the PPS200 panel via the mashup’s data context, compares it to the entered receipt quantity, and uses the Smart Office notification API to display a warning message if the tolerance threshold is exceeded. The user can acknowledge the warning and proceed, or correct the quantity. The validation does not prevent the user from completing the transaction – it informs and guides rather than blocking.

Script-Based Event Handling with JScript

Smart Office supports JScript (Microsoft’s ECMAScript implementation) for client-side scripting within the mashup framework. Scripts are defined in the mashup XML or in separate .js files referenced by the mashup, and they execute within the Smart Office process with access to the Smart Office API surface.

The Smart Office API available to scripts includes:

  • MForms.Manager for accessing M3 program data from the current session
  • MashupPanel for reading and writing field values in other panels within the same mashup
  • NotificationService for displaying user notifications and confirmation dialogs
  • LogService for writing debug and audit information to the Smart Office log

A practical use case for script-based event handling is dynamic field visibility. If your receiving process has different required fields depending on the item type – certain item categories require a batch number and expiry date at receipt, while others do not – an event handler script can show or hide those fields based on the item type selected in the PO line panel, keeping the screen clean for standard receipts while making the additional fields available when they are needed.

JavaScript

function HandleItemTypeChange(sender, args) {        var itemType = MashupPanel.GetFieldValue("PPS200_List", "ITTY");      var batchPanel = MashupPanel.GetControl("BatchDetail");        if (itemType === "LOT" || itemType === "SER") {          batchPanel.Visibility = "Visible";      } else {          batchPanel.Visibility = "Collapsed";      }    }    

Connecting to External Systems via Event Handlers

One of the more powerful applications of Smart Office event handling is triggering external system calls in response to M3 events. When a goods receipt is confirmed in M3, an event handler can call an external REST API to notify the supplier portal, update a quality management system, or write a message to Infor ION for routing to a downstream system.

These external calls are implemented using .NET assembly extensions registered with the Smart Office framework, rather than JScript, because JScript does not have direct access to .NET HTTP client libraries. The extension assembly is a compiled .NET class library that implements the Smart Office ICommand interface, which allows it to be invoked as an action target in event handler definitions.

For organisations already using Infor ION as their integration middleware, Smart Office event handlers that publish BODs to ION on M3 transaction events are a clean and supportable pattern. The ION connection point for Smart Office is configured in the ION administration console, and the BOD type published by the event handler is mapped to the appropriate downstream routing in the ION workflow. The Infor ION integration service at Sama Consulting covers how ION is configured for exactly these kinds of event-driven integration patterns.

Still navigating multiple M3 screens to complete a single workflow?

Sama builds Smart Office mashups and event-driven UI extensions that consolidate your M3 processes into purpose-built screens your team will actually use.

Part Three: XAML-Based UI Extensions

XAML (Extensible Application Markup Language) is the markup language that defines the visual structure and behaviour of WPF applications. Since Smart Office is built on WPF, XAML is the native language of every screen you see in the client. Understanding XAML unlocks the deepest level of Smart Office customisation: the ability to build entirely new UI components, modify the visual structure of existing panels at a level below what the Mashup Designer exposes, and apply custom styling and branding across the Smart Office interface.

XAML in the Context of Smart Office

Every panel in a Smart Office mashup is defined by XAML. When you use the Mashup Designer, it generates XAML behind the scenes. When the mashup XML specifies a panel layout, the Smart Office runtime interprets that definition and renders WPF controls accordingly. For customisations that go beyond what the Mashup Designer supports, you write or edit XAML directly.

The Smart Office SDK includes a set of custom WPF controls built specifically for the M3 context. These controls handle M3-specific interaction patterns – selecting values from M3 reference fields, navigating to related M3 records, triggering M3 program actions – and they extend standard WPF controls with M3-aware behaviour. When building XAML extensions for Smart Office, you use these SDK controls rather than vanilla WPF controls wherever M3 interaction is involved.

Building a Custom Panel with XAML

The most common XAML-based extension scenario is building a custom detail panel that presents M3 data in a layout that the standard M3 program view does not support. This is particularly useful for executive or management-facing views where data needs to be presented as a summary dashboard rather than a transaction form.

A practical example: a production planning dashboard that shows open work orders grouped by production line, with colour-coded status indicators based on schedule adherence, and a summary bar showing overall production efficiency for the shift. None of this is available in standard M3 screens, but all of the underlying data exists in M3’s production management module.

The XAML for this panel defines a WPF Grid layout containing a header section with summary statistics, a DataGrid control for the work order list, and a custom ItemsControl for the production line grouping. The data binding connects each visual element to the corresponding M3 field values loaded by the mashup’s data context.

XML

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        xmlns:m3="clr-namespace:Mango.UI.Controls;assembly=Mango.UI">      <Grid.RowDefinitions>      <RowDefinition Height="80"/>      <RowDefinition Height="*"/>    </Grid.RowDefinitions>      <!-- Summary header -->    <Border Grid.Row="0"            Background="#1E4D8C"            CornerRadius="4"            Margin="4">        <StackPanel Orientation="Horizontal"                  VerticalAlignment="Center"                  Margin="12,0">          <TextBlock Text="Production Dashboard"                   Foreground="White"                   FontSize="16"                   FontWeight="SemiBold"/>          <TextBlock Text="{Binding ShiftEfficiency, StringFormat='Shift Efficiency: {0:P0}'}"                   Foreground="#7EC8E3"                   FontSize="14"                   Margin="24,0,0,0"/>        </StackPanel>    </Border>      <!-- Work order grid -->    <DataGrid Grid.Row="1"              ItemsSource="{Binding WorkOrders}"              AutoGenerateColumns="False"              CanUserAddRows="False"              GridLinesVisibility="Horizontal">        <DataGrid.Columns>          <DataGridTextColumn Header="Work Order"                            Binding="{Binding WONO}"                            Width="120"/>          <DataGridTextColumn Header="Item"                            Binding="{Binding PRNO}"                            Width="160"/>          <DataGridTemplateColumn Header="Status"                                Width="100">            <DataGridTemplateColumn.CellTemplate>            <DataTemplate>                <Border CornerRadius="10"                      Padding="8,2"                      Background="{Binding StatusColour}">                  <TextBlock Text="{Binding StatusLabel}"                           Foreground="White"                           FontSize="11"                           HorizontalAlignment="Center"/>                </Border>              </DataTemplate>          </DataGridTemplateColumn.CellTemplate>          </DataGridTemplateColumn>        </DataGrid.Columns>      </DataGrid>    </Grid>    

The StatusColour binding in the template above is a value converter – a .NET class that takes the raw M3 status code and returns the corresponding WPF Brush object (green for on-schedule, amber for at-risk, red for overdue). Value converters are registered with the XAML resource dictionary and referenced in bindings using the Converter attribute. They are one of the most useful tools for making data visually meaningful without changing anything in M3 itself.

Applying Custom Styles and Themes

Smart Office supports resource dictionaries – XAML files that define reusable styles, templates, and brushes – which can be applied globally across all mashups in a Smart Office deployment or scoped to specific mashups. A global resource dictionary is the right place to define your organisation’s standard colours, fonts, button styles, and control templates so that all custom mashups have a consistent visual identity.

The resource dictionary is referenced in each mashup’s XAML using a MergedDictionaries declaration:

XML

<UserControl.Resources>      <ResourceDictionary>        <ResourceDictionary.MergedDictionaries>          <ResourceDictionary           Source="/YourOrg.SmartOffice.Styles;                  component/Themes/Corporate.xaml"/>        </ResourceDictionary.MergedDictionaries>      </ResourceDictionary>    </UserControl.Resources>    

With the resource dictionary in place, every control in the mashup that matches a style key defined in Corporate.xaml will automatically pick up the corporate styling. When the corporate style needs updating – a brand refresh, an accessibility improvement, a contrast ratio adjustment – you update the resource dictionary once and every mashup that references it is updated.

Custom Controls for Reusable Functionality

When the same UI pattern appears across multiple mashups – a standard header with user and shift information, a common action button bar, a reusable item search panel – building it as a custom WPF UserControl rather than replicating the XAML in each mashup is the right approach.

A custom UserControl is a compiled .NET class that encapsulates XAML layout and code-behind logic. It exposes dependency properties for the values it needs to display and events for the actions it can trigger, making it composable within any mashup that needs it. Custom controls are packaged in a .NET class library assembly, registered with the Smart Office extension framework, and then available in mashup XAML just like the built-in Smart Office SDK controls.

Building a library of custom controls for your organisation’s Smart Office environment creates a reusable foundation for future mashup development that reduces build time, ensures consistency, and localises maintenance. When a common control needs to change, you update it in one place.

Still navigating multiple M3 screens to complete a single workflow?

Sama builds Smart Office mashups and event-driven UI extensions that consolidate your M3 processes into purpose-built screens your team will actually use.

Managing Customisations Across M3 Upgrades

The question every organisation asks before investing in Smart Office customisation is: what happens when Infor releases an M3 upgrade? The answer depends on how the customisations were built.

Mashups and XAML extensions that interact with M3 programs via the official Smart Office API surface – using published M3 program names, standard panel IDs, and documented field names – are the most resilient to upgrades. When M3 program structures change in an upgrade, the change is typically documented in the Infor release notes and the affected mashup bindings can be updated with a focused remediation effort rather than a complete rebuild.

Customisations that rely on undocumented M3 program internals, direct database queries, or the internal structure of M3’s UI panels are fragile. They work until they do not, and they break without warning when M3’s internal structure changes. Avoiding these patterns from the start is the most important architectural discipline in Smart Office customisation.

Maintain a customisation inventory that records every mashup, every event handler, and every XAML extension in production, alongside the M3 programs and fields each one depends on. Before each M3 upgrade, review the upgrade release notes against this inventory to identify customisations that need remediation. Testing customisations against the upgrade in a non-production environment before promoting the upgrade to production is a requirement, not a recommendation.

For organisations using Infor Birst alongside M3 for reporting and analytics, it is worth noting that the data models exposed through Birst are also affected by M3 upgrades in some cases. The Infor Birst analytics and business intelligence capabilities at Sama cover how Birst is maintained in a live M3 environment, which is directly relevant to upgrade planning.

Performance Considerations for Smart Office Customisations

A mashup that loads slowly or a panel that takes several seconds to refresh in response to a user selection will not be adopted, regardless of how useful the underlying layout is. Smart Office performance depends on several factors that are within the developer’s control.

Panel load time is primarily determined by the number of M3 API calls the mashup initiates on load. Every panel that displays live M3 data makes at least one API call to retrieve that data. A mashup with four panels that all load simultaneously makes four API calls in parallel. If those calls are synchronous and sequential rather than parallel, load time multiplies. Use Smart Office’s asynchronous panel loading where available and avoid making panels dependent on each other’s completion unless the data relationship genuinely requires it.

Data binding refresh behaviour deserves careful design. A binding that refreshes a panel every time a field value changes fires on every keystroke in a text input, generating an API call for each character entered. Debounce the binding so it fires only after the user has finished typing (typically 300 to 500 milliseconds of inactivity) rather than on every character.

XAML rendering performance is affected by the depth of the visual tree. Deeply nested XAML layouts with many levels of Grid and StackPanel containers are slower to render than flat layouts. Use XAML Perf Analysis tooling from the Visual Studio WPF diagnostic suite to identify rendering bottlenecks in complex custom panels.

Governance and Version Control for Smart Office Customisations

Smart Office customisations are code. They should be treated with the same version control discipline as any other code in your enterprise software portfolio.

Store all mashup XML files, XAML extension files, JScript event handlers, and .NET extension assemblies in a source control system – Git is the standard choice. Use branches for active development work and tags to mark the version deployed to production. This gives you a clear audit trail of what changed and when, the ability to roll back a specific customisation without affecting others, and a foundation for reviewing customisation changes before they are promoted to production.

Maintain separate Smart Office LCM environments aligned to your development, test, and production tenants. Promote customisations through environments in sequence – development to test, test to production – never directly from development to production. This mirrors the Infor CloudSuite LCM promotion process for application configuration and ensures that customisations are validated before users depend on them in production.

For organisations that are also managing configuration changes in Infor CloudSuite alongside Smart Office customisations, the Infor CloudSuite consulting and optimisation service at Sama covers how configuration governance is structured across the full Infor CloudSuite environment – the same principles apply to Smart Office.

Still navigating multiple M3 screens to complete a single workflow?

Sama builds Smart Office mashups and event-driven UI extensions that consolidate your M3 processes into purpose-built screens your team will actually use.

Where to Start: A Practical Prioritisation Framework

If your organisation is new to Smart Office customisation, the breadth of what is possible can make it difficult to know where to begin. A simple prioritisation approach avoids the trap of building impressive customisations that nobody uses.

Start by identifying the three to five workflows where your M3 users spend the most time navigating between programs. These are the highest-ROI candidates for mashup development because consolidating navigation saves measurable time every day for a significant number of users. Talk to the users themselves – not just the managers – to understand which screen transitions are most disruptive to their concentration and which data they most frequently need to cross-reference.

Build the first mashup for the single highest-impact workflow, deploy it to a pilot group of users, and measure adoption and feedback before building the next one. Mashup development that runs ahead of user feedback produces screens that are technically complete but miss what users actually needed. Each iteration of a mashup should be informed by structured feedback from the users who work with it daily.

Event handling and XAML extensions belong in the second and third phases, after mashup structure is established. Event handlers that add intelligence to existing mashups are more valuable than event handlers built before users have validated the underlying layout. XAML extensions that build on a proven mashup structure deliver better outcomes than XAML work done speculatively.

For organisations looking to discuss the specific M3 workflows in their environment and understand what Smart Office customisation could realistically achieve, the Sama Consulting contact and scoping process is the right starting point.

Conclusion

Smart Office customisation – through mashups, event handling, and XAML-based UI extensions – is the most direct path to improving how your M3 users experience and interact with the system. It does not require changes to M3 configuration or customisation of the application code. It works within the presentation layer, using the tools Infor designed for exactly this purpose, and it can be built, tested, and deployed in cycles that are independent of the M3 release schedule.

The three capabilities build on each other. Mashups define what data is presented together and how it is laid out. Event handlers make the layout respond intelligently to user actions and M3 program events. XAML extensions push the visual design to the level of precision and branding that standard Mashup Designer tooling cannot reach. Together, they give your development team the tools to build user interfaces that match the way your operations actually work, not the way a generic ERP screen was designed to look.

Getting the foundation right matters: clear use case definition before building, proper data binding design, upgrade-resilient API usage, version control for all customisation assets, and user feedback loops that ensure what is built actually gets used. These disciplines are not optional overhead. They are what separates a Smart Office customisation programme that delivers lasting value from one that creates technical debt.

If your organisation is planning Smart Office customisation work, dealing with an existing implementation that is not performing as expected, or evaluating whether Smart Office is the right approach for a specific M3 workflow challenge, Sama Consulting’s team has direct, hands-on M3 and Smart Office experience across manufacturing, aerospace, and industrial environments. Get in touch to talk through what you are trying to achieve.