SYSPRO Integration Overview
Overview
The EFT Remittance Dashboard is deeply integrated with SYSPRO 8 through the MepDash module framework, providing seamless access to SYSPRO's Accounts Payable data and business logic. This integration enables the dashboard to operate as a native SYSPRO plugin while maintaining independence in its implementation approach. The architecture leverages SYSPRO's session management, security model, and database infrastructure to ensure consistent behavior and data integrity.
Key Concepts
- MepDash Module Integration: Plugin framework for SYSPRO extensions
- Session Management: SYSPRO operator and company context
- Database Connectivity: Direct access to SYSPRO database
- Security Integration: SYSPRO's role-based access control
- Business Object Compatibility: Interaction with SYSPRO business logic
Implementation Details
MepDash Module Architecture
The dashboard integrates through the MepDash module framework:
// MepApps.Dash.Ap.Rpt.EftRemittance.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net471</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MepApps.Erp.Syspro.Win.Module.MepDash" Version="0.3.6" />
</ItemGroup>
</Project>
The MepDash module provides critical integration points:
// Integration through MepDash interfaces
using MepApps.Erp.Syspro.Win.Module.MepDash.SysproContainers.Interfaces;
using MepApps.Erp.Syspro.Win.HostUI.SharedKernel;
using MepApps.Erp.Syspro.Win.Module.Utilities.SharedKernel;
public partial class MainView : UserControl
{
private readonly ISharedShellInterface _sharedShellInterface;
private readonly IContainerEvents _events;
private readonly IContainerNavigation _navigation;
private readonly IMepPluginServiceHandler _mepPluginServiceHandler;
public MainView(
ISharedShellInterface sharedShellInterface,
IContainerEvents events,
IContainerNavigation navigation,
IMepPluginServiceHandler mepPluginServiceHandler)
{
_sharedShellInterface = sharedShellInterface; // SYSPRO session access
_events = events; // Container event system
_navigation = navigation; // Navigation framework
_mepPluginServiceHandler = mepPluginServiceHandler; // Service registration
InitializeComponent();
InitializeSysproIntegration();
}
}
SYSPRO Session Integration
Access to SYSPRO session information is fundamental:
// Accessing SYSPRO session context
public class SysproSessionService
{
private readonly ISharedShellInterface _sharedShellInterface;
public SysproSessionInfo GetCurrentSession()
{
var session = _sharedShellInterface.CurrentSession;
return new SysproSessionInfo
{
// Company Information
Company = session.SysproCompany,
CompanyName = session.SysproCompanyName,
CompanyDatabase = session.CompanyDatabaseName,
// Operator Information
Operator = session.SysproOperator,
OperatorName = session.SysproOperatorName,
OperatorGroup = session.SysproOperatorGroup,
OperatorLanguage = session.SysproOperatorLanguage,
// System Information
SysproVersion = session.SysproVersion,
SysproPath = session.SysproPath,
ServerName = session.ServerName,
// Connection Settings
ConnectionString = session.GetConnectionString(),
SsrsReportAddress = session.AppConnectionSettings.SsrsReportAddress,
SsrsReportUserName = session.AppConnectionSettings.SsrsReportUserName
};
}
public bool HasPermission(string permission)
{
return _sharedShellInterface.CurrentSession.HasPermission(permission);
}
}
Database Connection Management
SYSPRO database access through Entity Framework:
// MepApps.Dash.Ap.Rpt.EftRemittance/Db/PluginSysproDataContext.cs
public class PluginSysproDataContext : SysproSessionEmptyDataContext
{
public PluginSysproDataContext(ISysproSession sysproSession)
: base(sysproSession?.GetConnectionString() ?? "")
{
// Inherits SYSPRO connection string
Database.SetInitializer<PluginSysproDataContext>(null);
// Configure for SYSPRO database
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
Configuration.AutoDetectChangesEnabled = false;
// Set command timeout for long-running queries
Database.CommandTimeout = 300; // 5 minutes
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Map to SYSPRO schema
modelBuilder.HasDefaultSchema("dbo");
// Configure SYSPRO-specific conventions
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
}
Examples
Example 1: SYSPRO Menu Integration
The dashboard integrates with SYSPRO's menu system:
<!-- SYSPRO Menu Configuration (CustomForms.xml) -->
<CustomForm>
<FormType>Plugin</FormType>
<FormId>IMPEFT01</FormId>
<Description>EFT Remittance Processing</Description>
<Program>MepApps.Dash.Ap.Rpt.EftRemittance</Program>
<MainView>MainView</MainView>
<MenuPath>Accounts Payable,Reports,EFT Remittance</MenuPath>
<SecurityKey>APRREP</SecurityKey>
<Icon>Report</Icon>
<Parameters>
<Parameter Name="AutoStart" Value="true"/>
<Parameter Name="DefaultView" Value="RunReports"/>
</Parameters>
</CustomForm>
Example 2: SYSPRO Security Integration
public class SysproSecurityService
{
private readonly ISharedShellInterface _sharedShellInterface;
private readonly ILogger<SysproSecurityService> _logger;
public bool ValidateAccess(string module, string function)
{
try
{
var operator_ = _sharedShellInterface.CurrentSession.SysproOperator;
// Check operator group permissions
var hasGroupAccess = CheckGroupAccess(
_sharedShellInterface.CurrentSession.SysproOperatorGroup,
module,
function);
// Check specific operator overrides
var hasOperatorAccess = CheckOperatorAccess(operator_, module, function);
// Check company-specific restrictions
var hasCompanyAccess = CheckCompanyAccess(
_sharedShellInterface.CurrentSession.SysproCompany,
module,
function);
var hasAccess = hasGroupAccess && hasOperatorAccess && hasCompanyAccess;
if (!hasAccess)
{
_logger.LogWarning("Access denied for {Operator} to {Module}/{Function}",
operator_, module, function);
}
return hasAccess;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error validating SYSPRO security");
return false; // Fail secure
}
}
private bool CheckGroupAccess(string group, string module, string function)
{
var sql = @"
SELECT COUNT(*)
FROM OperatorGroupAccess
WHERE OperatorGroup = @Group
AND Module = @Module
AND Function = @Function
AND AllowAccess = 'Y'";
using (var connection = new SqlConnection(
_sharedShellInterface.CurrentSession.GetConnectionString()))
{
var count = connection.QuerySingle<int>(sql, new { group, module, function });
return count > 0;
}
}
}
Example 3: SYSPRO Version Compatibility
public class SysproVersionChecker
{
private readonly ISharedShellInterface _sharedShellInterface;
private readonly ILogger<SysproVersionChecker> _logger;
public bool IsCompatible()
{
var version = _sharedShellInterface.CurrentSession.SysproVersion;
// Parse version string (e.g., "8.0.0.123")
if (!Version.TryParse(version, out var sysproVersion))
{
_logger.LogError("Invalid SYSPRO version format: {Version}", version);
return false;
}
// Minimum supported version
var minimumVersion = new Version(8, 0, 0, 0);
if (sysproVersion < minimumVersion)
{
_logger.LogError("SYSPRO version {Version} is below minimum {Minimum}",
sysproVersion, minimumVersion);
return false;
}
// Check for version-specific features
if (sysproVersion.Major == 8)
{
EnableVersion8Features();
}
_logger.LogInformation("Running on SYSPRO version {Version}", sysproVersion);
return true;
}
private void EnableVersion8Features()
{
// Enable features specific to SYSPRO 8
Features.EnableEnhancedReporting = true;
Features.EnableBulkProcessing = true;
Features.EnableAdvancedSecurity = true;
}
}
SYSPRO Module Dependencies
The dashboard interacts with several SYSPRO modules:
Accounts Payable (AP) Module
public class ApModuleIntegration
{
// Access AP master tables
public async Task<ApSupplier> GetSupplier(string supplierCode)
{
var sql = @"
SELECT
Supplier,
SupplierName,
SupplierClass,
Currency,
OnHold,
DateLastPurchase,
Email
FROM ApSupplier
WHERE Supplier = @SupplierCode";
return await _context.Database.Connection
.QuerySingleOrDefaultAsync<ApSupplier>(sql, new { supplierCode });
}
// Access AP transaction tables
public async Task<IEnumerable<ApTransaction>> GetTransactions(string supplier)
{
var sql = @"
SELECT * FROM ApTrans
WHERE Supplier = @Supplier
AND TransactionType IN ('I', 'C', 'D')
ORDER BY TransactionDate DESC";
return await _context.Database.Connection
.QueryAsync<ApTransaction>(sql, new { supplier });
}
}
General Ledger (GL) Module
public class GlModuleIntegration
{
// Validate GL codes
public async Task<bool> ValidateGlCode(string glCode)
{
var sql = "SELECT COUNT(*) FROM GenMaster WHERE GlCode = @GlCode";
var count = await _context.Database.Connection
.QuerySingleAsync<int>(sql, new { glCode });
return count > 0;
}
}
SYSPRO-Specific Constraints
Database Constraints
- Table Naming: Must follow SYSPRO conventions
- Field Types: Use SYSPRO-compatible data types
- Key Length: Maximum 15 characters for key fields
- Decimal Precision: 2 decimal places for amounts
- Date Format: SYSPRO uses CCYYMMDD format internally
Business Logic Constraints
- Transaction Integrity: Must maintain SYSPRO audit trails
- Period Control: Respect SYSPRO period end dates
- Currency Handling: Use SYSPRO currency tables
- Tax Calculations: Align with SYSPRO tax engine
- Number Generation: Use SYSPRO numbering sequences
Container Event Handling
Integration with SYSPRO's container events:
public class ContainerEventHandler
{
private readonly IContainerEvents _containerEvents;
public void Initialize()
{
_containerEvents.OnRefresh += HandleRefresh;
_containerEvents.OnSave += HandleSave;
_containerEvents.OnClose += HandleClose;
_containerEvents.OnPrint += HandlePrint;
}
private void HandleRefresh(object sender, EventArgs e)
{
// Reload data when SYSPRO requests refresh
ReloadCurrentData();
}
private void HandleSave(object sender, EventArgs e)
{
// Save changes when SYSPRO triggers save
SavePendingChanges();
}
}
Performance Considerations
public class SysproPerformanceOptimizer
{
// Use SYSPRO's connection pooling
public void ConfigureConnectionPooling()
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(
_sharedShellInterface.CurrentSession.GetConnectionString());
builder.Pooling = true;
builder.MinPoolSize = 5;
builder.MaxPoolSize = 100;
builder.ConnectTimeout = 30;
builder.LoadBalanceTimeout = 30;
}
// Respect SYSPRO's query governor
public async Task<T> ExecuteWithGovernor<T>(Func<Task<T>> operation)
{
var queryGovernor = GetQueryGovernorLimit();
using (var cts = new CancellationTokenSource(queryGovernor))
{
return await operation().ConfigureAwait(false);
}
}
}
Best Practices
- Always use SYSPRO session context for database connections
- Respect SYSPRO security model in all operations
- Maintain SYSPRO audit requirements for all changes
- Use SYSPRO business objects when available
- Follow SYSPRO naming conventions for custom objects
- Test with multiple SYSPRO versions for compatibility
- Handle SYSPRO-specific exceptions appropriately
- Document SYSPRO dependencies clearly
Common Pitfalls
- Not handling SYSPRO session timeouts
- Bypassing SYSPRO security checks
- Ignoring SYSPRO transaction boundaries
- Using incompatible data types
- Not respecting SYSPRO period controls
- Missing SYSPRO audit trail updates
Related Documentation
Summary
The SYSPRO integration layer provides comprehensive access to SYSPRO's functionality while maintaining the independence and flexibility needed for custom business logic. Through careful use of the MepDash module framework, session management, and database integration, the EFT Remittance Dashboard operates as a seamless extension of SYSPRO while providing enhanced functionality specific to remittance processing needs. The integration respects all SYSPRO constraints and security requirements while leveraging SYSPRO's robust infrastructure for enterprise-grade reliability.