public async Task <ReconciliationGetReconciledResponse> SaveAndGetReconciled(ReconciliationSavePayload payload, ReconciliationGetReconciledArguments args)
        {
            // Start transaction
            using var trx = ControllerUtilities.CreateTransaction();

            // Preprocess and Validate
            await PermissionsPreprocessAndValidate(args.AccountId, args.CustodyId, payload);

            // Save
            var(
                reconciledCount,
                reconciliations
                ) = await _repo.Reconciliations__SaveAndLoad_Reconciled(
                accountId : args.AccountId,
                custodyId : args.CustodyId,
                externalEntriesForSave : payload.ExternalEntries,
                reconciliations : payload.Reconciliations,
                deletedExternalEntryIds : payload.DeletedExternalEntryIds,
                deletedReconciliationIds : payload.DeletedReconciliationIds,
                fromDate : args.FromDate,
                toDate : args.ToDate,
                fromAmount : args.FromAmount,
                toAmount : args.ToAmount,
                externalReferenceContains : args.ExternalReferenceContains,
                top : args.Top,
                skip : args.Skip);

            trx.Complete();

            return(new ReconciliationGetReconciledResponse
            {
                ReconciledCount = reconciledCount,
                Reconciliations = reconciliations
            });
        }
        public async Task <UnreconciledResult> SaveAndGetUnreconciled(ReconciliationSavePayload payload, ReconciliationGetUnreconciledArguments args)
        {
            await Initialize();

            // Start transaction
            using var trx = TransactionFactory.ReadCommitted();

            // Preprocess and Validate
            await PermissionsPreprocessAndValidate(args.AccountId, args.AgentId, payload);

            // Save
            UnreconciledOutput output = await _behavior.Repository.Reconciliations__SaveAndLoad_Unreconciled(
                accountId : args.AccountId,
                agentId : args.AgentId,
                externalEntriesForSave : payload.ExternalEntries,
                reconciliations : payload.Reconciliations,
                deletedExternalEntryIds : payload.DeletedExternalEntryIds,
                deletedReconciliationIds : payload.DeletedReconciliationIds,
                asOfDate : args.AsOfDate,
                top : args.EntriesTop,
                skip : args.EntriesSkip,
                topExternal : args.ExternalEntriesTop,
                skipExternal : args.ExternalEntriesSkip,
                userId : UserId);

            trx.Complete();

            return(MapFromOutput(output));
        }
Example #3
0
        public async Task <ActionResult <ReconciliationGetReconciledResponse> > SaveAndGetReconciled([FromBody] ReconciliationSavePayload payload, [FromQuery] ReconciliationGetReconciledArguments args)
        {
            var result = await _service.SaveAndGetReconciled(payload, args);

            return(Ok(MapFromResult(result)));
        }
 public async Task <ActionResult <ReconciliationGetReconciledResponse> > SaveAndGetReconciled([FromBody] ReconciliationSavePayload payload, [FromQuery] ReconciliationGetReconciledArguments args)
 {
     return(await ControllerUtilities.InvokeActionImpl(async() =>
     {
         var result = await _service.SaveAndGetReconciled(payload, args);
         return Ok(result);
     },
                                                       _logger));
 }
        private async Task PermissionsPreprocessAndValidate(int accountId, int custodyId, ReconciliationSavePayload payload)
        {
            // Authorized access (Criteria are not supported here)
            var permissions = await _repo.PermissionsFromCache(VIEW, Constants.Update, default);

            if (!permissions.Any())
            {
                throw new ForbiddenException();
            }

            // Makes the subsequent logic simpler
            payload.ExternalEntries ??= new List <ExternalEntryForSave>();
            payload.Reconciliations ??= new List <ReconciliationForSave>();
            foreach (var reconciliation in payload.Reconciliations)
            {
                reconciliation.Entries ??= new List <ReconciliationEntryForSave>();
                reconciliation.ExternalEntries ??= new List <ReconciliationExternalEntryForSave>();
            }

            // Trim the only string property
            payload.ExternalEntries.ForEach(e =>
            {
                if (e != null && e.ExternalReference != null)
                {
                    e.ExternalReference = e.ExternalReference.Trim();
                }
            });

            // C# Validation
            int?tenantId = _tenantIdAccessor.GetTenantIdIfAny();

            var exEntryMeta = _metadata.GetMetadata(tenantId, typeof(ExternalEntryForSave));

            ValidateList(payload.ExternalEntries, exEntryMeta, "ExternalEntries");

            var reconciliationMeta = _metadata.GetMetadata(tenantId, typeof(ReconciliationForSave));

            ValidateList(payload.Reconciliations, reconciliationMeta, "Reconciliation");

            ModelState.ThrowIfInvalid();

            // SQL Validation
            int remainingErrorCount = ModelState.MaxAllowedErrors - ModelState.ErrorCount;
            var sqlErrors           = await _repo.Reconciliations_Validate__Save(
                accountId : accountId,
                custodyId : custodyId,
                externalEntriesForSave : payload.ExternalEntries,
                reconciliations : payload.Reconciliations,
                top : ModelState.MaxAllowedErrors);

            ModelState.AddLocalizedErrors(sqlErrors, _localizer);
            ModelState.ThrowIfInvalid();
        }
        public async Task <ReconciliationGetUnreconciledResponse> SaveAndGetUnreconciled(ReconciliationSavePayload payload, ReconciliationGetUnreconciledArguments args)
        {
            // Start transaction
            using var trx = ControllerUtilities.CreateTransaction();

            // Preprocess and Validate
            await PermissionsPreprocessAndValidate(args.AccountId, args.CustodyId, payload);

            // Save
            var(
                entriesBalance,
                unreconciledEntriesBalance,
                unreconciledExternalEntriesBalance,
                unreconciledEntriesCount,
                unreconciledExternalEntriesCount,
                entries,
                externalEntries
                ) = await _repo.Reconciliations__SaveAndLoad_Unreconciled(
                accountId : args.AccountId,
                custodyId : args.CustodyId,
                externalEntriesForSave : payload.ExternalEntries,
                reconciliations : payload.Reconciliations,
                deletedExternalEntryIds : payload.DeletedExternalEntryIds,
                deletedReconciliationIds : payload.DeletedReconciliationIds,
                asOfDate : args.AsOfDate,
                top : args.EntriesTop,
                skip : args.EntriesSkip,
                topExternal : args.ExternalEntriesTop,
                skipExternal : args.ExternalEntriesSkip);

            trx.Complete();

            return(new ReconciliationGetUnreconciledResponse
            {
                EntriesBalance = entriesBalance,
                UnreconciledEntriesBalance = unreconciledEntriesBalance,
                UnreconciledExternalEntriesBalance = unreconciledExternalEntriesBalance,
                UnreconciledEntriesCount = unreconciledEntriesCount,
                UnreconciledExternalEntriesCount = unreconciledExternalEntriesCount,
                Entries = entries,
                ExternalEntries = externalEntries
            });
        }
        private async Task PermissionsPreprocessAndValidate(int accountId, int agentId, ReconciliationSavePayload payload)
        {
            // Authorized access (Criteria are not supported here)
            var permissions = await UserPermissions(PermissionActions.Update);

            if (!permissions.Any())
            {
                throw new ForbiddenException();
            }

            // Makes the subsequent logic simpler
            payload.ExternalEntries ??= new List <ExternalEntryForSave>();
            payload.Reconciliations ??= new List <ReconciliationForSave>();
            foreach (var reconciliation in payload.Reconciliations)
            {
                reconciliation.Entries ??= new List <ReconciliationEntryForSave>();
                reconciliation.ExternalEntries ??= new List <ReconciliationExternalEntryForSave>();
            }

            // Trim the only string property
            payload.ExternalEntries.ForEach(e =>
            {
                if (e != null && e.ExternalReference != null)
                {
                    e.ExternalReference = e.ExternalReference.Trim();
                }
            });

            // Structural Validation
            int tenantId    = _behavior.TenantId;
            var exEntryMeta = _metadata.GetMetadata(tenantId, typeof(ExternalEntryForSave), null, null);

            ValidateList(payload.ExternalEntries, exEntryMeta, nameof(payload.ExternalEntries));

            var reconciliationMeta = _metadata.GetMetadata(tenantId, typeof(ReconciliationForSave), null, null);

            ValidateList(payload.Reconciliations, reconciliationMeta, nameof(payload.Reconciliations));

            ModelState.ThrowIfInvalid();

            // SQL Validation
            var sqlErrors = await _behavior.Repository.Reconciliations_Validate__Save(
                accountId : accountId,
                agentId : agentId,
                externalEntriesForSave : payload.ExternalEntries,
                reconciliations : payload.Reconciliations,
                top : ModelState.RemainingErrors,
                userId : UserId);

            AddLocalizedErrors(sqlErrors, _localizer);
            ModelState.ThrowIfInvalid();
        }