Simple Audit for Microsoft Dynamics GP: Create Triggers for Audit of Customer Items

Microsoft Dynamics GPThis post as been added as part of the series on creating a simple audit for Microsoft Dynamics GP, but wsn;t part of the original series.

I recently used the simple audit to add an audit to the Sales Customer Item Cross Reference (SOP60300) table to allow a client to keep an audit of changes to customer items. They wanted to keep track of all changes so this means three triggers are required on:

  1. INSERT
  2. UPDATE
  3. DELETE

These triggers will record all customer items which are added, amended or removed. The Customer Items window contains a few fields, but the only ones with sensitive dta which needs to be audited are:

  1. Customer Item Number
  2. Customer Item Description

The first trigger creates the trigger which runs when data is inserted:

/*
Created by Ian Grieve of azurecurve | Ramblings of an IT Professional (http://www.azurecurve.co.uk) This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 Int). */
CREATE TRIGGER utr_AZRCRV_SOP60300_AuditInsert ON SOP60300 AFTER INSERT AS INSERT INTO ut_AZRCRV_Audit SELECT 'Sales Customer Item Cross Reference' ,CAST(RTRIM(I.ITEMNMBR) AS VARCHAR(30)) + '|' + CAST(RTRIM(I.CUSTNMBR) AS VARCHAR(15)) ,'Insert' ,SYSTEM_USER ,GETDATE() ,'' ,'Customer Item Number = ' + CAST(RTRIM(i.CUSTITEMNMBR) AS VARCHAR(30)) + ' | ' + 'Customer Item Description = ' + CAST(RTRIM(i.CUSTITEMDESC) AS VARCHAR(30)) FROM inserted AS i GO

Continue reading “Simple Audit for Microsoft Dynamics GP: Create Triggers for Audit of Customer Items”

SQL Stored Procedure to Get the Next Microsoft Dynamics GP Sales Document Number

Microsoft Dynamics GPThis stored procedure can be executed to generate the next sequential sales document number; this script was created to get the next sales invoice number for a transaction to be inserted into Microsoft Dynamics GP through eConnect. I write stored procedures as a wrapper around the eConnect stored procedure as we are often working with the clients IT department or a third party and this abstracts the call way from the other application so any changes by Microsoft can be managed within the wrapper stored procedure rather than the application.

This particular example is for generating a sales order number, but can be used to generate a document number for any of the sales document transactions. To do this, change the first highlighted parameter to one of the following numbers:

  1. Quote
  2. Order
  3. Invoice
  4. Return
  5. Back Order
  6. Fulfillment Order

The second parameter should be set to the Doc ID which will vary depending on how you have configured Sales Order Processing.

The stored procedure to get the next sales document number is:

-- drop stored proc if it exists[/sqlgrey]
IF OBJECT_ID (N'usp_AZRCRV_GetNextSOPDocumentNumber', N'P') IS NOT NULL
	DROP PROCEDURE usp_AZRCRV_GetNextSOPDocumentNumber
GO
-- create stored proc
CREATE PROCEDURE usp_AZRCRV_GetNextSOPDocumentNumber AS
/*
Created by Ian Grieve of azurecurve | Ramblings of an IT Professional (http://www.azurecurve.co.uk) This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 Int). */
BEGIN DECLARE @return_value INT DECLARE @I_tSOPType TINYINT = 2 DECLARE @I_cDOCID CHAR(15) = 'STDORD' DECLARE @I_tInc_Dec TINYINT = 1 DECLARE @O_vSopNumber AS VARCHAR(21) DECLARE @O_iErrorState INT EXEC @return_value = taGetSopNumber @I_tSOPType = @I_tSOPType, @I_cDOCID = @I_cDOCID, @I_tInc_Dec = @I_tInc_Dec, @O_vSopNumber = @O_vSopNumber OUTPUT, @O_iErrorState = @O_iErrorState OUTPUT SELECT @O_vSopNumber END GO -- grant execute permission on stored proc to DYNGRP GRANT EXECUTE ON usp_AZRCRV_GetNextSOPDocumentNumber TO DYNGRP GO

You can execute the stored procedure using the below:

-- execute stored proc
EXEC usp_AZRCRV_GetNextSOPDocumentNumber
GO

I’ve written similar stored procedures in the past in other next numbers for other parts of Dynamics GP:

I have also posted a custom solution which can be used to generate a next number when there isn’t a method available in eConnect.

SQL View to Return Sales Invoice Lines

Microsoft Dynamics GPI’ve been organising a demo of software which can be used to produce documentation using data from Microsoft Dynamics GP and integrate it with data from other systems or network shares. I thought about a few ways of getting the Dynamics GP data and decided that a custom SQL view returning only the required information was the best way to go.

This view returns sales invoice lines and related fields such as the sales user defined.

-- drop view if it exists
IF OBJECT_ID(N'uv_AZRCRV_SalesInvoiceLines', N'V') IS NOT NULL
	DROP VIEW uv_AZRCRV_SalesInvoiceLines
GO
-- create view
CREATE VIEW [dbo].[uv_AZRCRV_SalesInvoiceLines] AS
/*
Created by Ian Grieve of azurecurve | Ramblings of an IT Professional (http://www.azurecurve.co.uk) This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 Int). */
SELECT RTRIM(['Sales Transaction Work'].SOPNUMBE) AS 'Invoice Number' ,['Sales Transaction Amounts Work'].LNITMSEQ AS 'Line Number' ,RTRIM(ISNULL(['Sales Customer Item Cross Reference'].CUSTITEMNMBR, ['Sales Transaction Amounts Work'].ITEMNMBR)) AS 'Item Number' ,RTRIM(ISNULL(['Sales Customer Item Cross Reference'].CUSTITEMDESC, ['Sales Transaction Amounts Work'].ITEMDESC)) AS 'Item Description' ,RTRIM(['Item Master'].TCC) AS 'Tax Commodity Code' ,'UK' AS 'Country of Origin' ,RTRIM(['Sales Transaction Amounts Work'].UOFM) AS 'Unit of Measure' ,['Sales Transaction Amounts Work'].QUANTITY AS 'Quantity' ,CONVERT(DECIMAL(10,2),['Sales Transaction Amounts Work'].ORUNTPRC) AS 'Originating Unit Price' ,CONVERT(DECIMAL(10,2),['Sales Transaction Amounts Work'].OREXTCST) AS 'Originating Extended Price' ,RTRIM(['Sales Transaction Amounts Work'].LOCNCODE) AS 'Site' FROM SOP10100 AS ['Sales Transaction Work'] -- Sales Transaction Work (SOP10100) INNER JOIN SOP10200 AS ['Sales Transaction Amounts Work'] -- Sales Transaction Amounts Work (SOP10200) ON ['Sales Transaction Amounts Work'].SOPTYPE = ['Sales Transaction Work'].SOPTYPE AND ['Sales Transaction Amounts Work'].SOPNUMBE = ['Sales Transaction Work'].SOPNUMBE INNER JOIN IV00101 AS ['Item Master'] -- Item Master (IV00101) ON ['Item Master'].ITEMNMBR = ['Sales Transaction Amounts Work'].ITEMNMBR LEFT JOIN SOP60300 AS ['Sales Customer Item Cross Reference'] -- Sales Customer Item Cross Reference (SOP60300) ON ['Sales Customer Item Cross Reference'].ITEMNMBR = ['Sales Transaction Amounts Work'].ITEMNMBR AND ['Sales Customer Item Cross Reference'].CUSTNMBR = ['Sales Transaction Work'].CUSTNMBR WHERE ['Sales Transaction Amounts Work'].SOPTYPE = 3 GO GRANT SELECT ON uv_AZRCRV_SalesInvoiceLines TO DYNGRP GO

SQL View to Return Sales Invoice Headers

Microsoft Dynamics GPI’ve been organising a demo of software which can be used to produce documentation using data from Microsoft Dynamics GP and integrate it with data from other systems or network shares. I thought about a few ways of getting the Dynamics GP data and decided that a custom SQL view returning only the required information was the best way to go.

This view returns sales invoice headers and related fields such as the sales user defined.

-- drop view if it exists
IF OBJECT_ID(N'uv_AZRCRV_SalesInvoiceHeaders', N'V') IS NOT NULL
	DROP VIEW uv_AZRCRV_SalesInvoiceHeaders
GO
-- create view
CREATE VIEW [dbo].[uv_AZRCRV_SalesInvoiceHeaders] AS
/*
Created by Ian Grieve of azurecurve | Ramblings of an IT Professional (http://www.azurecurve.co.uk) This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 Int). */
SELECT RTRIM(['Sales Transaction Work'].SOPNUMBE) AS 'Invoice Number' ,['Sales Transaction Work'].DOCID AS 'Invoice Type' ,FORMAT(['Sales Transaction Work'].DOCDATE, 'dd-MM-yyyy') AS 'Document Date' ,FORMAT(['Sales Transaction Work'].INVODATE, 'dd-MM-yyyy') AS 'Invoice Date' ,FORMAT(['Sales Transaction Work'].INVODATE, 'yyyy-MM-dd') AS 'Invoice Date Sortable' ,FORMAT(['Sales Transaction Work'].DUEDATE, 'dd-MM-yyyy') AS 'Due Date' ,FORMAT(['Sales Transaction Work'].ReqShipDate, 'dd-MM-yyyy') AS 'Requested Ship Date' ,RTRIM(['Company Master'].ADRCNTCT) AS 'Shipper Contact Person' ,RTRIM(['Company Master'].ADDRESS1) AS 'Shipper Address 1' ,RTRIM(['Company Master'].ADDRESS2) AS 'Shipper Address 2' ,RTRIM(['Company Master'].ADDRESS3) AS 'Shipper Address 3' ,RTRIM(['Company Master'].CITY) AS 'Shipper City' ,RTRIM(['Company Master'].STATE) AS 'Shipper State' ,RTRIM(['Company Master'].ZIPCODE) AS 'Shipper Zip Code' ,RTRIM(['Company Master'].COUNTY) AS 'Shipper Country' ,RTRIM(['Company Master'].PHONE1) AS 'Shipper Phone 1' ,RTRIM(['Sales Transaction Work'].CUSTNMBR) AS 'Customer Number' ,RTRIM(['Sales Transaction Work'].CUSTNAME) AS 'Customer Name' ,RTRIM(['RM Customer Master'].TXRGNNUM) AS 'Tax Registration Number' ,RTRIM(['Sales Transaction Work'].PRSTADCD) AS 'Ship To Address Code' ,RTRIM(['Sales Transaction Work'].CNTCPRSN) AS 'Contact Person' ,RTRIM(['Sales Transaction Work'].ShipToName) AS 'Ship To Name' ,RTRIM(['Sales Transaction Work'].ADDRESS1) AS 'Address 1' ,RTRIM(['Sales Transaction Work'].ADDRESS2) AS 'Address 2' ,RTRIM(['Sales Transaction Work'].ADDRESS3) AS 'Address 3' ,RTRIM(['Sales Transaction Work'].CITY) AS 'City' ,RTRIM(['Sales Transaction Work'].STATE) AS 'State' ,RTRIM(['Sales Transaction Work'].ZIPCODE) AS 'Zip Code' ,RTRIM(['Sales Transaction Work'].COUNTRY) AS 'Country' ,RTRIM(['Sales Transaction Work'].PHNUMBR1) AS 'Phone 1' ,RTRIM(['Sales Transaction Work'].CURNCYID) AS 'Currency ID' ,( SELECT CONVERT(DECIMAL(10,0), SUM(QUANTITY)) FROM SOP10200 AS ['Sales Transaction Amounts Work'] -- Sales Transaction Amounts Work (SOP10200) WHERE ['Sales Transaction Amounts Work'].SOPTYPE = ['Sales Transaction Work'].SOPTYPE AND ['Sales Transaction Amounts Work'].SOPNUMBE = ['Sales Transaction Work'].SOPNUMBE ) AS 'Number Of Pieces' ,( SELECT CONVERT(DECIMAL(10,2), SUM(QUANTITY) * SUM(['Item Master'].ITEMSHWT)) FROM SOP10200 AS ['Sales Transaction Amounts Work'] -- Sales Transaction Amounts Work (SOP10200) INNER JOIN IV00101 AS ['Item Master'] -- Item Master (IV00101) ON ['Item Master'].ITEMNMBR = ['Sales Transaction Amounts Work'].ITEMNMBR WHERE ['Sales Transaction Amounts Work'].SOPTYPE = ['Sales Transaction Work'].SOPTYPE AND ['Sales Transaction Amounts Work'].SOPNUMBE = ['Sales Transaction Work'].SOPNUMBE ) AS 'Total Weight' ,CONVERT(DECIMAL(10,2),['Sales Transaction Work'].SUBTOTAL) AS 'Sub Total' ,CONVERT(DECIMAL(10,2),['Sales Transaction Work'].TAXAMNT) AS 'Tax Amount' ,CONVERT(DECIMAL(10,2),['Sales Transaction Work'].FRTAMNT) AS 'Freight Amount' ,CONVERT(DECIMAL(10,2),['Sales Transaction Work'].DOCAMNT) AS 'Document Amount' FROM SOP10100 AS ['Sales Transaction Work'] -- Sales Transaction Work (SOP10100) LEFT JOIN RM00101 AS ['RM Customer Master'] -- RM Customer MSTR (RM00101) ON ['RM Customer Master'].CUSTNMBR = ['Sales Transaction Work'].CUSTNMBR LEFT JOIN DYNAMICS..SY01500 AS ['Company Master'] -- Company Master (SY01500) ON ['Company Master'].INTERID = DB_NAME() WHERE ['Sales Transaction Work'].SOPTYPE = 3 GO GRANT SELECT ON uv_AZRCRV_SalesInvoiceHeaders TO DYNGRP GO

[/postcode]

SQL View to Return Sales Quote Lines

Microsoft Dynamics GPI’ve been organising a demo of software which can be used to produce documentation using data from Microsoft Dynamics GP and integrate it with data from other systems or network shares. I thought about a few ways of getting the Dynamics GP data and decided that a custom SQL view returning only the required information was the best way to go.

This view returns sales quote lines and related fields such as the sales user defined.

-- drop view if it exists
IF OBJECT_ID(N'uv_AZRCRV_SalesQuoteLines', N'V') IS NOT NULL
	DROP VIEW uv_AZRCRV_SalesQuoteLines
GO
-- create view
CREATE VIEW [dbo].[uv_AZRCRV_SalesQuoteLines] AS
/*
Created by Ian Grieve of azurecurve | Ramblings of an IT Professional (http://www.azurecurve.co.uk) This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 Int). */
SELECT RTRIM(['Sales Transaction Work'].SOPNUMBE) AS 'Quote Number' ,['Sales Transaction Amounts Work'].LNITMSEQ AS 'Line Number' ,RTRIM(ISNULL(['Sales Customer Item Cross Reference'].CUSTITEMNMBR, ['Sales Transaction Amounts Work'].ITEMNMBR)) AS 'Item Number' ,RTRIM(ISNULL(['Sales Customer Item Cross Reference'].CUSTITEMDESC, ['Sales Transaction Amounts Work'].ITEMDESC)) AS 'Item Description' ,RTRIM(['Sales Transaction Amounts Work'].UOFM) AS 'Unit of Measure' ,['Sales Transaction Amounts Work'].QUANTITY AS 'Quantity' ,CONVERT(DECIMAL(10,2),['Sales Transaction Amounts Work'].ORUNTPRC) AS 'Originating Unit Price' ,CONVERT(DECIMAL(10,2),['Sales Transaction Amounts Work'].OREXTCST) AS 'Originating Extended Price' ,RTRIM(['Sales Transaction Amounts Work'].LOCNCODE) AS 'Site' FROM SOP10100 AS ['Sales Transaction Work'] -- Sales Transaction Work (SOP10100) INNER JOIN SOP10200 AS ['Sales Transaction Amounts Work'] -- Sales Transaction Amounts Work (SOP10200) ON ['Sales Transaction Amounts Work'].SOPTYPE = ['Sales Transaction Work'].SOPTYPE AND ['Sales Transaction Amounts Work'].SOPNUMBE = ['Sales Transaction Work'].SOPNUMBE LEFT JOIN SOP60300 AS ['Sales Customer Item Cross Reference'] -- Sales Customer Item Cross Reference (SOP60300) ON ['Sales Customer Item Cross Reference'].ITEMNMBR = ['Sales Transaction Amounts Work'].ITEMNMBR AND ['Sales Customer Item Cross Reference'].CUSTNMBR = ['Sales Transaction Work'].CUSTNMBR WHERE ['Sales Transaction Amounts Work'].SOPTYPE = 1 GO GRANT SELECT ON uv_AZRCRV_SalesQuoteLines TO DYNGRP GO

SQL View to Return Sales Quote Headers

Microsoft Dynamics GPI’ve been organising a demo of software which can be used to produce documentation using data from Microsoft Dynamics GP and integrate it with data from other systems or network shares. I thought about a few ways of getting the Dynamics GP data and decided that a custom SQL view returning only the required information was the best way to go.

This view returns sales quote headers and related fields such as the sales user defined.

-- drop view if it exists
IF OBJECT_ID(N'uv_AZRCRV_SalesQuoteHeaders', N'V') IS NOT NULL
	DROP VIEW uv_AZRCRV_SalesQuoteHeaders
GO
-- create view
CREATE VIEW [dbo].[uv_AZRCRV_SalesQuoteHeaders] AS
/*
Created by Ian Grieve of azurecurve | Ramblings of an IT Professional (http://www.azurecurve.co.uk) This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 Int). */
SELECT RTRIM(['Sales Transaction Work'].SOPNUMBE) AS 'Quote Number' ,['Sales Transaction Work'].DOCID AS 'Quote Type' ,['Sales Transaction Work'].DOCDATE AS 'Document Date' ,FORMAT(['Sales Transaction Work'].QUOTEDAT, 'dd-MM-yyyy') AS 'Quote Date' ,FORMAT(['Sales Transaction Work'].QUOEXPDA, 'dd-MM-yyyy') AS 'Quote Expiry Date' ,FORMAT(['Sales Transaction Work'].DUEDATE, 'dd-MM-yyyy') AS 'Due Date' ,FORMAT(['Sales Transaction Work'].ReqShipDate, 'dd-MM-yyyy') AS 'Requested Ship Date' ,RTRIM(['Sales Transaction Work'].CUSTNMBR) AS 'Customer Number' ,RTRIM(['Sales Transaction Work'].CUSTNAME) AS 'Customer Name' ,RTRIM(['Sales Transaction Work'].PRSTADCD) AS 'Ship To Address Code' ,RTRIM(['Sales Transaction Work'].CNTCPRSN) AS 'Contact Person' ,RTRIM(['Sales Transaction Work'].ShipToName) AS 'Ship To Name' ,RTRIM(['Sales Transaction Work'].ADDRESS1) AS 'Address 1' ,RTRIM(['Sales Transaction Work'].ADDRESS2) AS 'Address 2' ,RTRIM(['Sales Transaction Work'].ADDRESS3) AS 'Address 3' ,RTRIM(['Sales Transaction Work'].CITY) AS 'City' ,RTRIM(['Sales Transaction Work'].STATE) AS 'State' ,RTRIM(['Sales Transaction Work'].ZIPCODE) AS 'Zip Code' ,RTRIM(['Sales Transaction Work'].COUNTRY) AS 'Country' ,RTRIM(['Sales Transaction Work'].CURNCYID) AS 'Currency ID' ,CONVERT(DECIMAL(10,2),['Sales Transaction Work'].ORSUBTOT) AS 'Originating Sub Total' ,CONVERT(DECIMAL(10,2),['Sales Transaction Work'].ORTAXAMT) AS 'Originating Tax Amount' ,CONVERT(DECIMAL(10,2),['Sales Transaction Work'].ORDOCAMT) AS 'Originating Document Amount' ,RTRIM(['Sales Transaction Work'].SALSTERR) AS 'Sales Territory ID' ,RTRIM(['Sales Territory Master'].SALSTERR) AS 'Sales Territory' ,RTRIM(['Sales Transaction Work'].SLPRSNID) AS 'Salesperson ID' ,RTRIM(['Sales User-Defined Work History'].USERDEF1) AS 'Priority' ,RTRIM(['Sales User-Defined Work History'].USERDEF2) AS 'Confirmation' ,RTRIM(['Sales User-Defined Work History'].USRDEF03) AS 'Ordered By' ,RTRIM(['Sales User-Defined Work History'].USRDEF04) AS 'Project Number' ,RTRIM(['Sales User-Defined Work History'].USRDEF05) AS 'Project Name' ,RTRIM(['RM Salesperson Master'].SLPRSNFN) + ' ' + RTRIM(['RM Salesperson Master'].SPRSNSLN) AS 'Salesperson' FROM SOP10100 AS ['Sales Transaction Work'] -- Sales Transaction Work (SOP10100) LEFT JOIN SOP10106 AS ['Sales User-Defined Work History'] -- Sales User-Defined Work History (SOP10106) ON ['Sales User-Defined Work History'].SOPTYPE = ['Sales Transaction Work'].SOPTYPE AND ['Sales User-Defined Work History'].SOPNUMBE = ['Sales Transaction Work'].SOPNUMBE LEFT JOIN RM00301 AS ['RM Salesperson Master'] -- RM Salesperson Master (RM00301) ON ['RM Salesperson Master'].SLPRSNID = ['Sales Transaction Work'].SLPRSNID LEFT JOIN RM00303 AS ['Sales Territory Master'] -- Sales Territory Master File (RM00303) ON ['Sales Territory Master'].SALSTERR = ['Sales Transaction Work'].SALSTERR WHERE ['Sales Transaction Work'].SOPTYPE = 1 GO GRANT SELECT ON uv_AZRCRV_SalesQuoteHeaders TO DYNGRP GO

Error Running Fastpath hybrid Grant script

FastpathIn yesterdays post on encountering an error deploying the Fastpath Audit Trails to a new company, there was a problem which came up, but I forgot to mention.

When the minimum permissions script (also know as the hybrid grant script) from Fastpath was run, an error in SSMS was produced which was not seen when implementing:

Msg 3729, Level 16, State 1, Procedure sp_revokedbaccess, Line 51 [Batch Start Line 18]
Cannot drop schema 'Fastpathsql' because it is being referenced by object 'GP_DR_AT_BankDetailChanges'.

The problem here was because we had created a report via the portal and this had the owner of the SQL login configured for use by Audit Trails. The solution is to change the database owner to dbo.

This can be done a few ways, but the “safest” is to use the sp_changeobjectowner stored procedure to alter the owner to dbo:

EXEC dbo.sp_changeobjectowner @objname = 'Audit Trails SQL Login.SQL view name', @newowner = 'dbo'

The two highlighted sections need to be replaced; the first with the current owner of the view, the second is the view name.

Error Deploying Fastpath Audit Trails to a New Company

FastpathI implemented Audit Trails from Fastpath for a client a while ago. They created the required triggers in a few company databases and all worked well.

Recently they deployed the triggers to another company, but none of the data was flowing through to the portal.

I did some investigation and found the triggers were working correctly as the audit tables in the company database were being populated, but the data collect wasn’t moving them to the audit table in the FPAUDIT database. Further investigation and a quick suggestion from the Fastpath support team had me checking permissions on the databases; the database triggers were being added to did not have the required permissions for the Fastpath SQL login.

When I checked with the user, this was a company created after the initial deployment of Audit Trails and so the user had never had permissions to this database. We re-ran the minimum permissions script and the data collect was then able to run successfully and collect the audit changes from the new company.

SQL Script: Get First Email from Semi-colon delimited string

Microsoft SQL ServerI had a request to produce a SQl view for a client recently which extracted the first email address from the EmailToAddress field in the Address Electronic Funds Transfer Master (SY06000) table linked to a creditor record in Microsoft Dynamics GP. This field generally stores a single email, but sometimes stores multiple email addresses separated with a semi-colon.

The below script will extract the first email address from the field if it is delimited with a semi-colon or the entire content of the field if there is no semi-colon.

/*
Created by Ian Grieve of azurecurve | Ramblings of an IT Professional (http://www.azurecurve.co.uk) This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 Int). */
SELECT CASE WHEN SUBSTRING(EmailToAddress, 0, CHARINDEX(';', EmailToAddress)) = '' THEN EmailToAddress ELSE SUBSTRING(EmailToAddress, 0, CHARINDEX(';', EmailToAddress)) END AS Email FROM SY01200 -- Address Electronic Funds Transfer Master (SY06000)

SQL View to Return Budgets with Account User-Defined Fields

Microsoft Dynamics 365 Business CentralI was helping a client create a budget report recently where they wanted to have the same information available in more than one reporting too. While queries could be written and embedded there is scope for them to then diverge over time; the solution to this is to create a SQL view which all of the reporting tools can then select to make sure they always have the same data.

The view uses data from the following tables:

-- drop view if it exists
IF OBJECT_ID(N'uv_AZRCRV_Budgets', N'V') IS NOT NULL
	DROP VIEW uv_AZRCRV_Budgets
GO
-- create view
CREATE VIEW uv_AZRCRV_Budgets AS
/*
Created by Ian Grieve of azurecurve | Ramblings of an IT Professional (http://www.azurecurve.co.uk) This code is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0 Int). */
SELECT ['Budget Master'].BUDGETID ,['Budget Master'].YEAR1 ,['Budget Summary Master'].PERIODID ,['Account Master'].ACTINDX ,['Account Master'].ACTNUMBR_1 ,['Account Master'].ACTNUMBR_2 ,['Account Master'].ACTNUMBR_3 ,['Account Master'].ACTNUMBR_4 ,['Account Master'].ACTNUMBR_5 ,['Account Master'].ACTNUMBR_6 ,['Account Master'].ACTNUMBR_7 ,['Account Master'].ACTNUMBR_8 ,['Account Master'].ACTNUMBR_9 ,['Account Master'].ACTNUMBR_10 ,['Account Index Master'].ACTNUMST ,['Account Master'].ACTDESCR ,['Account Category Master'].ACCATDSC ,['Account Master'].USERDEF1 ,['Account Master'].USERDEF2 ,['Account Master'].USRDEFS1 ,['Account Master'].USRDEFS2 ,['Budget Summary Master'].BUDGETAMT FROM GL00200 AS ['Budget Master'] INNER JOIN GL00201 AS ['Budget Summary Master'] ON ['Budget Summary Master'].BUDGETID = ['Budget Master'].BUDGETID INNER JOIN GL00100 AS ['Account Master'] ON ['Account Master'].ACTINDX = ['Budget Summary Master'].ACTINDX INNER JOIN GL00105 AS ['Account Index Master'] ON ['Account Index Master'].ACTINDX = ['Budget Summary Master'].ACTINDX INNER JOIN GL00102 AS ['Account Category Master'] ON ['Account Category Master'].ACCATNUM = ['Account Master'].ACCATNUM GO GRANT SELECT ON uv_AZRCRV_Budgets TO DYNGRP GO