Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 Complex Workflow - Fun Code

Author  Topic 

Onamuji
Aged Yak Warrior

504 Posts

Posted - 2002-01-10 : 10:16:49
For our purchase order system we want to specify a set of workflow for the following variations...

- cost center charged by the PO if the is no appropriations request (ar)
- purchase order type (planned, unplanned, budgeted, etc)
- catalog item categories (each catalog belongs to a master set or is a child of the master set (Desktop, ESS, Telecom, Other, Hardware, Software)
- True|False (based on if an AR is entered in the PO)
- PO item total (sum(quantity * unitprice))
- Compare type (<=, <, >=, >, =, !=)

The top set is pretty easy to go through, the point i'm having problems (logically) is deciding how to find the default workflow for the compare type. I guess I could define a logical order but I'm hoping that someone else can help me.

Here's what I have so far:

CREATE TABLE dbo.PurchaseOrderDefaultWorkflows (
PurchaseOrderDefaultWorkflowID INT NOT NULL IDENTITY,
Step INT NOT NULL CHECK(Step > 0),
LogonUser VARCHAR(255) NOT NULL CHECK(LEN(LogonUser) > 0),
CostCenterID INT NULL,
CategoryID INT NULL,
POTypeID INT NULL,
AttachedAR BIT NOT NULL DEFAULT 0,
TotalLimit MONEY NOT NULL DEFAULT 0.0000,
TotalLimitCompare VARCHAR(2) NOT NULL DEFAULT '<=',
)

CREATE PROCEDURE GeneratePOWorkflow @po INT AS
SET NOCOUNT ON

DECLARE @ar BIT
DECLARE @cc INT
DECLARE @pt INT
DECLARE @t MONEY
DECLARE @cat INT
DECLARE @mcat INT
DECLARE @categories TABLE (catid INT)
DECLARE @workflow TABLE (step INT, logonuser VARCHAR(255))

-- Get the basic information
SELECT @ar = CASE WHEN ARID IS NULL THEN 0 ELSE 1 END,
@cc = CostCenterID,
@pt = TypeID
FROM PurchaseOrders
WHERE ID = @po

-- If an AR is entered don't require cost center
IF @ar = 1 SET @cc = NULL

-- Get total of items
SELECT @t = SUM(Quantity * UnitPrice)
FROM PurchaseOrderItems
WHERE PurchaseOrderID = @po

-- Get all distinct categories from items
INSERT INTO @categories
SELECT CategoryID
FROM PurchaseOrderItems poi
INNER JOIN CatalogItems ci ON poi.CatalogItemID = ci.CatalogItemID
WHERE poi.PurchaseOrderID = @po

-- For each category find the default workflow and insert
WHILE (SELECT COUNT(*) FROM @categories) > 0
BEGIN
-- Select a category
SELECT @cat = catid
FROM @categories

-- Find master category
SELECT @mcat = dbo.fn_MasterCatalogCategory(@cat)

-- This is where I need to add some good logic, this function
-- Returns 1 or 0 depending on if it can find a workflow for the set
-- See below for continuation...
SELECT dbo.fn_HasDefaultPurchaseOrderWorkflow(@cc, @mcat, @pt, @ar, '<=', @t)

-- Delete from categories list
DELETE FROM @categories WHERE catid = @cat
END

Now I'm guessing I could just do every compare type but I want to select the best fitting one, for example there could be a compare set like the following: (<= 500.00) and one for (<= 8000.00) and one for (> 500.00) ... how can I limit this... obviously if my PO total was 500 < x <= 8000 both the workflows should be included logically I guess I want to pick the closest matching one where the difference between the two is the smallest. Another possibility is to have
x < 500 < 8000 which would result in the workflow for 8000 being included but I only want to include the one from 500. Oh and there are times when the value will be 0.00 in the total column which will mean if no other workflow is found for that set to include that workflow.

Any helps, suggestions are gladly welcomed. If you see anything in my code that could be enhanced let me know :-)

<update>
Here's the fn_HasDefaultPurchaseOrderWorkflow function .. it needs to be modified to handle the different value and compare types right now it just looks for an exact match.

CREATE FUNCTION dbo.fn_HasDefaultPurchaseOrderWorkflow (
@CostCenterID INT,
@CategoryID INT,
@TypeID INT,
@AttachedAR BIT,
@LimitCompare VARCHAR(2),
@Limit MONEY
) RETURNS BIT AS
BEGIN
DECLARE @rc BIT

IF EXISTS(SELECT PurchaseOrderDefaultWorkflowID
FROM PurchaseOrderDefaultWorkflows
WHERE (CostCenterID = @CostCenterID
OR (@CostCenterID IS NULL
AND CostCenterID IS NULL))
AND (CategoryID = @CategoryID
OR (@CategoryID IS NULL
AND CategoryID IS NULL))
AND (POTypeID = @TypeID
OR (@TypeID IS NULL
AND POTypeID IS NULL))
AND (AttachedAR = @AttachedAR)
AND (TotalLimit = @Limit)
AND (TotalLimitCompare = @LimitCompare))
SET @rc = 1
ELSE
SET @rc = 0

RETURN @rc
END

</update>

Thanks!

Edited by - onamuji on 01/10/2002 10:32:42

Onamuji
Aged Yak Warrior

504 Posts

Posted - 2002-01-10 : 11:58:18
So the solution for the time being is this, select the closet value and it's compare operator, then see if the compare operator selected it valid, if not remove it from the list and try again.


INSERT INTO @wf (total, compare)
SELECT DISTINCT
TotalLimit,
TotalLimitCompare
FROM PurchaseOrderDefaultWorkflows
WHERE (CostCenterID = @cc
OR (@cc IS NULL
AND CostCenterID IS NULL))
AND (CategoryID = @mcat
OR (@mcat IS NULL
AND CategoryID IS NULL))
AND (POTypeID = @pt
OR (@pt IS NULL
AND POTypeID IS NULL))
AND (AttachedAR = @ar)

FindWorkflow3:
SELECT @total = total,
@compare = compare
FROM @wf
WHERE ABS(total - @t) = (SELECT MIN(ABS(total - @t)) FROM @wf)
AND total <> 0

SELECT @use = CASE @compare
WHEN '<=' THEN CASE WHEN @t <= @total THEN 1 ELSE 0 END
WHEN '>=' THEN CASE WHEN @t >= @total THEN 1 ELSE 0 END
WHEN '<' THEN CASE WHEN @t < @total THEN 1 ELSE 0 END
WHEN '>' THEN CASE WHEN @t > @total THEN 1 ELSE 0 END
WHEN '=' THEN CASE WHEN @t = @total THEN 1 ELSE 0 END
WHEN '!=' THEN CASE WHEN @t <> @total THEN 1 ELSE 0 END
END

IF (@use = 1)
BEGIN
INSERT INTO @workflow
SELECT Step,
LogonUser
FROM dbo.fn_DefaultPurchaseOrderWorkflow(@cc, @mcat, @pt, @ar, @compare, @total)
END
ELSE
BEGIN
DELETE FROM @wf WHERE total = @total AND compare = @compare
IF (SELECT COUNT(*) FROM @wf) > 0
BEGIN
GOTO FindWorkflow3
END
END

I know, dear god I used a GOTO ... first time in ages but it suited the purpose quite fine, what's the status of GOTO in T-SQL code? is it ok to use?

Thanks!

- Onamuji
Go to Top of Page
   

- Advertisement -