BUSINESS ANALYSIS
Requirements Management, Problem Solving and Solution Definitions, Professional Facilitation, Impact Assessment, Business Case, Process Modelling, Functional Requirements Specification, Agile Analysis & Design
Requirements Management, Problem Solving and Solution Definitions, Professional Facilitation, Impact Assessment, Business Case, Process Modelling, Functional Requirements Specification, Agile Analysis & Design
MIS, Operational Reporting and Analytics using Microsoft's Power BI or your own BI software. Microsoft SQL Server T-SQL, Stored Procedures, Views, Agent Jobs, SSIS, SSRS, SSAS and MSQuery
ERP (Syspro and Sage) support and integration
PRINCE2 based project management
When bringing companies’ systems together, ‘duplications’ in master data are likely to occur.
Take for example the following three StockCodes and Descriptions:
StockCode | Description |
001 | LG TV 42 inch LCD |
ABC | TV LG (42 lcd) |
A01 | LG TV 32″ LED 32LJ500D |
For a human it is easy to see that the first two products refer to the same thing. A simple ‘exact’ comparison (WHERE InvMaster.Description = #InvMaster.Description) will fail, so one will have to use a method to show ‘most likely’ matches.
I’ve chosen a ‘word match and score’ technique because of the programming simplicity and (small) size of my data set (+-2000 lines).
(Machine learning algorithms are more suited for much larger data sets)
Using the example above, I create the following ‘base’ table:
StockCode | Word |
001 | LG |
001 | TV |
001 | 42 |
001 | INCH |
001 | LCD |
ABC | TV |
ABC | LG |
ABC | 42 |
ABC | LCD |
A01 | LG |
A01 | TV |
A01 | 32 |
A01 | 32LJ500D |
Note the standardisation, using a nested REPLACE containing
– UPPER
– elimination of sequential spaces (delimiter in this case)
– removing of ‘special’ characters and punctuation: ‘&’, ‘-‘, ‘.’, ‘”‘, ‘/’, ‘\’, ‘(‘ and ‘)’.
I break up each string into words by looping the following insert into my (say) ‘StockCodeWordList’ table:
SELECT StockCode,
SUBSTRING(Description, 1, CASE WHEN CHARINDEX(‘ ‘, Description) = 0 THEN 100 ELSE CHARINDEX(‘ ‘, Description) END) AS [Word]
The next step is to ‘score’ StockCodes based on the amount of ‘word matches’ with a specific (Source) Description.
I do this by looping the following statement:
UPDATE dbo.StockCodeWordList SET Score =0; — Reset for a new match exercise
DECLARE @DescString VARCHAR(100) = (SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(UPPER(Description),’-‘,”),’&’,”),’ ‘,’ ‘),’ ‘,’ ‘),’ ‘,’ ‘),’ ‘,’ ‘) FROM dbo.InvMaster WHERE StockCode = @SourceStockCode);
DECLARE @Counter INT = 0;
WHILE @Counter < 10 — Assuming there’s a maximum of 10 ‘words’ in a Description
BEGIN
UPDATE dbo.StockCodeWordList SET Score = Score+1
WHERE [Word] = (SELECT REPLACE(REPLACE(SUBSTRING(@DescString, 1, CASE WHEN CHARINDEX(‘ ‘, @DescString) = 0 THEN 100 ELSE CHARINDEX(‘ ‘, @DescString) END),'(‘,”),’)’,”))
SET @DescString = (SELECT CASE WHEN CHARINDEX(‘ ‘, @DescString) = 0 THEN NULL
ELSE LTRIM(SUBSTRING(@DescString, CHARINDEX(‘ ‘, @DescString)+1, 100)) END);
SET @Counter = @Counter+1
END
Using StockCode: 001 Description: ‘LG TV 42 inch LCD’ as Source, will produce the following result:
StockCode: ABC Description: TV LG (42 lcd) Score: 4
StockCode: A01 Description: LG TV 32″ LED 32LJ500D Score: 2
I was tasked to project manage the incorporation of a newly acquired company into our group.
Apart from arranging the infrastructure changes, systems setups and training required, I wrote the SQL (Jobs) to migrate data from Pastel Evolution to Syspro.
Herewith a link between some of the main Syspro tables and their counterparts in Pastel Evolution:
Syspro | Evolution |
ApBank | BankMain |
ApInvoice | InvNum, PostAP |
ApSupplier | Vendor |
ArCustomer | Client |
ArInvoice | InvNum, PostAR |
ArMasterSub | Client.MainAccLink |
ArTrnDetail | _btblInvoiceLines |
GenMaster | Accounts |
InvMaster | StkItem, _etblUnits |
InvWarehouse | WhseStk |
InvWhControl | WhseMst |
LotDetail | _etblLotTracking |
SalArea | Areas |
SalSalesperson | SalesRep |
TblCurrency | Currency |
A very handy Evolution table worth mentioning is TrCodes. Link this with PostAP and PostAR to provide you with the whole spectrum of AP and AR postings.
Presenting Syspro’s BOMs in a ‘flattened’ (or ‘exploded’) format in Excel or in SQL Server is very handy for doing/checking Costings or doing Advanced Trail Kits.
My initial attempt at flattening BOMs was to use the TSQL recursive loop method:
WITH FlatBom(ParentPart, Component, BomLevel, RequiredQty)
AS (
— Anchor
SELECT StockCode AS ‘ParentPart’,
StockCode AS ‘Component’,
1,
CAST(0 AS DECIMAL (12,6))
FROM dbo.InvMaster
WHERE StockCode = ‘YourParentStockCode’ — Insert your Parent item – or list of Parent items – in here
UNION ALL
— Recursive call
SELECT BOM.ParentPart AS ‘ParentPart’,
BOM.Component AS ‘Component’,
BomLevel + 1,
QtyPer
FROM FlatBom CTE
JOIN(SELECT
ParentPart AS ‘ParentPart’,
Component AS ‘Component’,
QtyPer
FROM dbo.BomStructure
WHERE Route = ‘1’ AND ParentPart IS NOT NULL AND ParentPart <> ‘ ‘ –Note Route
) AS BOM
ON CTE.Component = BOM.ParentPart
)
SELECT * FROM FlatBom
But I found this method to be extremely slow – especially when one has thousands of multilevel BOMs. A whole lot of articles on the Net confirms this – and discourages the use of recursive loops.
As simple (and much faster) alternative is to use a (temp) table with an insert for each of your BOM levels:
SELECT ParentPart AS [Parent], 1 AS [BomLevel], ParentPart, Component, QtyPer AS [RequiredQty]
INTO #FlatBom
FROM dbo.BomStructure
WHERE ParentPart = ‘YourParentStockCode’ — Insert your Parent item – or list of Parent items – in here
AND Route = ‘1’;
INSERT INTO #FlatBom(Parent, BomLevel, ParentPart, Component, RequiredQty)
SELECT t.Parent, 2, b.ParentPart, b.Component, b.QtyPer
FROM dbo.BomStructure b
INNER JOIN #FlatBom t ON t.Component = b.ParentPart
WHERE Route = ‘1’;
INSERT INTO #FlatBom(Parent, BomLevel, ParentPart, Component, RequiredQty)
SELECT t.Parent, 3, b.ParentPart, b.Component, b.QtyPer
FROM dbo.BomStructure b
INNER JOIN #FlatBom t ON t.Component = b.ParentPart AND t.BomLevel = 2
WHERE Route = ‘1’
AND t.BomLevel = 2;
INSERT INTO #FlatBom(Parent, BomLevel, ParentPart, Component, RequiredQty)
SELECT t.Parent, 4, b.ParentPart, b.Component, b.QtyPer
FROM dbo.BomStructure b
INNER JOIN #FlatBom t ON t.Component = b.ParentPart AND t.BomLevel = 3
WHERE Route = ‘1’
AND t.BomLevel = 3;
… — Repeat, for your MAX BomLevel times
SELECT * FROM #FlatBom
I would suggest including the ScrapPercentage and other attributes in your flattening script to make (e.g.) Costings and Trail Kits more accurate.
Generally, I found that it is difficult to answer the question: “How far are we with the stock take?”
The most commonly used, quick-and-dirty measures are to
But none of these measures provide an indication of how much of the physical warehouse (space) has been covered.
The following method might be helpful, assuming you make use of Syspro’s MultiBin functionality:
For the purpose of explanation, let’s assume you have (as shown in Figure 1 below):
So you have 12 x Bins in total, numbered (say) <Rack number><Level number><Depth>: 11A, 12A, 13A, 11B, 12B, 13B and 21A, 22A, 23A, 21B, 22B, 23B
Import data from Syspro into Excel using the following Query:
SELECT Bin, MAX(NumTimesCaptured) AS [Count] FROM dbo.InvStockTake
(one can add filters for specific Warehouses, etc.)
Use Excel’s VLOOKUP function – and Conditional Formatting – to set up the simple visualization below (Figure 2, query data in column A and B).
The formula in (say) Cell F3 – which can be copied to the rest of the ‘Bin’ cells (columns F to H):
=IF(ISNA(VLOOKUP($D3&F$2&$E3,$A:$C,2,FALSE)),””,IF(VLOOKUP($D3&F$2&$E3,$A:$C,2,FALSE)=0,$D3&F$2&$E3,VLOOKUP($D3&F$2&$E3,$A:$C,2,FALSE)))
The visualization tells us the following:
Hope it helps!