void WriteBatchLine(ABatchRow batch) { WriteStringQuoted("B"); WriteStringQuoted(batch.BatchDescription); WriteCurrency(batch.BatchControlTotal); WriteDate(batch.DateEffective, true); }
/// <summary> /// /// </summary> /// <param name="ACurrentBatchRow"></param> /// <returns></returns> public Boolean BatchIsAutoGenerated(ABatchRow ACurrentBatchRow) { Boolean containsSystemGenerated = false; DataView transactionView = new DataView(FMainDS.ATransaction); transactionView.RowFilter = "a_batch_number_i=" + ACurrentBatchRow.BatchNumber; if (transactionView.Count == 0) { LoadJournals(ACurrentBatchRow); } foreach (DataRowView rv in transactionView) { if (((ATransactionRow)rv.Row).SystemGenerated) { containsSystemGenerated = true; } break; // In practice, Batches are always EITHER SystemGenerated, or not. // I only need to look at the first transaction in the batch, to see if it's SystemGenerated. } return(containsSystemGenerated); }
/// <summary> /// Calculate the base amount for the transactions, and update the totals for the journals and the current batch /// </summary> /// <param name="AMainDS"></param> /// <param name="ACurrentBatch"></param> public static void UpdateTotalsOfBatch(ref GLBatchTDS AMainDS, ABatchRow ACurrentBatch) { decimal BatchDebitTotal = 0.0m; decimal BatchCreditTotal = 0.0m; DataView jnlDataView = new DataView(AMainDS.AJournal); jnlDataView.RowFilter = String.Format("{0}={1}", AJournalTable.GetBatchNumberDBName(), ACurrentBatch.BatchNumber); foreach (DataRowView journalView in jnlDataView) { GLBatchTDSAJournalRow journalRow = (GLBatchTDSAJournalRow)journalView.Row; UpdateTotalsOfJournal(ref AMainDS, ref journalRow); BatchDebitTotal += journalRow.JournalDebitTotal; BatchCreditTotal += journalRow.JournalCreditTotal; } if ((ACurrentBatch.BatchDebitTotal != BatchDebitTotal) || (ACurrentBatch.BatchCreditTotal != BatchCreditTotal)) { ACurrentBatch.BatchDebitTotal = BatchDebitTotal; ACurrentBatch.BatchCreditTotal = BatchCreditTotal; } }
private void InitBatchAndJournal() { F_GLDataset = TGLPosting.CreateABatch(F_LedgerNum); F_batch = F_GLDataset.ABatch[0]; F_batch.BatchDescription = Catalog.GetString("Period end revaluations"); TAccountPeriodInfo accountingPeriodInfo = new TAccountPeriodInfo(F_LedgerNum); accountingPeriodInfo.AccountingPeriodNumber = F_batch.BatchPeriod; F_batch.DateEffective = accountingPeriodInfo.PeriodEndDate; F_batch.BatchStatus = MFinanceConstants.BATCH_UNPOSTED; F_journal = F_GLDataset.AJournal.NewRowTyped(); F_journal.LedgerNumber = F_batch.LedgerNumber; F_journal.BatchNumber = F_batch.BatchNumber; F_journal.JournalNumber = 1; F_journal.DateEffective = F_batch.DateEffective; F_journal.JournalPeriod = F_batch.BatchPeriod; F_journal.TransactionCurrency = F_BaseCurrency; F_journal.JournalDescription = F_batch.BatchDescription; F_journal.TransactionTypeCode = CommonAccountingTransactionTypesEnum.REVAL.ToString(); F_journal.SubSystemCode = CommonAccountingSubSystemsEnum.GL.ToString(); F_journal.LastTransactionNumber = 0; F_journal.DateOfEntry = DateTime.Now; F_journal.ExchangeRateToBase = 1.0M; F_GLDataset.AJournal.Rows.Add(F_journal); }
private void ValidateDataDetailsManual(ABatchRow ARow) { if ((ARow == null) || (ARow.BatchStatus != MFinanceConstants.BATCH_UNPOSTED)) { return; } TVerificationResultCollection VerificationResultCollection = FPetraUtilsObject.VerificationResultCollection; ParseHashTotal(ARow); TSharedFinanceValidation_GL.ValidateGLBatchManual(this, ARow, ref VerificationResultCollection, FValidationControlsDict, FStartDateCurrentPeriod, FEndDateLastForwardingPeriod); //TODO: remove this once database definition is set for Batch Description to be NOT NULL // Description is mandatory then make sure it is set if (txtDetailBatchDescription.Text.Length == 0) { DataColumn ValidationColumn; TVerificationResult VerificationResult = null; object ValidationContext; ValidationColumn = ARow.Table.Columns[ABatchTable.ColumnBatchDescriptionId]; ValidationContext = String.Format("Batch number {0}", ARow.BatchNumber); VerificationResult = TStringChecks.StringMustNotBeEmpty(ARow.BatchDescription, "Description of " + ValidationContext, this, ValidationColumn, null); // Handle addition/removal to/from TVerificationResultCollection VerificationResultCollection.Auto_Add_Or_AddOrRemove(this, VerificationResult, ValidationColumn, true); } }
private void ShowDetailsManual(ABatchRow ARow) { AutoEnableTransTabForBatch(); grdDetails.TabStop = (ARow != null); if (ARow == null) { pnlDetails.Enabled = false; ((TFrmGLBatch)this.ParentForm).DisableJournals(); ((TFrmGLBatch)this.ParentForm).DisableTransactions(); EnableButtonControl(false); ClearDetailControls(); return; } FPetraUtilsObject.DetailProtectedMode = (ARow.BatchStatus.Equals(MFinanceConstants.BATCH_POSTED) || ARow.BatchStatus.Equals(MFinanceConstants.BATCH_CANCELLED)); FCurrentEffectiveDate = ARow.DateEffective; UpdateBatchPeriod(null, null); UpdateChangeableStatus(); ((TFrmGLBatch)this.ParentForm).EnableJournals(); }
private int GetDataTableRowIndexByPrimaryKeys(int ALedgerNumber, int ABatchNumber) { int rowPos = 0; bool batchFound = false; foreach (DataRowView rowView in FMainDS.ABatch.DefaultView) { ABatchRow row = (ABatchRow)rowView.Row; if ((row.LedgerNumber == ALedgerNumber) && (row.BatchNumber == ABatchNumber)) { batchFound = true; break; } rowPos++; } if (!batchFound) { rowPos = 0; } //remember grid is out of sync with DataView by 1 because of grid header rows return(rowPos + 1); }
/// <summary> /// Update the dictionary that stores all unposted batches /// and whether or not they have been warned about inactive /// fields /// </summary> /// <param name="ABatchNumberToExclude"></param> public void UpdateUnpostedBatchDictionary(int ABatchNumberToExclude = 0) { if (ABatchNumberToExclude > 0) { FUnpostedBatchesVerifiedOnSavingDict.Remove(ABatchNumberToExclude); } DataView BatchDV = new DataView(FMainDS.ABatch); //Just want unposted batches BatchDV.RowFilter = string.Format("{0}='{1}'", ABatchTable.GetBatchStatusDBName(), MFinanceConstants.BATCH_UNPOSTED); foreach (DataRowView bRV in BatchDV) { ABatchRow br = (ABatchRow)bRV.Row; int currentBatch = br.BatchNumber; if ((currentBatch != ABatchNumberToExclude) && !FUnpostedBatchesVerifiedOnSavingDict.ContainsKey(currentBatch)) { FUnpostedBatchesVerifiedOnSavingDict.Add(br.BatchNumber, false); } } }
/// <summary> /// update the journal header fields from a batch /// </summary> /// <param name="ABatch"></param> public void UpdateHeaderTotals(ABatchRow ABatch) { decimal SumDebits = 0.0M; decimal SumCredits = 0.0M; DataView JournalDV = new DataView(FMainDS.AJournal); JournalDV.RowFilter = String.Format("{0}={1}", AJournalTable.GetBatchNumberDBName(), ABatch.BatchNumber); foreach (DataRowView v in JournalDV) { AJournalRow r = (AJournalRow)v.Row; SumCredits += r.JournalCreditTotal; SumDebits += r.JournalDebitTotal; } FPetraUtilsObject.DisableDataChangedEvent(); txtDebit.NumberValueDecimal = SumDebits; txtCredit.NumberValueDecimal = SumCredits; txtControl.NumberValueDecimal = ABatch.BatchControlTotal; txtCurrentPeriod.Text = ABatch.BatchPeriod.ToString(); FPetraUtilsObject.EnableDataChangedEvent(); }
/// <summary> /// Validates the GL Batch data. /// </summary> /// <param name="AContext">Context that describes where the data validation failed.</param> /// <param name="ARow">The <see cref="DataRow" /> which holds the the data against which the validation is run.</param> /// <param name="AVerificationResultCollection">Will be filled with any <see cref="TVerificationResult" /> items if /// data validation errors occur.</param> /// <param name="AValidationControlsDict">A <see cref="TValidationControlsDict" /> containing the Controls that /// display data that is about to be validated.</param> /// <param name="AStartDateCurrentPeriod">If the caller knows this value it can be supplied. Otherwise the server will supply the value for the ledger.</param> /// <param name="AEndDateLastForwardingPeriod">If the caller knows this value it can be supplied. Otherwise the server will supply the value for the ledger.</param> /// <returns>True if the validation found no data validation errors, otherwise false.</returns> public static bool ValidateGLBatchManual(object AContext, ABatchRow ARow, ref TVerificationResultCollection AVerificationResultCollection, TValidationControlsDict AValidationControlsDict, DateTime? AStartDateCurrentPeriod = null, DateTime? AEndDateLastForwardingPeriod = null) { DataColumn ValidationColumn; TValidationControlsData ValidationControlsData; TScreenVerificationResult VerificationResult; object ValidationContext; int VerifResultCollAddedCount = 0; // Don't validate deleted or posted DataRows if ((ARow.RowState == DataRowState.Deleted) || (ARow.BatchStatus == MFinanceConstants.BATCH_POSTED) || (ARow.BatchStatus == MFinanceConstants.BATCH_CANCELLED)) { return true; } bool isImporting = AContext.ToString().Contains("Importing"); // 'Effective From Date' must be valid ValidationColumn = ARow.Table.Columns[ABatchTable.ColumnDateEffectiveId]; ValidationContext = ARow.BatchNumber; DateTime StartDateCurrentPeriod; DateTime EndDateLastForwardingPeriod; if ((AStartDateCurrentPeriod == null) || (AEndDateLastForwardingPeriod == null)) { TSharedFinanceValidationHelper.GetValidPostingDateRange(ARow.LedgerNumber, out StartDateCurrentPeriod, out EndDateLastForwardingPeriod); } else { StartDateCurrentPeriod = AStartDateCurrentPeriod.Value; EndDateLastForwardingPeriod = AEndDateLastForwardingPeriod.Value; } if (AValidationControlsDict.TryGetValue(ValidationColumn, out ValidationControlsData)) { VerificationResult = (TScreenVerificationResult)TDateChecks.IsDateBetweenDates(ARow.DateEffective, StartDateCurrentPeriod, EndDateLastForwardingPeriod, ValidationControlsData.ValidationControlLabel + (isImporting ? String.Empty : " of Batch Number " + ValidationContext.ToString()), TDateBetweenDatesCheckType.dbdctUnspecific, TDateBetweenDatesCheckType.dbdctUnspecific, AContext, ValidationColumn, ValidationControlsData.ValidationControl); // Handle addition/removal to/from TVerificationResultCollection if (AVerificationResultCollection.Auto_Add_Or_AddOrRemove(AContext, VerificationResult, ValidationColumn, true)) { VerifResultCollAddedCount++; } } return VerifResultCollAddedCount == 0; }
/// <summary> /// Validates the GL Batch data. /// </summary> /// <param name="AContext">Context that describes where the data validation failed.</param> /// <param name="ARow">The <see cref="DataRow" /> which holds the the data against which the validation is run.</param> /// <param name="AVerificationResultCollection">Will be filled with any <see cref="TVerificationResult" /> items if /// data validation errors occur.</param> /// <param name="AValidationControlsDict">A <see cref="TValidationControlsDict" /> containing the Controls that /// display data that is about to be validated.</param> /// <param name="AStartDateCurrentPeriod">If the caller knows this value it can be supplied. Otherwise the server will supply the value for the ledger.</param> /// <param name="AEndDateLastForwardingPeriod">If the caller knows this value it can be supplied. Otherwise the server will supply the value for the ledger.</param> /// <returns>True if the validation found no data validation errors, otherwise false.</returns> public static bool ValidateGLBatchManual(object AContext, ABatchRow ARow, ref TVerificationResultCollection AVerificationResultCollection, TValidationControlsDict AValidationControlsDict, DateTime?AStartDateCurrentPeriod = null, DateTime?AEndDateLastForwardingPeriod = null) { DataColumn ValidationColumn; TValidationControlsData ValidationControlsData; TScreenVerificationResult VerificationResult; object ValidationContext; int VerifResultCollAddedCount = 0; // Don't validate deleted or posted DataRows if ((ARow.RowState == DataRowState.Deleted) || (ARow.BatchStatus == MFinanceConstants.BATCH_POSTED)) { return(true); } bool isImporting = AContext.ToString().Contains("Importing"); // 'Effective From Date' must be valid ValidationColumn = ARow.Table.Columns[ABatchTable.ColumnDateEffectiveId]; ValidationContext = ARow.BatchNumber; DateTime StartDateCurrentPeriod; DateTime EndDateLastForwardingPeriod; if ((AStartDateCurrentPeriod == null) || (AEndDateLastForwardingPeriod == null)) { TSharedFinanceValidationHelper.GetValidPostingDateRange(ARow.LedgerNumber, out StartDateCurrentPeriod, out EndDateLastForwardingPeriod); } else { StartDateCurrentPeriod = AStartDateCurrentPeriod.Value; EndDateLastForwardingPeriod = AEndDateLastForwardingPeriod.Value; } if (AValidationControlsDict.TryGetValue(ValidationColumn, out ValidationControlsData)) { VerificationResult = (TScreenVerificationResult)TDateChecks.IsDateBetweenDates(ARow.DateEffective, StartDateCurrentPeriod, EndDateLastForwardingPeriod, ValidationControlsData.ValidationControlLabel + (isImporting ? String.Empty : " of Batch Number " + ValidationContext.ToString()), TDateBetweenDatesCheckType.dbdctUnspecific, TDateBetweenDatesCheckType.dbdctUnspecific, AContext, ValidationColumn, ValidationControlsData.ValidationControl); // Handle addition/removal to/from TVerificationResultCollection if (AVerificationResultCollection.Auto_Add_Or_AddOrRemove(AContext, VerificationResult, ValidationColumn, true)) { VerifResultCollAddedCount++; } } return(VerifResultCollAddedCount == 0); }
/// <summary> /// Reload batches after an import /// </summary> public void ReloadBatches(bool AIsFromMessage = false) { try { FPetraUtilsObject.GetForm().Cursor = Cursors.WaitCursor; if (!AIsFromMessage) { // Before we re-load make a note of the 'last' batch number so we can work out which batches have been imported. DataView dv = new DataView(FMainDS.ABatch, String.Empty, String.Format("{0} DESC", ABatchTable.GetBatchNumberDBName()), DataViewRowState.CurrentRows); int lastBatchNumber = (dv.Count == 0) ? 0 : ((ABatchRow)dv[0].Row).BatchNumber; // Merge the new batches into our data set FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatch(FLedgerNumber, FCurrentLedgerYear, 0)); // Go round each imported batch loading its journals // Start with the highest batch number and continue until we reach the 'old' last batch for (int i = 0; i < dv.Count; i++) { ABatchRow batchRow = (ABatchRow)dv[i].Row; int batchNumber = batchRow.BatchNumber; if (batchNumber <= lastBatchNumber) { break; } batchRow.SetModified(); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadAJournalAndRelatedTablesForBatch(FLedgerNumber, batchNumber)); } EnsureNewBatchIsVisible(); } else { if (FPetraUtilsObject.HasChanges && !((TFrmGLBatch)ParentForm).SaveChanges()) { string msg = String.Format(Catalog.GetString("A validation error has occured on the GL Batches" + " form while trying to refresh.{0}{0}" + "You will need to close and reopen the GL Batches form to see the new batch" + " after you have fixed the validation error."), Environment.NewLine); MessageBox.Show(msg, "Refresh GL Batches"); return; } FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatch(FLedgerNumber, FCurrentLedgerYear, 0)); grdDetails.SelectRowInGrid(1); } } finally { FPetraUtilsObject.GetForm().Cursor = Cursors.Default; } }
private void TCommonAccountingTool_(string ABatchDescription) { FBatchTDS = TGLPosting.CreateABatch(FLedgerInfo.LedgerNumber); FBaseCurrencyInfo = new TCurrencyInfo(FLedgerInfo.BaseCurrency); FBatchRow = FBatchTDS.ABatch[0]; FBatchRow.BatchDescription = ABatchDescription; FBatchRow.BatchStatus = MFinanceConstants.BATCH_UNPOSTED; FBatchNumber = FBatchRow.BatchNumber; FJournalCount = 0; blnReadyForTransaction = false; blnInitBatchDate = true; }
/// <summary> /// Print out the selected batch using FastReports template. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void FilePrint(object sender, EventArgs e) { if (!this.tpgJournals.Enabled) { MessageBox.Show(Catalog.GetString("No Batch is selected"), Catalog.GetString("Batch Posting Register"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } ABatchRow BatchRow = ucoBatches.GetSelectedDetailRow(); PrintPostingRegister(FLedgerNumber, BatchRow.BatchNumber, ModifierKeys.HasFlag(Keys.Control)); }
/// <summary> /// Uses the current Batch effective date to return the /// corporate exchange rate value /// </summary> /// <returns></returns> public decimal GetInternationalCurrencyExchangeRate() { string NotUsed = string.Empty; ABatchRow BatchRow = ucoBatches.GetSelectedDetailRow(); if (BatchRow == null) { return(0); } return(GetInternationalCurrencyExchangeRate(BatchRow.DateEffective, out NotUsed)); }
/// <summary> /// Uses the current Batch effective date to return the /// corporate exchange rate value /// </summary> /// <returns></returns> public decimal GetInternationalCurrencyExchangeRate() { decimal IntlToBaseCurrencyExchRate = 0; ABatchRow BatchRow = ucoBatches.GetSelectedDetailRow(); if (BatchRow == null) { return(IntlToBaseCurrencyExchRate); } return(GetInternationalCurrencyExchangeRate(BatchRow.DateEffective)); }
/// <summary> /// Re-show the specified row /// </summary> /// <param name="AModifiedBatchRow"></param> /// <param name="ARedisplay"></param> public void UndoModifiedBatchRow(ABatchRow AModifiedBatchRow, bool ARedisplay) { //Check if new row or not if (AModifiedBatchRow.RowState == DataRowState.Added) { return; } AModifiedBatchRow.RejectChanges(); if (ARedisplay) { ShowDetails(AModifiedBatchRow); } }
/// <summary> /// Print out the selected batch using FastReports template. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void FilePrint(object sender, EventArgs e) { if (!this.tpgJournals.Enabled) { MessageBox.Show(Catalog.GetString("No Batch is selected"), Catalog.GetString("Batch Posting Register"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } ABatchRow BatchRow = ucoBatches.GetSelectedDetailRow(); TFrmBatchPostingRegister ReportGui = new TFrmBatchPostingRegister(this); // ReportGui.PrintReportNoUi(FLedgerNumber, BatchRow.BatchNumber); // This alternative doesn't show the UI ReportGui.LedgerNumber = FLedgerNumber; ReportGui.BatchNumber = BatchRow.BatchNumber; ReportGui.Show(); }
private void ParseHashTotal(ABatchRow ARow) { if (ARow.BatchStatus != MFinanceConstants.BATCH_UNPOSTED) { return; } if ((txtDetailBatchControlTotal.NumberValueDecimal == null) || !txtDetailBatchControlTotal.NumberValueDecimal.HasValue) { bool prev = FPetraUtilsObject.SuppressChangeDetection; FPetraUtilsObject.SuppressChangeDetection = true; txtDetailBatchControlTotal.NumberValueDecimal = 0m; FPetraUtilsObject.SuppressChangeDetection = prev; } if (ARow.BatchControlTotal != txtDetailBatchControlTotal.NumberValueDecimal.Value) { ARow.BatchControlTotal = txtDetailBatchControlTotal.NumberValueDecimal.Value; } }
private Boolean CloseSaveAndPost_(TVerificationResultCollection AVerifications) { if (FJournalCount != 0) { // The checksum of the "last journal" is used to update the checksum of the batch. FBatchRow.BatchControlTotal += FJournalRow.JournalDebitTotal - FJournalRow.JournalCreditTotal; } FBatchTDS.ThrowAwayAfterSubmitChanges = true; GLBatchTDSAccess.SubmitChanges(FBatchTDS); Boolean PostedOk = TGLPosting.PostGLBatch( FLedgerInfo.LedgerNumber, FBatchNumber, out AVerifications); // Make sure that this object cannot be used for another posting ... FBatchTDS = null; FBatchRow = null; FJournalRow = null; return(PostedOk); }
/// <summary> /// Calculate the base amount for the transactions, and update the totals for the journals and the current batch /// Assumes that all transactions for the journal are already loaded. /// </summary> /// <param name="AMainDS"></param> /// <param name="ACurrentBatch"></param> /// <param name="ACurrentJournal"></param> public static void UpdateTotalsOfBatchForJournal(ref GLBatchTDS AMainDS, ABatchRow ACurrentBatch, GLBatchTDSAJournalRow ACurrentJournal) { //Save current values decimal JournalDebitTotal = ACurrentJournal.JournalDebitTotal; decimal JournalCreditTotal = ACurrentJournal.JournalCreditTotal; bool JournalUpdated; UpdateTotalsOfJournal(ref AMainDS, ref ACurrentJournal, out JournalUpdated); if (JournalUpdated) { //Subtract old amounts ACurrentBatch.BatchDebitTotal -= JournalDebitTotal; ACurrentBatch.BatchCreditTotal -= JournalCreditTotal; //Add updated Journals amounts ACurrentBatch.BatchDebitTotal += ACurrentJournal.JournalDebitTotal; ACurrentBatch.BatchCreditTotal += ACurrentJournal.JournalCreditTotal; } }
private void ParseHashTotal(ABatchRow ARow) { decimal CorrectHashValue = 0m; if (ARow.BatchStatus != MFinanceConstants.BATCH_UNPOSTED) { return; } if ((txtDetailBatchControlTotal.NumberValueDecimal == null) || !txtDetailBatchControlTotal.NumberValueDecimal.HasValue) { CorrectHashValue = 0m; } else { CorrectHashValue = txtDetailBatchControlTotal.NumberValueDecimal.Value; } // AlanP: is this another case of needing to check for a real change?? txtDetailBatchControlTotal.NumberValueDecimal = CorrectHashValue; ARow.BatchControlTotal = CorrectHashValue; }
private void InitBatchAndJournal(decimal AExchangeRate, string ACurrencyCode) { F_GLDataset = TGLPosting.CreateABatch(F_LedgerNum, false, true); F_batch = F_GLDataset.ABatch[0]; F_batch.BatchDescription = Catalog.GetString("Period end revaluations"); TAccountPeriodInfo accountingPeriodInfo = new TAccountPeriodInfo(F_LedgerNum); accountingPeriodInfo.AccountingPeriodNumber = F_batch.BatchPeriod; F_batch.DateEffective = accountingPeriodInfo.PeriodEndDate; F_batch.BatchStatus = MFinanceConstants.BATCH_UNPOSTED; F_journal = F_GLDataset.AJournal.NewRowTyped(); F_journal.LedgerNumber = F_batch.LedgerNumber; F_journal.BatchNumber = F_batch.BatchNumber; F_journal.JournalNumber = 1; F_journal.DateEffective = F_batch.DateEffective; F_journal.ExchangeRateTime = 14400; // revaluations are typically later than 'new rates' F_journal.JournalPeriod = F_batch.BatchPeriod; F_journal.TransactionCurrency = F_BaseCurrency; F_journal.JournalDescription = F_batch.BatchDescription; F_journal.TransactionTypeCode = CommonAccountingTransactionTypesEnum.REVAL.ToString(); F_journal.SubSystemCode = CommonAccountingSubSystemsEnum.GL.ToString(); F_journal.LastTransactionNumber = 0; F_journal.DateOfEntry = DateTime.Now; F_journal.ExchangeRateToBase = 1.0M; F_GLDataset.AJournal.Rows.Add(F_journal); ARevaluationRow revalRow = F_GLDataset.ARevaluation.NewRowTyped(); revalRow.LedgerNumber = F_journal.LedgerNumber; revalRow.BatchNumber = F_journal.BatchNumber; revalRow.JournalNumber = F_journal.JournalNumber; revalRow.ExchangeRateToBase = AExchangeRate; revalRow.RevaluationCurrency = ACurrencyCode; F_GLDataset.ARevaluation.Rows.Add(revalRow); }
/// <summary> /// mark each journal, each transaction as being posted; /// add sums for costcentre/account combinations /// </summary> /// <param name="MainDS">can contain several batches and journals and transactions</param> /// <param name="APostingDS"></param> /// <param name="APostingLevel">the balance changes at the posting level</param> /// <param name="ABatchToPost">the batch to post</param> /// <returns>a list with the sums for each costcentre/account combination</returns> private static SortedList <string, TAmount>MarkAsPostedAndCollectData(GLBatchTDS MainDS, GLPostingTDS APostingDS, SortedList <string, TAmount>APostingLevel, ABatchRow ABatchToPost) { DataView myView = new DataView(MainDS.ATransaction); myView.Sort = ATransactionTable.GetJournalNumberDBName(); foreach (AJournalRow journal in MainDS.AJournal.Rows) { if (journal.BatchNumber != ABatchToPost.BatchNumber) { continue; } foreach (DataRowView transactionview in myView.FindRows(journal.JournalNumber)) { ATransactionRow transaction = (ATransactionRow)transactionview.Row; if (transaction.BatchNumber != ABatchToPost.BatchNumber) { continue; } transaction.TransactionStatus = true; // get the account that this transaction is writing to AAccountRow Account = (AAccountRow)APostingDS.AAccount.Rows.Find(new object[] { transaction.LedgerNumber, transaction.AccountCode }); // Set the sign of the amounts according to the debit/credit indicator decimal SignBaseAmount = transaction.AmountInBaseCurrency; decimal SignTransAmount = transaction.TransactionAmount; if (Account.DebitCreditIndicator != transaction.DebitCreditIndicator) { SignBaseAmount *= -1.0M; SignTransAmount *= -1.0M; } // TODO: do we need to check for base currency corrections? // or do we get rid of these problems by not having international currency? string key = TAmount.MakeKey(transaction.AccountCode, transaction.CostCentreCode); if (!APostingLevel.ContainsKey(key)) { APostingLevel.Add(key, new TAmount()); } APostingLevel[key].baseAmount += SignBaseAmount; // Only foreign currency accounts store a value in the transaction currency, // if the transaction was actually in the foreign currency. if (Account.ForeignCurrencyFlag && (journal.TransactionCurrency == Account.ForeignCurrencyCode)) { APostingLevel[key].transAmount += SignTransAmount; } } journal.JournalStatus = MFinanceConstants.BATCH_POSTED; } ABatchToPost.BatchStatus = MFinanceConstants.BATCH_POSTED; return APostingLevel; }
/// <summary> /// Load Journals for current Batch /// </summary> /// <param name="ACurrentBatchRow"></param> public void LoadJournals(ABatchRow ACurrentBatchRow) { this.ucoJournals.LoadJournals(ACurrentBatchRow); }
/// load transactions from a CSV file into the currently selected batch private void CreateBatchFromCSVFile(string ADataFilename, XmlNode ARootNode, AJournalRow ARefJournalRow, Int32 AFirstTransactionRow, string ADefaultCostCentre, out DateTime ALatestTransactionDate) { StreamReader dataFile = new StreamReader(ADataFilename, System.Text.Encoding.Default); XmlNode ColumnsNode = TXMLParser.GetChild(ARootNode, "Columns"); string Separator = TXMLParser.GetAttribute(ARootNode, "Separator"); string DateFormat = TXMLParser.GetAttribute(ARootNode, "DateFormat"); string ThousandsSeparator = TXMLParser.GetAttribute(ARootNode, "ThousandsSeparator"); string DecimalSeparator = TXMLParser.GetAttribute(ARootNode, "DecimalSeparator"); Int32 lineCounter; // read headers for (lineCounter = 0; lineCounter < AFirstTransactionRow - 1; lineCounter++) { dataFile.ReadLine(); } decimal sumDebits = 0.0M; decimal sumCredits = 0.0M; ALatestTransactionDate = DateTime.MinValue; do { string line = dataFile.ReadLine(); lineCounter++; GLBatchTDSATransactionRow NewTransaction = FMainDS.ATransaction.NewRowTyped(true); FMyForm.GetTransactionsControl().NewRowManual(ref NewTransaction, ARefJournalRow); FMainDS.ATransaction.Rows.Add(NewTransaction); foreach (XmlNode ColumnNode in ColumnsNode.ChildNodes) { string Value = StringHelper.GetNextCSV(ref line, Separator); string UseAs = TXMLParser.GetAttribute(ColumnNode, "UseAs"); if (UseAs.ToLower() == "reference") { NewTransaction.Reference = Value; } else if (UseAs.ToLower() == "narrative") { NewTransaction.Narrative = Value; } else if (UseAs.ToLower() == "dateeffective") { NewTransaction.SetTransactionDateNull(); if (Value.Trim().ToString().Length > 0) { try { NewTransaction.TransactionDate = XmlConvert.ToDateTime(Value, DateFormat); if (NewTransaction.TransactionDate > ALatestTransactionDate) { ALatestTransactionDate = NewTransaction.TransactionDate; } } catch (Exception exp) { MessageBox.Show(Catalog.GetString("Problem with date in row " + lineCounter.ToString() + " Error: " + exp.Message)); } } } else if (UseAs.ToLower() == "account") { if (Value.Length > 0) { if (Value.Contains(" ")) { // cut off currency code; should have been defined in the data description file, for the whole batch Value = Value.Substring(0, Value.IndexOf(" ") - 1); } Value = Value.Replace(ThousandsSeparator, ""); Value = Value.Replace(DecimalSeparator, "."); NewTransaction.TransactionAmount = Convert.ToDecimal(Value, System.Globalization.CultureInfo.InvariantCulture); NewTransaction.CostCentreCode = ADefaultCostCentre; NewTransaction.AccountCode = ColumnNode.Name; NewTransaction.DebitCreditIndicator = true; if (TXMLParser.HasAttribute(ColumnNode, "CreditDebit") && (TXMLParser.GetAttribute(ColumnNode, "CreditDebit").ToLower() == "credit")) { NewTransaction.DebitCreditIndicator = false; } if (NewTransaction.TransactionAmount < 0) { NewTransaction.TransactionAmount *= -1.0M; NewTransaction.DebitCreditIndicator = !NewTransaction.DebitCreditIndicator; } if (TXMLParser.HasAttribute(ColumnNode, "AccountCode")) { NewTransaction.AccountCode = TXMLParser.GetAttribute(ColumnNode, "AccountCode"); } if (NewTransaction.DebitCreditIndicator) { sumDebits += NewTransaction.TransactionAmount; } else if (!NewTransaction.DebitCreditIndicator) { sumCredits += NewTransaction.TransactionAmount; } } } } if (!NewTransaction.IsTransactionDateNull()) { NewTransaction.AmountInBaseCurrency = GLRoutines.CurrencyMultiply(NewTransaction.TransactionAmount, TExchangeRateCache.GetDailyExchangeRate( ARefJournalRow.TransactionCurrency, FMainDS.ALedger[0].BaseCurrency, NewTransaction.TransactionDate, false)); // // The International currency calculation is changed to "Base -> International", because it's likely // we won't have a "Transaction -> International" conversion rate defined. // NewTransaction.AmountInIntlCurrency = GLRoutines.CurrencyMultiply(NewTransaction.AmountInBaseCurrency, TExchangeRateCache.GetDailyExchangeRate( FMainDS.ALedger[0].BaseCurrency, FMainDS.ALedger[0].IntlCurrency, NewTransaction.TransactionDate, false)); } } while (!dataFile.EndOfStream); // create a balancing transaction; not sure if this is needed at all??? if (Convert.ToDecimal(sumCredits - sumDebits) != 0) { GLBatchTDSATransactionRow BalancingTransaction = FMainDS.ATransaction.NewRowTyped(true); FMyForm.GetTransactionsControl().NewRowManual(ref BalancingTransaction, ARefJournalRow); FMainDS.ATransaction.Rows.Add(BalancingTransaction); BalancingTransaction.TransactionDate = ALatestTransactionDate; BalancingTransaction.DebitCreditIndicator = true; BalancingTransaction.TransactionAmount = sumCredits - sumDebits; if (BalancingTransaction.TransactionAmount < 0) { BalancingTransaction.TransactionAmount *= -1; BalancingTransaction.DebitCreditIndicator = !BalancingTransaction.DebitCreditIndicator; } if (BalancingTransaction.DebitCreditIndicator) { sumDebits += BalancingTransaction.TransactionAmount; } else { sumCredits += BalancingTransaction.TransactionAmount; } BalancingTransaction.AmountInIntlCurrency = GLRoutines.CurrencyMultiply(BalancingTransaction.TransactionAmount, TExchangeRateCache.GetDailyExchangeRate( ARefJournalRow.TransactionCurrency, FMainDS.ALedger[0].IntlCurrency, BalancingTransaction.TransactionDate, false)); BalancingTransaction.AmountInBaseCurrency = GLRoutines.CurrencyMultiply(BalancingTransaction.TransactionAmount, TExchangeRateCache.GetDailyExchangeRate( ARefJournalRow.TransactionCurrency, FMainDS.ALedger[0].BaseCurrency, BalancingTransaction.TransactionDate, false)); BalancingTransaction.Narrative = Catalog.GetString("Automatically generated balancing transaction"); BalancingTransaction.CostCentreCode = TXMLParser.GetAttribute(ARootNode, "CashCostCentre"); BalancingTransaction.AccountCode = TXMLParser.GetAttribute(ARootNode, "CashAccount"); } ARefJournalRow.JournalCreditTotal = sumCredits; ARefJournalRow.JournalDebitTotal = sumDebits; ARefJournalRow.JournalDescription = Path.GetFileNameWithoutExtension(ADataFilename); ABatchRow RefBatch = (ABatchRow)FMainDS.ABatch.Rows[FMainDS.ABatch.Rows.Count - 1]; RefBatch.BatchCreditTotal = sumCredits; RefBatch.BatchDebitTotal = sumDebits; // todo RefBatch.BatchControlTotal = sumCredits - sumDebits; // csv ! }
/// <summary> /// Method to cancel a specified journal /// </summary> /// <param name="AJournalRowToCancel">The row to cancel</param> /// <returns>True if the journal is cancelled.</returns> public bool CancelRow(GLBatchTDSAJournalRow AJournalRowToCancel) { bool CancellationSuccessful = false; if ((AJournalRowToCancel == null) || (AJournalRowToCancel.JournalStatus != MFinanceConstants.BATCH_UNPOSTED)) { return(false); } int CurrentBatchNo = AJournalRowToCancel.BatchNumber; int CurrentJournalNo = AJournalRowToCancel.JournalNumber; bool CurrentJournalTransactionsLoadedAndCurrent = false; string CancelMessage = string.Empty; string CompletionMessage = string.Empty; CancelMessage = String.Format(Catalog.GetString("Are you sure you want to cancel GL Journal {0} in Batch {1}?"), CurrentJournalNo, CurrentBatchNo); if ((MessageBox.Show(CancelMessage, Catalog.GetString("Confirm Cancel"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != System.Windows.Forms.DialogResult.Yes)) { return(false); } //Backup the Dataset for reversion purposes GLBatchTDS BackupMainDS = null; try { FMyForm.Cursor = Cursors.WaitCursor; //Backup the Dataset for reversion purposes BackupMainDS = (GLBatchTDS)FMainDS.GetChangesTyped(false); //Don't run an inactive fields check on this batch FMyForm.GetBatchControl().UpdateUnpostedBatchDictionary(CurrentBatchNo); //Check if current batch details are currently loaded CurrentJournalTransactionsLoadedAndCurrent = (FMyForm.GetTransactionsControl().FBatchNumber == CurrentBatchNo); //Save and check for inactive values in other unsaved Batches FPetraUtilsObject.SetChangedFlag(); if (!FMyForm.SaveChangesManual(FMyForm.FCurrentGLBatchAction, false, !CurrentJournalTransactionsLoadedAndCurrent)) { FMyForm.GetBatchControl().UpdateUnpostedBatchDictionary(); CompletionMessage = String.Format(Catalog.GetString("Journal {0} in GL Batch {1} has not been cancelled."), CurrentJournalNo, CurrentBatchNo); MessageBox.Show(CompletionMessage, Catalog.GetString("GL Journal Cancellation"), MessageBoxButtons.OK, MessageBoxIcon.Information); return(false); } //Remove any changes, which may cause validation issues, before cancelling FMyForm.GetJournalsControl().PrepareJournalDataForCancelling(CurrentBatchNo, CurrentJournalNo, true); if (CurrentJournalTransactionsLoadedAndCurrent) { //Clear any transactions currently being edited in the Transaction Tab FMyForm.GetTransactionsControl().ClearCurrentSelection(CurrentBatchNo); } //Delete transactions and attributes for current jouernal only FMyForm.GetTransactionsControl().DeleteTransactionData(CurrentBatchNo, CurrentJournalNo); //Edit current Journal decimal journalCreditTotal = AJournalRowToCancel.JournalCreditTotal; decimal journalDebitTotal = AJournalRowToCancel.JournalDebitTotal; AJournalRowToCancel.BeginEdit(); AJournalRowToCancel.JournalStatus = MFinanceConstants.BATCH_CANCELLED; AJournalRowToCancel.LastTransactionNumber = 0; AJournalRowToCancel.JournalCreditTotal = 0; AJournalRowToCancel.JournalDebitTotal = 0; AJournalRowToCancel.EndEdit(); //Edit current Batch ABatchRow CurrentBatchRow = FMyForm.GetBatchControl().GetSelectedDetailRow(); decimal batchControlTotal = CurrentBatchRow.BatchControlTotal; CurrentBatchRow.BeginEdit(); CurrentBatchRow.BatchCreditTotal -= journalCreditTotal; CurrentBatchRow.BatchDebitTotal -= journalDebitTotal; CurrentBatchRow.BatchControlTotal -= (batchControlTotal != 0 ? journalCreditTotal : 0); CurrentBatchRow.EndEdit(); FPetraUtilsObject.SetChangedFlag(); FMyForm.SaveChangesManual(); CompletionMessage = String.Format(Catalog.GetString("Journal no.: {0} cancelled successfully."), CurrentJournalNo); MessageBox.Show(CompletionMessage, Catalog.GetString("Journal Cancelled"), MessageBoxButtons.OK, MessageBoxIcon.Information); FMyForm.DisableTransactions(); CancellationSuccessful = true; } catch (Exception ex) { //Revert to previous state if (BackupMainDS != null) { FMainDS.RejectChanges(); FMainDS.Merge(BackupMainDS); FMyForm.GetJournalsControl().ShowDetailsRefresh(); } TLogging.LogException(ex, Utilities.GetMethodSignature()); throw; } finally { FMyForm.Cursor = Cursors.Default; } return(CancellationSuccessful); }
/// <summary> /// Method to cancel a specified batch /// </summary> /// <param name="ACurrentBatchRow">The row to cancel</param> /// <param name="ABatchDescriptionTextBox">Pass a reference to a TextBox that is used to display the batch description text. This is required /// to ensure that validation passes when the cancelled batch is saved.</param> /// <returns></returns> public bool CancelBatch(ABatchRow ACurrentBatchRow, TextBox ABatchDescriptionTextBox) { if ((ACurrentBatchRow == null) || !FMyForm.SaveChanges()) { return false; } int CurrentBatchNumber = ACurrentBatchRow.BatchNumber; if ((MessageBox.Show(String.Format(Catalog.GetString("You have chosen to cancel this batch ({0}).\n\nDo you really want to cancel it?"), CurrentBatchNumber), Catalog.GetString("Confirm Cancel"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)) { try { //clear any transactions currently being editied in the Transaction Tab FMyForm.GetTransactionsControl().ClearCurrentSelection(); //clear any journals currently being editied in the Journals Tab FMyForm.GetJournalsControl().ClearCurrentSelection(); //Clear Journals etc for current Batch FMainDS.ATransAnalAttrib.Clear(); FMainDS.ATransaction.Clear(); FMainDS.AJournal.Clear(); //Load tables afresh FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadAJournal(FLedgerNumber, CurrentBatchNumber)); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadATransactionForBatch(FLedgerNumber, CurrentBatchNumber)); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadATransAnalAttribForBatch(FLedgerNumber, CurrentBatchNumber)); //Delete transactions for (int i = FMainDS.ATransAnalAttrib.Count - 1; i >= 0; i--) { FMainDS.ATransAnalAttrib[i].Delete(); } for (int i = FMainDS.ATransaction.Count - 1; i >= 0; i--) { FMainDS.ATransaction[i].Delete(); } //Update Journal totals and status foreach (AJournalRow journal in FMainDS.AJournal.Rows) { if (journal.BatchNumber == CurrentBatchNumber) { journal.BeginEdit(); journal.JournalStatus = MFinanceConstants.BATCH_CANCELLED; journal.JournalCreditTotal = 0; journal.JournalDebitTotal = 0; journal.EndEdit(); } } // Edit the batch row ACurrentBatchRow.BeginEdit(); //Ensure validation passes if (ACurrentBatchRow.BatchDescription.Length == 0) { ABatchDescriptionTextBox.Text = " "; } ACurrentBatchRow.BatchCreditTotal = 0; ACurrentBatchRow.BatchDebitTotal = 0; ACurrentBatchRow.BatchControlTotal = 0; ACurrentBatchRow.BatchStatus = MFinanceConstants.BATCH_CANCELLED; ACurrentBatchRow.EndEdit(); FPetraUtilsObject.SetChangedFlag(); //Need to call save if (FMyForm.SaveChanges()) { MessageBox.Show(Catalog.GetString("The batch has been cancelled successfully!"), Catalog.GetString("Success"), MessageBoxButtons.OK, MessageBoxIcon.Information); return true; } else { // saving failed, therefore do not try to post MessageBox.Show(Catalog.GetString( "The batch has been cancelled but there were problems during saving; ") + Environment.NewLine + Catalog.GetString("Please try and save the cancellation immediately."), Catalog.GetString("Failure"), MessageBoxButtons.OK, MessageBoxIcon.Error); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } return false; }
/// <summary> /// load the transactions into the grid /// </summary> /// <param name="ALedgerNumber"></param> /// <param name="ABatchNumber"></param> /// <param name="AJournalNumber"></param> /// <param name="ACurrencyCode"></param> /// <param name="AFromBatchTab"></param> /// <param name="ABatchStatus"></param> /// <param name="AJournalStatus"></param> /// <returns>True if new GL transactions were loaded, false if transactions had been loaded already.</returns> public bool LoadTransactions(Int32 ALedgerNumber, Int32 ABatchNumber, Int32 AJournalNumber, string ACurrencyCode, bool AFromBatchTab = false, string ABatchStatus = MFinanceConstants.BATCH_UNPOSTED, string AJournalStatus = MFinanceConstants.BATCH_UNPOSTED) { TFrmStatusDialog dlgStatus = null; bool DifferentBatchSelected = false; FLoadCompleted = false; FBatchRow = GetBatchRow(); FJournalRow = GetJournalRow(); if ((FBatchRow == null) || (FJournalRow == null)) { return false; } //FBatchNumber and FJournalNumber may have already been set outside // so need to reset to previous value if ((txtBatchNumber.Text.Length > 0) && (FBatchNumber.ToString() != txtBatchNumber.Text)) { FBatchNumber = Int32.Parse(txtBatchNumber.Text); } if ((txtJournalNumber.Text.Length > 0) && (FJournalNumber.ToString() != txtJournalNumber.Text)) { FJournalNumber = Int32.Parse(txtJournalNumber.Text); } bool FirstRun = (FLedgerNumber != ALedgerNumber); bool BatchChanged = (FBatchNumber != ABatchNumber); bool BatchStatusChanged = (!BatchChanged && (FBatchStatus != ABatchStatus)); bool JournalChanged = (BatchChanged || (FJournalNumber != AJournalNumber)); bool JournalStatusChanged = (!JournalChanged && (FJournalStatus != AJournalStatus)); bool CurrencyChanged = (FTransactionCurrency != ACurrencyCode); if (FirstRun) { FLedgerNumber = ALedgerNumber; } if (BatchChanged) { FBatchNumber = ABatchNumber; } if (BatchStatusChanged) { FBatchStatus = ABatchStatus; } if (JournalChanged) { FJournalNumber = AJournalNumber; } if (JournalStatusChanged) { FJournalStatus = AJournalStatus; } if (CurrencyChanged) { FTransactionCurrency = ACurrencyCode; } FIsUnposted = (FBatchRow.BatchStatus == MFinanceConstants.BATCH_UNPOSTED); if (FirstRun) { InitialiseControls(); } try { this.Cursor = Cursors.WaitCursor; //Check if the same batch and journal is selected, so no need to apply filter if (!FirstRun && !BatchChanged && !JournalChanged && !BatchStatusChanged && !JournalStatusChanged && !CurrencyChanged && (FMainDS.ATransaction.DefaultView.Count > 0)) { //Same as previously selected batch and journal //Need to reconnect FPrev in some circumstances if (FPreviouslySelectedDetailRow == null) { DataRowView rowView = (DataRowView)grdDetails.Rows.IndexToDataSourceRow(FPrevRowChangedRow); if (rowView != null) { FPreviouslySelectedDetailRow = (GLBatchTDSATransactionRow)(rowView.Row); } } if (FIsUnposted && (GetSelectedRowIndex() > 0)) { if (AFromBatchTab) { SelectRowInGrid(GetSelectedRowIndex()); } else { GetDetailsFromControls(FPreviouslySelectedDetailRow); } } FLoadCompleted = true; return false; } // Different batch selected DifferentBatchSelected = true; bool requireControlSetup = (FLedgerNumber == -1) || (FTransactionCurrency != ACurrencyCode); //Handle dialog dlgStatus = new TFrmStatusDialog(FPetraUtilsObject.GetForm()); if (FShowStatusDialogOnLoad == true) { dlgStatus.Show(); FShowStatusDialogOnLoad = false; dlgStatus.Heading = String.Format(Catalog.GetString("Batch {0}, Journal {1}"), ABatchNumber, AJournalNumber); dlgStatus.CurrentStatus = Catalog.GetString("Loading transactions ..."); } FLedgerNumber = ALedgerNumber; FBatchNumber = ABatchNumber; FJournalNumber = AJournalNumber; FTransactionNumber = -1; FTransactionCurrency = ACurrencyCode; FBatchStatus = ABatchStatus; FJournalStatus = AJournalStatus; FPreviouslySelectedDetailRow = null; grdDetails.SuspendLayout(); //Empty grids before filling them grdDetails.DataSource = null; grdAnalAttributes.DataSource = null; // This sets the main part of the filter but excluding the additional items set by the user GUI // It gets the right sort order SetTransactionDefaultView(); //Set the Analysis attributes filter as well FAnalysisAttributesLogic = new TAnalysisAttributes(FLedgerNumber, FBatchNumber, FJournalNumber); FAnalysisAttributesLogic.SetTransAnalAttributeDefaultView(FMainDS); FMainDS.ATransAnalAttrib.DefaultView.AllowNew = false; //Load from server if necessary if (FMainDS.ATransaction.DefaultView.Count == 0) { dlgStatus.CurrentStatus = Catalog.GetString("Requesting transactions from server..."); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadATransactionATransAnalAttrib(ALedgerNumber, ABatchNumber, AJournalNumber)); } else if (FMainDS.ATransAnalAttrib.DefaultView.Count == 0) // just in case transactions have been loaded in a separate process without analysis attributes { dlgStatus.CurrentStatus = Catalog.GetString("Requesting analysis attributes from server..."); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadATransAnalAttribForJournal(ALedgerNumber, ABatchNumber, AJournalNumber)); } FContainsSystemGenerated = false; // check if any of the rows are system generated (i.e. reversals) foreach (DataRowView rv in FMainDS.ATransaction.DefaultView) { if (((ATransactionRow)rv.Row).SystemGenerated) { FContainsSystemGenerated = true; break; } } // We need to call this because we have not called ShowData(), which would have set it. This differs from the Gift screen. grdDetails.DataSource = new DevAge.ComponentModel.BoundDataView(FMainDS.ATransaction.DefaultView); // Now we set the full filter dlgStatus.CurrentStatus = Catalog.GetString("Selecting the records..."); FFilterAndFindObject.ApplyFilter(); dlgStatus.CurrentStatus = Catalog.GetString("Configuring analysis attributes ..."); if (grdAnalAttributes.Columns.Count == 1) { grdAnalAttributes.SpecialKeys = GridSpecialKeys.Default | GridSpecialKeys.Tab; FcmbAnalAttribValues = new SourceGrid.Cells.Editors.ComboBox(typeof(string)); FcmbAnalAttribValues.EnableEdit = true; FcmbAnalAttribValues.EditableMode = EditableMode.Focus; grdAnalAttributes.AddTextColumn(Catalog.GetString("Value"), FMainDS.ATransAnalAttrib.Columns[ATransAnalAttribTable.GetAnalysisAttributeValueDBName()], 150, FcmbAnalAttribValues); FcmbAnalAttribValues.Control.SelectedValueChanged += new EventHandler(this.AnalysisAttributeValueChanged); grdAnalAttributes.Columns[0].Width = 99; } grdAnalAttributes.DataSource = new DevAge.ComponentModel.BoundDataView(FMainDS.ATransAnalAttrib.DefaultView); grdAnalAttributes.SetHeaderTooltip(0, Catalog.GetString("Type")); grdAnalAttributes.SetHeaderTooltip(1, Catalog.GetString("Value")); // if this form is readonly or batch is posted, then we need all account and cost centre codes, because old codes might have been used bool ActiveOnly = false; //(this.Enabled && FIsUnposted && !FContainsSystemGenerated); if (requireControlSetup || (FActiveOnly != ActiveOnly)) { FActiveOnly = ActiveOnly; //Load all analysis attribute values if (FCacheDS == null) { dlgStatus.CurrentStatus = Catalog.GetString("Loading analysis attributes ..."); FCacheDS = TRemote.MFinance.GL.WebConnectors.LoadAAnalysisAttributes(FLedgerNumber, FActiveOnly); } SetupExtraGridFunctionality(); dlgStatus.CurrentStatus = Catalog.GetString("Initialising accounts and cost centres ..."); // We suppress change detection because these are the correct values // Then initialise our combo boxes for the correct account codes and cost centres bool prevSuppressChangeDetection = FPetraUtilsObject.SuppressChangeDetection; FPetraUtilsObject.SuppressChangeDetection = true; TFinanceControls.InitialiseAccountList(ref cmbDetailAccountCode, FLedgerNumber, true, false, ActiveOnly, false, ACurrencyCode, true); TFinanceControls.InitialiseCostCentreList(ref cmbDetailCostCentreCode, FLedgerNumber, true, false, ActiveOnly, false); FPetraUtilsObject.SuppressChangeDetection = prevSuppressChangeDetection; cmbDetailCostCentreCode.AttachedLabel.Text = TFinanceControls.SELECT_VALID_COST_CENTRE; cmbDetailAccountCode.AttachedLabel.Text = TFinanceControls.SELECT_VALID_ACCOUNT; } UpdateTransactionTotals(); grdDetails.ResumeLayout(); FLoadCompleted = true; ShowData(); SelectRowInGrid(1); ShowDetails(); //Needed because of how currency is handled UpdateChangeableStatus(); UpdateRecordNumberDisplay(); FFilterAndFindObject.SetRecordNumberDisplayProperties(); //Check for missing analysis attributes and their values if (FIsUnposted && (grdDetails.Rows.Count > 1)) { string updatedTransactions = string.Empty; dlgStatus.CurrentStatus = Catalog.GetString("Checking analysis attributes ..."); FAnalysisAttributesLogic.ReconcileTransAnalysisAttributes(FMainDS, FCacheDS, out updatedTransactions); if (updatedTransactions.Length > 0) { //Remove trailing comma updatedTransactions = updatedTransactions.Remove(updatedTransactions.Length - 2); MessageBox.Show(String.Format(Catalog.GetString( "Analysis Attributes have been updated in transaction(s): {0}.{1}{1}Remeber to set their values before posting!"), updatedTransactions, Environment.NewLine), "Analysis Attributes", MessageBoxButtons.OK, MessageBoxIcon.Information); FPetraUtilsObject.SetChangedFlag(); } } RefreshAnalysisAttributesGrid(); } catch (Exception ex) { TLogging.Log(String.Format("Method:{0} - Unexpected error!{1}{1}{2}", Utilities.GetMethodSignature(), Environment.NewLine, ex.Message)); throw ex; } finally { if (dlgStatus != null) { dlgStatus.Close(); } this.Cursor = Cursors.Default; } return DifferentBatchSelected; }
private static bool ValidateGLBatchJournalNumbering(ref GLBatchTDS AGLBatch, ref ABatchRow ABatchToPost, ref TVerificationResultCollection AVerifications) { #region Validate Arguments if ((AGLBatch.ABatch == null) || (AGLBatch.ABatch.Count == 0) || (ABatchToPost == null)) { throw new EFinanceSystemDataTableReturnedNoDataException(String.Format(Catalog.GetString( "Function:{0} - No GL Batch data is present!"), Utilities.GetMethodName(true))); } #endregion Validate Arguments //Default to most likely outcome bool NumberingIsValid = true; string SQLStatement = string.Empty; string TempTableName = "TempCheckForConsecutiveJournals"; //Parameters for SQL as strings string prmLedgerNumber = ABatchToPost.LedgerNumber.ToString(); string prmBatchNumber = ABatchToPost.BatchNumber.ToString(); //Tables with alias string BatchTableAlias = "b"; string bBatchTable = ABatchTable.GetTableDBName() + " " + BatchTableAlias; string JournalTableAlias = "j"; string jJournalTable = AJournalTable.GetTableDBName() + " " + JournalTableAlias; //Table: ABudgetTable and fields string bLedgerNumber = BatchTableAlias + "." + ABatchTable.GetLedgerNumberDBName(); string bBatchNumber = BatchTableAlias + "." + ABatchTable.GetBatchNumberDBName(); string bBatchNumberAlias = "BatchNumber"; string bBatchLastJournal = BatchTableAlias + "." + ABatchTable.GetLastJournalDBName(); string bBatchLastJournalAlias = "BatchLastJournal"; string jLedgerNumber = JournalTableAlias + "." + AJournalTable.GetLedgerNumberDBName(); string jBatchNumber = JournalTableAlias + "." + AJournalTable.GetBatchNumberDBName(); string jJournalNumber = JournalTableAlias + "." + AJournalTable.GetJournalNumberDBName(); string jFirstJournalAlias = "FirstJournal"; string jLastJournalAlias = "LastJournal"; string jCountJournalAlias = "CountJournal"; try { DataTable tempTable = AGLBatch.Tables.Add(TempTableName); tempTable.Columns.Add(bBatchNumberAlias, typeof(Int32)); tempTable.Columns.Add(bBatchLastJournalAlias, typeof(Int32)); tempTable.Columns.Add(jFirstJournalAlias, typeof(Int32)); tempTable.Columns.Add(jLastJournalAlias, typeof(Int32)); tempTable.Columns.Add(jCountJournalAlias, typeof(Int32)); SQLStatement = "SELECT " + bBatchNumber + " " + bBatchNumberAlias + "," + " MIN(" + bBatchLastJournal + ") " + bBatchLastJournalAlias + "," + " COALESCE(MIN(" + jJournalNumber + "), 0) " + jFirstJournalAlias + "," + " COALESCE(MAX(" + jJournalNumber + "), 0) " + jLastJournalAlias + "," + " Count(" + jJournalNumber + ") " + jCountJournalAlias + " FROM " + bBatchTable + " LEFT OUTER JOIN " + jJournalTable + " ON " + bLedgerNumber + " = " + jLedgerNumber + " AND " + bBatchNumber + " = " + jBatchNumber + " WHERE " + bLedgerNumber + " = " + prmLedgerNumber + " AND " + bBatchNumber + " = " + prmBatchNumber + " GROUP BY " + bBatchNumber + ";"; //Create temp table to check veracity of Journal numbering GLBatchTDS gLBatch = AGLBatch; TDBTransaction transaction = null; DBAccess.GDBAccessObj.GetNewOrExistingAutoReadTransaction(IsolationLevel.ReadCommitted, TEnforceIsolationLevel.eilMinimum, ref transaction, delegate { DBAccess.GDBAccessObj.Select(gLBatch, SQLStatement, TempTableName, transaction); }); //As long as Batches exist, rows will be returned int numTempRows = AGLBatch.Tables[TempTableName].Rows.Count; DataView tempDV = new DataView(AGLBatch.Tables[TempTableName]); //Confirm are all equal and correct - the most common tempDV.RowFilter = string.Format("{0}={1} And {1}={2} And {0}={2} And (({2}>0 And {3}=1) Or ({2}=0 And {3}=0))", bBatchLastJournalAlias, jLastJournalAlias, jCountJournalAlias, jFirstJournalAlias); //If all records are correct, nothing to do if (tempDV.Count == numTempRows) { return NumberingIsValid; } //!!Reaching this point means there are issues that need addressing. //Confirm that no negative numbers exist tempDV.RowFilter = string.Format("{0} < 0 Or {1} < 0", bBatchLastJournalAlias, jFirstJournalAlias); if (tempDV.Count > 0) { string errMessage = "The following Batches have a negative LastJournalNumber or have Journals with a negative JournalNumber!"; foreach (DataRowView drv in tempDV) { errMessage += string.Format("{0}Batch:{1}", Environment.NewLine, drv[bBatchNumberAlias]); } AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ABatchToPost.LedgerNumber), errMessage, TResultSeverity.Resv_Critical)); return false; } //Display non-sequential journals tempDV.RowFilter = string.Format("{2}>0 And ({3}<>1 Or {1}<>{2})", bBatchLastJournalAlias, jLastJournalAlias, jCountJournalAlias, jFirstJournalAlias); if (tempDV.Count > 0) { string errMessage = "The following Batches have gaps in their Journal numbering! You will need to cancel the Batch(es) and recreate:"; foreach (DataRowView drv in tempDV) { errMessage += string.Format("{0}Batch:{1}", Environment.NewLine, drv[bBatchNumberAlias]); } AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ABatchToPost.LedgerNumber), errMessage, TResultSeverity.Resv_Critical)); return false; } //The next most likely, is where the BatchLastJournal needs updating //Display mismatched journal last number tempDV.RowFilter = string.Format("{0}<>{1} And {1}={2} And (({2}>0 And {3}=1) Or ({2}=0 And {3}=0))", bBatchLastJournalAlias, jLastJournalAlias, jCountJournalAlias, jFirstJournalAlias); if (tempDV.Count > 0) { ABatchToPost.LastJournal = Convert.ToInt32(tempDV[0][jLastJournalAlias]); } } catch (Exception ex) { TLogging.Log(String.Format("Method:{0} - Unexpected error!{1}{1}{2}", Utilities.GetMethodSignature(), Environment.NewLine, ex.Message)); throw ex; } finally { if (AGLBatch.Tables.Contains(TempTableName)) { AGLBatch.Tables.Remove(TempTableName); } } return NumberingIsValid; }
/// <summary> /// Posts a batch /// </summary> /// <param name="ACurrentBatchRow">The data row corresponding to the batch to post</param> /// <param name="AEffectiveDate">The effective date for the batch</param> /// <param name="AStartDateCurrentPeriod">The earliest postable date</param> /// <param name="AEndDateLastForwardingPeriod">The latest postable date</param> /// <returns> /// True if the batch was successfully posted /// </returns> public bool PostBatch(ABatchRow ACurrentBatchRow, DateTime AEffectiveDate, DateTime AStartDateCurrentPeriod, DateTime AEndDateLastForwardingPeriod) { bool RetVal = false; if (!SaveBatchForPosting()) { return RetVal; } // TODO: display progress of posting TVerificationResultCollection Verifications; int CurrentBatchNumber = ACurrentBatchRow.BatchNumber; if ((AEffectiveDate.Date < AStartDateCurrentPeriod) || (AEffectiveDate.Date > AEndDateLastForwardingPeriod)) { MessageBox.Show(String.Format(Catalog.GetString( "The Date Effective is outside the periods available for posting. Enter a date between {0:d} and {1:d}."), AStartDateCurrentPeriod, AEndDateLastForwardingPeriod)); return RetVal; } // check that a corportate exchange rate exists FMyForm.WarnAboutMissingIntlExchangeRate = true; if (FMyForm.GetInternationalCurrencyExchangeRate() == 0) { return false; } if (MessageBox.Show(String.Format(Catalog.GetString("Are you sure you want to post batch {0}?"), CurrentBatchNumber), Catalog.GetString("Question"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.Yes) { try { Cursor.Current = Cursors.WaitCursor; if (!TRemote.MFinance.GL.WebConnectors.PostGLBatch(FLedgerNumber, CurrentBatchNumber, out Verifications)) { string ErrorMessages = String.Empty; foreach (TVerificationResult verif in Verifications) { ErrorMessages += "[" + verif.ResultContext + "] " + verif.ResultTextCaption + ": " + verif.ResultText + Environment.NewLine; } System.Windows.Forms.MessageBox.Show(ErrorMessages, Catalog.GetString("Posting failed"), MessageBoxButtons.OK, MessageBoxIcon.Error); } else { //I don't need to call this directly, because the server calls it: //TFrmGLBatch.PrintPostingRegister(FLedgerNumber, CurrentBatchNumber); // TODO: print reports on successfully posted batch MessageBox.Show(Catalog.GetString("The batch has been posted successfully!"), Catalog.GetString("Success"), MessageBoxButtons.OK, MessageBoxIcon.Information); // refresh the grid, to reflect that the batch has been posted FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAndContent(FLedgerNumber, CurrentBatchNumber)); // make sure that the current dataset is clean, // otherwise the next save would try to modify the posted batch, even though no values have been changed FMainDS.AcceptChanges(); // Ensure these tabs will ask the server for updates FMyForm.GetJournalsControl().ClearCurrentSelection(); FMyForm.GetTransactionsControl().ClearCurrentSelection(); FMyUserControl.UpdateDisplay(); RetVal = true; } } catch (Exception ex) { string msg = (String.Format(Catalog.GetString("Unexpected error occurred during the posting of a GL Batch!{0}{1}{2}{1} {3}"), Utilities.GetMethodSignature(), Environment.NewLine, ex.Message, ex.InnerException.Message)); TLogging.Log(msg); MessageBox.Show(msg, "Post GL Batch Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { Cursor.Current = Cursors.Default; } } return RetVal; }
/// <summary> /// Runs a test on posting a batch /// </summary> /// <param name="ACurrentBatchRow">The data row corresponding to the batch to post</param> public void TestPostBatch(ABatchRow ACurrentBatchRow) { if (!SaveBatchForPosting()) { return; } TVerificationResultCollection Verifications; FMyForm.Cursor = Cursors.WaitCursor; List <TVariant>Result = TRemote.MFinance.GL.WebConnectors.TestPostGLBatch(FLedgerNumber, ACurrentBatchRow.BatchNumber, out Verifications); try { if ((Verifications != null) && (Verifications.Count > 0)) { string ErrorMessages = string.Empty; foreach (TVerificationResult verif in Verifications) { ErrorMessages += "[" + verif.ResultContext + "] " + verif.ResultTextCaption + ": " + verif.ResultText + Environment.NewLine; } System.Windows.Forms.MessageBox.Show(ErrorMessages, Catalog.GetString("Posting failed"), MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (Result.Count < 25) { string message = string.Empty; foreach (TVariant value in Result) { ArrayList compValues = value.ToComposite(); message += string.Format( Catalog.GetString("{1}/{0} ({3}/{2}) is: {4} and would be: {5}"), ((TVariant)compValues[0]).ToString(), ((TVariant)compValues[2]).ToString(), ((TVariant)compValues[1]).ToString(), ((TVariant)compValues[3]).ToString(), StringHelper.FormatCurrency((TVariant)compValues[4], "currency"), StringHelper.FormatCurrency((TVariant)compValues[5], "currency")) + Environment.NewLine; } MessageBox.Show(message, Catalog.GetString("Result of Test Posting")); } else { // store to CSV file string message = string.Empty; foreach (TVariant value in Result) { ArrayList compValues = value.ToComposite(); string[] columns = new string[] { ((TVariant)compValues[0]).ToString(), ((TVariant)compValues[1]).ToString(), ((TVariant)compValues[2]).ToString(), ((TVariant)compValues[3]).ToString(), StringHelper.FormatCurrency((TVariant)compValues[4], "CurrencyCSV"), StringHelper.FormatCurrency((TVariant)compValues[5], "CurrencyCSV") }; message += StringHelper.StrMerge(columns, Thread.CurrentThread.CurrentCulture.TextInfo.ListSeparator[0]) + Environment.NewLine; } string CSVFilePath = TClientSettings.PathLog + Path.DirectorySeparatorChar + "Batch" + ACurrentBatchRow.BatchNumber.ToString() + "_TestPosting.csv"; StreamWriter sw = new StreamWriter(CSVFilePath, false, System.Text.Encoding.UTF8); sw.Write(message); sw.Close(); MessageBox.Show( String.Format(Catalog.GetString("Please see file {0} for the result of the test posting"), CSVFilePath), Catalog.GetString("Result of Test Posting")); } } finally { FMyForm.Cursor = Cursors.Default; } }
/// <summary> /// update the journal header fields from a batch /// </summary> /// <param name="ABatch"></param> public void UpdateHeaderTotals(ABatchRow ABatch) { decimal SumDebits = 0.0M; decimal SumCredits = 0.0M; DataView JournalDV = new DataView(FMainDS.AJournal); JournalDV.RowFilter = String.Format("{0}={1}", AJournalTable.GetBatchNumberDBName(), ABatch.BatchNumber); foreach (DataRowView v in JournalDV) { AJournalRow r = (AJournalRow)v.Row; SumCredits += r.JournalCreditTotal; SumDebits += r.JournalDebitTotal; } FPetraUtilsObject.DisableDataChangedEvent(); txtCurrentPeriod.Text = ABatch.BatchPeriod.ToString(); txtDebit.NumberValueDecimal = SumDebits; txtCredit.NumberValueDecimal = SumCredits; txtControl.NumberValueDecimal = ABatch.BatchControlTotal; FPetraUtilsObject.EnableDataChangedEvent(); }
/// <summary> /// load the journals into the grid /// </summary> /// <param name="ALedgerNumber"></param> /// <param name="ABatchNumber"></param> /// <param name="ABatchStatus"></param> public void LoadJournals(Int32 ALedgerNumber, Int32 ABatchNumber, string ABatchStatus = MFinanceConstants.BATCH_UNPOSTED) { FJournalsLoaded = false; FBatchRow = GetBatchRow(); if (FBatchRow == null) { return; } FCancelLogicObject = new TUC_GLJournals_Cancel(FPetraUtilsObject, FLedgerNumber, FMainDS); //Make sure the current effective date for the Batch is correct DateTime BatchDateEffective = FBatchRow.DateEffective; bool FirstRun = (FLedgerNumber != ALedgerNumber); bool BatchChanged = (FBatchNumber != ABatchNumber); bool BatchStatusChanged = (!BatchChanged && FBatchStatus != ABatchStatus); //Check if need to load Journals if (FirstRun || BatchChanged || BatchStatusChanged) { FLedgerNumber = ALedgerNumber; FBatchNumber = ABatchNumber; FBatchStatus = ABatchStatus; SetJournalDefaultView(); FPreviouslySelectedDetailRow = null; //Load Journals if (FMainDS.AJournal.DefaultView.Count == 0) { FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadAJournalAndContent(FLedgerNumber, FBatchNumber)); } if (FBatchStatus == MFinanceConstants.BATCH_UNPOSTED) { if (!dtpDetailDateEffective.Date.HasValue || (dtpDetailDateEffective.Date.Value != BatchDateEffective)) { dtpDetailDateEffective.Date = BatchDateEffective; } } foreach (DataRowView drv in FMainDS.AJournal.DefaultView) { AJournalRow jr = (AJournalRow)drv.Row; if (jr.DateEffective != BatchDateEffective) { ((TFrmGLBatch)ParentForm).GetTransactionsControl().UpdateTransactionTotals("BATCH", true); break; } } ShowData(); // Now set up the complete current filter FFilterAndFindObject.FilterPanelControls.SetBaseFilter(FMainDS.AJournal.DefaultView.RowFilter, true); FFilterAndFindObject.ApplyFilter(); } else { // The journals are the same and we have loaded them already if (FBatchRow.BatchStatus == MFinanceConstants.BATCH_UNPOSTED) { if (GetSelectedRowIndex() > 0) { GetDetailsFromControls(GetSelectedDetailRow()); } } } int nRowToSelect = 1; TFrmGLBatch myParentForm = (TFrmGLBatch)ParentForm; if (myParentForm.InitialBatchFound) { string filter = String.Format("{0}={1}", AJournalTable.GetJournalNumberDBName(), myParentForm.InitialJournalNumber); DataView dv = new DataView(FMainDS.AJournal, filter, "", DataViewRowState.CurrentRows); if (dv.Count > 0) { nRowToSelect = grdDetails.DataSourceRowToIndex2(dv[0].Row) + 1; } } else { nRowToSelect = (BatchChanged || FirstRun) ? 1 : FPrevRowChangedRow; } //This will also call UpdateChangeableStatus SelectRowInGrid(nRowToSelect); UpdateRecordNumberDisplay(); FFilterAndFindObject.SetRecordNumberDisplayProperties(); FJournalsLoaded = true; }
/// <summary> /// this supports the transaction export files from Petra 2.x. /// Lines do NOT start with T for transaction /// </summary> public void ImportTransactions(ABatchRow ACurrentBatchRow, AJournalRow ACurrentJournalRow, TImportDataSourceEnum AImportDataSource) { bool ok = false; String importString; String impOptions; OpenFileDialog dialog = null; if (FPetraUtilsObject.HasChanges && !FMyForm.SaveChanges()) { // saving failed, therefore do not try to import MessageBox.Show(Catalog.GetString("Please save your changes before Importing new transactions"), Catalog.GetString( "Import GL Transactions"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if ((ACurrentBatchRow == null) || (ACurrentJournalRow == null) || (ACurrentJournalRow.JournalStatus != MFinanceConstants.BATCH_UNPOSTED)) { MessageBox.Show(Catalog.GetString("Please select an unposted journal to import transactions."), Catalog.GetString("Import GL Transactions")); return; } if (ACurrentJournalRow.LastTransactionNumber > 0) { if (MessageBox.Show(Catalog.GetString( "The current journal already contains some transactions. Do you really want to add more transactions to this journal?"), Catalog.GetString("Import GL Transactions"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No) { return; } } FdlgSeparator = new TDlgSelectCSVSeparator(false); if (AImportDataSource == TImportDataSourceEnum.FromClipboard) { importString = Clipboard.GetText(TextDataFormat.UnicodeText); if ((importString == null) || (importString.Length == 0)) { MessageBox.Show(Catalog.GetString("Please first copy data from your spreadsheet application!"), Catalog.GetString("Failure"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } impOptions = TUserDefaults.GetStringDefault("Imp Options", ";American"); String dateFormatString = TUserDefaults.GetStringDefault("Imp Date", "MDY"); FdlgSeparator = new TDlgSelectCSVSeparator(false); FdlgSeparator.SelectedSeparator = "\t"; FdlgSeparator.CSVData = importString; FdlgSeparator.DateFormat = dateFormatString; if (impOptions.Length > 1) { FdlgSeparator.NumberFormat = impOptions.Substring(1); } } else if (AImportDataSource == TImportDataSourceEnum.FromFile) { dialog = new OpenFileDialog(); string exportPath = TClientSettings.GetExportPath(); string fullPath = TUserDefaults.GetStringDefault("Imp Filename", exportPath + Path.DirectorySeparatorChar + "import.csv"); TImportExportDialogs.SetOpenFileDialogFilePathAndName(dialog, fullPath, exportPath); dialog.Title = Catalog.GetString("Import Transactions from CSV File"); dialog.Filter = Catalog.GetString("GL Transactions files (*.csv)|*.csv"); impOptions = TUserDefaults.GetStringDefault("Imp Options", ";" + TDlgSelectCSVSeparator.NUMBERFORMAT_AMERICAN); // This call fixes Windows7 Open File Dialogs. It must be the line before ShowDialog() TWin7FileOpenSaveDialog.PrepareDialog(Path.GetFileName(fullPath)); if (dialog.ShowDialog() == DialogResult.OK) { Boolean fileCanOpen = FdlgSeparator.OpenCsvFile(dialog.FileName); if (!fileCanOpen) { MessageBox.Show(Catalog.GetString("Unable to open file."), Catalog.GetString("Transaction Import"), MessageBoxButtons.OK, MessageBoxIcon.Stop); return; } importString = File.ReadAllText(dialog.FileName, Encoding.Default); String dateFormatString = TUserDefaults.GetStringDefault("Imp Date", "MDY"); FdlgSeparator.DateFormat = dateFormatString; if (impOptions.Length > 1) { FdlgSeparator.NumberFormat = impOptions.Substring(1); } FdlgSeparator.SelectedSeparator = impOptions.Substring(0, 1); } else { return; } } else { // unknown source!! The following need a value... impOptions = String.Empty; importString = String.Empty; } if (FdlgSeparator.ShowDialog() == DialogResult.OK) { Hashtable requestParams = new Hashtable(); requestParams.Add("ALedgerNumber", FLedgerNumber); requestParams.Add("Delimiter", FdlgSeparator.SelectedSeparator); requestParams.Add("DateFormatString", FdlgSeparator.DateFormat); requestParams.Add("NumberFormat", FdlgSeparator.NumberFormat); requestParams.Add("NewLine", Environment.NewLine); TVerificationResultCollection AMessages = new TVerificationResultCollection(); Thread ImportThread = new Thread(() => ImportGLTransactions(requestParams, importString, ACurrentBatchRow.BatchNumber, ACurrentJournalRow.JournalNumber, out AMessages, out ok)); using (TProgressDialog ImportDialog = new TProgressDialog(ImportThread)) { ImportDialog.ShowDialog(); } // It is important to save user defaults here, even if there were errors // because in that case the user will want to import the same file again after fixing it. SaveUserDefaults(dialog, impOptions); ShowMessages(AMessages); } if (ok) { MessageBox.Show(Catalog.GetString("Your data was imported successfully!"), Catalog.GetString("Transactions Import"), MessageBoxButtons.OK, MessageBoxIcon.Information); // Update the client side with new information from the server FMyForm.Cursor = Cursors.WaitCursor; FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAJournal(FLedgerNumber, ACurrentBatchRow.BatchNumber)); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadATransactionATransAnalAttrib(FLedgerNumber, ACurrentBatchRow.BatchNumber, ACurrentJournalRow.JournalNumber)); FMainDS.AcceptChanges(); FMyForm.Cursor = Cursors.Default; FMyForm.GetTransactionsControl().SelectRow(1); } }
/// <summary> /// Load all GLM and GLMPeriod records for the batch period and the following periods, since that will avoid loading them one by one during submitchanges. /// this is called after ValidateBatchAndTransactions, because the BatchYear and BatchPeriod are validated and recalculated there /// </summary> private static void LoadGLMData(ref GLPostingTDS AGLPostingDS, Int32 ALedgerNumber, ABatchRow ABatchToPost) { TDBTransaction Transaction = null; GLPostingTDS GLPostingDS = AGLPostingDS; DBAccess.GDBAccessObj.GetNewOrExistingAutoReadTransaction(IsolationLevel.ReadCommitted, TEnforceIsolationLevel.eilMinimum, ref Transaction, delegate { AGeneralLedgerMasterRow GLMTemplateRow = GLPostingDS.AGeneralLedgerMaster.NewRowTyped(false); GLMTemplateRow.LedgerNumber = ALedgerNumber; GLMTemplateRow.Year = ABatchToPost.BatchYear; AGeneralLedgerMasterAccess.LoadUsingTemplate(GLPostingDS, GLMTemplateRow, Transaction); string query = "SELECT PUB_a_general_ledger_master_period.* " + "FROM PUB_a_general_ledger_master, PUB_a_general_ledger_master_period " + "WHERE PUB_a_general_ledger_master.a_ledger_number_i = ? " + "AND PUB_a_general_ledger_master.a_year_i = ? " + "AND PUB_a_general_ledger_master_period.a_glm_sequence_i = PUB_a_general_ledger_master.a_glm_sequence_i " + "AND PUB_a_general_ledger_master_period.a_period_number_i >= ?"; List <OdbcParameter>parameters = new List <OdbcParameter>(); OdbcParameter parameter = new OdbcParameter("ledgernumber", OdbcType.Int); parameter.Value = ALedgerNumber; parameters.Add(parameter); parameter = new OdbcParameter("year", OdbcType.Int); parameter.Value = ABatchToPost.BatchYear; parameters.Add(parameter); parameter = new OdbcParameter("period", OdbcType.Int); parameter.Value = ABatchToPost.BatchPeriod; parameters.Add(parameter); DBAccess.GDBAccessObj.Select(GLPostingDS, query, GLPostingDS.AGeneralLedgerMasterPeriod.TableName, Transaction, parameters.ToArray()); }); }
private void InitBatchAndJournal(decimal AExchangeRate, string ACurrencyCode) { F_GLDataset = TGLPosting.CreateABatch(F_LedgerNum); F_batch = F_GLDataset.ABatch[0]; F_batch.BatchDescription = Catalog.GetString("Period end revaluations"); TAccountPeriodInfo accountingPeriodInfo = new TAccountPeriodInfo(F_LedgerNum); accountingPeriodInfo.AccountingPeriodNumber = F_batch.BatchPeriod; F_batch.DateEffective = accountingPeriodInfo.PeriodEndDate; F_batch.BatchStatus = MFinanceConstants.BATCH_UNPOSTED; F_journal = F_GLDataset.AJournal.NewRowTyped(); F_journal.LedgerNumber = F_batch.LedgerNumber; F_journal.BatchNumber = F_batch.BatchNumber; F_journal.JournalNumber = 1; F_journal.DateEffective = F_batch.DateEffective; F_journal.ExchangeRateTime = 14400; // revaluations are typically later than 'new rates' F_journal.JournalPeriod = F_batch.BatchPeriod; F_journal.TransactionCurrency = F_BaseCurrency; F_journal.JournalDescription = F_batch.BatchDescription; F_journal.TransactionTypeCode = CommonAccountingTransactionTypesEnum.REVAL.ToString(); F_journal.SubSystemCode = CommonAccountingSubSystemsEnum.GL.ToString(); F_journal.LastTransactionNumber = 0; F_journal.DateOfEntry = DateTime.Now; F_journal.ExchangeRateToBase = 1.0M; F_GLDataset.AJournal.Rows.Add(F_journal); ARevaluationRow revalRow = F_GLDataset.ARevaluation.NewRowTyped(); revalRow.LedgerNumber = F_journal.LedgerNumber; revalRow.BatchNumber = F_journal.BatchNumber; revalRow.JournalNumber = F_journal.JournalNumber; revalRow.ExchangeRateToBase = AExchangeRate; revalRow.RevaluationCurrency = ACurrencyCode; F_GLDataset.ARevaluation.Rows.Add(revalRow); }
private void ValidateDataDetailsManual(ATransactionRow ARow) { //Can be called from outside, so need to update fields FBatchRow = GetBatchRow(); if (FBatchRow == null) { return; } FJournalRow = GetJournalRow(); if (FJournalRow != null) { FJournalNumber = FJournalRow.JournalNumber; FJournalStatus = FJournalRow.JournalStatus; } FIsUnposted = (FBatchRow.BatchStatus == MFinanceConstants.BATCH_UNPOSTED); if ((ARow == null) || (FBatchRow.BatchNumber != ARow.BatchNumber) || !FIsUnposted) { return; } TVerificationResultCollection VerificationResultCollection = FPetraUtilsObject.VerificationResultCollection; Control controlToPass = null; //Local validation if (((txtDebitAmount.NumberValueDecimal.Value == 0) && (txtCreditAmount.NumberValueDecimal.Value == 0)) || (txtDebitAmount.NumberValueDecimal.Value < 0)) { controlToPass = txtDebitAmount; } else if (txtCreditAmount.NumberValueDecimal.Value < 0) { controlToPass = txtCreditAmount; } else if (TSystemDefaults.GetSystemDefault(SharedConstants.SYSDEFAULT_GLREFMANDATORY, "no") == "yes") { controlToPass = txtDetailReference; } else if ((VerificationResultCollection.Count == 1) && (VerificationResultCollection[0].ResultCode == CommonErrorCodes.ERR_INVALIDNUMBER)) { //The amount controls register as invalid even when value is correct. Need to reset // Verifications accordingly. FPetraUtilsObject.VerificationResultCollection.Clear(); } TSharedFinanceValidation_GL.ValidateGLDetailManual(this, FBatchRow, ARow, controlToPass, ref VerificationResultCollection, FValidationControlsDict); if ((FPreviouslySelectedDetailRow != null) && !FAnalysisAttributesLogic.AccountAnalysisAttributeCountIsCorrect( FPreviouslySelectedDetailRow.TransactionNumber, FPreviouslySelectedDetailRow.AccountCode, FMainDS, FIsUnposted)) { DataColumn ValidationColumn; TVerificationResult VerificationResult = null; object ValidationContext; ValidationColumn = ARow.Table.Columns[ATransactionTable.ColumnAccountCodeId]; ValidationContext = "unused because of OverrideResultText"; // This code is only running because of failure, so cause an error to occur. VerificationResult = TStringChecks.StringMustNotBeEmpty("", ValidationContext.ToString(), this, ValidationColumn, null); VerificationResult.OverrideResultText(String.Format( "A value must be entered for 'Analysis Attributes' for Account Code {0} in Transaction {1}.", ARow.AccountCode, ARow.TransactionNumber)); // Handle addition/removal to/from TVerificationResultCollection VerificationResultCollection.Auto_Add_Or_AddOrRemove(this, VerificationResult, ValidationColumn, true); } String ValueRequiredForType; if ((FPreviouslySelectedDetailRow != null) && !FAnalysisAttributesLogic.AccountAnalysisAttributesValuesExist( FPreviouslySelectedDetailRow.TransactionNumber, FPreviouslySelectedDetailRow.AccountCode, FMainDS, out ValueRequiredForType, FIsUnposted)) { DataColumn ValidationColumn; TVerificationResult VerificationResult = null; object ValidationContext; ValidationColumn = ARow.Table.Columns[ATransactionTable.ColumnAccountCodeId]; ValidationContext = String.Format("Analysis code {0} for Account Code {1} in Transaction {2}", ValueRequiredForType, ARow.AccountCode, ARow.TransactionNumber); // This code is only running because of failure, so cause an error to occur. VerificationResult = TStringChecks.StringMustNotBeEmpty("", ValidationContext.ToString(), this, ValidationColumn, null); // Handle addition/removal to/from TVerificationResultCollection VerificationResultCollection.Auto_Add_Or_AddOrRemove(this, VerificationResult, ValidationColumn, true); } }
/// <summary> /// Load all GLM and GLMPeriod records for the batch period and the following periods, since that will avoid loading them one by one during submitchanges. /// this is called after ValidateBatchAndTransactions, because the BatchYear and BatchPeriod are validated and recalculated there /// /// This should probably be changed, in the new, skinny summarization, only a few rows need to be accessed. /// </summary> private static void LoadGLMData(ref GLPostingTDS AGLPostingDS, Int32 ALedgerNumber, ABatchRow ABatchToPost) { #region Validate Arguments if (AGLPostingDS == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString( "Function:{0} - The GL Posting dataset is null!"), Utilities.GetMethodName(true))); } else if (ALedgerNumber <= 0) { throw new EFinanceSystemInvalidLedgerNumberException(String.Format(Catalog.GetString( "Function:{0} - The Ledger number must be greater than 0!"), Utilities.GetMethodName(true)), ALedgerNumber); } else if (ABatchToPost == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString( "Function:{0} - The GL Batch to post data row is null!"), Utilities.GetMethodName(true))); } #endregion Validate Arguments GLPostingTDS GLPostingDS = AGLPostingDS; TDBTransaction Transaction = null; try { DBAccess.GDBAccessObj.GetNewOrExistingAutoReadTransaction(IsolationLevel.ReadCommitted, TEnforceIsolationLevel.eilMinimum, ref Transaction, delegate { AGeneralLedgerMasterRow GLMTemplateRow = GLPostingDS.AGeneralLedgerMaster.NewRowTyped(false); GLMTemplateRow.LedgerNumber = ALedgerNumber; GLMTemplateRow.Year = ABatchToPost.BatchYear; AGeneralLedgerMasterAccess.LoadUsingTemplate(GLPostingDS, GLMTemplateRow, Transaction); string query = "SELECT PUB_a_general_ledger_master_period.* " + "FROM PUB_a_general_ledger_master, PUB_a_general_ledger_master_period " + "WHERE PUB_a_general_ledger_master.a_ledger_number_i = ? " + "AND PUB_a_general_ledger_master.a_year_i = ? " + "AND PUB_a_general_ledger_master_period.a_glm_sequence_i = PUB_a_general_ledger_master.a_glm_sequence_i " + "AND PUB_a_general_ledger_master_period.a_period_number_i >= ?"; List <OdbcParameter>parameters = new List <OdbcParameter>(); OdbcParameter parameter = new OdbcParameter("ledgernumber", OdbcType.Int); parameter.Value = ALedgerNumber; parameters.Add(parameter); parameter = new OdbcParameter("year", OdbcType.Int); parameter.Value = ABatchToPost.BatchYear; parameters.Add(parameter); parameter = new OdbcParameter("period", OdbcType.Int); parameter.Value = ABatchToPost.BatchPeriod; parameters.Add(parameter); DBAccess.GDBAccessObj.Select(GLPostingDS, query, GLPostingDS.AGeneralLedgerMasterPeriod.TableName, Transaction, parameters.ToArray()); }); } catch (Exception ex) { TLogging.Log(String.Format("Method:{0} - Unexpected error!{1}{1}{2}", Utilities.GetMethodSignature(), Environment.NewLine, ex.Message)); throw ex; } }
/// <summary> /// Posts a batch /// </summary> /// <param name="ACurrentBatchRow">The data row corresponding to the batch to post</param> /// <param name="AEffectiveDate">The effective date for the batch</param> /// <param name="AStartDateCurrentPeriod">The earliest postable date</param> /// <param name="AEndDateLastForwardingPeriod">The latest postable date</param> /// <returns>True if the batch was successfully posted</returns> public bool PostBatch(ABatchRow ACurrentBatchRow, DateTime AEffectiveDate, DateTime AStartDateCurrentPeriod, DateTime AEndDateLastForwardingPeriod) { bool RetVal = false; if (!SaveBatchForPosting()) { return(RetVal); } // TODO: display progress of posting TVerificationResultCollection Verifications; int CurrentBatchNumber = ACurrentBatchRow.BatchNumber; if ((AEffectiveDate.Date < AStartDateCurrentPeriod) || (AEffectiveDate.Date > AEndDateLastForwardingPeriod)) { MessageBox.Show(String.Format(Catalog.GetString( "The Date Effective is outside the periods available for posting. Enter a date between {0:d} and {1:d}."), AStartDateCurrentPeriod, AEndDateLastForwardingPeriod)); return(RetVal); } if (MessageBox.Show(String.Format(Catalog.GetString("Are you sure you want to post batch {0}?"), CurrentBatchNumber), Catalog.GetString("Question"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.Yes) { try { Cursor.Current = Cursors.WaitCursor; if (!TRemote.MFinance.GL.WebConnectors.PostGLBatch(FLedgerNumber, CurrentBatchNumber, out Verifications)) { string ErrorMessages = String.Empty; foreach (TVerificationResult verif in Verifications) { ErrorMessages += "[" + verif.ResultContext + "] " + verif.ResultTextCaption + ": " + verif.ResultText + Environment.NewLine; } System.Windows.Forms.MessageBox.Show(ErrorMessages, Catalog.GetString("Posting failed"), MessageBoxButtons.OK, MessageBoxIcon.Error); } else { // I don't need to call this directly, because the server calls it: // TFrmGLBatch.PrintPostingRegister(FLedgerNumber, CurrentBatchNumber); // TODO: print reports on successfully posted batch MessageBox.Show(Catalog.GetString("The batch has been posted successfully!"), Catalog.GetString("Success"), MessageBoxButtons.OK, MessageBoxIcon.Information); // refresh the grid, to reflect that the batch has been posted FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAndContent(FLedgerNumber, CurrentBatchNumber)); // make sure that the current dataset is clean, // otherwise the next save would try to modify the posted batch, even though no values have been changed FMainDS.AcceptChanges(); // Ensure these tabs will ask the server for updates FMyForm.GetJournalsControl().ClearCurrentSelection(); FMyForm.GetTransactionsControl().ClearCurrentSelection(); FMyUserControl.UpdateDisplay(); RetVal = true; } } finally { Cursor.Current = Cursors.Default; } } return(RetVal); }
/// <summary> /// this supports the transaction export files from Petra 2.x. /// Lines do NOT start with T for transaction /// </summary> public void ImportTransactions(ABatchRow ACurrentBatchRow, AJournalRow ACurrentJournalRow, TImportDataSourceEnum AImportDataSource) { bool ok = false; bool RefreshGUIAfterImport = false; OpenFileDialog dialog = null; if (FPetraUtilsObject.HasChanges && !FMyForm.SaveChanges()) { // saving failed, therefore do not try to import MessageBox.Show(Catalog.GetString("Please save your changes before Importing new transactions"), Catalog.GetString( "Import GL Transactions"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if ((ACurrentBatchRow == null) || (ACurrentJournalRow == null) || (ACurrentJournalRow.JournalStatus != MFinanceConstants.BATCH_UNPOSTED)) { MessageBox.Show(Catalog.GetString("Please select an unposted journal to import transactions."), Catalog.GetString("Import GL Transactions")); return; } if (ACurrentJournalRow.LastTransactionNumber > 0) { if (MessageBox.Show(Catalog.GetString( "The current journal already contains some transactions. Do you really want to add more transactions to this journal?"), Catalog.GetString("Import GL Transactions"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No) { return; } } bool datesMayBeIntegers = TUserDefaults.GetBooleanDefault(MCommonConstants.USERDEFAULT_IMPORTEDDATESMAYBEINTEGERS, false); FdlgSeparator = new TDlgSelectCSVSeparator(false); FdlgSeparator.DateMayBeInteger = datesMayBeIntegers; if (AImportDataSource == TImportDataSourceEnum.FromClipboard) { string importString = Clipboard.GetText(TextDataFormat.UnicodeText); if ((importString == null) || (importString.Length == 0)) { MessageBox.Show(Catalog.GetString("Please first copy data from your spreadsheet application!"), Catalog.GetString("Failure"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } FdlgSeparator.CSVData = importString; } else if (AImportDataSource == TImportDataSourceEnum.FromFile) { dialog = new OpenFileDialog(); string exportPath = TClientSettings.GetExportPath(); string fullPath = TUserDefaults.GetStringDefault("Imp Filename", exportPath + Path.DirectorySeparatorChar + "import.csv"); TImportExportDialogs.SetOpenFileDialogFilePathAndName(dialog, fullPath, exportPath); dialog.Title = Catalog.GetString("Import Transactions from CSV File"); dialog.Filter = Catalog.GetString("GL Transactions files (*.csv)|*.csv|Text Files (*.txt)|*.txt"); // This call fixes Windows7 Open File Dialogs. It must be the line before ShowDialog() TWin7FileOpenSaveDialog.PrepareDialog(Path.GetFileName(fullPath)); if (dialog.ShowDialog() == DialogResult.OK) { Boolean fileCanOpen = FdlgSeparator.OpenCsvFile(dialog.FileName); if (!fileCanOpen) { MessageBox.Show(Catalog.GetString("Unable to open file."), Catalog.GetString("Transaction Import"), MessageBoxButtons.OK, MessageBoxIcon.Stop); return; } } else { return; } } else { // unknown source!! return; } String impOptions = TUserDefaults.GetStringDefault("Imp Options", ";" + TDlgSelectCSVSeparator.NUMBERFORMAT_AMERICAN); String dateFormatString = TUserDefaults.GetStringDefault("Imp Date", "MDY"); FdlgSeparator.DateFormat = dateFormatString; FdlgSeparator.NumberFormat = (impOptions.Length > 1) ? impOptions.Substring(1) : TDlgSelectCSVSeparator.NUMBERFORMAT_AMERICAN; FdlgSeparator.SelectedSeparator = StringHelper.GetCSVSeparator(FdlgSeparator.FileContent) ?? ((impOptions.Length > 0) ? impOptions.Substring(0, 1) : ";"); if (FdlgSeparator.ShowDialog() == DialogResult.OK) { Hashtable requestParams = new Hashtable(); requestParams.Add("ALedgerNumber", FLedgerNumber); requestParams.Add("Delimiter", FdlgSeparator.SelectedSeparator); requestParams.Add("DateFormatString", FdlgSeparator.DateFormat); requestParams.Add("DatesMayBeIntegers", datesMayBeIntegers); requestParams.Add("NumberFormat", FdlgSeparator.NumberFormat); requestParams.Add("NewLine", Environment.NewLine); requestParams.Add("LastTransactionNumber", ACurrentJournalRow.LastTransactionNumber); TVerificationResultCollection AMessages = new TVerificationResultCollection(); Thread ImportThread = new Thread(() => ImportGLTransactions(requestParams, FdlgSeparator.FileContent, ACurrentBatchRow.BatchNumber, ACurrentJournalRow.JournalNumber, out AMessages, out ok, out RefreshGUIAfterImport)); using (TProgressDialog ImportDialog = new TProgressDialog(ImportThread)) { ImportDialog.ShowDialog(); } ShowMessages(AMessages); } // It is important to save user defaults here, even if there were errors // because in that case the user will want to import the same file again after fixing it. SaveUserDefaults(dialog); if (ok || RefreshGUIAfterImport) { if (ok) { MessageBox.Show(Catalog.GetString("Your data was imported successfully!"), Catalog.GetString("Transactions Import"), MessageBoxButtons.OK, MessageBoxIcon.Information); } // Update the client side with new information from the server FMyForm.Cursor = Cursors.WaitCursor; FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAJournal(FLedgerNumber, ACurrentBatchRow.BatchNumber)); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadATransactionAndRelatedTablesForJournal(FLedgerNumber, ACurrentBatchRow.BatchNumber, ACurrentJournalRow.JournalNumber)); FMainDS.AcceptChanges(); FMyForm.Cursor = Cursors.Default; FMyForm.GetTransactionsControl().SelectRow(1); } }
/// <summary> /// load the journals into the grid /// </summary> /// <param name="ACurrentBatchRow"></param> public void LoadJournals(ABatchRow ACurrentBatchRow) { FJournalsLoaded = false; FBatchRow = ACurrentBatchRow; if (FBatchRow == null) { return; } Int32 CurrentLedgerNumber = FBatchRow.LedgerNumber; Int32 CurrentBatchNumber = FBatchRow.BatchNumber; string CurrentBatchStatus = FBatchRow.BatchStatus; bool BatchIsUnposted = (FBatchRow.BatchStatus == MFinanceConstants.BATCH_UNPOSTED); bool FirstRun = (FLedgerNumber != CurrentLedgerNumber); bool BatchChanged = (FBatchNumber != CurrentBatchNumber); bool BatchStatusChanged = (!BatchChanged && (FBatchStatus != CurrentBatchStatus)); if (FirstRun) { FLedgerNumber = CurrentLedgerNumber; } if (BatchChanged) { FBatchNumber = CurrentBatchNumber; } if (BatchStatusChanged) { FBatchStatus = CurrentBatchStatus; } //Create object to control deletion FCancelLogicObject = new TUC_GLJournals_Cancel(FPetraUtilsObject, FLedgerNumber, FMainDS); //Make sure the current effective date for the Batch is correct DateTime BatchDateEffective = FBatchRow.DateEffective; //Check if need to load Journals if (!(FirstRun || BatchChanged || BatchStatusChanged)) { //Need to reconnect FPrev in some circumstances if (FPreviouslySelectedDetailRow == null) { DataRowView rowView = (DataRowView)grdDetails.Rows.IndexToDataSourceRow(FPrevRowChangedRow); if (rowView != null) { FPreviouslySelectedDetailRow = (GLBatchTDSAJournalRow)(rowView.Row); } } // The journals are the same and we have loaded them already if (BatchIsUnposted) { if (GetSelectedRowIndex() > 0) { GetDetailsFromControls(GetSelectedDetailRow()); } } } else { // a different journal SetJournalDefaultView(); FPreviouslySelectedDetailRow = null; //Load Journals if (FMainDS.AJournal.DefaultView.Count == 0) { FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadAJournal(FLedgerNumber, FBatchNumber)); } if (BatchIsUnposted) { if (!dtpDetailDateEffective.Date.HasValue || (dtpDetailDateEffective.Date.Value != BatchDateEffective)) { dtpDetailDateEffective.Date = BatchDateEffective; } } //Check if DateEffective has changed and then update all foreach (DataRowView drv in FMainDS.AJournal.DefaultView) { AJournalRow jr = (AJournalRow)drv.Row; if (jr.DateEffective != BatchDateEffective) { ((TFrmGLBatch)ParentForm).GetTransactionsControl().UpdateTransactionTotals(TFrmGLBatch.eGLLevel.Batch, true); break; } } ShowData(); // Now set up the complete current filter FFilterAndFindObject.FilterPanelControls.SetBaseFilter(FMainDS.AJournal.DefaultView.RowFilter, true); FFilterAndFindObject.ApplyFilter(); } int nRowToSelect = 1; TFrmGLBatch myParentForm = (TFrmGLBatch)ParentForm; if (myParentForm.InitialBatchFound) { DataView myView = (grdDetails.DataSource as DevAge.ComponentModel.BoundDataView).DataView; for (int counter = 0; (counter < myView.Count); counter++) { int myViewJournalNumber = (int)myView[counter][AJournalTable.GetJournalNumberDBName()]; if (myViewJournalNumber == myParentForm.InitialJournalNumber) { nRowToSelect = counter + 1; break; } } } else { nRowToSelect = (BatchChanged || FirstRun) ? 1 : FPrevRowChangedRow; } //This will also call UpdateChangeableStatus SelectRowInGrid(nRowToSelect); UpdateRecordNumberDisplay(); FFilterAndFindObject.SetRecordNumberDisplayProperties(); txtControl.CurrencyCode = TTxtCurrencyTextBox.CURRENCY_STANDARD_2_DP; txtCredit.CurrencyCode = FLedgerBaseCurrency; txtDebit.CurrencyCode = FLedgerBaseCurrency; FJournalsLoaded = true; }
/// <summary> /// Method to cancel a specified batch /// </summary> /// <param name="ABatchRowToCancel">The row to cancel</param> /// <returns></returns> public bool CancelBatch(ABatchRow ABatchRowToCancel) { //Assign default value(s) bool CancellationSuccessful = false; if ((ABatchRowToCancel == null)) { return(CancellationSuccessful); } int CurrentBatchNumber = ABatchRowToCancel.BatchNumber; if ((MessageBox.Show(String.Format(Catalog.GetString("You have chosen to cancel this batch ({0}).\n\nDo you really want to cancel it?"), CurrentBatchNumber), Catalog.GetString("Confirm Cancel"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != System.Windows.Forms.DialogResult.Yes)) { return(CancellationSuccessful); } //Backup the Dataset for reversion purposes GLBatchTDS BackupMainDS = (GLBatchTDS)FMainDS.Copy(); BackupMainDS.Merge(FMainDS); bool RowToDeleteIsNew = (ABatchRowToCancel.RowState == DataRowState.Added); if (!RowToDeleteIsNew) { //Remove any changes, which may cause validation issues, before cancelling FMyForm.GetBatchControl().UndoModifiedBatchRow(ABatchRowToCancel, true); if (!(FMyForm.SaveChanges())) { MessageBox.Show(Catalog.GetString("Error in trying to save prior to cancelling current Batch!"), Catalog.GetString("Cancellation Error"), MessageBoxButtons.OK, MessageBoxIcon.Error); return(CancellationSuccessful); } } try { FMyForm.Cursor = Cursors.WaitCursor; //clear any transactions currently being editied in the Transaction Tab FMyForm.GetTransactionsControl().ClearCurrentSelection(); //clear any journals currently being editied in the Journals Tab FMyForm.GetJournalsControl().ClearCurrentSelection(); //Clear Journals etc for current Batch FMainDS.ATransAnalAttrib.Clear(); FMainDS.ATransaction.Clear(); FMainDS.AJournal.Clear(); //Load tables afresh FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadAJournal(FLedgerNumber, CurrentBatchNumber)); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadATransaction(FLedgerNumber, CurrentBatchNumber)); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadATransAnalAttribForBatch(FLedgerNumber, CurrentBatchNumber)); FMainDS.AcceptChanges(); //Delete transactions and analysis attributes for (int i = FMainDS.ATransAnalAttrib.Count - 1; i >= 0; i--) { FMainDS.ATransAnalAttrib[i].Delete(); } for (int i = FMainDS.ATransaction.Count - 1; i >= 0; i--) { FMainDS.ATransaction[i].Delete(); } //Update Journal totals and status foreach (AJournalRow journal in FMainDS.AJournal.Rows) { if (journal.BatchNumber == CurrentBatchNumber) { journal.BeginEdit(); journal.JournalStatus = MFinanceConstants.BATCH_CANCELLED; journal.JournalCreditTotal = 0; journal.JournalDebitTotal = 0; journal.LastTransactionNumber = 0; journal.EndEdit(); } } // Edit the batch row ABatchRowToCancel.BeginEdit(); ABatchRowToCancel.BatchCreditTotal = 0; ABatchRowToCancel.BatchDebitTotal = 0; ABatchRowToCancel.BatchControlTotal = 0; ABatchRowToCancel.BatchStatus = MFinanceConstants.BATCH_CANCELLED; ABatchRowToCancel.EndEdit(); FPetraUtilsObject.SetChangedFlag(); //Need to call save if (FMyForm.SaveChanges()) { MessageBox.Show(Catalog.GetString("The batch has been cancelled successfully!"), Catalog.GetString("Success"), MessageBoxButtons.OK, MessageBoxIcon.Information); FMyForm.DisableTransactions(); FMyForm.DisableJournals(); } else { throw new Exception(Catalog.GetString("The batch failed to save after being cancelled! Reopen the form and retry.")); } CancellationSuccessful = true; } catch (Exception ex) { MessageBox.Show(ex.Message, "Cancellation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); //Revert to previous state FMainDS.Merge(BackupMainDS); } finally { FMyForm.Cursor = Cursors.Default; } return(CancellationSuccessful); }
public static void UpdateTotalsOfBatch(ref GLBatchTDS AMainDS, ABatchRow ACurrentBatch) { decimal sumDebits = 0.0M; decimal sumCredits = 0.0M; DataView jnlDataView = new DataView(AMainDS.AJournal); jnlDataView.RowFilter = String.Format("{0}={1}", AJournalTable.GetBatchNumberDBName(), ACurrentBatch.BatchNumber); foreach (DataRowView journalview in jnlDataView) { GLBatchTDSAJournalRow journalrow = (GLBatchTDSAJournalRow)journalview.Row; UpdateTotalsOfJournal(ref AMainDS, journalrow); sumDebits += journalrow.JournalDebitTotal; sumCredits += journalrow.JournalCreditTotal; } ACurrentBatch.BatchDebitTotal = sumDebits; ACurrentBatch.BatchCreditTotal = sumCredits; ACurrentBatch.BatchRunningTotal = Math.Round(sumDebits - sumCredits, 2); }
/// <summary> /// mark each journal, each transaction as being posted; /// add sums for costcentre/account combinations /// </summary> /// <param name="AMainDS">can contain several batches and journals and transactions</param> /// <param name="APostingDS"></param> /// <param name="APostingLevel">the balance changes at the posting level</param> /// <param name="ABatchToPost">the batch to post</param> /// <returns>a list with the sums for each costcentre/account combination</returns> private static SortedList <string, TAmount>MarkAsPostedAndCollectData(GLBatchTDS AMainDS, GLPostingTDS APostingDS, SortedList <string, TAmount>APostingLevel, ABatchRow ABatchToPost) { #region Validate Arguments if (AMainDS == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString("Function:{0} - The GL Batch dataset is null!"), Utilities.GetMethodName(true))); } else if (APostingDS == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString( "Function:{0} - The GL Posting dataset is null!"), Utilities.GetMethodName(true))); } else if (ABatchToPost == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString( "Function:{0} - The GL Batch to post data row is null!"), Utilities.GetMethodName(true))); } #endregion Validate Arguments DataView TransactionsDV = new DataView(AMainDS.ATransaction); TransactionsDV.Sort = ATransactionTable.GetJournalNumberDBName(); foreach (AJournalRow journal in AMainDS.AJournal.Rows) { if (journal.BatchNumber != ABatchToPost.BatchNumber) { continue; } foreach (DataRowView transactionview in TransactionsDV.FindRows(journal.JournalNumber)) { ATransactionRow transaction = (ATransactionRow)transactionview.Row; if (transaction.BatchNumber != ABatchToPost.BatchNumber) { continue; } transaction.TransactionStatus = true; // get the account that this transaction is writing to AAccountRow accountRow = (AAccountRow)APostingDS.AAccount.Rows.Find(new object[] { transaction.LedgerNumber, transaction.AccountCode }); #region Validate Data if (accountRow == null) { throw new EFinanceSystemDataTableReturnedNoDataException(String.Format(Catalog.GetString( "Function:{0} - Account row data for Account code {1} in Ledger number {2} does not exist or could not be accessed!"), Utilities.GetMethodName(true), transaction.AccountCode, transaction.LedgerNumber)); } #endregion Validate Data // Set the sign of the amounts according to the debit/credit indicator decimal SignBaseAmount = transaction.AmountInBaseCurrency; decimal SignIntlAmount = transaction.AmountInIntlCurrency; decimal SignTransAmount = transaction.TransactionAmount; if (accountRow.DebitCreditIndicator != transaction.DebitCreditIndicator) { SignBaseAmount *= -1.0M; SignIntlAmount *= -1.0M; SignTransAmount *= -1.0M; } // TODO: do we need to check for base currency corrections? // or do we get rid of these problems by not having international currency? string key = TAmount.MakeKey(transaction.AccountCode, transaction.CostCentreCode); if (!APostingLevel.ContainsKey(key)) { APostingLevel.Add(key, new TAmount()); } APostingLevel[key].BaseAmount += SignBaseAmount; APostingLevel[key].IntlAmount += SignIntlAmount; // Only foreign currency accounts store a value in the transaction currency, // if the transaction was actually in the foreign currency. if (accountRow.ForeignCurrencyFlag && (journal.TransactionCurrency == accountRow.ForeignCurrencyCode)) { APostingLevel[key].TransAmount += SignTransAmount; } } journal.JournalStatus = MFinanceConstants.BATCH_POSTED; } ABatchToPost.BatchStatus = MFinanceConstants.BATCH_POSTED; return APostingLevel; }
/// <summary> /// runs validations on batch, journals and transactions /// some things are even modified, eg. batch period etc from date effective /// </summary> private static bool ValidateBatchAndTransactions(ref GLBatchTDS AGLBatchDS, GLPostingTDS APostingDS, Int32 ALedgerNumber, ABatchRow ABatchToPost, out TVerificationResultCollection AVerifications) { AVerifications = new TVerificationResultCollection(); TVerificationResultCollection Verifications = AVerifications; if ((ABatchToPost.BatchStatus == MFinanceConstants.BATCH_CANCELLED) || (ABatchToPost.BatchStatus == MFinanceConstants.BATCH_POSTED)) { AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ALedgerNumber), String.Format(Catalog.GetString("It has status {0}"), ABatchToPost.BatchStatus), TResultSeverity.Resv_Critical)); } // Calculate the base currency amounts for each transaction, using the exchange rate from the journals. // erm - this is done already? I don't want to do it here, since my journal may contain forex-reval elements. // Calculate the credit and debit totals GLRoutines.UpdateTotalsOfBatch(ref AGLBatchDS, ABatchToPost); if (ABatchToPost.BatchCreditTotal != ABatchToPost.BatchDebitTotal) { AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ALedgerNumber), String.Format(Catalog.GetString("It does not balance: Debit is {0:N2}, Credit is {1:N2}"), ABatchToPost.BatchDebitTotal, ABatchToPost.BatchCreditTotal), TResultSeverity.Resv_Critical)); } else if ((ABatchToPost.BatchCreditTotal == 0) && ((AGLBatchDS.AJournal.Rows.Count == 0) || (AGLBatchDS.ATransaction.Rows.Count == 0))) { AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ALedgerNumber), Catalog.GetString("The batch has no monetary value. Please cancel it or add transactions."), TResultSeverity.Resv_Critical)); } else if ((ABatchToPost.BatchControlTotal != 0) && (ABatchToPost.BatchControlTotal != ABatchToPost.BatchCreditTotal)) { AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ALedgerNumber), String.Format(Catalog.GetString("The control total {0:n2} does not fit the Credit/Debit Total {1:n2}."), ABatchToPost.BatchControlTotal, ABatchToPost.BatchCreditTotal), TResultSeverity.Resv_Critical)); } Int32 DateEffectivePeriodNumber, DateEffectiveYearNumber; TDBTransaction Transaction = null; GLBatchTDS GLBatchDS = AGLBatchDS; DBAccess.GDBAccessObj.GetNewOrExistingAutoReadTransaction(IsolationLevel.ReadCommitted, TEnforceIsolationLevel.eilMinimum, ref Transaction, delegate { if (!TFinancialYear.IsValidPostingPeriod(ABatchToPost.LedgerNumber, ABatchToPost.DateEffective, out DateEffectivePeriodNumber, out DateEffectiveYearNumber, Transaction)) { Verifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ALedgerNumber), String.Format(Catalog.GetString("The Date Effective {0:d-MMM-yyyy} does not fit any open accounting period."), ABatchToPost.DateEffective), TResultSeverity.Resv_Critical)); } else { // just make sure that the correct BatchPeriod is used ABatchToPost.BatchPeriod = DateEffectivePeriodNumber; ABatchToPost.BatchYear = DateEffectiveYearNumber; } // check that all transactions are inside the same period as the GL date effective of the batch DateTime PostingPeriodStartDate, PostingPeriodEndDate; TFinancialYear.GetStartAndEndDateOfPeriod(ABatchToPost.LedgerNumber, DateEffectivePeriodNumber, out PostingPeriodStartDate, out PostingPeriodEndDate, Transaction); foreach (ATransactionRow transRow in GLBatchDS.ATransaction.Rows) { if ((transRow.BatchNumber == ABatchToPost.BatchNumber) && (transRow.TransactionDate < PostingPeriodStartDate) || (transRow.TransactionDate > PostingPeriodEndDate)) { Verifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ALedgerNumber), String.Format( "invalid transaction date for transaction {0} in Batch {1} Journal {2}: {3:d-MMM-yyyy} must be inside period {4} ({5:d-MMM-yyyy} till {6:d-MMM-yyyy})", transRow.TransactionNumber, transRow.BatchNumber, transRow.JournalNumber, transRow.TransactionDate, DateEffectivePeriodNumber, PostingPeriodStartDate, PostingPeriodEndDate), TResultSeverity.Resv_Critical)); } } }); AVerifications = Verifications; DataView TransactionsOfJournalView = new DataView(AGLBatchDS.ATransaction); foreach (AJournalRow journal in AGLBatchDS.AJournal.Rows) { journal.DateEffective = ABatchToPost.DateEffective; journal.JournalPeriod = ABatchToPost.BatchPeriod; if (journal.JournalCreditTotal != journal.JournalDebitTotal) { AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ALedgerNumber), String.Format(Catalog.GetString("The journal {0} does not balance: Debit is {1:N2}, Credit is {2:N2}"), journal.JournalNumber, journal.JournalDebitTotal, journal.JournalCreditTotal), TResultSeverity.Resv_Critical)); } TransactionsOfJournalView.RowFilter = ATransactionTable.GetJournalNumberDBName() + " = " + journal.JournalNumber.ToString(); foreach (DataRowView TransactionViewRow in TransactionsOfJournalView) { ATransactionRow transaction = (ATransactionRow)TransactionViewRow.Row; // check that transactions on foreign currency accounts are using the correct currency // (fx reval transactions are an exception because they are posted in base currency) if (!((transaction.Reference == CommonAccountingTransactionTypesEnum.REVAL.ToString()) && (journal.TransactionTypeCode == CommonAccountingTransactionTypesEnum.REVAL.ToString()))) { // get the account that this transaction is writing to AAccountRow Account = (AAccountRow)APostingDS.AAccount.Rows.Find(new object[] { ALedgerNumber, transaction.AccountCode }); if (Account == null) { // should not get here throw new Exception("ValidateBatchAndTransactions: Cannot find account " + transaction.AccountCode); } if (Account.ForeignCurrencyFlag && (journal.TransactionCurrency != Account.ForeignCurrencyCode)) { AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ALedgerNumber), String.Format(Catalog.GetString( "Transaction {0} in Journal {1} with currency {2} does not fit the foreign currency {3} of account {4}."), transaction.TransactionNumber, transaction.JournalNumber, journal.TransactionCurrency, Account.ForeignCurrencyCode, transaction.AccountCode), TResultSeverity.Resv_Critical)); } } if ((transaction.AmountInBaseCurrency == 0) && (transaction.TransactionAmount != 0)) { AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot post Batch {0} in Ledger {1}"), ABatchToPost.BatchNumber, ALedgerNumber), String.Format(Catalog.GetString("Transaction {0} in Journal {1} has invalid base transaction amount of 0."), transaction.TransactionNumber, transaction.JournalNumber), TResultSeverity.Resv_Critical)); } } } return TVerificationHelper.IsNullOrOnlyNonCritical(AVerifications); }
} // Import GL Transactions private void ImportGLTransactionsInner(Int32 ALedgerNumber, Int32 ARowNumber, ref GLBatchTDS AMainDS, ref GLSetupTDS ASetupDS, ref ABatchRow ANewBatchRow, ref AJournalRow ANewJournalRow, decimal AIntlRateFromBase, ref TDBTransaction ATransaction, ref string AImportMessage, ref TVerificationResultCollection AMessages, ref TValidationControlsDict AValidationControlsDictTransaction) { AImportMessage = Catalog.GetString("Parsing a transaction line."); string strIgnoreAnalysisTypeAndValue = Catalog.GetString(" The analysis type/value pair will be ignored."); GLBatchTDSATransactionRow NewTransaction = AMainDS.ATransaction.NewRowTyped(true); NewTransaction.LedgerNumber = ANewJournalRow.LedgerNumber; NewTransaction.BatchNumber = ANewJournalRow.BatchNumber; NewTransaction.JournalNumber = ANewJournalRow.JournalNumber; NewTransaction.TransactionNumber = ++ANewJournalRow.LastTransactionNumber; AMainDS.ATransaction.Rows.Add(NewTransaction); int preParseMessageCount = AMessages.Count; int nonCriticalErrorCount = 0; string costCentreCode = TCommonImport.ImportString(ref FImportLine, FDelimiter, Catalog.GetString("Cost centre"), AMainDS.ATransaction.ColumnCostCentreCode, ARowNumber, AMessages, AValidationControlsDictTransaction).ToUpper(); string accountCode = TCommonImport.ImportString(ref FImportLine, FDelimiter, Catalog.GetString("Account code"), AMainDS.ATransaction.ColumnAccountCode, ARowNumber, AMessages, AValidationControlsDictTransaction).ToUpper(); // This might add a non-critical error int msgCount = AMessages.Count; TCommonImport.FixAccountCodes(ALedgerNumber, ARowNumber, ref accountCode, ASetupDS.AAccount, ref costCentreCode, ASetupDS.ACostCentre, AMessages); nonCriticalErrorCount = AMessages.Count - msgCount; NewTransaction.CostCentreCode = costCentreCode; NewTransaction.AccountCode = accountCode; NewTransaction.Narrative = TCommonImport.ImportString(ref FImportLine, FDelimiter, Catalog.GetString("Narrative"), AMainDS.ATransaction.ColumnNarrative, ARowNumber, AMessages, AValidationControlsDictTransaction); NewTransaction.Reference = TCommonImport.ImportString(ref FImportLine, FDelimiter, Catalog.GetString("Reference"), AMainDS.ATransaction.ColumnReference, ARowNumber, AMessages, AValidationControlsDictTransaction); DateTime TransactionDate = TCommonImport.ImportDate(ref FImportLine, FDelimiter, FCultureInfoDate, Catalog.GetString("Transaction date"), AMainDS.ATransaction.ColumnTransactionDate, ARowNumber, AMessages, AValidationControlsDictTransaction); decimal DebitAmount = TCommonImport.ImportDecimal(ref FImportLine, FDelimiter, FCultureInfoNumberFormat, Catalog.GetString("Debit amount"), AMainDS.ATransaction.ColumnTransactionAmount, ARowNumber, AMessages, AValidationControlsDictTransaction, "0"); decimal CreditAmount = TCommonImport.ImportDecimal(ref FImportLine, FDelimiter, FCultureInfoNumberFormat, Catalog.GetString("Credit amount"), AMainDS.ATransaction.ColumnTransactionAmount, ARowNumber, AMessages, AValidationControlsDictTransaction, "0"); // The critical parsing is complete now bool hasParsingErrors = (AMessages.Count != (preParseMessageCount + nonCriticalErrorCount)); for (int i = 0; i < 10; i++) { String analysisType = TCommonImport.ImportString(ref FImportLine, FDelimiter, Catalog.GetString("Analysis Type") + "#" + i, AMainDS.ATransAnalAttrib.ColumnAnalysisTypeCode, ARowNumber, AMessages, AValidationControlsDictTransaction).ToUpper(); String analysisValue = TCommonImport.ImportString(ref FImportLine, FDelimiter, Catalog.GetString("Analysis Value") + "#" + i, AMainDS.ATransAnalAttrib.ColumnAnalysisAttributeValue, ARowNumber, AMessages, AValidationControlsDictTransaction); bool gotType = (analysisType != null) && (analysisType.Length > 0); bool gotValue = (analysisValue != null) && (analysisValue.Length > 0); if (gotType && !gotValue) { // All analysis analysisType errors are non-critical AMessages.Add(new TVerificationResult(String.Format(MCommonConstants.StrImportValidationWarningInLine, ARowNumber), Catalog.GetString("Transaction analysis attributes must have an attribute value.") + strIgnoreAnalysisTypeAndValue, TResultSeverity.Resv_Noncritical)); } if (!hasParsingErrors) { // The analysis data is only imported if all corresponding values are there: // Errors are recorded on-the-fly but are marked as non-critical if (gotType && gotValue) { DataRow atrow = ASetupDS.AAnalysisType.Rows.Find(new Object[] { NewTransaction.LedgerNumber, analysisType }); DataRow afrow = ASetupDS.AFreeformAnalysis.Rows.Find(new Object[] { NewTransaction.LedgerNumber, analysisType, analysisValue }); AAnalysisAttributeRow anrow = (AAnalysisAttributeRow)ASetupDS.AAnalysisAttribute.Rows.Find( new Object[] { NewTransaction.LedgerNumber, analysisType, NewTransaction.AccountCode }); bool isActive = (anrow != null) && anrow.Active; if ((atrow != null) && (afrow != null) && isActive) { ATransAnalAttribRow NewTransAnalAttrib = AMainDS.ATransAnalAttrib.NewRowTyped(true); NewTransAnalAttrib.LedgerNumber = NewTransaction.LedgerNumber; NewTransAnalAttrib.BatchNumber = NewTransaction.BatchNumber; NewTransAnalAttrib.JournalNumber = NewTransaction.JournalNumber; NewTransAnalAttrib.TransactionNumber = NewTransaction.TransactionNumber; NewTransAnalAttrib.AnalysisTypeCode = analysisType; NewTransAnalAttrib.AnalysisAttributeValue = analysisValue; NewTransAnalAttrib.AccountCode = NewTransaction.AccountCode; AMainDS.ATransAnalAttrib.Rows.Add(NewTransAnalAttrib); } else { // All analysis analysisType errors are non-critical if (atrow == null) { AMessages.Add(new TVerificationResult(String.Format(MCommonConstants.StrImportValidationWarningInLine, ARowNumber), String.Format(Catalog.GetString("Unknown transaction analysis attribute '{0}'."), analysisType) + strIgnoreAnalysisTypeAndValue, TResultSeverity.Resv_Noncritical)); } else if (afrow == null) { AMessages.Add(new TVerificationResult(String.Format(MCommonConstants.StrImportValidationWarningInLine, ARowNumber), String.Format(Catalog.GetString("Unknown transaction analysis value '{0}' for type '{1}'."), analysisValue, analysisType) + strIgnoreAnalysisTypeAndValue, TResultSeverity.Resv_Noncritical)); } else if (!isActive) { if (anrow == null) { AMessages.Add(new TVerificationResult(String.Format(MCommonConstants.StrImportValidationWarningInLine, ARowNumber), String.Format(Catalog.GetString( "Transaction analysis type/value '{0}'/'{1}' is not associated with account '{2}'."), analysisType, analysisValue, NewTransaction.AccountCode) + strIgnoreAnalysisTypeAndValue, TResultSeverity.Resv_Noncritical)); } else { AMessages.Add(new TVerificationResult(String.Format(MCommonConstants.StrImportValidationWarningInLine, ARowNumber), String.Format(Catalog.GetString("Transaction analysis type/value '{0}'/'{1}' is no longer active."), analysisType, analysisValue) + strIgnoreAnalysisTypeAndValue, TResultSeverity.Resv_Noncritical)); } } } } } } if (!hasParsingErrors) { NewTransaction.TransactionDate = TransactionDate; if ((DebitAmount == 0) && (CreditAmount == 0)) { AMessages.Add(new TVerificationResult(String.Format(MCommonConstants.StrImportValidationErrorInLine, ARowNumber), Catalog.GetString("Either the debit amount or the credit amount must be greater than 0."), TResultSeverity.Resv_Critical)); } if ((DebitAmount < 0) || (CreditAmount < 0)) { AMessages.Add(new TVerificationResult(String.Format(MCommonConstants.StrImportValidationErrorInLine, ARowNumber), Catalog.GetString("Negative amount specified - debits and credits must be positive."), TResultSeverity.Resv_Critical)); } if ((DebitAmount != 0) && (CreditAmount != 0)) { AMessages.Add(new TVerificationResult(String.Format(MCommonConstants.StrImportValidationErrorInLine, ARowNumber), Catalog.GetString("Transactions cannot have values for both debit and credit amounts."), TResultSeverity.Resv_Critical)); } if (DebitAmount != 0) { NewTransaction.DebitCreditIndicator = true; NewTransaction.TransactionAmount = DebitAmount; } else { NewTransaction.DebitCreditIndicator = false; NewTransaction.TransactionAmount = CreditAmount; } NewTransaction.AmountInBaseCurrency = GLRoutines.Divide(NewTransaction.TransactionAmount, ANewJournalRow.ExchangeRateToBase); // If we know the international currency exchange rate we can set the value for the transaction amount if (AIntlRateFromBase > 0.0m) { NewTransaction.AmountInIntlCurrency = GLRoutines.Divide(NewTransaction.AmountInBaseCurrency, AIntlRateFromBase, 2); } // Now we can start validation int messageCountBeforeValidate = AMessages.Count; // Do our standard gift batch validation checks on this row AImportMessage = Catalog.GetString("Validating the transaction data"); ATransactionValidation.Validate(this, NewTransaction, ref AMessages, AValidationControlsDictTransaction); // And do the additional manual ones AImportMessage = Catalog.GetString("Additional validation of the transaction data"); TSharedFinanceValidation_GL.ValidateGLDetailManual(this, ANewBatchRow, NewTransaction, null, ref AMessages, AValidationControlsDictTransaction, ASetupDS.ACostCentre, ASetupDS.AAccount); for (int i = messageCountBeforeValidate; i < AMessages.Count; i++) { ((TVerificationResult)AMessages[i]).OverrideResultContext(String.Format(MCommonConstants.StrValidationErrorInLine, ARowNumber)); if (AMessages[i] is TScreenVerificationResult) { TVerificationResult downgrade = new TVerificationResult((TScreenVerificationResult)AMessages[i]); AMessages.RemoveAt(i); AMessages.Insert(i, downgrade); } } if (NewTransaction.TransactionAmount <= 0.0m) { // We will have a validation message that will duplicate one we already have and may not really make sense in the context // of separate credit and debit amounts for (int i = messageCountBeforeValidate; i < AMessages.Count; i++) { TVerificationResult msg = (TVerificationResult)AMessages[i]; if (msg.ResultText.Contains(Catalog.GetString("Debit amount")) || msg.ResultText.Contains(Catalog.GetString("Credit amount"))) { AMessages.RemoveAt(i); break; } } } } }
private void ShowDetailsManual(ABatchRow ARow) { AutoEnableTransTabForBatch(); grdDetails.TabStop = (ARow != null); if (ARow == null) { pnlDetails.Enabled = false; ((TFrmGLBatch) this.ParentForm).DisableJournals(); ((TFrmGLBatch) this.ParentForm).DisableTransactions(); EnableButtonControl(false); ClearDetailControls(); return; } FPetraUtilsObject.DetailProtectedMode = (ARow.BatchStatus.Equals(MFinanceConstants.BATCH_POSTED) || ARow.BatchStatus.Equals(MFinanceConstants.BATCH_CANCELLED)); FCurrentEffectiveDate = ARow.DateEffective; UpdateBatchPeriod(null, null); UpdateChangeableStatus(); ((TFrmGLBatch) this.ParentForm).EnableJournals(); }
public static Int32 CreateGLBatch(BankImportTDS AMainDS, Int32 ALedgerNumber, Int32 AStatementKey, Int32 AGLBatchNumber, out TVerificationResultCollection AVerificationResult) { AMainDS.AEpTransaction.DefaultView.RowFilter = String.Format("{0}={1}", AEpTransactionTable.GetStatementKeyDBName(), AStatementKey); AMainDS.AEpStatement.DefaultView.RowFilter = String.Format("{0}={1}", AEpStatementTable.GetStatementKeyDBName(), AStatementKey); AEpStatementRow stmt = (AEpStatementRow)AMainDS.AEpStatement.DefaultView[0].Row; AVerificationResult = null; Int32 DateEffectivePeriodNumber, DateEffectiveYearNumber; TDBTransaction Transaction = DBAccess.GDBAccessObj.BeginTransaction(IsolationLevel.ReadCommitted); if (!TFinancialYear.IsValidPostingPeriod(ALedgerNumber, stmt.Date, out DateEffectivePeriodNumber, out DateEffectiveYearNumber, Transaction)) { string msg = String.Format(Catalog.GetString("Cannot create a GL batch for date {0} since it is not in an open period of the ledger."), stmt.Date.ToShortDateString()); TLogging.Log(msg); AVerificationResult = new TVerificationResultCollection(); AVerificationResult.Add(new TVerificationResult(Catalog.GetString("Creating GL Batch"), msg, TResultSeverity.Resv_Critical)); DBAccess.GDBAccessObj.RollbackTransaction(); return(-1); } Int32 BatchYear, BatchPeriod; // if DateEffective is outside the range of open periods, use the most fitting date DateTime DateEffective = stmt.Date; TFinancialYear.GetLedgerDatePostingPeriod(ALedgerNumber, ref DateEffective, out BatchYear, out BatchPeriod, Transaction, true); ALedgerTable LedgerTable = ALedgerAccess.LoadByPrimaryKey(ALedgerNumber, Transaction); DBAccess.GDBAccessObj.RollbackTransaction(); GLBatchTDS GLDS = TGLTransactionWebConnector.CreateABatch(ALedgerNumber); ABatchRow glbatchRow = GLDS.ABatch[0]; glbatchRow.BatchPeriod = BatchPeriod; glbatchRow.DateEffective = DateEffective; glbatchRow.BatchDescription = String.Format(Catalog.GetString("bank import for date {0}"), stmt.Date.ToShortDateString()); decimal HashTotal = 0.0M; decimal DebitTotal = 0.0M; decimal CreditTotal = 0.0M; // TODO: support several journals // TODO: support several currencies, support other currencies than the base currency AJournalRow gljournalRow = GLDS.AJournal.NewRowTyped(); gljournalRow.LedgerNumber = glbatchRow.LedgerNumber; gljournalRow.BatchNumber = glbatchRow.BatchNumber; gljournalRow.JournalNumber = glbatchRow.LastJournal + 1; gljournalRow.TransactionCurrency = LedgerTable[0].BaseCurrency; glbatchRow.LastJournal++; gljournalRow.JournalPeriod = glbatchRow.BatchPeriod; gljournalRow.DateEffective = glbatchRow.DateEffective; gljournalRow.JournalDescription = glbatchRow.BatchDescription; gljournalRow.SubSystemCode = CommonAccountingSubSystemsEnum.GL.ToString(); gljournalRow.TransactionTypeCode = CommonAccountingTransactionTypesEnum.STD.ToString(); gljournalRow.ExchangeRateToBase = 1.0m; GLDS.AJournal.Rows.Add(gljournalRow); foreach (DataRowView dv in AMainDS.AEpTransaction.DefaultView) { AEpTransactionRow transactionRow = (AEpTransactionRow)dv.Row; DataView v = AMainDS.AEpMatch.DefaultView; v.RowFilter = AEpMatchTable.GetActionDBName() + " = '" + MFinanceConstants.BANK_STMT_STATUS_MATCHED_GL + "' and " + AEpMatchTable.GetMatchTextDBName() + " = '" + transactionRow.MatchText + "'"; if (v.Count > 0) { AEpMatchRow match = (AEpMatchRow)v[0].Row; ATransactionRow trans = GLDS.ATransaction.NewRowTyped(); trans.LedgerNumber = glbatchRow.LedgerNumber; trans.BatchNumber = glbatchRow.BatchNumber; trans.JournalNumber = gljournalRow.JournalNumber; trans.TransactionNumber = gljournalRow.LastTransactionNumber + 1; trans.AccountCode = match.AccountCode; trans.CostCentreCode = match.CostCentreCode; trans.Reference = match.Reference; trans.Narrative = match.Narrative; trans.TransactionDate = transactionRow.DateEffective; if (transactionRow.TransactionAmount < 0) { trans.AmountInBaseCurrency = -1 * transactionRow.TransactionAmount; trans.TransactionAmount = -1 * transactionRow.TransactionAmount; trans.DebitCreditIndicator = true; DebitTotal += trans.AmountInBaseCurrency; } else { trans.AmountInBaseCurrency = transactionRow.TransactionAmount; trans.TransactionAmount = transactionRow.TransactionAmount; trans.DebitCreditIndicator = false; CreditTotal += trans.AmountInBaseCurrency; } GLDS.ATransaction.Rows.Add(trans); gljournalRow.LastTransactionNumber++; // add one transaction for the bank as well trans = GLDS.ATransaction.NewRowTyped(); trans.LedgerNumber = glbatchRow.LedgerNumber; trans.BatchNumber = glbatchRow.BatchNumber; trans.JournalNumber = gljournalRow.JournalNumber; trans.TransactionNumber = gljournalRow.LastTransactionNumber + 1; trans.AccountCode = stmt.BankAccountCode; trans.CostCentreCode = TLedgerInfo.GetStandardCostCentre(ALedgerNumber); trans.Reference = match.Reference; trans.Narrative = match.Narrative; trans.TransactionDate = transactionRow.DateEffective; if (transactionRow.TransactionAmount < 0) { trans.AmountInBaseCurrency = -1 * transactionRow.TransactionAmount; trans.TransactionAmount = -1 * transactionRow.TransactionAmount; trans.DebitCreditIndicator = false; CreditTotal += trans.AmountInBaseCurrency; } else { trans.AmountInBaseCurrency = transactionRow.TransactionAmount; trans.TransactionAmount = transactionRow.TransactionAmount; trans.DebitCreditIndicator = true; DebitTotal += trans.AmountInBaseCurrency; } GLDS.ATransaction.Rows.Add(trans); gljournalRow.LastTransactionNumber++; } } gljournalRow.JournalDebitTotal = DebitTotal; gljournalRow.JournalCreditTotal = CreditTotal; glbatchRow.BatchDebitTotal = DebitTotal; glbatchRow.BatchCreditTotal = CreditTotal; glbatchRow.BatchControlTotal = HashTotal; TVerificationResultCollection VerificationResult; TSubmitChangesResult result = TGLTransactionWebConnector.SaveGLBatchTDS(ref GLDS, out VerificationResult); if (result == TSubmitChangesResult.scrOK) { return(glbatchRow.BatchNumber); } TLogging.Log("Problems storing GL Batch"); return(-1); }
/// <summary> /// Reverses the specified batch /// </summary> /// <param name="ACurrentBatchRow">The DataRow for the batch to be reversed</param> /// <param name="ADateForReverseBatch">The reversal date - this will get checked to ensure the date is valid</param> /// <param name="AStartDateCurrentPeriod">The earliest date that can be used as reversal date</param> /// <param name="AEndDateLastForwardingPeriod">The latest date that can be used as a reversal date</param> /// <returns></returns> public bool ReverseBatch(ABatchRow ACurrentBatchRow, DateTime ADateForReverseBatch, DateTime AStartDateCurrentPeriod, DateTime AEndDateLastForwardingPeriod) { //TODO: Allow the user in a dialog to specify the reverse date TVerificationResultCollection Verifications; if (FPetraUtilsObject.HasChanges) { // save first, then post if (!FMyForm.SaveChanges()) { // saving failed, therefore do not try to reverse MessageBox.Show(Catalog.GetString("The batch was not reversed due to problems during saving; ") + Environment.NewLine + Catalog.GetString("Please first save the batch, and then you can reverse it!"), Catalog.GetString("Failure"), MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } } try { FMyForm.Cursor = Cursors.WaitCursor; int SelectedBatchNumber = ACurrentBatchRow.BatchNumber; string Msg = string.Empty; // load journals belonging to batch GLBatchTDS TempDS = TRemote.MFinance.GL.WebConnectors.LoadAJournalAndContent(FLedgerNumber, ACurrentBatchRow.BatchNumber); FMainDS.Merge(TempDS); foreach (AJournalRow Journal in TempDS.AJournal.Rows) { // if at least one journal in the batch has already been reversed then confirm with user if (Journal.Reversed) { Msg = String.Format(Catalog.GetString("One or more of the Journals in Batch {0} have already been reversed. " + "Are you sure you want to continue?"), SelectedBatchNumber); break; } } if (Msg == string.Empty) { Msg = String.Format(Catalog.GetString("Are you sure you want to reverse Batch {0}?"), SelectedBatchNumber); } if (MessageBox.Show(Msg, Catalog.GetString("GL Batch Reversal"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes) { TFrmBatchDateDialog Form = new TFrmBatchDateDialog(FMyForm); Form.SetParameters(AStartDateCurrentPeriod, AEndDateLastForwardingPeriod, SelectedBatchNumber); if (Form.ShowDialog() == DialogResult.Cancel) { return false; } ADateForReverseBatch = Form.BatchDate; int ReversalGLBatch; if (!TRemote.MFinance.GL.WebConnectors.ReverseBatch(FLedgerNumber, SelectedBatchNumber, ADateForReverseBatch, out ReversalGLBatch, out Verifications, false)) { string ErrorMessages = String.Empty; foreach (TVerificationResult verif in Verifications) { ErrorMessages += "[" + verif.ResultContext + "] " + verif.ResultTextCaption + ": " + verif.ResultText + Environment.NewLine; } System.Windows.Forms.MessageBox.Show(ErrorMessages, Catalog.GetString("Reversal failed"), MessageBoxButtons.OK, MessageBoxIcon.Error); } else { MessageBox.Show( String.Format(Catalog.GetString("A reversal batch has been created, with batch number {0}!"), ReversalGLBatch), Catalog.GetString("Success"), MessageBoxButtons.OK, MessageBoxIcon.Information); // refresh the grid, to reflect that the batch has been reversed FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAndContent(FLedgerNumber, ReversalGLBatch)); // make sure that the current dataset is clean, // otherwise the next save would try to modify the posted batch, even though no values have been changed FMainDS.AcceptChanges(); // Ensure these tabs will ask the server for updates FMyForm.GetJournalsControl().ClearCurrentSelection(); FMyForm.GetTransactionsControl().ClearCurrentSelection(); FMyUserControl.UpdateDisplay(); return true; } } } catch (Exception) { throw; } finally { FMyForm.Cursor = Cursors.Default; } return false; }
/// <summary> /// Runs a test on posting a batch /// </summary> /// <param name="ACurrentBatchRow">The data row corresponding to the batch to post</param> public void TestPostBatch(ABatchRow ACurrentBatchRow) { if (!SaveBatchForPosting()) { return; } TVerificationResultCollection Verifications; FMyForm.Cursor = Cursors.WaitCursor; List <TVariant> Result = TRemote.MFinance.GL.WebConnectors.TestPostGLBatch(FLedgerNumber, ACurrentBatchRow.BatchNumber, out Verifications); try { if ((Verifications != null) && (Verifications.Count > 0)) { string ErrorMessages = string.Empty; foreach (TVerificationResult verif in Verifications) { ErrorMessages += "[" + verif.ResultContext + "] " + verif.ResultTextCaption + ": " + verif.ResultText + Environment.NewLine; } System.Windows.Forms.MessageBox.Show(ErrorMessages, Catalog.GetString("Posting failed"), MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (Result.Count < 25) { string message = string.Empty; foreach (TVariant value in Result) { ArrayList compValues = value.ToComposite(); message += string.Format( Catalog.GetString("{1}/{0} ({3}/{2}) is: {4} and would be: {5}"), ((TVariant)compValues[0]).ToString(), ((TVariant)compValues[2]).ToString(), ((TVariant)compValues[1]).ToString(), ((TVariant)compValues[3]).ToString(), StringHelper.FormatCurrency((TVariant)compValues[4], "currency"), StringHelper.FormatCurrency((TVariant)compValues[5], "currency")) + Environment.NewLine; } MessageBox.Show(message, Catalog.GetString("Result of Test Posting")); } else { // store to CSV file string message = string.Empty; foreach (TVariant value in Result) { ArrayList compValues = value.ToComposite(); string[] columns = new string[] { ((TVariant)compValues[0]).ToString(), ((TVariant)compValues[1]).ToString(), ((TVariant)compValues[2]).ToString(), ((TVariant)compValues[3]).ToString(), StringHelper.FormatCurrency((TVariant)compValues[4], "CurrencyCSV"), StringHelper.FormatCurrency((TVariant)compValues[5], "CurrencyCSV") }; message += StringHelper.StrMerge(columns, Thread.CurrentThread.CurrentCulture.TextInfo.ListSeparator[0]) + Environment.NewLine; } string CSVFilePath = TClientSettings.PathLog + Path.DirectorySeparatorChar + "Batch" + ACurrentBatchRow.BatchNumber.ToString() + "_TestPosting.csv"; StreamWriter sw = new StreamWriter(CSVFilePath, false, System.Text.Encoding.UTF8); sw.Write(message); sw.Close(); MessageBox.Show( String.Format(Catalog.GetString("Please see file {0} for the result of the test posting"), CSVFilePath), Catalog.GetString("Result of Test Posting")); } } finally { FMyForm.Cursor = Cursors.Default; } }
private Boolean CloseSaveAndPost_(TVerificationResultCollection AVerifications) { if (FJournalCount != 0) { // The checksum of the "last journal" is used to update the checksum of the batch. FBatchRow.BatchControlTotal += FJournalRow.JournalDebitTotal - FJournalRow.JournalCreditTotal; } FBatchTDS.ThrowAwayAfterSubmitChanges = true; GLBatchTDSAccess.SubmitChanges(FBatchTDS); Boolean PostedOk = TGLPosting.PostGLBatch( FLedgerInfo.LedgerNumber, FBatchNumber, out AVerifications); // Make sure that this object cannot be used for another posting ... FBatchTDS = null; FBatchRow = null; FJournalRow = null; return PostedOk; }
/// <summary> /// Calculate the base amount for the transactions, and update the totals for the journals and the current batch /// </summary> /// <param name="AMainDS"></param> /// <param name="ACurrentBatch"></param> /// <param name="AAmountsChanged"></param> public static void UpdateTotalsOfBatch(ref GLBatchTDS AMainDS, ABatchRow ACurrentBatch, out bool AAmountsChanged) { AAmountsChanged = false; decimal BatchDebitTotal = 0.0m; decimal BatchCreditTotal = 0.0m; DataView jnlDataView = new DataView(AMainDS.AJournal); jnlDataView.RowFilter = String.Format("{0}={1}", AJournalTable.GetBatchNumberDBName(), ACurrentBatch.BatchNumber); foreach (DataRowView journalView in jnlDataView) { GLBatchTDSAJournalRow journalRow = (GLBatchTDSAJournalRow)journalView.Row; bool journalUpdated; UpdateTotalsOfJournal(ref AMainDS, ref journalRow, out journalUpdated); if (journalUpdated && !AAmountsChanged) { AAmountsChanged = true; } BatchDebitTotal += journalRow.JournalDebitTotal; BatchCreditTotal += journalRow.JournalCreditTotal; } if ((ACurrentBatch.BatchDebitTotal != BatchDebitTotal) || (ACurrentBatch.BatchCreditTotal != BatchCreditTotal)) { ACurrentBatch.BatchDebitTotal = BatchDebitTotal; ACurrentBatch.BatchCreditTotal = BatchCreditTotal; } }