Overview

This documentation describes the migration process from the legacy salesperson management to the new system based on Salesperson Set ID. The migration is necessary to transition from a redundant data model to a normalized one, with significant benefits in terms of disk space and performance.

Migration Activation

The migration occurs through activating the feature flag in the Eos Admin Library (EAL). Once the feature is activated, the system automatically switches to using the new data model based on Salesperson Set ID.

Important:

  • A migration to the new salesperson engine is considered complete only when the entire migration activity activated with the EAL feature flag is completed without errors.
  • The migration is performed per company: each company in the environment must complete its own migration independently.

Differences Between Legacy System and New System

Legacy System

In the legacy system, salesperson management (roles and salesperson) was replicated for each individual entity managed by the Commissions app (CMS):

┌─────────────────────────────────────────────────────────────────────┐
│                        LEGACY SYSTEM                                │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Customer "CUST001"                                                 │
│    └── EOS Add. Salesperson/Purchaser                               │
│          ├── Role: AGENT1, Salesperson: SP001                       │
│          └── Role: AGENT2, Salesperson: SP002                       │
│                                                                     │
│  Sales Header "INV-0001"                                            │
│    └── EOS Add. Salesperson/Purchaser                               │
│          ├── Role: AGENT1, Salesperson: SP001  ◄── DUPLICATE        │
│          └── Role: AGENT2, Salesperson: SP002  ◄── DUPLICATE        │
│                                                                     │
│  Sales Line "INV-0001, Line 10000"                                  │
│    └── EOS Add. Salesperson/Purchaser                               │
│          ├── Role: AGENT1, Salesperson: SP001  ◄── DUPLICATE        │
│          └── Role: AGENT2, Salesperson: SP002  ◄── DUPLICATE        │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Legacy system issues:

  • Data redundancy: the same set of roles/salespersons is stored N times
  • High disk space: exponential storage growth
  • Degraded performance: slow queries on tables with millions of records
  • Complex maintenance: updates requiring changes across multiple records

New System (Dimension-like)

The new system adopts an approach similar to Business Central’s dimension management. Each unique combination of roles and salespersons is assigned a unique integer ID (Salesperson Set ID). Entities managed by CMS store only this ID.

┌────────────────────────────────────────────────────────────────────┐
│                        NEW SYSTEM                                  │
├────────────────────────────────────────────────────────────────────┤
│                                                                    │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │  EOS010 Role-Salesperson Sets (normalized table)             │  │
│  │  ┌────┬────────────┬─────────────────┐                       │  │
│  │  │ ID │ Salesp.Role│ Salesperson Code│                       │  │
│  │  ├────┼────────────┼─────────────────┤                       │  │
│  │  │ 1  │ AGENT1     │ SP001           │                       │  │
│  │  │ 2  │ AGENT2     │ SP002           │                       │  │
│  │  │... │ ...        │ ...             │                       │  │
│  │  └────┴────────────┴─────────────────┘                       │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                    │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │  EOS010 Salesperson Set Entry (unique combinations)          │  │
│  │  ┌──────────────────┬──────────────────────────┐             │  │
│  │  │ Salesperson Set  │ Role-Salesperson Set ID  │             │  │
│  │  │       ID         │  (references table above)│             │  │
│  │  ├──────────────────┼──────────────────────────┤             │  │
│  │  │ 100              │ 1 (AGENT1/SP001)         │             │  │
│  │  │ 100              │ 2 (AGENT2/SP002)         │             │  │
│  │  │ 101              │ 1 (AGENT1/SP001)         │             │  │
│  │  │ 101              │ 5 (AGENT3/SP003)         │             │  │
│  │  └──────────────────┴──────────────────────────┘             │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                    │
│  Customer "CUST001"                                                │
│    └── EOS Salesperson Set ID = 100  ◄── JUST ONE INTEGER!         │
│                                                                    │
│  Sales Header "INV-0001"                                           │
│    └── EOS Salesperson Set ID = 100  ◄── SAME ID = SAME SET        │
│                                                                    │
│  Sales Line "INV-0001, Line 10000"                                 │
│    └── EOS Salesperson Set ID = 100  ◄── NO REDUNDANCY             │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

Benefits of the new system:

  • Drastic reduction in disk space: from N records per entity to 1 integer field
  • Faster processing speed: queries on integer indexes much more performant
  • Responsive user interface: instant lookups and filters
  • Maintainability: normalized structure and simplified maintenance

Objects involved in migration

Tables Involved in Migration

The migration affects the following tables (identified by their respective Database IDs):

Database ID Table Type Notes
18 Customer Master Includes Ship-to Address (222)
222 Ship-to Address Master Processed together with Customer
36 Sales Header Document Includes Sales Line (37)
37 Sales Line Document Processed together with Header
112 Sales Invoice Header Posted Includes Sales Invoice Line (113)
113 Sales Invoice Line Posted Processed together with Header
114 Sales Cr.Memo Header Posted Includes Sales Cr.Memo Line (115)
115 Sales Cr.Memo Line Posted Processed together with Header
5107 Sales Header Archive Archive Includes Sales Line Archive (5108)
5108 Sales Line Archive Archive Processed together with Header

Upgrade Status Field

Each involved table contains a field “EOS Salesperson Upgrade Status” of enum type EOS010 Salesp. Upgrade Status:

Value Meaning
To Calculate Record not yet processed (default)
Valued Record processed and valued with Salesperson Set ID

Migration Codeunits

Codeunit “EOS010 SalesP Upgrade” (ID: 18008321)

This codeunit executes the complete and synchronous migration of all data. It is designed to be executed once in a controlled environment.

Main Characteristics

Characteristic Description
Execution Synchronous, blocking
Scope Per company (each company is migrated separately)
Duration Can take hours depending on company data volume
Transaction Single transaction with automatic rollback in case of error
Log Generates detailed log saved in CommissionsSetup."SalesPDataUpdate Log"
Typical Use Initial migration or environments with planned downtime

Execution Flow

  1. Checking Environment

    • CheckInterferences(): Verifies interferences with other apps
    • CheckMissingRolesAndSalesPersons(): Checks for missing roles/salespersons
    • CheckUnknowTable(): Verifies unknown tables
  2. Data Upgrade

    • TestModifyPermissions(): Verifies modify permissions
    • CreateAllRoleSalespersons(): Creates Role-Salesperson combinations
    • UpdateAddSalesPersonPurchaser(): Migrates active document data
    • UpdateAddSalesPersonPurchaserArchive(): Migrates archived data
    • UpdateSalesNetworks(): Updates sales networks
  3. Data Verification

    • CheckDataUpgrade(): Verifies migrated data integrity
    • CheckDataUpgradeArchive(): Verifies archived data

When to Use

  • ✅ Initial migration in test environment
  • ✅ Production environment with downtime possibility
  • ✅ Small/medium-sized databases
  • ⚠️ Note: The codeunit is executed automatically when activating the EAL feature flag, it cannot be executed manually via code
  • DO NOT activate the feature flag in production environment without downtime
  • DO NOT activate the feature flag on large databases without planning

Codeunit “EOS010 SalesP JobQueue Upg” (ID: 18008325)

This codeunit executes incremental and asynchronous migration via Job Queue. It is designed for production environments where downtime is not possible.

Main Characteristics

Characteristic Description
Execution Asynchronous via Job Queue
Scope Per company (each Job Queue works on a specific company)
Single execution duration Maximum 10 minutes per execution
Behavior Resumes from where it left off
Commit Progressive commits for each document/entity
Configuration Recommended to configure via page “EOS010 Salesp Upgrade Status” using action Setup Job Queue
Typical Use Gradual migration in production

Operation and Purpose

The activity executed via job queue allows to calculate the “Salesperson Set ID” value on all supported tables in advance, thus speeding up the final upgrade when the feature flag is activated.

Important: The Job Queue operates on the current company data. If you have multiple companies in the environment, you need to configure a separate Job Queue Entry for each company.

Recommended Scheduling:

  • The job queue should be scheduled in a time window with few or no users, for example during night hours
  • To avoid exceeding the time window, it is designed to execute for a maximum of 10 minutes at a time
  • Automatically stops after 10 minutes and resumes at the next scheduled execution

Change Management: Any record that was already processed by the job queue, if modified by a user, will be automatically recalculated at the next Job Queue execution.

Important Note: The update activity via job queue is optional and serves exclusively to speed up the final migration. The actual migration is completed only with the activation of the EAL feature flag.

Codeunit Properties

codeunit 18008325 "EOS010 SalesP JobQueue Upg"
{
    SingleInstance = true;           // Single instance for state tracking
    TableNo = "Job Queue Entry";     // Executable from Job Queue
    InherentPermissions = X;
    InherentEntitlements = X;
    ...
}

Job Queue Entry Configuration

The Parameter String of the Job Queue Entry defines which tables to process:

18|36|112|114|5107
Value Processed Table
18 Customer + Ship-to Address
36 Sales Header + Sales Line
112 Sales Invoice Header + Lines
114 Sales Cr.Memo Header + Lines
5107 Sales Header Archive + Lines

Note: Accepted separators are | (pipe) and , (comma).

Execution Flow

┌──────────────────────────────────────────────────────────────────┐
│                    Job Queue Entry Start                         │
└──────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌──────────────────────────────────────────────────────────────────┐
│  Check: CommissionsSetup."Enable SalesP. JobQueue Upg." = TRUE   │
└──────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌──────────────────────────────────────────────────────────────────┐
│  Parse Parameter String → Table ID List                          │
└──────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌──────────────────────────────────────────────────────────────────┐
│  CreateAllRoleSalespersons() + Commit                            │
└──────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌──────────────────────────────────────────────────────────────────┐
│  For each TableID in List:                                       │
│    ├── Check: (CurrentDateTime - StartDateTime) > 10 min?        │
│    │     └── YES → Exit                                          │
│    └── NO → Process Table                                        │
│              ├── Filter: "Upgrade Status" = "To Calculate"       │
│              ├── Get Salespersons → Calculate Set ID             │
│              ├── Update Record with Set ID                       │
│              ├── Set Status = "Valued"                           │
│              └── Commit                                          │
└──────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌──────────────────────────────────────────────────────────────────┐
│  Next Job Queue Execution → Resumes from unprocessed records     │
└──────────────────────────────────────────────────────────────────┘

Execution Control

// Checks if Job Queue Upgrade is running
procedure GetIsRunningJobQueueUpgrade(): Boolean

Scenario 1: Test Environment or Small Database

Prerequisite: Activate the feature flag in Eos Admin Library (EAL).

  1. Open the Salesperson Upgrade Status (CMS) page
  2. Verify current status with Calculate Status
  3. Enable the feature flag in Eos Admin Library (EAL) - this will automatically start the execution of codeunit EOS010 SalesP Upgrade
  4. Verify completion via “Completed” status
  5. Check log in case of errors

Prerequisite: Activate the feature flag in Eos Admin Library (EAL).

Phase 1: Preparation via Job Queue (before final upgrade)

  1. Open the EOS010 Salesp Upgrade Status page
  2. Enable the Enable Salesperson Job Queue Upgrade flag
  3. Click the Setup Job Queue action - this action automatically creates the Job Queue Entry with all parameters pre-configured
  4. Optionally, customize the newly created Job Queue Entry:
    • Set night-time window or low-user time
    • Set appropriate recurrence (e.g., every hour during the night)
    • Maximum execution duration is automatically limited to 10 minutes
  5. Set to Ready status the Job Queue Entry
  6. Monitor progress via Calculate Status in the upgrade page
  7. The Job Queue calculates “Salesperson Set ID” in advance on all supported tables

Phase 2: Final Activation

Once the Job Queue has processed most records:

  1. Verify that completion percentage is high (e.g., > 95%)
  2. The final upgrade will be much faster since most data is already valued
  3. Disable the Job Queue if no longer needed

Benefits of this approach:

  • ✅ Very fast final upgrade
  • ✅ No impact on users during preparation
  • ✅ User changes automatically managed (recalculation at next execution)
  • ✅ Safety: short processing (max 10 minutes) that doesn’t block the system

Scenario 3: Optimization with Multiple Job Queues (Advanced)

Table filters that can be applied to the job queue can be used to optimize the update based on user activity:

Low User Activity Tables (posted or archived documents):

  • Can be processed during user activity hours
  • Tables: 112 (Sales Invoice), 114 (Sales Cr.Memo), 5107 (Sales Archive)
  • Low impact on performance perceived by users

High User Activity Tables (active documents):

  • Must be processed during low-traffic time slots (e.g., night-time)
  • Tables: 36 (Sales Header), 37 (Sales Line)
  • Require time windows with few or no active users

Multiple Job Queue Configuration

It is possible to have multiple update job queues running concurrently as long as they work on different tables.

Configuration example:

Job Queue Entry #1 - Low activity tables (daytime hours):

Parameter String: 112|114|5107
Schedule: 08:00 - 18:00
Recurrence: every 30 minutes

Job Queue Entry #2 - High activity tables (night-time hours):

Parameter String: 18|36
Schedule: 22:00 - 06:00
Recurrence: every 15 minutes

Benefits:

  • ✅ Maximizes resource utilization across 24 hours
  • ✅ Minimizes impact on active users
  • ✅ Accelerates overall preparation
  • ✅ Scheduling flexibility

Cautions:

  • Ensure tables don’t overlap between different Job Queues
  • Monitor overall database load
  • Customer tables (18) may require specific considerations based on usage

Page “EOS010 Salesp Upgrade Status” (ID: 18008330)

Monitoring and management page for the upgrade process.

Layout

Setup Section

Field Description
Enable Salesperson Job Queue Upgrade Enables/disables Job Queue execution
SalesPerson DataUpdate Date Date/time of last execution
SalesPerson DataUpdate User User who executed the last upgrade
SalesPerson DataUpdate Status Status: In Progress, Completed, Error

Tip: Click on “SalesPerson DataUpdate Status” to download the detailed log.

Tables Section (Repeater)

Column Description
Table Table name
Total Records Total records in table
Processed Records Records with Status = “Valued”
Progress % Completion percentage

Actions

Calculate Status

Calculates upgrade status for all tables. This operation can take significant time on large databases.

Setup Job Queue

Automatically creates a new Job Queue Entry (if it doesn’t already exist) configured to:

  • Execute codeunit EOS010 SalesP JobQueue Upg
  • Parameter String: 18|36|112|114|5107 (all tables)
  • Recurrence: every minute, every day
  • Maximum 3 retry attempts in case of error

Note: This action automatically creates and configures the Job Queue Entry with all the correct parameters, significantly simplifying the setup process.

Troubleshooting

Error “Enable SalesP. JobQueue Upg. must have a value”

Cause: The enable flag is not active.

Solution: Enable “Enable Salesperson Job Queue Upgrade” in the status page.

Degraded Performance During Execution

Cause: Migration competes with user operations.

Solution:

  1. Limit Job Queue time window to night hours
  2. Reduce number of tables processed per execution
  3. Increase interval between executions

Technical References

New Structure Tables

Table ID Description
EOS010 Role-Salesperson Sets 18008320 Unique Role-Salesperson combinations
EOS010 Salesperson Set Entry - Entry for each Salesperson Set ID
EOS010 Salesp. Set Tree Node - Tree structure for fast lookup

Enum

Enum ID Values
EOS010 Salesp. Upgrade Status 18008320 To Calculate, Valued
Codeunit ID Usage
EOS010 Salespersons Mngt 18008320 Salesperson Set management
EOS010 DataUpg ManualBinding - Event binding during migration

Notes for Implementers

  1. Backup: Always perform a complete backup before starting the migration.

  2. Test: Always test the migration in a copy environment before production.

  3. Monitoring: During Job Queue migration, regularly monitor:

    • Disk space
    • Database performance
    • Job Queue Entry status
  4. Rollback: In case of serious problems, it is possible to:

    • Restore the backup
    • Reset all “EOS Salesperson Upgrade Status” fields to “To Calculate”
    • Empty the new structure tables
  5. Post-Migration: After completion:

    • Disable the “Enable SalesP. JobQueue Upg.” flag
    • Remove the Job Queue Entry
    • Verify application performance

EOS Labs -