diff --git a/.gitignore b/.gitignore index 1e3d82ec..3cd7e22c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ npm-debug.* package-lock.json yarn.lock .scannerwork +.lint/ \ No newline at end of file diff --git a/api/sql/schema/350-rule.conditionUnapproved.sql b/api/sql/schema/350-rule.conditionUnapproved.sql new file mode 100644 index 00000000..a2b5d88d --- /dev/null +++ b/api/sql/schema/350-rule.conditionUnapproved.sql @@ -0,0 +1,17 @@ +CREATE TABLE [rule].[conditionUnapproved] ( + conditionId INT IDENTITY(1000, 1) NOT NULL, + [priority] INT, + operationStartDate DATETIME, + operationEndDate DATETIME, + sourceAccountId NVARCHAR(255), + destinationAccountId NVARCHAR(255), + isDeleted BIT NOT NULL DEFAULT(0), -- a flag to show if the rule is deleted, e.g. 1 - Deleted + createdBy BIGINT NULL, -- id of the actor + createdOn DATETIME2 (0) NULL, -- date of the rule created + updatedBy BIGINT NULL, -- id of the actor + updatedOn DATETIME2 (0) NULL, -- date of the rule updated + status VARCHAR(20) NULL DEFAULT('pending'), + rejectReason VARCHAR(255) NULL, + CONSTRAINT [pkRuleConditionUnapproved] PRIMARY KEY CLUSTERED ([conditionId] ASC), + CONSTRAINT fkRuleConditionUnapproved_status FOREIGN KEY(status) REFERENCES [core].[status] (statusId) +) diff --git a/api/sql/schema/350-rule.conditionUnapprovedActor.sql b/api/sql/schema/350-rule.conditionUnapprovedActor.sql new file mode 100644 index 00000000..ac1081d0 --- /dev/null +++ b/api/sql/schema/350-rule.conditionUnapprovedActor.sql @@ -0,0 +1,11 @@ +CREATE TABLE [rule].[conditionActorUnapproved] ( + conditionId INT NOT NULL, + factor CHAR(2) NOT NULL, + actorId BIGINT NOT NULL, + status VARCHAR(20) NULL DEFAULT('pending'), + CONSTRAINT pkRuleConditionActorUnapproved PRIMARY KEY CLUSTERED (conditionId, factor, actorId), + CONSTRAINT fkRuleConditionActorUnapproved_conditionId FOREIGN KEY (conditionId) REFERENCES [rule].[conditionUnapproved](conditionId), + CONSTRAINT fkRuleConditionActorUnapproved_actorId FOREIGN KEY(actorId) REFERENCES [core].[actor] (actorId), + CONSTRAINT ccRuleConditionActorUnapproved_factor CHECK (factor IN ('so', 'do', 'co')), -- source organization, destination organization, channel organization + CONSTRAINT fkRuleConditionActorUnapproved_status FOREIGN KEY(status) REFERENCES [core].[status] (statusId) +) diff --git a/api/sql/schema/350-rule.conditionUnapprovedItem.sql b/api/sql/schema/350-rule.conditionUnapprovedItem.sql new file mode 100644 index 00000000..57d322ae --- /dev/null +++ b/api/sql/schema/350-rule.conditionUnapprovedItem.sql @@ -0,0 +1,11 @@ +CREATE TABLE [rule].[conditionItemUnapproved] ( + conditionId INT NOT NULL, + factor CHAR(2) NOT NULL, + itemNameId BIGINT NOT NULL, + status VARCHAR(20) NULL DEFAULT('pending'), + CONSTRAINT pkRuleConditionItemUnapproved PRIMARY KEY CLUSTERED (conditionId, factor, itemNameId), + CONSTRAINT fkRuleConditionItemUnapproved_conditionId FOREIGN KEY (conditionId) REFERENCES [rule].[conditionUnapproved](conditionId), + CONSTRAINT fkRuleConditionItemUnapproved_itemNameId FOREIGN KEY(itemNameId) REFERENCES [core].[itemName] (itemNameId), + CONSTRAINT ccRuleConditionItemUnapproved_factor CHECK (factor IN ('ss', 'ds', 'cs', 'oc', 'sc', 'dc')), -- source spatial, destination spatial, channel spatial, operation category, source category, destination category + CONSTRAINT fkRuleConditionItemUnapproved_status FOREIGN KEY(status) REFERENCES [core].[status] (statusId) +) diff --git a/api/sql/schema/350-rule.conditionUnapprovedProperty.sql b/api/sql/schema/350-rule.conditionUnapprovedProperty.sql new file mode 100644 index 00000000..7d16929d --- /dev/null +++ b/api/sql/schema/350-rule.conditionUnapprovedProperty.sql @@ -0,0 +1,12 @@ +CREATE TABLE [rule].[conditionPropertyUnapproved] ( + conditionId INT NOT NULL, + factor CHAR(2) NOT NULL, + [name] NVARCHAR(50) NOT NULL, + [value] NVARCHAR(200) NOT NULL, + status VARCHAR(20) NULL DEFAULT('pending'), + CONSTRAINT pkRuleConditionPropertyUnapproved PRIMARY KEY CLUSTERED (conditionId, factor, [name]), + CONSTRAINT fkRuleConditionPropertyUnapproved_conditionId FOREIGN KEY (conditionId) REFERENCES [rule].[conditionUnapproved](conditionId), + CONSTRAINT ccRuleConditionPropertyUnapproved_factor CHECK (factor IN ('so', 'do', 'co', 'ss', 'ds', 'cs', 'oc', 'sc', 'dc')), + -- source organization, destination organization, channel organization, source spatial, destination spatial, channel spatial, operation category, source category, destination category + CONSTRAINT fkRuleConditionPropertyUnapproved_status FOREIGN KEY(status) REFERENCES [core].[status] (statusId) +) diff --git a/api/sql/schema/360-rule.limitUnapproved.sql b/api/sql/schema/360-rule.limitUnapproved.sql new file mode 100644 index 00000000..c67d4932 --- /dev/null +++ b/api/sql/schema/360-rule.limitUnapproved.sql @@ -0,0 +1,21 @@ +CREATE TABLE [rule].[limitUnapproved] ( + limitId INT IDENTITY(1000, 1) NOT NULL, + conditionId INT NOT NULL, + currency VARCHAR(3) NOT NULL, + minAmount MONEY, + maxAmount MONEY, + maxAmountDaily MONEY, + maxCountDaily BIGINT, + maxAmountWeekly MONEY, + maxCountWeekly BIGINT, + maxAmountMonthly MONEY, + maxCountMonthly BIGINT, + [credentials] INT, + [priority] SMALLINT, + status VARCHAR(20) NULL DEFAULT('pending'), + CONSTRAINT [pkRuleLimitUnapproved] PRIMARY KEY CLUSTERED (limitId ASC), + CONSTRAINT ukRuleLimitUnapprovedConditionCurrencyPriority UNIQUE (conditionId, currency, [priority]), + CONSTRAINT ukRuleLimitUnapprovedConditionCurrencyCredentials UNIQUE (conditionId, currency, [credentials]), + CONSTRAINT [fkRuleLimitUnapproved_condition] FOREIGN KEY (conditionId) REFERENCES [rule].[conditionUnapproved](conditionId), + CONSTRAINT fkRuleLimitUnapproved_status FOREIGN KEY(status) REFERENCES [core].[status] (statusId) +) diff --git a/api/sql/schema/360-rule.splitNameUnapproved.sql b/api/sql/schema/360-rule.splitNameUnapproved.sql new file mode 100644 index 00000000..051fe7fe --- /dev/null +++ b/api/sql/schema/360-rule.splitNameUnapproved.sql @@ -0,0 +1,11 @@ +CREATE TABLE [rule].[splitNameUnapproved] ( + splitNameId INT IDENTITY(1000, 1) NOT NULL, + conditionId INT NOT NULL, + name VARCHAR(50) NOT NULL, + tag VARCHAR(max), + status VARCHAR(20) NULL DEFAULT('pending'), + CONSTRAINT [pkRuleSplitNameUnapproved] PRIMARY KEY CLUSTERED (splitNameId ASC), + CONSTRAINT [fkRuleSplitNameUnapproved_ruleCondition] FOREIGN KEY (conditionId) REFERENCES [rule].[conditionUnapproved](conditionId), + CONSTRAINT [ukRuleSplitNameUnapprovedConditionIdName] UNIQUE (conditionId, name), + CONSTRAINT fkRuleSplitNameUnapproved_status FOREIGN KEY(status) REFERENCES [core].[status] (statusId) +) diff --git a/api/sql/schema/370-rule.splitAssignmentUnapproved.sql b/api/sql/schema/370-rule.splitAssignmentUnapproved.sql new file mode 100644 index 00000000..16b6d73f --- /dev/null +++ b/api/sql/schema/370-rule.splitAssignmentUnapproved.sql @@ -0,0 +1,14 @@ +CREATE TABLE [rule].[splitAssignmentUnapproved] ( + splitAssignmentId INT IDENTITY(1000, 1) NOT NULL, + splitNameId INT NOT NULL, + debit VARCHAR(50) NOT NULL, + credit VARCHAR(50) NOT NULL, + minValue MONEY, + maxValue MONEY, + [percent] DECIMAL(9, 2), + description VARCHAR(50) NOT NULL, + status VARCHAR(20) NULL DEFAULT('pending'), + CONSTRAINT [pkRuleSplitAssignmentUnapproved] PRIMARY KEY CLUSTERED (splitAssignmentId ASC), + CONSTRAINT [fkRuleSplitAssignmentUnapproved_ruleSplitName] FOREIGN KEY (splitNameId) REFERENCES [rule].[splitNameUnapproved](splitNameId), + CONSTRAINT fkRuleSplitAssignmentUnapproved_status FOREIGN KEY(status) REFERENCES [core].[status] (statusId) +) diff --git a/api/sql/schema/370-rule.splitRangeUnapproved.sql b/api/sql/schema/370-rule.splitRangeUnapproved.sql new file mode 100644 index 00000000..898e704a --- /dev/null +++ b/api/sql/schema/370-rule.splitRangeUnapproved.sql @@ -0,0 +1,22 @@ +CREATE TABLE [rule].[splitRangeUnapproved] ( + splitRangeId INT IDENTITY(1000, 1) NOT NULL, + splitNameId INT NOT NULL, + startAmount MONEY NOT NULL, + startAmountCurrency VARCHAR(3) NOT NULL, + startAmountDaily MONEY NOT NULL, + startCountDaily BIGINT NOT NULL, + startAmountWeekly MONEY NOT NULL, + startCountWeekly BIGINT NOT NULL, + startAmountMonthly MONEY NOT NULL, + startCountMonthly BIGINT NOT NULL, + isSourceAmount BIT NOT NULL, + minValue MONEY, + maxValue MONEY, + [percent] DECIMAL(9, 2), + percentBase MONEY, + status VARCHAR(20) NULL DEFAULT('pending'), + CONSTRAINT [pkRuleSplitRangeUnapproved] PRIMARY KEY CLUSTERED (splitRangeId ASC), + CONSTRAINT [ukRuleSplitRangeUnapproved_splitNameId__startAmount__startAmountCurrency] UNIQUE (splitNameId, startAmount, startAmountCurrency, startAmountDaily, startCountDaily, startAmountWeekly, startCountWeekly, startAmountMonthly, startCountMonthly), + CONSTRAINT [fkRuleSplitRangeUnapproved_ruleSplitName] FOREIGN KEY (splitNameId) REFERENCES [rule].[splitNameUnapproved](splitNameId), + CONSTRAINT fkRuleSplitRangeUnapproved_status FOREIGN KEY(status) REFERENCES [core].[status] (statusId) +) diff --git a/api/sql/schema/380-rule.splitAnalyticUnapproved.sql b/api/sql/schema/380-rule.splitAnalyticUnapproved.sql new file mode 100644 index 00000000..009a740a --- /dev/null +++ b/api/sql/schema/380-rule.splitAnalyticUnapproved.sql @@ -0,0 +1,11 @@ +CREATE TABLE [rule].[splitAnalyticUnapproved] ( + splitAnalyticId INT IDENTITY(1000, 1) NOT NULL, + splitAssignmentId INT NOT NULL, + [name] VARCHAR(50), + [value] VARCHAR(100), + status VARCHAR(20) NULL DEFAULT('pending'), + CONSTRAINT [pkRuleSplitAnalyticUnapproved] PRIMARY KEY CLUSTERED (splitAnalyticId ASC), + CONSTRAINT [ukRuleSplitAnalyticUnapproved_splitAssignmentId_name] UNIQUE (splitAssignmentId, [name]), + CONSTRAINT [fkRuleSplitAnalyticUnapproved_ruleSplitName] FOREIGN KEY (splitAssignmentId) REFERENCES [rule].[splitAssignmentUnapproved](splitAssignmentId), + CONSTRAINT fkRuleSplitAnalyticUnapproved_status FOREIGN KEY(status) REFERENCES [core].[status] (statusId) +) diff --git a/api/sql/schema/750-rule.rule.addUnapproved.sql b/api/sql/schema/750-rule.rule.addUnapproved.sql new file mode 100644 index 00000000..8896b392 --- /dev/null +++ b/api/sql/schema/750-rule.rule.addUnapproved.sql @@ -0,0 +1,269 @@ +ALTER PROCEDURE [rule].[rule.addUnapproved] + @condition [rule].conditionUnapprovedTT READONLY, + @conditionActor [rule].conditionActorUnapprovedTT READONLY, + @conditionItem [rule].conditionItemUnapprovedTT READONLY, + @conditionProperty [rule].conditionPropertyUnapprovedTT READONLY, + @limit [rule].limitUnapprovedTT READONLY, + @split XML, + @meta core.metaDataTT READONLY -- information for the logged user +AS +DECLARE @userId BIGINT = (SELECT [auth.actorId] FROM @meta) +DECLARE @splitName [rule].splitNameUnapprovedTT, + @splitAssignment [rule].splitAssignmentUnapprovedTT, + @conditionId INT +BEGIN TRY + + IF EXISTS + ( + SELECT [priority] + FROM [rule].condition + WHERE [priority] = (SELECT [priority] FROM @condition) + AND isDeleted = 0 + ) + OR + EXISTS + ( + SELECT [priority] + FROM [rule].conditionUnapproved + WHERE [priority] = (SELECT [priority] FROM @condition) + ) + BEGIN + RAISERROR ('rule.duplicatedPriority', 16, 1) + END + + BEGIN TRANSACTION + + INSERT INTO [rule].conditionUnapproved( + [priority], + operationStartDate, + operationEndDate, + sourceAccountId, + destinationAccountId, + createdOn, + createdBy, + status + ) + SELECT + [priority], + operationStartDate, + operationEndDate, + sourceAccountId, + destinationAccountId, + GETDATE(), + ISNULL(createdBy, @userId), + 'pending' + FROM @condition; + + SET @conditionId = SCOPE_IDENTITY() + + INSERT INTO [rule].conditionActorUnapproved + ( + conditionId, + factor, + actorId, + status + ) + SELECT + @conditionId, + factor, + actorId, + 'pending' + FROM @conditionActor + + INSERT INTO [rule].conditionItemUnapproved + ( + conditionId, + factor, + itemNameId, + status + ) + SELECT + @conditionId, + factor, + itemNameId, + 'pending' + FROM @conditionItem + + INSERT INTO [rule].conditionPropertyUnapproved + ( + conditionId, + factor, + name, + value, + status + ) + SELECT + @conditionId, + factor, + name, + value, + 'pending' + FROM @conditionProperty + + INSERT INTO [rule].limitUnapproved( + conditionId, + currency, + minAmount, + maxAmount, + maxAmountDaily, + maxCountDaily, + maxAmountWeekly, + maxCountWeekly, + maxAmountMonthly, + maxCountMonthly, + [credentials], + [priority], + status + ) + SELECT @conditionId, + [currency], + [minAmount], + [maxAmount], + [maxAmountDaily], + [maxCountDaily], + [maxAmountWeekly], + [maxCountWeekly], + [maxAmountMonthly], + [maxCountMonthly], + [credentials], + [priority], + 'pending' + FROM @limit + + MERGE INTO [rule].splitNameUnapproved + USING @split.nodes('/data/rows/splitName') AS records(r) + ON 1 = 0 + WHEN NOT MATCHED THEN + INSERT (conditionId, name, tag, status) VALUES (@conditionId, r.value('(name)[1]', 'NVARCHAR(50)'), r.value('(tag)[1]', 'NVARCHAR(max)'), 'pending') + OUTPUT INSERTED.* INTO @splitName; + + MERGE INTO [rule].splitRangeUnapproved + USING ( + SELECT + sn.splitNameId AS splitNameId, + splitRange.x.value('(startAmount)[1]', 'money') AS startAmount, + splitRange.x.value('(startAmountCurrency)[1]', 'VARCHAR(3)') AS startAmountCurrency, + ISNULL(splitRange.x.value('(./startAmountDaily/text())[1]', 'money'), 0) AS startAmountDaily, + ISNULL(splitRange.x.value('(./startCountDaily/text())[1]', 'BIGINT'), 0) AS startCountDaily, + ISNULL(splitRange.x.value('(./startAmountWeekly/text())[1]', 'money'), 0) AS startAmountWeekly, + ISNULL(splitRange.x.value('(./startCountWeekly/text())[1]', 'BIGINT'), 0) AS startCountWeekly, + ISNULL(splitRange.x.value('(./startAmountMonthly/text())[1]', 'money'), 0) AS startAmountMonthly, + ISNULL(splitRange.x.value('(./startCountMonthly/text())[1]', 'BIGINT'), 0) AS startCountMonthly, + ISNULL(splitRange.x.value('(isSourceAmount)[1]', 'BIT'), 1) AS isSourceAmount, + splitRange.x.value('(minValue)[1]', 'money') AS minValue, + splitRange.x.value('(maxValue)[1]', 'money') AS maxValue, + splitRange.x.value('(percent)[1]', 'money') AS [percent], + splitRange.x.value('(percentBase)[1]', 'money') AS percentBase, + 'pending' AS status + FROM + @split.nodes('/data/rows/splitRange') AS splitRange(x) + JOIN + @splitName sn + ON + splitRange.x.value('(../splitName/name)[1]', 'NVARCHAR(50)') = sn.name + ) AS r + ON 1 = 0 + WHEN NOT MATCHED THEN + INSERT ( + splitNameId, + startAmount, + startAmountCurrency, + startAmountDaily, + startCountDaily, + startAmountWeekly, + startCountWeekly, + startAmountMonthly, + startCountMonthly, + isSourceAmount, + minValue, + maxValue, + [percent], + percentBase, + status) + VALUES ( + r.splitNameId, + r.startAmount, + r.startAmountCurrency, + r.startAmountDaily, + r.startCountDaily, + r.startAmountWeekly, + r.startCountWeekly, + r.startAmountMonthly, + r.startCountMonthly, + r.isSourceAmount, + r.minValue, + r.maxValue, + r.[percent], + r.percentBase, + 'pending'); + + MERGE INTO [rule].splitAssignmentUnapproved + USING ( + SELECT + sn.splitNameId AS splitNameId, + splitAssignment.x.value('(debit)[1]', 'VARCHAR(50)') AS debit, + splitAssignment.x.value('(credit)[1]', 'VARCHAR(50)') AS credit, + splitAssignment.x.value('(minValue)[1]', 'money') AS minValue, + splitAssignment.x.value('(maxValue)[1]', 'money') AS maxValue, + splitAssignment.x.value('(percent)[1]', 'decimal') AS [percent], + splitAssignment.x.value('(description)[1]', 'VARCHAR(50)') AS description, + 'pending' AS status + FROM + @split.nodes('/data/rows/splitAssignment') AS splitAssignment(x) + JOIN + @splitName sn + ON + splitAssignment.x.value('(../splitName/name)[1]', 'NVARCHAR(50)') = sn.name + ) AS r + ON 1 = 0 + WHEN NOT MATCHED THEN + INSERT (splitNameId, debit, credit, minValue, maxValue, [percent], description, status) + VALUES (r.splitNameId, r.debit, r.credit, r.minValue, r.maxValue, r.[percent], r.description, 'pending') + OUTPUT INSERTED.* INTO @splitAssignment; + + + MERGE INTO [rule].splitAnalyticUnapproved + USING ( + SELECT + sn.splitAssignmentId AS splitAssignmentId, + records.x.value('(name)[1]', 'NVARCHAR(50)') AS [name], + records.x.value('(value)[1]', 'NVARCHAR(150)') AS [value], + 'pending' AS status + FROM + @split.nodes('/data/rows/splitAssignment/splitAnalytic') records(x) + JOIN + @splitAssignment sn + ON + records.x.value('(../debit)[1]', 'NVARCHAR(50)') = sn.debit + AND records.x.value('(../credit)[1]', 'NVARCHAR(50)') = sn.credit + AND records.x.value('(../description)[1]', 'NVARCHAR(50)') = sn.[description] + + ) AS r (splitAssignmentId, [name], [value], status) + ON 1 = 0 + WHEN NOT MATCHED THEN + INSERT (splitAssignmentId, [name], [value], status) + VALUES (r.splitAssignmentId, r.[name], r.[value], 'pending'); + + COMMIT TRANSACTION + + DECLARE @outcome XML = ( + SELECT + @conditionId [key], + c.priority rulePriority, + GETUTCDATE() creationDateTime + FROM + @condition c + FOR XML RAW + ) + + EXEC core.outcome @proc = @@PROCID, @outcome = @outcome, @meta = @meta + + EXEC [rule].[rule.fetch] @meta = @meta, @conditionId = @conditionId +END TRY +BEGIN CATCH + IF @@TRANCOUNT > 0 + ROLLBACK TRANSACTION + + EXEC core.error + RETURN 55555 +END CATCH diff --git a/api/sql/schema/750-rule.rule.approve.sql b/api/sql/schema/750-rule.rule.approve.sql new file mode 100644 index 00000000..033a61a6 --- /dev/null +++ b/api/sql/schema/750-rule.rule.approve.sql @@ -0,0 +1,345 @@ +ALTER PROCEDURE [rule].[rule.approve] + @conditionId INT, + @meta core.metaDataTT READONLY -- information for the logged user +AS + +BEGIN TRY + + DECLARE @userId BIGINT = (SELECT [auth.actorId] FROM @meta) + -- checks if the user has a right to get user + DECLARE @actionID VARCHAR(100) = OBJECT_SCHEMA_NAME(@@PROCID) + '.' + OBJECT_NAME(@@PROCID), @return INT = 0 + EXEC @return = [user].[permission.check] @actionId = @actionID, @objectId = NULL, @meta = @meta + IF @return != 0 + BEGIN + RETURN 55555 + END + + IF NOT EXISTS( + SELECT 1 + FROM [rule].[condition] c + WHERE c.conditionId = @conditionId) + AND + NOT EXISTS( + SELECT 1 + FROM [rule].[conditionUnapproved] c + WHERE c.conditionId = @conditionId) + BEGIN + RAISERROR ('rule.ruleNotExists', 16, 1) + END + + BEGIN TRANSACTION + + -- handle condition + IF EXISTS(SELECT 1 FROM [rule].[conditionUnapproved] WHERE conditionId = @conditionId AND isDeleted = 1) + BEGIN + DECLARE @conditionRemoveIds core.arrayList + INSERT INTO @conditionRemoveIds + SELECT @conditionId + EXEC [rule].[rule.remove] @conditionId = @conditionRemoveIds + END + ELSE + BEGIN + IF EXISTS(SELECT 1 FROM [rule].[condition] WHERE conditionId = @conditionId) + BEGIN + UPDATE c + SET + c.updatedBy = cu.updatedBy, + c.updatedOn = cu.updatedOn, + c.status = 'approved', + c.operationStartDate = cu.operationStartDate, + c.operationEndDate = cu.operationEndDate, + c.sourceAccountId = cu.sourceAccountId, + c.priority = cu.priority, + c.isEnabled = cu.isEnabled + FROM [rule].[condition] c + INNER JOIN [rule].[conditionUnapproved] cu ON cu.conditionId = c.conditionId + WHERE c.conditionId = @conditionId + END + ELSE + BEGIN + SET IDENTITY_INSERT [rule].[condition] ON -- allow conditionId to be inserted in the condition table + INSERT INTO [rule].[condition] (conditionId, priority, status, operationStartDate, operationEndDate, sourceAccountId, isDeleted, createdBy, updatedBy, isEnabled) + SELECT cu.conditionId, cu.priority, 'approved', cu.operationStartDate, cu.operationEndDate, cu.sourceAccountId, 0, cu.createdBy, cu.updatedBy, cu.isEnabled + FROM [rule].[conditionUnapproved] cu + WHERE cu.conditionId = @conditionId + SET IDENTITY_INSERT [rule].[condition] OFF + END + END + + + + -- handle condition actor + IF EXISTS(SELECT 1 FROM [rule].[conditionActor] WHERE conditionId = @conditionId) + BEGIN + UPDATE ca + SET + ca.factor = cau.factor, + ca.actorId = cau.actorId, + ca.status = 'approved' + FROM [rule].[conditionActor] ca + INNER JOIN [rule].[conditionActorUnapproved] cau ON cau.conditionId = ca.conditionId + WHERE ca.conditionId = @conditionId + END + ELSE + BEGIN + INSERT INTO [rule].[conditionActor] (conditionId, factor, actorId, status) + SELECT cau.conditionId, cau.factor, cau.actorId, 'approved' + FROM [rule].[conditionActorUnapproved] cau + WHERE cau.conditionId = @conditionId + END + + + + -- handle condition item + IF EXISTS(SELECT 1 FROM [rule].[conditionItem] WHERE conditionId = @conditionId) + BEGIN + UPDATE ca + SET + ca.factor = cau.factor, + ca.itemNameId = cau.itemNameId, + ca.status = 'approved' + FROM [rule].[conditionItem] ca + INNER JOIN [rule].[conditionItemUnapproved] cau ON cau.conditionId = ca.conditionId + WHERE ca.conditionId = @conditionId + END + ELSE + BEGIN + INSERT INTO [rule].[conditionItem] (conditionId, factor, itemNameId, status) + SELECT ciu.conditionId, ciu.factor, ciu.itemNameId, 'approved' + FROM [rule].[conditionItemUnapproved] ciu + WHERE ciu.conditionId = @conditionId + END + + + + -- handle condition property + IF EXISTS(SELECT 1 FROM [rule].[conditionProperty] WHERE conditionId = @conditionId) + BEGIN + UPDATE ca + SET + ca.factor = cau.factor, + ca.name = cau.name, + ca.value = cau.value, + ca.status = 'approved' + FROM [rule].[conditionProperty] ca + INNER JOIN [rule].[conditionPropertyUnapproved] cau ON cau.conditionId = ca.conditionId + WHERE ca.conditionId = @conditionId + END + ELSE + BEGIN + INSERT INTO [rule].[conditionProperty] (conditionId, factor, name, value, status) + SELECT cai.conditionId, cai.factor, cai.name, cai.value, 'approved' + FROM [rule].[conditionPropertyUnapproved] cai + WHERE cai.conditionId = @conditionId + END + + + + -- handle limit + IF EXISTS(SELECT 1 FROM [rule].[limit] WHERE conditionId = @conditionId) + BEGIN + UPDATE ca + SET + ca.currency = cau.currency, + ca.minAmount = cau.minAmount, + ca.maxAmount = cau.maxAmount, + ca.maxAmountDaily = cau.maxAmountDaily, + ca.maxCountDaily = cau.maxCountDaily, + ca.maxAmountWeekly = cau.maxAmountWeekly, + ca.maxCountWeekly = cau.maxCountWeekly, + ca.maxAmountMonthly = cau.maxAmountMonthly, + ca.maxCountMonthly = cau.maxCountMonthly, + ca.credentials = cau.credentials, + ca.priority = cau.priority, + ca.status = 'approved' + FROM [rule].limit ca + INNER JOIN [rule].[limitUnapproved] cau ON cau.conditionId = ca.conditionId + WHERE ca.conditionId = @conditionId + END + ELSE + BEGIN + SET IDENTITY_INSERT [rule].[limit] ON -- allow limitId to be inserted in the limit table + INSERT INTO [rule].[limit] (limitId, conditionId, currency, minAmount, maxAmount, maxAmountDaily, maxCountDaily, maxAmountWeekly, maxCountWeekly, maxAmountMonthly, maxCountMonthly, [credentials], [priority], status) + SELECT + cai.limitId, + cai.conditionId, + cai.currency, + cai.minAmount, + cai.maxAmount, + cai.maxAmountDaily, + cai.maxCountDaily, + cai.maxAmountWeekly, + cai.maxCountWeekly, + cai.maxAmountMonthly, + cai.maxCountMonthly, + cai.credentials, + cai.priority, + 'approved' + FROM [rule].[limitUnapproved] cai + WHERE cai.conditionId = @conditionId + SET IDENTITY_INSERT [rule].[limit] OFF + END + + + + -- handle split analytic + IF EXISTS( + SELECT 1 FROM [rule].[splitAnalytic] sa + JOIN [rule].[splitAssignment] sp ON sp.splitAssignmentId = sa.splitAssignmentId + JOIN [rule].[splitName] sn ON sp.splitNameId = sn.splitNameId + WHERE sn.conditionId = @conditionId + ) + BEGIN + UPDATE spa + SET + spa.name = spau.name, + spa.value = spau.value, + spa.status = 'approved' + FROM [rule].[splitAnalytic] spa + INNER JOIN [rule].[splitAnalyticUnapproved] spau ON spau.splitAnalyticId = spa.splitAnalyticId + INNER JOIN [rule].[splitAssignmentUnapproved] sp ON sp.splitAssignmentId = spau.splitAssignmentId + INNER JOIN [rule].[splitNameUnapproved] sn ON sp.splitNameId = sp.splitNameId + WHERE sn.conditionId = @conditionId + END + ELSE + BEGIN + SET IDENTITY_INSERT [rule].[splitAnalytic] ON -- allow splitAnalyticId to be inserted in the split analytic table + INSERT INTO [rule].[splitAnalytic] (splitAnalyticId, splitAssignmentId, name, value, status) + SELECT spau.splitAnalyticId, spau.splitAssignmentId, spau.name, spau.value, 'approved' + FROM [rule].[splitAnalyticUnapproved] spau + JOIN [rule].[splitAssignmentUnapproved] sp ON sp.splitAssignmentId = spau.splitAssignmentId + JOIN [rule].[splitNameUnapproved] sn ON sp.splitNameId = sn.splitNameId + WHERE sn.conditionId = @conditionId + SET IDENTITY_INSERT [rule].[splitAnalytic] OFF + END + + + + -- handle split name + IF EXISTS(SELECT 1 FROM [rule].[splitName] WHERE conditionId = @conditionId) + BEGIN + UPDATE sn + SET + sn.name = snu.name, + sn.tag = snu.tag, + sn.status = 'approved' + FROM [rule].[splitName] sn + INNER JOIN [rule].[splitNameUnapproved] snu ON snu.splitNameId = sn.splitNameId + WHERE sn.conditionid = @conditionId + END + ELSE + BEGIN + SET IDENTITY_INSERT [rule].[splitName] ON -- allow split name to be inserted in the split name table + INSERT INTO [rule].[splitName] (splitNameId, conditionId, name, tag, status) + SELECT snu.splitNameId, snu.conditionId, snu.name, snu.tag, 'approved' + FROM [rule].[splitNameUnapproved] snu + WHERE snu.conditionId = @conditionId + SET IDENTITY_INSERT [rule].[splitName] OFF + END + + + + -- handle split range + IF EXISTS( + SELECT 1 FROM [rule].[splitRange] sr + JOIN [rule].[splitName] sn ON sn.splitNameId = sr.splitNameId + WHERE sn.conditionId = @conditionId + ) + BEGIN + UPDATE sr + SET + sr.startAmount = sru.startAmount, + sr.startAmountCurrency = sru.startAmountCurrency, + sr.startAmountDaily = sru.startAmountDaily, + sr.startCountDaily = sru.startCountDaily, + sr.startAmountWeekly = sru.startAmountWeekly, + sr.startCountWeekly = sru.startCountWeekly, + sr.startAmountMonthly = sru.startAmountMonthly, + sr.startCountMonthly = sru.startCountMonthly, + sr.isSourceAmount = sru.isSourceAmount, + sr.minValue = sru.minValue, + sr.maxValue = sru.maxValue, + sr.[percent] = sru.[percent], + sr.percentBase = sru.percentBase, + sr.status = 'approved' + FROM [rule].[splitRange] sr + INNER JOIN [rule].[splitRangeUnapproved] sru ON sru.splitRangeId = sr.splitRangeId + INNER JOIN [rule].[splitNameUnapproved] sn ON sn.splitNameId = sr.splitNameId + WHERE sn.conditionId = @conditionId + END + ELSE + BEGIN + SET IDENTITY_INSERT [rule].[splitRange] ON --allow split range id to be inserted + INSERT INTO [rule].[splitRange] ( splitRangeId, startAmount, startAmountCurrency, startAmountDaily, startCountDaily, startAmountWeekly, startCountWeekly, startAmountMonthly, startCountMonthly, isSourceAmount, minValue, maxValue, [percent], percentBase, splitNameId, status) + SELECT + sr.splitRangeId, + sr.startAmount, + sr.startAmountCurrency, + sr.startAmountDaily, + sr.startCountDaily, + sr.startAmountWeekly, + sr.startCountWeekly, + sr.startAmountMonthly, + sr.startCountMonthly, + sr.isSourceAmount, + sr.minValue, + sr.maxValue, + sr.[percent], + sr.percentBase, + sr.splitNameId, + 'approved' + FROM [rule].[splitRangeUnapproved] sr + INNER JOIN [rule].[splitNameUnapproved] sn ON sn.splitNameId = sr.splitNameId + WHERE sn.conditionId = @conditionId + SET IDENTITY_INSERT [rule].[splitRange] OFF + END + + + + -- handle split assignment + IF EXISTS( + SELECT 1 FROM [rule].[splitAssignment] sa + JOIN [rule].[splitName] sn ON sn.splitNameId = sa.splitNameId + WHERE sn.conditionId = @conditionId + ) + BEGIN + UPDATE sa + SET + sa.debit = sau.debit, + sa.credit = sau.credit, + sa.minValue = sau.minValue, + sa.maxValue = sau.maxValue, + sa.[percent] = sau.[percent], + sa.description = sau.description, + sa.status = 'approved' + FROM [rule].[splitAssignment] sa + INNER JOIN [rule].[splitAssignmentUnapproved] sau ON sau.splitAssignmentId = sa.splitAssignmentId + JOIN [rule].[splitNameUnapproved] sna ON sau.splitNameId = sna.splitNameId + WHERE sna.conditionId = @conditionId + END + ELSE + BEGIN + SET IDENTITY_INSERT [rule].[splitAssignment] ON -- allow splitAssignment to be inserted in the split assignment table + INSERT INTO [rule].[splitAssignment] (splitAssignmentId, splitNameId, debit, credit, minValue, maxValue, [percent], description, status) + SELECT sa.splitAssignmentId, sa.splitNameId, sa.debit, sa.credit, sa.minValue, sa.maxValue, sa.[percent], sa.description, 'approved' + FROM [rule].[splitAssignmentUnapproved] sa + JOIN [rule].[splitNameUnapproved] sn ON sn.splitNameId = sa.splitNameId + WHERE sn.conditionId = @conditionId + SET IDENTITY_INSERT [rule].[splitAssignment] OFF + END + + + DECLARE @conditionIds core.arrayList + INSERT INTO @conditionIds + SELECT @conditionId + EXEC [rule].[rule.deleteUnapproved] @conditionId = @conditionIds + + COMMIT TRANSACTION + +END TRY +BEGIN CATCH + IF @@TRANCOUNT > 0 + ROLLBACK TRANSACTION + EXEC core.error + RETURN 55555 +END CATCH diff --git a/api/sql/schema/750-rule.rule.deleteUnapproved.sql b/api/sql/schema/750-rule.rule.deleteUnapproved.sql new file mode 100644 index 00000000..377e7093 --- /dev/null +++ b/api/sql/schema/750-rule.rule.deleteUnapproved.sql @@ -0,0 +1,93 @@ +ALTER PROCEDURE [rule].[rule.deleteUnapproved] + @conditionId core.arrayList READONLY, + @meta core.metaDataTT READONLY -- information for the user that makes the operation +AS +DECLARE @userId BIGINT = (SELECT [auth.actorId] FROM @meta) +BEGIN TRY + + BEGIN TRANSACTION + DELETE x + FROM + [rule].limitUnapproved x + JOIN + @conditionId item ON x.conditionId = item.value + + DELETE x + FROM + [rule].conditionActorUnapproved x + JOIN + @conditionId item ON x.conditionId = item.value + + DELETE x + FROM + [rule].conditionItemUnapproved x + JOIN + @conditionId item ON x.conditionId = item.value + + DELETE x + FROM + [rule].conditionPropertyUnapproved x + JOIN + @conditionId item ON x.conditionId = item.value + + DELETE + x + FROM + [rule].splitRangeUnapproved x + JOIN + [rule].splitNameUnapproved s ON s.splitNameId = x.splitNameId + JOIN + @conditionId item ON s.conditionId = item.value + + DELETE + x + FROM + [rule].splitAnalyticUnapproved x + JOIN + [rule].splitAssignmentUnapproved y ON y.splitAssignmentId = x.splitAssignmentId + JOIN + [rule].splitNameUnapproved s ON s.splitNameId = y.splitNameId + JOIN + @conditionId item ON s.conditionId = item.value + + DELETE + x + FROM + [rule].splitAssignmentUnapproved x + JOIN + [rule].splitNameUnapproved s ON s.splitNameId = x.splitNameId + JOIN + @conditionId item ON s.conditionId = item.value + + DELETE + x + FROM + [rule].splitRangeUnapproved x + JOIN + [rule].splitNameUnapproved s ON s.splitNameId = x.splitNameId + JOIN + @conditionId item ON s.conditionId = item.value + + DELETE + x + FROM + [rule].splitNameUnapproved x + JOIN + @conditionId item ON x.conditionId = item.value + + DELETE + x + FROM + [rule].conditionUnapproved x + JOIN + @conditionId item ON x.conditionId = item.value + + + COMMIT TRANSACTION +END TRY +BEGIN CATCH + IF @@TRANCOUNT > 0 + ROLLBACK TRANSACTION + EXEC core.error + RETURN 55555 +END CATCH diff --git a/api/sql/schema/750-rule.rule.discard.sql b/api/sql/schema/750-rule.rule.discard.sql new file mode 100644 index 00000000..a7ef78c7 --- /dev/null +++ b/api/sql/schema/750-rule.rule.discard.sql @@ -0,0 +1,109 @@ +ALTER PROCEDURE [rule].[rule.discard] + @conditionId INT, + @meta core.metaDataTT READONLY -- information for the logged user +AS + +BEGIN TRY + + DECLARE @userId BIGINT = (SELECT [auth.actorId] FROM @meta) + -- checks if the user has a right to get user + DECLARE @actionID VARCHAR(100) = OBJECT_SCHEMA_NAME(@@PROCID) + '.' + OBJECT_NAME(@@PROCID), @return INT = 0 + EXEC @return = [user].[permission.check] @actionId = @actionID, @objectId = NULL, @meta = @meta + IF @return != 0 + BEGIN + RETURN 55555 + END + + IF NOT EXISTS( + SELECT 1 + FROM [rule].[condition] c + WHERE c.conditionId = @conditionId) + AND + NOT EXISTS( + SELECT 1 + FROM [rule].[conditionUnapproved] c + WHERE c.conditionId = @conditionId) + BEGIN + RAISERROR ('rule.ruleNotExists', 16, 1) + END + + + + -- check if the maker and the checker are different users + IF EXISTS ( + SELECT u.updatedBy + FROM [user].[userUnapproved] u + LEFT JOIN [user].[vSystemUser] su ON su.actorId = u.updatedBy + WHERE u.actorId = @userId + AND u.updatedBy = @userId + AND su.actorId IS NULL) + RAISERROR('user.cannotPerformThisOperation', 16, 1) + + BEGIN TRANSACTION + + DECLARE @splitNameId NVARCHAR(25); + SET @splitNameId = (SELECT splitNameId FROM [rule].[splitNameUnapproved] WHERE conditionId = @conditionId ) + + + -- handle condition actor + DELETE FROM [rule].[conditionActorUnapproved] + WHERE conditionId = @conditionId + + + -- handle condition item + DELETE FROM [rule].[conditionItemUnapproved] + WHERE conditionId = @conditionId + + + + -- handle condition property + DELETE FROM [rule].[conditionPropertyUnapproved] + WHERE conditionId = @conditionId + + + -- handle limit + DELETE FROM [rule].limit + WHERE conditionId = @conditionId + + + IF @splitNameId IS NOT NULL + BEGIN + -- handle split analytic + DELETE spa + FROM [rule].[splitAnalyticUnapproved] spa + INNER JOIN [rule].[splitAssignmentUnapproved] sp ON sp.splitAssignmentId = spa.splitAssignmentId + INNER JOIN [rule].[splitNameUnapproved] sn ON sp.splitNameId = sp.splitNameId + WHERE sn.splitNameId = @splitNameId + + + -- handle split assignment + DELETE sau + FROM [rule].[splitAssignmentUnapproved] sau + INNER JOIN [rule].[splitNameUnapproved] sn ON sn.splitNameId = sau.splitNameId + WHERE sn.conditionId = @conditionId + + -- handle split range + DELETE sau + FROM [rule].[splitRangeUnapproved] sau + INNER JOIN [rule].[splitNameUnapproved] sn ON sn.splitNameId = sau.splitNameId + WHERE sn.conditionId = @conditionId + + -- handle split name + DELETE FROM [rule].[splitNameUnapproved] + WHERE conditionid = @conditionId + END + + -- handle condition + DELETE FROM [rule].[conditionUnapproved] + WHERE conditionId = @conditionId + + + COMMIT TRANSACTION + +END TRY +BEGIN CATCH + IF @@TRANCOUNT > 0 + ROLLBACK TRANSACTION + EXEC core.error + RETURN 55555 +END CATCH diff --git a/api/sql/schema/750-rule.rule.edit.sql b/api/sql/schema/750-rule.rule.edit.sql index e73c0122..5130bb09 100644 --- a/api/sql/schema/750-rule.rule.edit.sql +++ b/api/sql/schema/750-rule.rule.edit.sql @@ -10,7 +10,7 @@ AS SET NOCOUNT ON DECLARE @userId BIGINT = (SELECT [auth.actorId] FROM @meta) DECLARE @splitName TABLE (splitNameId INT, rowPosition INT) -DECLARE @splitAssignment [rule].splitAssignmentTT +DECLARE @splitAssignment [rule].splitAssignmentUnapprovedTT DECLARE @conditionId INT = (SELECT conditionId FROM @condition) BEGIN TRY @@ -18,7 +18,7 @@ BEGIN TRY IF EXISTS ( SELECT [priority] - FROM [rule].condition + FROM [rule].conditionUnapproved WHERE [priority] = (SELECT [priority] FROM @condition) AND conditionId != @conditionId AND isDeleted = 0 @@ -37,12 +37,12 @@ BEGIN TRY operationEndDate = DATEADD(ms, -3, DATEADD(dd, 1, DATEADD(dd, DATEDIFF(dd, 0, c1.operationEndDate), 0))), -- the last time on this date - 23:59:59.997 sourceAccountId = c1.sourceAccountId, destinationAccountId = c1.destinationAccountId, - updatedOn = GETUTCDATE(), + updatedOn = GETDATE(), updatedBy = @userId - FROM [rule].condition c + FROM [rule].conditionUnapproved c JOIN @condition c1 ON c.conditionId = c1.conditionId - MERGE INTO [rule].conditionActor ca + MERGE INTO [rule].conditionActorUnapproved ca USING @conditionActor ca1 ON ca.conditionId = ca1.conditionId AND ca.factor = ca1.factor AND ca.actorId = ca1.actorId WHEN NOT MATCHED BY TARGET THEN @@ -51,7 +51,7 @@ BEGIN TRY WHEN NOT MATCHED BY SOURCE AND ca.conditionId = @conditionId THEN DELETE; - MERGE INTO [rule].conditionItem ci + MERGE INTO [rule].conditionItemUnapproved ci USING @conditionItem ci1 ON ci.conditionId = ci1.conditionId AND ci.factor = ci1.factor AND ci.itemNameId = ci1.itemNameId WHEN NOT MATCHED BY TARGET THEN @@ -60,7 +60,7 @@ BEGIN TRY WHEN NOT MATCHED BY SOURCE AND ci.conditionId = @conditionId THEN DELETE; - MERGE INTO [rule].conditionProperty cp + MERGE INTO [rule].conditionPropertyUnapproved cp USING @conditionProperty cp1 ON cp.conditionId = cp1.conditionId AND cp.factor = cp1.factor AND cp.name = cp1.name WHEN MATCHED THEN @@ -72,7 +72,7 @@ BEGIN TRY WHEN NOT MATCHED BY SOURCE AND cp.conditionId = @conditionId THEN DELETE; - MERGE INTO [rule].limit l + MERGE INTO [rule].limitUnapproved l USING @limit l1 ON l.[limitId] = l1.limitId WHEN MATCHED THEN UPDATE @@ -94,25 +94,25 @@ BEGIN TRY DELETE; DELETE x - FROM [rule].splitRange x - JOIN [rule].splitName sn ON x.splitNameId = sn.splitNameId + FROM [rule].splitRangeUnapproved x + JOIN [rule].splitNameUnapproved sn ON x.splitNameId = sn.splitNameId LEFT JOIN @split.nodes('/data/rows/splitRange/splitRangeId') AS records(x) ON x.splitRangeId = records.x.value('(./text())[1]', 'INT') WHERE sn.conditionId = @conditionId AND records.x.value('(./text())[1]', 'INT') IS NULL DELETE x - FROM [rule].splitAnalytic x - JOIN [rule].splitAssignment sa ON x.splitAssignmentId = sa.splitAssignmentId - JOIN [rule].splitName sn ON sa.splitNameId = sn.splitNameId + FROM [rule].splitAnalyticUnapproved x + JOIN [rule].splitAssignmentUnapproved sa ON x.splitAssignmentId = sa.splitAssignmentId + JOIN [rule].splitNameUnapproved sn ON sa.splitNameId = sn.splitNameId LEFT JOIN @split.nodes('/data/rows/splitAssignment/splitAnalytic/splitAnalyticId') AS records(x) ON x.splitAnalyticId = records.x.value('(./text())[1]', 'INT') WHERE sn.conditionId = @conditionId AND records.x.value('(./text())[1]', 'INT') IS NULL DELETE x - FROM [rule].splitAssignment x - JOIN [rule].splitName sn ON x.splitNameId = sn.splitNameId + FROM [rule].splitAssignmentUnapproved x + JOIN [rule].splitNameUnapproved sn ON x.splitNameId = sn.splitNameId LEFT JOIN @split.nodes('/data/rows/splitAssignment/splitAssignmentId') AS records(x) ON x.splitAssignmentId = records.x.value('(./text())[1]', 'INT') WHERE sn.conditionId = @conditionId AND records.x.value('(./text())[1]', 'INT') IS NULL - MERGE INTO [rule].splitName x + MERGE INTO [rule].splitNameUnapproved x USING ( SELECT records.r.value('(./splitNameId)[1]', 'INT') AS splitNameId, @@ -132,7 +132,7 @@ BEGIN TRY DELETE OUTPUT INSERTED.splitNameId, sn.rowPos INTO @splitName; - MERGE INTO [rule].splitRange x + MERGE INTO [rule].splitRangeUnapproved x USING ( SELECT records.x.value('(./splitRangeId)[1]', 'INT') AS splitRangeId, @@ -200,7 +200,7 @@ BEGIN TRY r.[percent], r.percentBase); - MERGE INTO [rule].splitAssignment x + MERGE INTO [rule].splitAssignmentUnapproved x USING ( SELECT records.x.value('(./splitAssignmentId)[1]', 'INT') AS splitAssignmentId, @@ -227,7 +227,7 @@ BEGIN TRY VALUES (r.splitNameId, r.debit, r.credit, r.minValue, r.maxValue, r.[percent], r.description) OUTPUT INSERTED.* INTO @splitAssignment; - MERGE INTO [rule].splitAnalytic x + MERGE INTO [rule].splitAnalyticUnapproved x USING ( SELECT DISTINCT -- new splitAnalytic & new splitAssignment NULL AS [splitAnalyticId], @@ -288,7 +288,7 @@ BEGIN TRY SELECT @conditionId [key], c.priority rulePriority, - GETUTCDATE() editDateTime + GETDATE() editDateTime FROM @condition c FOR XML RAW @@ -297,7 +297,7 @@ BEGIN TRY EXEC core.outcome @proc = @@PROCID, @outcome = @outcome, @meta = @meta - EXEC [rule].[rule.fetch] @conditionId = @conditionId + EXEC [rule].[rule.fetch] @meta = @meta, @conditionId = @conditionId END TRY BEGIN CATCH IF @@TRANCOUNT > 0 diff --git a/api/sql/schema/750-rule.rule.fetch.sql b/api/sql/schema/750-rule.rule.fetch.sql index 6a3fe87d..46252557 100644 --- a/api/sql/schema/750-rule.rule.fetch.sql +++ b/api/sql/schema/750-rule.rule.fetch.sql @@ -1,26 +1,42 @@ ALTER PROCEDURE [rule].[rule.fetch] @conditionId INT = NULL, - @operationCode NVARCHAR(200) = NULL, -- used for filtering, the code of the operation for which the rules are defined - @pageSize INT = 25, -- how many rows will be returned per page - @pageNumber INT = 1, -- which page number to display, - @meta core.metaDataTT READONLY -- information for the logged user + @pageSize INT = 25, + -- how many ROWS will be returned per page + @pageNumber INT = 1, + -- which page number to display, + @meta core.metaDataTT READONLY +-- information for the logged user AS -SET NOCOUNT ON +DECLARE @userId BIGINT = (SELECT [auth.actorId] +FROM @meta) +DECLARE @startRow INT = (@pageNumber - 1) * @pageSize + 1 +DECLARE @endRow INT = @startRow + @pageSize - 1 BEGIN - IF @conditionId IS NOT NULL AND NOT EXISTS (SELECT conditionid FROM [rule].[condition] WHERE conditionId = @conditionId) - RAISERROR ('rule.ruleNotExists', 16, 1) - DECLARE @operationId BIGINT = (SELECT itemNameId FROM core.itemName i - JOIN core.itemType it ON i.itemTypeId = it.itemTypeId - WHERE it.alias = 'operation' AND i.itemCode = @operationCode) + -- checks if the user has a right to get user + DECLARE @actionID VARCHAR(100) = OBJECT_SCHEMA_NAME(@@PROCID) + '.' + OBJECT_NAME(@@PROCID), @return INT = 0 + EXEC @return = [user].[permission.check] @actionId = @actionID, @objectId = NULL, @meta = @meta + IF @return != 0 + BEGIN + RETURN 55555 + END - DECLARE @recordsTotal INT = 0 + IF @conditionId IS NOT NULL AND NOT EXISTS (SELECT conditionId + FROM [rule].[condition] + WHERE conditionId = @conditionId) + AND + NOT EXISTS + (SELECT conditionId + FROM [rule].[conditionUnapproved] + WHERE conditionId = @conditionId) + RAISERROR ('rule.ruleNotExists', 16, 1) IF OBJECT_ID('tempdb..#RuleConditions') IS NOT NULL DROP TABLE #RuleConditions - CREATE TABLE #RuleConditions ( + CREATE TABLE #RuleConditions + ( conditionId INT, [priority] INT, operationEndDate DATETIME, @@ -28,24 +44,53 @@ BEGIN sourceAccountId NVARCHAR(255), destinationAccountId NVARCHAR(255), rowNum INT, - recordsTotal INT) - - INSERT INTO #RuleConditions(conditionId, [priority], operationEndDate, operationStartDate, sourceAccountId, destinationAccountId, rowNum, recordsTotal) - SELECT rc.conditionId, rc.[priority], - rc.operationEndDate, rc.operationStartDate, - rc.sourceAccountId, rc.destinationAccountId, - ROW_NUMBER() OVER(ORDER BY rc.[priority] ASC) AS rowNum, - COUNT(*) OVER(PARTITION BY 1) AS recordsTotal - FROM [rule].condition rc - WHERE (@conditionId IS NULL OR rc.conditionId = @conditionId ) - AND rc.isDeleted = 0 - AND (@operationId IS NULL - OR EXISTS(SELECT * FROM [rule].conditionItem ri WHERE ri.conditionId = rc.conditionId AND ri.factor = 'oc' AND ri.itemNameId = @operationId)) - ORDER BY rc.[priority] ASC - OFFSET (@pageNumber - 1) * @PageSize ROWS - FETCH NEXT @PageSize ROWS ONLY - - SET @recordsTotal = ISNULL((SELECT TOP 1 recordsTotal FROM #RuleConditions), 0) + status VARCHAR(20), + recordsTotal INT, + isEnabled INT + ); + WITH + CTE + AS + ( + SELECT rc.conditionId, + rc.[priority], + rc.operationEndDate, + rc.operationStartDate, + rc.sourceAccountId, + rc.destinationAccountId, + rc.status, + rc.isEnabled, + ROW_NUMBER() OVER(ORDER BY rc.[priority] ASC) AS rowNum, + COUNT(*) OVER(PARTITION BY 1) AS recordsTotal + FROM + ( + SELECT c.conditionId, c.status, c.[priority], c.operationStartDate, c.operationEndDate, c.sourceAccountId, c.destinationAccountId, 0 AS [isDeleted], c.isEnabled + FROM [rule].condition c + LEFT JOIN [rule].conditionUnapproved cu ON cu.conditionId = c.conditionId + UNION ALL + SELECT cu.conditionId, cu.status, cu.[priority], cu.operationStartDate, cu.operationEndDate, cu.sourceAccountId, cu.destinationAccountId, cu.isDeleted, cu.isEnabled + FROM [rule].conditionUnapproved cu + LEFT JOIN [rule].condition c ON c.conditionId = cu.conditionId + ) rc + WHERE (@conditionId IS NULL OR rc.conditionId = @conditionId ) AND rc.isDeleted = 0 + ) + + INSERT INTO #RuleConditions + ( conditionId, [priority], operationEndDate, operationStartDate, sourceAccountId, destinationAccountId, rowNum, recordsTotal, status, isEnabled) + SELECT + conditionId, + [priority], + operationEndDate, + operationStartDate, + sourceAccountId, + destinationAccountId, + rowNum, + recordsTotal, + status, + isEnabled + FROM CTE + WHERE (rowNum BETWEEN @startRow AND @endRow) OR (@startRow >= recordsTotal AND RowNum > recordsTotal - (recordsTotal % @pageSize)) + SELECT 'condition' AS resultSetName SELECT @@ -54,91 +99,165 @@ BEGIN rct.[operationEndDate], rct.[operationStartDate], rct.[sourceAccountId], - rct.[destinationAccountId] + rct.[destinationAccountId], + rct.status, + rct.isEnabled FROM #RuleConditions rct - ORDER BY rct.[priority] ASC SELECT 'conditionActor' AS resultSetName SELECT - ca.*, a.actorType AS [type], co.organizationName + cca.conditionId, cca.factor, cca.actorId, cca.status, + CASE WHEN @conditionId IS NOT NULL THEN CAST(cca.actorId AS NVARCHAR) ELSE org.organizationName END AS actorId, a.actorType AS [type] + -- ca.*, a.actorType AS [type] FROM - [rule].conditionActor ca - JOIN - #RuleConditions rct ON rct.conditionId = ca.conditionId - JOIN - core.actor a ON a.actorId = ca.actorId - LEFT JOIN [customer].[organization] co ON co.actorId = ca.actorId + ( + SELECT ca.conditionId, ca.status, ca.factor, ca.actorId + FROM [rule].conditionActor ca + + UNION ALL + + SELECT cau.conditionId, cau.status, cau.factor, cau.actorId + FROM [rule].conditionActorUnapproved cau + + ) cca + JOIN #RuleConditions rct ON rct.conditionId = cca.conditionId + JOIN core.actor a ON a.actorId = cca.actorId + JOIN customer.organization org ON org.actorId = cca.actorId + WHERE + @conditionId IS NULL OR cca.conditionId = @conditionId SELECT 'conditionItem' AS resultSetName SELECT - c.*, t.alias AS [type], t.name AS itemTypeName, i.itemName + c.conditionId, c.factor, c.status, t.alias AS [type], t.name AS itemTypeName, i.itemName AS itemName FROM - [rule].conditionItem c - JOIN - #RuleConditions rct ON rct.conditionId = c.conditionId - JOIN - core.itemName i ON i.itemNameId = c.itemNameId - JOIN - core.itemType t ON t.itemTypeId = i.itemTypeId + ( + SELECT ci.conditionId, ci.factor, ci.status, ci.itemNameId + FROM [rule].conditionItem ci + + UNION ALL + + SELECT ciu.conditionId, ciu.factor, ciu.status, ciu.itemNameId + FROM [rule].conditionItemUnapproved ciu + ) c + JOIN #RuleConditions rct ON rct.conditionId = c.conditionId + JOIN core.itemName i ON i.itemNameId = c.itemNameId + JOIN core.itemType t ON t.itemTypeId = i.itemTypeId + WHERE + @conditionId IS NULL OR c.conditionId = @conditionId + SELECT 'conditionProperty' AS resultSetName SELECT cp.* FROM - [rule].conditionProperty cp - JOIN - #RuleConditions rct ON rct.conditionId = cp.conditionId + ( + SELECT * + FROM [rule].conditionProperty + + UNION ALL + + SELECT * + FROM [rule].conditionPropertyUnapproved + ) cp + JOIN #RuleConditions rct ON rct.conditionId = cp.conditionId + WHERE + @conditionId IS NULL OR cp.conditionId = @conditionId SELECT 'splitName' AS resultSetName SELECT sn.* FROM - [rule].splitName sn - JOIN - #RuleConditions rct ON rct.conditionId = sn.conditionId + ( + SELECT * + FROM [rule].splitName + + UNION ALL + + SELECT * + FROM [rule].splitNameUnapproved + ) sn + JOIN #RuleConditions rct ON rct.conditionId = sn.conditionId + WHERE + @conditionId IS NULL OR sn.conditionId = @conditionId + + SELECT 'splitRange' AS resultSetName SELECT sr.* FROM - [rule].splitRange sr - JOIN - [rule].splitName sn ON sn.splitNameId = sr.splitNameId - JOIN - #RuleConditions rct ON rct.conditionId = sn.conditionId + ( + SELECT * + FROM [rule].splitRange + + UNION ALL + + SELECT * + FROM [rule].splitRangeUnapproved + ) sr + LEFT JOIN [rule].splitNameUnapproved snu ON snu.splitNameId = sr.splitNameId + LEFT JOIN [rule].splitName sn ON sn.splitNameId = sr.splitNameId + WHERE @conditionId IS NULL OR sn.conditionId = @conditionId OR snu.conditionId = @conditionId SELECT 'splitAssignment' AS resultSetName SELECT sa.* FROM - [rule].splitAssignment sa - JOIN - [rule].splitName sn ON sn.splitNameId = sa.splitNameId - JOIN - #RuleConditions rct ON rct.conditionId = sn.conditionId + ( + SELECT * + FROM [rule].splitAssignment + + UNION ALL + + SELECT * + FROM [rule].splitAssignmentUnapproved + ) sa + LEFT JOIN [rule].splitNameUnapproved snu ON snu.splitNameId = sa.splitNameId + LEFT JOIN [rule].splitName sn ON sn.splitNameId = sa.splitNameId + WHERE @conditionId IS NULL OR sn.conditionId = @conditionId OR snu.conditionId = @conditionId SELECT 'limit' AS resultSetName SELECT l.* FROM - [rule].limit l - JOIN - #RuleConditions rct ON rct.conditionId = l.conditionId + ( + SELECT * + FROM [rule].limit + + UNION ALL + + SELECT * + FROM [rule].limitUnapproved + ) l + JOIN #RuleConditions rct ON rct.conditionId = l.conditionId + WHERE + @conditionId IS NULL OR l.conditionId = @conditionId SELECT 'splitAnalytic' AS resultSetName SELECT san.* FROM - [rule].splitAnalytic san - JOIN - [rule].splitAssignment sa ON sa.splitAssignmentId = san.splitAssignmentId - JOIN - [rule].splitName sn ON sn.splitNameId = sa.splitNameId - JOIN - #RuleConditions rct ON rct.conditionId = sn.conditionId + ( + SELECT * + FROM [rule].splitAnalytic + + UNION ALL + + SELECT * + FROM [rule].splitAnalyticUnapproved ) san + JOIN [rule].splitAssignmentUnapproved sa ON sa.splitAssignmentId = san.splitAssignmentId + JOIN [rule].splitNameUnapproved sn ON sn.splitNameId = sa.splitNameId + JOIN #RuleConditions rct ON rct.conditionId = sn.conditionId + WHERE + @conditionId IS NULL OR sn.conditionId = @conditionId SELECT 'pagination' AS resultSetName - SELECT @pageSize AS pageSize, @recordsTotal AS recordsTotal, @pageNumber AS pageNumber, (@recordsTotal - 1) / @pageSize + 1 AS pagesTotal + SELECT TOP 1 + @pageSize AS pageSize, + recordsTotal AS recordsTotal, + CASE WHEN @pageNumber < (recordsTotal - 1) / @pageSize + 1 THEN @pageNumber ELSE (recordsTotal - 1) / @pageSize + 1 END AS pageNumber, + (recordsTotal - 1) / @pageSize + 1 AS pagesTotal + FROM #RuleConditions DROP TABLE #RuleConditions END diff --git a/api/sql/schema/750-rule.rule.get.sql b/api/sql/schema/750-rule.rule.get.sql new file mode 100644 index 00000000..1376eae5 --- /dev/null +++ b/api/sql/schema/750-rule.rule.get.sql @@ -0,0 +1,219 @@ +ALTER PROCEDURE [rule].[rule.get] + @conditionId INT, + @meta core.metaDataTT READONLY +-- information for the logged user +AS + +BEGIN + + DECLARE @userId BIGINT = (SELECT [auth.actorId] + FROM @meta) + -- checks if the user has a right to get user + DECLARE @actionID VARCHAR(100) = OBJECT_SCHEMA_NAME(@@PROCID) + '.' + OBJECT_NAME(@@PROCID), @return INT = 0 + EXEC @return = [user].[permission.check] @actionId = @actionID, @objectId = NULL, @meta = @meta + IF @return != 0 + BEGIN + RETURN 55555 + END + + IF NOT EXISTS( + SELECT 1 + FROM [rule].condition c + WHERE c.conditionId = @conditionId) + AND + NOT EXISTS( + SELECT 1 + FROM [rule].conditionUnapproved c + WHERE c.conditionId = @conditionId) + RAISERROR ('rule.ruleNotExists', 16, 1) + + + + + SELECT 'condition' AS resultSetName, 1 single + SELECT + c.[conditionId], + c.[priority], + c.[operationEndDate], + c.[operationStartDate], + c.[sourceAccountId], + c.[destinationAccountId], + CASE WHEN co.status IS NOT NULL THEN co.status ELSE c.status END AS [status], + CASE WHEN co.conditionId IS NULL THEN 1 ELSE 0 END AS [isNew], + c.[isEnabled] + FROM [rule].condition c + LEFT JOIN [rule].conditionUnapproved co ON co.conditionId = c.conditionId + WHERE c.conditionId = @conditionId + + SELECT 'conditionUnapproved' AS resultSetName, 1 single + SELECT + c.[conditionId], + c.[priority], + c.[operationEndDate], + c.[operationStartDate], + c.[sourceAccountId], + c.[destinationAccountId], + c.[rejectReason], + c.status, + CASE WHEN co.conditionId IS NULL THEN 1 ELSE 0 END AS [isNew], + c.[isEnabled] + FROM [rule].conditionUnapproved c + LEFT JOIN [rule].[condition] co ON co.conditionId = c.conditionId + WHERE c.conditionId = @conditionId + + + + + SELECT 'conditionActor' AS resultSetName + SELECT + cca.conditionId, cca.factor, cca.actorId, CASE WHEN cau.status IS NOT NULL THEN cau.status ELSE cca.status END AS [status], org.organizationName AS actorId, a.actorType AS [type] + -- ca.*, a.actorType AS [type] + FROM [rule].conditionActor cca + JOIN + core.actor a ON a.actorId = cca.actorId + JOIN + customer.organization org ON org.actorId = cca.actorId + LEFT JOIN + [rule].conditionActorUnapproved cau ON cau.conditionId = cca.conditionId + WHERE cca.conditionId = @conditionId + + SELECT 'conditionActorUnapproved' AS resultSetName + SELECT + cca.conditionId, cca.factor, cca.actorId, cca.status, org.organizationName AS actorId, a.actorType AS [type] + -- ca.*, a.actorType AS [type] + FROM [rule].conditionActorUnapproved cca + JOIN + core.actor a ON a.actorId = cca.actorId + JOIN + customer.organization org ON org.actorId = cca.actorId + WHERE cca.conditionId = @conditionId + + + + SELECT 'conditionItem' AS resultSetName + SELECT + c.conditionId, c.factor, CASE WHEN ciu.status IS NOT NULL THEN ciu.status ELSE c.status END AS [status], t.alias AS [type], t.name AS itemTypeName, i.itemName AS itemName + FROM [rule].conditionItem AS c + JOIN core.itemName i ON i.itemNameId = c.itemNameId + JOIN core.itemType t ON t.itemTypeId = i.itemTypeId + LEFT JOIN + [rule].conditionItemUnapproved ciu ON ciu.conditionId = c.conditionId + WHERE c.conditionId = @conditionId + + + SELECT 'conditionItemUnapproved' AS resultSetName + SELECT + c.conditionId, c.factor, c.status, t.alias AS [type], t.name AS itemTypeName, i.itemName AS itemName + FROM [rule].conditionItemUnapproved AS c + JOIN core.itemName i ON i.itemNameId = c.itemNameId + JOIN core.itemType t ON t.itemTypeId = i.itemTypeId + WHERE c.conditionId = @conditionId + + + + SELECT 'conditionProperty' AS resultSetName + SELECT + cp.conditionId, cp.factor, cp.name, cp.value, CASE WHEN cpu.status IS NOT NULL THEN cpu.status ELSE cp.status END AS [status] + FROM [rule].conditionProperty cp + LEFT JOIN [rule].conditionPropertyUnapproved cpu ON cpu.conditionId = cp.conditionId + WHERE cp.conditionId = @conditionId + + + SELECT 'conditionPropertyUnapproved' AS resultSetName + SELECT + cp.* + FROM [rule].conditionPropertyUnapproved cp + WHERE cp.conditionId = @conditionId + + + + + SELECT 'splitName' AS resultSetName + SELECT + sn.conditionId, sn.name, sn.splitNameId, sn.tag, CASE WHEN snu.status IS NOT NULL THEN snu.status ELSE sn.status END AS [status] + FROM [rule].splitName sn + LEFT JOIN [rule].splitNameUnapproved snu ON snu.conditionId = sn.conditionId + WHERE sn.conditionId = @conditionId + + SELECT 'splitNameUnapproved' AS resultSetName + SELECT + sn.* + FROM [rule].splitNameUnapproved sn + WHERE sn.conditionId = @conditionId + + + + SELECT 'splitRange' AS resultSetName + SELECT + sr.isSourceAmount, sr.maxValue, sr.minValue, sr.[percent], sr.percentBase, sr.splitNameId, sr.startAmount, sr.startAmountCurrency, + sr.startAmountDaily, sr.startAmountMonthly, sr.startAmountWeekly, sr.startCountDaily, sr.startCountMonthly, sr.startCountWeekly, + CASE WHEN sru.status IS NOT NULL THEN sru.status ELSE sr.status END AS [status] + FROM [rule].splitRange sr + JOIN [rule].splitName sn ON sn.splitNameId = sr.splitNameId + LEFT JOIN [rule].splitNameUnapproved snu ON snu.conditionId = sn.conditionId + LEFT JOIN [rule].splitRangeUnapproved sru ON sru.splitNameId = snu.splitNameId + WHERE sn.conditionId = @conditionId + + SELECT 'splitRangeUnapproved' AS resultSetName + SELECT + sr.* + FROM [rule].splitRangeUnapproved sr + JOIN [rule].splitNameUnapproved sn ON sn.splitNameId = sr.splitNameId + WHERE sn.conditionId = @conditionId + + + + + SELECT 'splitAssignment' AS resultSetName + SELECT + sa.credit, sa.debit, sa.description, sa.maxValue, sa.minValue, sa.[percent], sa.splitAssignmentId, sa.splitNameId, CASE WHEN sau.status IS NOT NULL THEN sau.status ELSE sa.status END AS status + FROM [rule].splitAssignment sa + JOIN [rule].splitName sn ON sn.splitNameId = sa.splitNameId + LEFT JOIN [rule].splitAssignmentUnapproved sau ON sau.splitAssignmentId = sa.splitAssignmentId + WHERE sn.conditionId = @conditionId + + SELECT 'splitAssignmentUnapproved' AS resultSetName + SELECT + sa.* + FROM [rule].splitAssignmentUnapproved sa + JOIN [rule].splitNameUnapproved sn ON sn.splitNameId = sa.splitNameId + WHERE sn.conditionId = @conditionId + + + + + SELECT 'limit' AS resultSetName + SELECT + l.conditionId, l.credentials, l.currency, l.limitId, l.maxAmount, l.maxAmountDaily, l.maxAmountMonthly, l.maxAmountWeekly, + l.maxCountDaily, l.maxCountMonthly, l.maxCountWeekly, l.minAmount, l.priority, CASE WHEN lu.status IS NOT NULL THEN lu.status ELSE l.status END AS [status] + FROM [rule].limit l + LEFT JOIN [rule].limitUnapproved lu ON lu.limitId = l.limitId + WHERE l.conditionId = @conditionId + + SELECT 'limitUnapproved' AS resultSetName + SELECT + l.* + FROM [rule].limitUnapproved l + WHERE l.conditionId = @conditionId + + + + + SELECT 'splitAnalytic' AS resultSetName + SELECT + san.name, san.splitAnalyticId, san.splitAssignmentId, san.value, CASE WHEN sau.status IS NOT NULL THEN sau.status ELSE san.status END AS [status] + FROM [rule].splitAnalytic san + JOIN [rule].splitAssignment sa ON sa.splitAssignmentId = san.splitAssignmentId + JOIN [rule].splitName sn ON sn.splitNameId = sa.splitNameId + LEFT JOIN [rule].splitAnalyticUnapproved sau ON sau.splitAnalyticId = san.splitAnalyticId + WHERE sn.conditionId = @conditionId + + SELECT 'splitAnalyticUnapproved' AS resultSetName + SELECT + san.* + FROM [rule].splitAnalyticUnapproved san + JOIN [rule].splitAssignmentUnapproved sa ON sa.splitAssignmentId = san.splitAssignmentId + JOIN [rule].splitNameUnapproved sn ON sn.splitNameId = sa.splitNameId + WHERE sn.conditionId = @conditionId + + END diff --git a/api/sql/schema/750-rule.rule.reject.sql b/api/sql/schema/750-rule.rule.reject.sql new file mode 100644 index 00000000..e8faa72c --- /dev/null +++ b/api/sql/schema/750-rule.rule.reject.sql @@ -0,0 +1,148 @@ +ALTER PROCEDURE [rule].[rule.reject] + @conditionId INT, + @rejectReason NVARCHAR(MAX), -- the reason the user was rejected by the checker + @meta core.metaDataTT READONLY -- information for the logged user +AS + +BEGIN TRY + + DECLARE @userId BIGINT = (SELECT [auth.actorId] FROM @meta) + -- checks if the user has a right to get user + DECLARE @actionID VARCHAR(100) = OBJECT_SCHEMA_NAME(@@PROCID) + '.' + OBJECT_NAME(@@PROCID), @return INT = 0 + EXEC @return = [user].[permission.check] @actionId = @actionID, @objectId = NULL, @meta = @meta + IF @return != 0 + BEGIN + RETURN 55555 + END + + IF NOT EXISTS( + SELECT 1 + FROM [rule].[condition] c + WHERE c.conditionId = @conditionId) + AND + NOT EXISTS( + SELECT 1 + FROM [rule].[conditionUnapproved] c + WHERE c.conditionId = @conditionId) + BEGIN + RAISERROR ('rule.ruleNotExists', 16, 1) + END + + + + -- check if the maker and the checker are different users + IF EXISTS ( + SELECT u.updatedBy + FROM [user].[userUnapproved] u + LEFT JOIN [user].[vSystemUser] su ON su.actorId = u.updatedBy + WHERE u.actorId = @userId + AND u.updatedBy = @userId + AND su.actorId IS NULL) + RAISERROR('user.cannotPerformThisOperation', 16, 1) + + BEGIN TRANSACTION + + -- handle condition + UPDATE c + SET + c.status = 'rejected', + c.rejectReason = @rejectReason + FROM [rule].[conditionUnapproved] c + WHERE c.conditionId = @conditionId + + + + + -- handle condition actor + UPDATE ca + SET + ca.status = 'rejected' + FROM [rule].[conditionActorUnapproved] ca + WHERE ca.conditionId = @conditionId + + + + -- handle condition item + UPDATE ca + SET + ca.status = 'rejected' + FROM [rule].[conditionItemUnapproved] ca + WHERE ca.conditionId = @conditionId + + + + -- handle condition property + UPDATE ca + SET + ca.status = 'rejected' + FROM [rule].[conditionPropertyUnapproved] ca + WHERE ca.conditionId = @conditionId + + + + -- handle limit + UPDATE ca + SET + ca.status = 'rejected' + FROM [rule].limit ca + WHERE ca.conditionId = @conditionId + + + + -- handle split analytic + UPDATE spa + SET + spa.status = 'rejected' + FROM [rule].[splitAnalyticUnapproved] spa + INNER JOIN [rule].[splitAssignmentUnapproved] sp ON sp.splitAssignmentId = spa.splitAssignmentId + INNER JOIN [rule].[splitNameUnapproved] sn ON sp.splitNameId = sp.splitNameId + WHERE sn.conditionId = @conditionId + + + + -- handle split name + UPDATE sn + SET + sn.status = 'rejected' + FROM [rule].[splitNameUnapproved] sn + WHERE sn.conditionid = @conditionId + + + + -- handle split range + UPDATE sa + SET + sa.status = 'rejected' + FROM [rule].[splitRangeUnapproved] sa + JOIN [rule].[splitNameUnapproved] sna ON sa.splitNameId = sna.splitNameId + WHERE sna.conditionId = @conditionId + + + -- handle split assignment + UPDATE sa + SET + sa.status = 'rejected' + FROM [rule].[splitAssignmentUnapproved] sa + JOIN [rule].[splitNameUnapproved] sna ON sa.splitNameId = sna.splitNameId + WHERE sna.conditionId = @conditionId + + + + -- handle split range + UPDATE sr + SET + sa.status = 'rejected' + FROM [rule].[splitRangeUnapproved] sr + JOIN [rule].[splitNameUnapproved] sna ON sr.splitNameId = sna.splitNameId + WHERE sna.conditionId = @conditionId + + + COMMIT TRANSACTION + +END TRY +BEGIN CATCH + IF @@TRANCOUNT > 0 + ROLLBACK TRANSACTION + EXEC core.error + RETURN 55555 +END CATCH diff --git a/api/sql/schema/751-rule.alter.sql b/api/sql/schema/751-rule.alter.sql new file mode 100644 index 00000000..f72af8e6 --- /dev/null +++ b/api/sql/schema/751-rule.alter.sql @@ -0,0 +1,101 @@ +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'status' AND OBJECT_ID = OBJECT_ID(N'rule.condition')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[condition] + ADD status VARCHAR(20) NULL DEFAULT('pending') + + ALTER TABLE [rule].[condition] + WITH CHECK ADD CONSTRAINT [fk_condition_status] FOREIGN KEY ([status]) + REFERENCES [core].[status] ([statusId]) + END + +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'status' AND OBJECT_ID = OBJECT_ID(N'rule.conditionActor')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[conditionActor] + ADD status VARCHAR(20) NULL DEFAULT('pending') + + ALTER TABLE [rule].[conditionActor] + WITH CHECK ADD CONSTRAINT [fk_conditionActor_status] FOREIGN KEY ([status]) + REFERENCES [core].[status] ([statusId]) + END + +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'status' AND OBJECT_ID = OBJECT_ID(N'rule.conditionItem')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[conditionItem] + ADD status VARCHAR(20) NULL DEFAULT('pending') + + ALTER TABLE [rule].[conditionItem] + WITH CHECK ADD CONSTRAINT [fk_conditionItem_status] FOREIGN KEY ([status]) + REFERENCES [core].[status] ([statusId]) + END + +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'status' AND OBJECT_ID = OBJECT_ID(N'rule.conditionProperty')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[conditionProperty] + ADD status VARCHAR(20) NULL DEFAULT('pending') + + ALTER TABLE [rule].[conditionProperty] + WITH CHECK ADD CONSTRAINT [fk_conditionProperty_status] FOREIGN KEY ([status]) + REFERENCES [core].[status] ([statusId]) + END + +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'status' AND OBJECT_ID = OBJECT_ID(N'rule.limit')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[limit] + ADD status VARCHAR(20) NULL DEFAULT('pending') + + ALTER TABLE [rule].[limit] + WITH CHECK ADD CONSTRAINT [fk_limit_status] FOREIGN KEY ([status]) + REFERENCES [core].[status] ([statusId]) + END + +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'status' AND OBJECT_ID = OBJECT_ID(N'rule.splitName')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[splitName] + ADD status VARCHAR(20) NULL DEFAULT('pending') + + ALTER TABLE [rule].[splitName] + WITH CHECK ADD CONSTRAINT [fk_splitName_status] FOREIGN KEY ([status]) + REFERENCES [core].[status] ([statusId]) + END + +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'status' AND OBJECT_ID = OBJECT_ID(N'rule.splitAssignment')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[splitAssignment] + ADD status VARCHAR(20) NULL DEFAULT('pending') + + ALTER TABLE [rule].[splitAssignment] + WITH CHECK ADD CONSTRAINT [fk_splitAssignment_status] FOREIGN KEY ([status]) + REFERENCES [core].[status] ([statusId]) + END + +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'status' AND OBJECT_ID = OBJECT_ID(N'rule.splitRange')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[splitRange] + ADD status VARCHAR(20) NULL DEFAULT('pending') + + ALTER TABLE [rule].[splitRange] + WITH CHECK ADD CONSTRAINT [fk_splitRange_status] FOREIGN KEY ([status]) + REFERENCES [core].[status] ([statusId]) + END + +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'status' AND OBJECT_ID = OBJECT_ID(N'rule.splitAnalytic')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[splitAnalytic] + ADD status VARCHAR(20) NULL DEFAULT('pending') + + ALTER TABLE [rule].[splitAnalytic] + WITH CHECK ADD CONSTRAINT [fk_splitAnalytic_status] FOREIGN KEY ([status]) + REFERENCES [core].[status] ([statusId]) + END + +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'isEnabled' AND OBJECT_ID = OBJECT_ID(N'rule.condition')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[condition] + ADD isEnabled BIT NOT NULL DEFAULT(0) + END + +IF NOT EXISTS(SELECT 1 FROM sys.columns WHERE Name = N'isEnabled' AND OBJECT_ID = OBJECT_ID(N'rule.conditionUnapproved')) -- add column if it does not exist + BEGIN + ALTER TABLE [rule].[conditionUnapproved] + ADD isEnabled BIT NOT NULL DEFAULT(0) + END diff --git a/api/sql/schema/751-rule.rule.lock.sql b/api/sql/schema/751-rule.rule.lock.sql new file mode 100644 index 00000000..d85dc49b --- /dev/null +++ b/api/sql/schema/751-rule.rule.lock.sql @@ -0,0 +1,53 @@ +ALTER PROCEDURE [rule].[rule.lock] -- the SP locks/unlocks(after approval) selected rules + @conditionId BIGINT, -- a condition id + @isEnabled BIT, -- the condition status to set + @meta core.metaDataTT READONLY -- information for the user that makes the operation +AS +BEGIN TRY + DECLARE @userId BIGINT = (SELECT [auth.actorId] FROM @meta) + + -- checks if the user has a right to make the operation + DECLARE @actionID VARCHAR(100) = OBJECT_SCHEMA_NAME(@@PROCID) + '.' + OBJECT_NAME(@@PROCID), @return INT = 0 + EXEC @return = [user].[permission.check] @actionId = @actionID, @objectId = NULL, @meta = @meta + IF @return != 0 + BEGIN + RETURN 55555 + END + + IF EXISTS( + SELECT ru.status + FROM [rule].conditionUnapproved ru + WHERE ru.status IN ('new', 'pending') AND @conditionId = ru.conditionId + ) + BEGIN + RAISERROR('user.cannotLockRule', 16, 1); + RETURN 5555 + END + + + IF @isEnabled = 1 + BEGIN + UPDATE c + SET isEnabled = @isEnabled, + updatedBy = @userId, + updatedOn = SYSDATETIME() + FROM [rule].condition c + WHERE c.conditionId = @conditionId + END + ELSE + BEGIN + SET IDENTITY_INSERT [rule].[conditionUnapproved] ON + INSERT INTO [rule].[conditionUnapproved] (conditionId, priority, status, operationStartDate, operationEndDate, sourceAccountId, isDeleted, createdBy, updatedBy, isEnabled) + SELECT cu.conditionId, cu.priority, 'pending', cu.operationStartDate, cu.operationEndDate, cu.sourceAccountId, 0, @userId, @userId, @isEnabled + FROM [rule].[condition] cu + WHERE cu.conditionId = @conditionId + SET IDENTITY_INSERT [rule].[conditionUnapproved] OFF + END + +END TRY +BEGIN CATCH + IF @@TRANCOUNT > 0 + ROLLBACK TRANSACTION + EXEC core.error + RETURN 55555 +END CATCH diff --git a/portal/index.stories.old.js b/portal/index.stories.old.js index 7fd17932..2ce63fdd 100644 --- a/portal/index.stories.old.js +++ b/portal/index.stories.old.js @@ -52,6 +52,17 @@ const page = app({ splitAnalytic: [], pagination: [] }), + 'rule.rule.addUnapproved': () => ({ + condition: [], + conditionActor: [], + conditionItem: [], + conditionProperty: [], + splitName: [], + splitRange: [], + splitAssignment: [], + limit: [], + splitAnalytic: [] + }), 'rule.rule.fetchDeleted': () => ({ condition: [], pagination: [] diff --git a/ui/react/components/Grid/index.js b/ui/react/components/Grid/index.js index 2f9c7014..7f8ced7c 100644 --- a/ui/react/components/Grid/index.js +++ b/ui/react/components/Grid/index.js @@ -1,12 +1,13 @@ import PropTypes from 'prop-types'; import React from 'react'; -import {fromJS} from 'immutable'; -import {SimpleGrid} from 'ut-front-react/components/SimpleGrid'; +import { fromJS } from 'immutable'; +import { SimpleGrid } from 'ut-front-react/components/SimpleGrid'; import { updateGridColumnStorage, prepareGridFields } from 'ut-front-react/components/GridMenu/helpers'; import Text from 'ut-front-react/components/Text'; import style from './style.css'; import { Link } from 'react-router-dom'; + const propInStorage = 'rule_grid_fields'; export default class Grid extends React.Component { @@ -22,13 +23,17 @@ export default class Grid extends React.Component { state = { expandedGridColumns: [], columns: this.props.columns, - fields: prepareGridFields(propInStorage, [ - {title: this.props.columns.priority.title, name: 'priority'}, - {title: this.props.columns.channel.title, name: 'channel'}, - {title: this.props.columns.operation.title, name: 'operation'}, - {title: this.props.columns.source.title, name: 'source'}, - {title: this.props.columns.destination.title, name: 'destination'}, - {title: this.props.columns.limit.title, name: 'limit'}, + fields: this.prepareFields() + }; + + prepareFields() { + const fields = prepareGridFields(propInStorage, [ + { title: this.props.columns.priority.title, name: 'priority' }, + { title: this.props.columns.channel.title, name: 'channel' }, + { title: this.props.columns.operation.title, name: 'operation' }, + { title: this.props.columns.source.title, name: 'source' }, + { title: this.props.columns.destination.title, name: 'destination' }, + { title: this.props.columns.limit.title, name: 'limit' }, { title: 'Expansion', name: 'expansion' @@ -36,8 +41,19 @@ export default class Grid extends React.Component { ].map(f => { f.key = f.name; return f; - })) - }; + })); + + const findStatus = fields.filter(item => item.name === 'status'); + if (findStatus.length === 0) { + fields.splice(2, 0, { title: this.props.columns.status.title, name: 'status' }); // insert column to the 3rd position + } + + const findLock = fields.filter(item => item.name === 'isEnabled'); + if (findLock.length === 0) { + fields.splice(5, 0, { title: this.props.columns.lock.title, name: 'isEnabled' }); // insert column to the 6th position + } + return fields; + } handleGridExpansion = (id) => { const expandedGridColumns = this.state.expandedGridColumns; @@ -47,7 +63,7 @@ export default class Grid extends React.Component { } else { expandedGridColumns.push(id); } - this.setState({expandedGridColumns}); + this.setState({ expandedGridColumns }); }; renderGridColumn = (condition, keysToInclude, row, column) => { @@ -55,6 +71,7 @@ export default class Grid extends React.Component { for (const keyToInclude of keysToInclude) { if (Array.isArray(condition[keyToInclude])) { for (const index in condition[keyToInclude]) { + // console.log('conditionssss', condition); const record = condition[keyToInclude][index]; if (index > 4 && !this.state.expandedGridColumns.some(v => v === row.priority)) break; result.push(