/// <summary> /// Build the dynamic edit controls for this file format. /// </summary> /// <param name="fileFormat">The file format whose controls need to be built.</param> /// <param name="SetValues">Whether or not to set the initial values.</param> protected void BuildDynamicControls(ImageCashLetterFileFormat fileFormat, bool SetValues) { FileFormatEntityTypeId = fileFormat.EntityTypeId; fileFormat.LoadAttributes(); phEditAttributes.Controls.Clear(); Rock.Attribute.Helper.AddEditControls(fileFormat, phEditAttributes, SetValues, BlockValidationGroup, new List <string> { "Active", "Order" }, false, 2); foreach (var tb in phAttributes.ControlsOfTypeRecursive <TextBox>()) { tb.AutoCompleteType = AutoCompleteType.Disabled; tb.Attributes["autocomplete"] = "off"; } }
/// <summary> /// Gets the bundle control record (type 70). /// </summary> /// <param name="fileFormat">The file format that contains the configuration to use.</param> /// <param name="records">The existing records in the bundle.</param> /// <returns>A BundleControl record.</returns> protected virtual X937.Records.BundleControl GetBundleControl(ImageCashLetterFileFormat fileFormat, List <X937.Record> records) { var checkDetailRecords = records.Where(r => r.GetType() == typeof(X937.Records.CheckDetail)) .Cast <X937.Records.CheckDetail>(); var imageViewRecords = records.Where(r => r.GetType() == typeof(X937.Records.ImageViewDetail) || r.GetType() == typeof(X937.Records.ImageViewData)); var control = new X937.Records.BundleControl { ItemCount = checkDetailRecords.Count(), TotalAmount = checkDetailRecords.Sum(r => r.ItemAmount), MICRValidTotalAmount = checkDetailRecords.Sum(r => r.ItemAmount), ImageCount = imageViewRecords.Count() }; return(control); }
/// <summary> /// Gets the file control record (type 99). /// </summary> /// <param name="fileFormat">The file format that contains the configuration to use.</param> /// <param name="records">The existing records in the file.</param> /// <returns>A FileControl record.</returns> protected virtual X937.Records.FileControl GetFileControlRecord(ImageCashLetterFileFormat fileFormat, List <X937.Record> records) { var detailRecords = records.Where(r => r.GetType() == typeof(X937.Records.CheckDetail)) .Cast <X937.Records.CheckDetail>(); var control = new X937.Records.FileControl { CashLetterCount = records.Count(r => r.GetType() == typeof(X937.Records.CashLetterHeader)), TotalRecordCount = records.Count + 1, TotalItemCount = detailRecords.Count(), TotalAmount = detailRecords.Sum(c => c.ItemAmount), ImmediateOriginContactName = GetAttributeValue(fileFormat, "ContactName"), ImmediateOriginContactPhoneNumber = GetAttributeValue(fileFormat, "ContactPhone") }; return(control); }
/// <summary> /// Gets the item detail records (type 25, 26, etc.) /// </summary> /// <param name="fileFormat">The file format that contains the configuration to use.</param> /// <param name="transaction">The transaction being deposited.</param> /// <returns>A collection of records.</returns> protected virtual List <X937.Record> GetItemDetailRecords(ImageCashLetterFileFormat fileFormat, FinancialTransaction transaction) { var accountNumber = Rock.Security.Encryption.DecryptString(GetAttributeValue(fileFormat, "AccountNumber")); var routingNumber = Rock.Security.Encryption.DecryptString(GetAttributeValue(fileFormat, "RoutingNumber")); // // Parse the MICR data from the transaction. // var micr = new Micr(Rock.Security.Encryption.DecryptString(transaction.CheckMicrEncrypted)); var transactionRoutingNumber = micr.GetField(5); // // Get the Check Detail record (type 25). // var detail = new X937.Records.CheckDetail { PayorBankRoutingNumber = transactionRoutingNumber.Substring(0, 8), PayorBankRoutingNumberCheckDigit = transactionRoutingNumber.Substring(8, 1), OnUs = micr.GetField(3) + "/" + micr.GetField(2), ExternalProcessingCode = micr.GetField(6), AuxiliaryOnUs = micr.GetField(7), ItemAmount = transaction.TotalAmount, ClientInstitutionItemSequenceNumber = accountNumber, DocumentationTypeIndicator = "G", BankOfFirstDepositIndicator = "Y", CheckDetailRecordAddendumCount = 1 }; // // Get the Addendum A record (type 26). // var detailA = new X937.Records.CheckDetailAddendumA { RecordNumber = 1, BankOfFirstDepositRoutingNumber = routingNumber, BankOfFirstDepositBusinessDate = DateTime.Now, TruncationIndicator = "N", BankOfFirstDepositConversionIndicator = "2", BankOfFirstDepositCorrectionIndicator = "0" }; return(new List <X937.Record> { detail, detailA }); }
/// <summary> /// Gets the bundle header record (type 20). /// </summary> /// <param name="fileFormat">The file format that contains the configuration to use.</param> /// <param name="bundleIndex">Number of existing bundle records in the cash letter.</param> /// <returns>A BundleHeader record.</returns> protected virtual X937.Records.BundleHeader GetBundleHeader(ImageCashLetterFileFormat fileFormat, int bundleIndex) { var routingNumber = Rock.Security.Encryption.DecryptString(GetAttributeValue(fileFormat, "RoutingNumber")); var header = new X937.Records.BundleHeader { CollectionTypeIndicator = 1, DestinationRoutingNumber = routingNumber, ClientInstitutionRoutingNumber = routingNumber, BusinessDate = DateTime.Now, CreationDate = DateTime.Now, ID = string.Empty, SequenceNumber = (bundleIndex + 1).ToString(), CycleNumber = string.Empty, ReturnLocationRoutingNumber = routingNumber }; return(header); }
/// <summary> /// Gets the cash letter control record (type 90). /// </summary> /// <param name="fileFormat">The file format that contains the configuration to use.</param> /// <param name="records">Existing records in the cash letter.</param> /// <returns>A CashLetterControl record.</returns> protected virtual X937.Records.CashLetterControl GetCashLetterControlRecord(ImageCashLetterFileFormat fileFormat, List <X937.Record> records) { var bundleHeaderRecords = records.Where(r => r.GetType() == typeof(X937.Records.BundleHeader)); var checkDetailRecords = records.Where(r => r.GetType() == typeof(X937.Records.CheckDetail)) .Cast <X937.Records.CheckDetail>(); var imageRecords = records.Where(r => r.GetType() == typeof(X937.Records.ImageViewDetail) || r.GetType() == typeof(X937.Records.ImageViewData)); var organizationName = Rock.Web.Cache.GlobalAttributesCache.Value("OrganizationName"); var control = new X937.Records.CashLetterControl { BundleCount = bundleHeaderRecords.Count(), ItemCount = checkDetailRecords.Count(), TotalAmount = checkDetailRecords.Sum(c => c.ItemAmount), ImageCount = imageRecords.Count(), ECEInstitutionName = organizationName }; return(control); }
/// <summary> /// Shows the edit panel. /// </summary> /// <param name="fileFormatId">The file format identifier.</param> public void ShowDetail(int fileFormatId) { var rockContext = new RockContext(); ImageCashLetterFileFormat fileFormat = null; bool editAllowed = IsUserAuthorized(Authorization.EDIT); if (fileFormatId != 0) { fileFormat = new ImageCashLetterFileFormatService(rockContext).Get(fileFormatId); editAllowed = editAllowed || fileFormat.IsAuthorized(Authorization.EDIT, CurrentPerson); pdAuditDetails.SetEntity(fileFormat, ResolveRockUrl("~")); } if (fileFormat == null) { fileFormat = new ImageCashLetterFileFormat { Id = 0 }; fileFormat.FileNameTemplate = "{{ 'Now' | Date:'yyyyMMddHHmm.x937' }}"; // hide the panel drawer that show created and last modified dates pdAuditDetails.Visible = false; } FileFormatId = fileFormat.Id; bool readOnly = false; nbEditModeMessage.Text = string.Empty; if (!editAllowed || !IsUserAuthorized(Authorization.EDIT)) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed("File Format"); } if (readOnly) { ShowReadonlyDetails(fileFormat); } else { ShowEditDetails(fileFormat); } }
/// <summary> /// Gets the attribute value for the file format /// </summary> /// <param name="fileFormat">The file format.</param> /// <param name="key">The key.</param> /// <returns></returns> public string GetAttributeValue(ImageCashLetterFileFormat fileFormat, string key) { if (fileFormat.AttributeValues == null) { fileFormat.LoadAttributes(); } var values = fileFormat.AttributeValues; if (values != null && values.ContainsKey(key)) { var keyValues = values[key]; if (keyValues != null) { return(keyValues.Value); } } return(string.Empty); }
/// <summary> /// Gets the file header record (type 01). /// </summary> /// <param name="fileFormat">The file format that contains the configuration to use.</param> /// <returns>A FileHeader record.</returns> protected virtual X937.Records.FileHeader GetFileHeaderRecord(ImageCashLetterFileFormat fileFormat) { var destinationRoutingNumber = Rock.Security.Encryption.DecryptString(GetAttributeValue(fileFormat, "RoutingNumber")); var originRoutingNumber = Rock.Security.Encryption.DecryptString(GetAttributeValue(fileFormat, "AccountNumber")); var header = new X937.Records.FileHeader { FileTypeIndicator = GetAttributeValue(fileFormat, "TestMode").AsBoolean(true) ? "T" : "P", ImmediateDestinationRoutingNumber = destinationRoutingNumber, ImmediateOriginRoutingNumber = originRoutingNumber, FileCreationDateTime = DateTime.Now, ResendIndicator = "N", ImmediateDestinationName = GetAttributeValue(fileFormat, "DestinationName"), ImmediateOriginName = GetAttributeValue(fileFormat, "OriginName"), FileIdModifier = "1", // TODO: Need some way to track this and reset each day. CountryCode = "US", /* Should be safe, X9.37 is only used in the US as far as I know. */ UserField = string.Empty }; return(header); }
/// <summary> /// Gets all the bundle records in required for the transactions specified. /// </summary> /// <param name="fileFormat">The file format that contains the configuration to use.</param> /// <param name="transactions">The transactions to be exported.</param> /// <returns>A collection of records that identify all the exported transactions.</returns> protected virtual List <X937.Record> GetBundleRecords(ImageCashLetterFileFormat fileFormat, List <FinancialTransaction> transactions) { var records = new List <X937.Record>(); for (int bundleIndex = 0; (bundleIndex * MaxItemsPerBundle) < transactions.Count(); bundleIndex++) { var bundleRecords = new List <X937.Record>(); var bundleTransactions = transactions.Skip(bundleIndex * MaxItemsPerBundle) .Take(MaxItemsPerBundle) .ToList(); // // Add the bundle header for this set of transactions. // bundleRecords.Add(GetBundleHeader(fileFormat, bundleIndex)); // // Allow subclasses to provide credit detail records (type 61) if they want. // bundleRecords.AddRange(GetCreditDetailRecords(fileFormat, bundleIndex, bundleTransactions)); // // Add records for each transaction in the bundle. // foreach (var transaction in bundleTransactions) { bundleRecords.AddRange(GetItemRecords(fileFormat, transaction)); } // // Add the bundle control record. // bundleRecords.Add(GetBundleControl(fileFormat, bundleRecords)); records.AddRange(bundleRecords); } return(records); }
/// <summary> /// Gets the cash letter header record (type 10). /// </summary> /// <param name="fileFormat">The file format that contains the configuration to use.</param> /// <returns>A CashLetterHeader record.</returns> protected virtual X937.Records.CashLetterHeader GetCashLetterHeaderRecord(ImageCashLetterFileFormat fileFormat) { var routingNumber = Rock.Security.Encryption.DecryptString(GetAttributeValue(fileFormat, "RoutingNumber")); var contactName = GetAttributeValue(fileFormat, "ContactName"); var contactPhone = GetAttributeValue(fileFormat, "ContactPhone"); var header = new X937.Records.CashLetterHeader { CollectionTypeIndicator = 1, DestinationRoutingNumber = routingNumber, ClientInstitutionRoutingNumber = routingNumber, BusinessDate = DateTime.Now, // TODO: We might need to ask the user this and pass it in. CreationDateTime = DateTime.Now, RecordTypeIndicator = "I", DocumentationTypeIndicator = "G", ID = "TODO", // TODO: Fix this, waiting for feedback from bank. OriginatorContactName = contactName, OriginatorContactPhoneNumber = contactPhone }; return(header); }
/// <summary> /// Shows the edit details. /// </summary> /// <param name="fileFormat">The file format.</param> private void ShowEditDetails(ImageCashLetterFileFormat fileFormat) { if (fileFormat.Id == 0) { lActionTitle.Text = ActionTitle.Add("File Format"); } else { lActionTitle.Text = fileFormat.Name.FormatAsHtmlTitle(); } hlInactive.Visible = !fileFormat.IsActive; SetEditMode(true); tbName.Text = fileFormat.Name; cbIsActive.Checked = fileFormat.IsActive; tbDescription.Text = fileFormat.Description; tbFileNameTemplate.Text = fileFormat.FileNameTemplate; cpFileFormatType.SetValue(fileFormat.EntityType != null ? fileFormat.EntityType.Guid.ToString().ToUpper() : string.Empty); BuildDynamicControls(fileFormat, true); }
/// <summary> /// Shows the readonly details. /// </summary> /// <param name="fileFormat">The file format.</param> private void ShowReadonlyDetails(ImageCashLetterFileFormat fileFormat) { SetEditMode(false); lActionTitle.Text = fileFormat.Name.FormatAsHtmlTitle(); hlInactive.Visible = !fileFormat.IsActive; lFileFormatDescription.Text = fileFormat.Description; var descriptionList = new DescriptionList(); if (fileFormat.EntityType != null) { descriptionList.Add("File Format Type", fileFormat.EntityType.Name); } descriptionList.Add("File Name Template", fileFormat.FileNameTemplate); lblMainDetails.Text = descriptionList.Html; phAttributes.Controls.Clear(); Rock.Attribute.Helper.AddDisplayControls(fileFormat, phAttributes, new List <string> { "Active", "Order" }); }
/// <summary> /// Gets the image record for a specific transaction image (type 50 and 52). /// </summary> /// <param name="fileFormat">The file format that contains the configuration to use.</param> /// <param name="transaction">The transaction being deposited.</param> /// <param name="image">The check image scanned by the scanning application.</param> /// <param name="isFront">if set to <c>true</c> [is front].</param> /// <returns>A collection of records.</returns> protected virtual List <X937.Record> GetImageRecords(ImageCashLetterFileFormat fileFormat, FinancialTransaction transaction, FinancialTransactionImage image, bool isFront) { var routingNumber = Rock.Security.Encryption.DecryptString(GetAttributeValue(fileFormat, "RoutingNumber")); var accountNumber = Rock.Security.Encryption.DecryptString(GetAttributeValue(fileFormat, "AccountNumber")); // // Get the Image View Detail record (type 50). // var detail = new X937.Records.ImageViewDetail { ImageIndicator = 1, ImageCreatorRoutingNumber = routingNumber, ImageCreatorDate = image.CreatedDateTime ?? DateTime.Now, ImageViewFormatIndicator = 0, CompressionAlgorithmIdentifier = 0, SideIndicator = isFront ? 0 : 1, ViewDescriptor = 0, DigitalSignatureIndicator = 0 }; // // Get the Image View Data record (type 51). // var data = new X937.Records.ImageViewData { InstitutionRoutingNumber = routingNumber, BundleBusinessDate = DateTime.Now, ClientInstitutionItemSequenceNumber = accountNumber, ClippingOrigin = 0, ImageData = image.BinaryFile.ContentStream.ReadBytesToEnd() }; return(new List <X937.Record> { detail, data }); }
/// <summary> /// Exports a collection of batches to a binary file that can be downloaded by the user /// and sent to their financial institution. The returned BinaryFile should not have been /// saved to the database yet. /// </summary> /// <param name="fileFormat">The <see cref="ImageCashLetterFileFormat" /> that is being used to export this data.</param> /// <param name="batches">The list of batches whose data needs to be exported.</param> /// <param name="errorMessages">On return will contain a list of error messages if not empty.</param> /// <returns>A <see cref="Stream" /> of data that should be downloaded to the user in a file.</returns> public abstract Stream ExportBatches(ImageCashLetterFileFormat fileFormat, List <FinancialBatch> batches, out List <string> errorMessages);
/// <summary> /// Gets the credit detail deposit record (type 61). /// </summary> /// <param name="fileFormat">The file format that contains the configuration to use.</param> /// <param name="bundleIndex">Number of existing bundle records in the cash letter.</param> /// <param name="transactions">The transactions associated with this deposit.</param> /// <returns>A collection of records.</returns> protected virtual List <X937.Record> GetCreditDetailRecords(ImageCashLetterFileFormat fileFormat, int bundleIndex, List <FinancialTransaction> transactions) { return(new List <X937.Record>()); }
/// <summary> /// Imports batches from a data file. The batches should not be added to the database /// but only initialized. /// </summary> /// <param name="fileFormat">The <see cref="ImageCashLetterFileFormat" /> that is being used to import this data.</param> /// <param name="content">A <see cref="Stream"/> that can be used to access the file data.</param> /// <param name="errorMessages">On return will contain a list of error messages if not empty.</param> /// <returns>A list of FinancialBatches that are ready to be saved to the database.</returns> public virtual List <FinancialBatch> ImportBatches(ImageCashLetterFileFormat fileFormat, Stream content, out List <string> errorMessages) { throw new NotImplementedException("Importing of batches is not supported by this component."); }