private void FormReconcileEdit_Load(object sender, EventArgs e) { textDate.Text = ReconcileCur.DateReconcile.ToShortDateString(); checkLocked.Checked = ReconcileCur.IsLocked; textStart.Text = ReconcileCur.StartingBal.ToString("n"); textEnd.Text = ReconcileCur.EndingBal.ToString("n"); textTarget.Text = (ReconcileCur.EndingBal - ReconcileCur.StartingBal).ToString("n"); bool includeUncleared = !ReconcileCur.IsLocked; JournalList = JournalEntries.GetForReconcile(ReconcileCur.AccountNum, includeUncleared, ReconcileCur.ReconcileNum); FillGrid(); }
private void checkLocked_Click(object sender, EventArgs e) { if (checkLocked.Checked) { if (textTarget.Text != textSum.Text) { MsgBox.Show(this, "Target change must match sum of transactions."); checkLocked.Checked = false; return; } } else //unchecking //need to check permissions here. { } SaveList(); bool includeUncleared = !checkLocked.Checked; JournalList = JournalEntries.GetForReconcile(ReconcileCur.AccountNum, includeUncleared, ReconcileCur.ReconcileNum); FillGrid(); }
///<summary>Saves all changes to JournalList to database. Can only be called once when closing form.</summary> private void SaveList() { JournalEntries.SaveList(JournalList, ReconcileCur.ReconcileNum); }
private void FormDepositEdit_Load(object sender, System.EventArgs e) { if (IsNew) { if (!Security.IsAuthorized(Permissions.DepositSlips, DateTime.Today)) { //we will check the date again when saving DialogResult = DialogResult.Cancel; return; } } else { //We enforce security here based on date displayed, not date entered if (!Security.IsAuthorized(Permissions.DepositSlips, DepositCur.DateDeposit)) { butOK.Enabled = false; butDelete.Enabled = false; } } if (IsNew) { textDateStart.Text = PIn.PDate(PrefB.GetString("DateDepositsStarted")).ToShortDateString(); if (PrefB.GetBool("EasyNoClinics")) { comboClinic.Visible = false; labelClinic.Visible = false; } comboClinic.Items.Clear(); comboClinic.Items.Add(Lan.g(this, "all")); comboClinic.SelectedIndex = 0; for (int i = 0; i < Clinics.List.Length; i++) { comboClinic.Items.Add(Clinics.List[i].Description); } for (int i = 0; i < DefB.Short[(int)DefCat.PaymentTypes].Length; i++) { listPayType.Items.Add(DefB.Short[(int)DefCat.PaymentTypes][i].ItemName); listPayType.SetSelected(i, true); } textDepositAccount.Visible = false; //this is never visible for new. It's a description if already attached. if (Accounts.DepositsLinked()) { DepositAccounts = Accounts.GetDepositAccounts(); for (int i = 0; i < DepositAccounts.Length; i++) { comboDepositAccount.Items.Add(Accounts.GetDescript(DepositAccounts[i])); } comboDepositAccount.SelectedIndex = 0; } else { labelDepositAccount.Visible = false; comboDepositAccount.Visible = false; } } else { groupSelect.Visible = false; gridIns.SelectionMode = GridSelectionMode.None; gridPat.SelectionMode = GridSelectionMode.None; //we never again let user change the deposit linking again from here. //They need to detach it from within the transaction //Might be enhanced later to allow, but that's very complex. Transaction trans = Transactions.GetAttachedToDeposit(DepositCur.DepositNum); if (trans == null) { labelDepositAccount.Visible = false; comboDepositAccount.Visible = false; textDepositAccount.Visible = false; } else { comboDepositAccount.Enabled = false; labelDepositAccount.Text = Lan.g(this, "Deposited into Account"); ArrayList jeAL = JournalEntries.GetForTrans(trans.TransactionNum); for (int i = 0; i < jeAL.Count; i++) { if (Accounts.GetAccount(((JournalEntry)jeAL[i]).AccountNum).AcctType == AccountType.Asset) { comboDepositAccount.Items.Add(Accounts.GetDescript(((JournalEntry)jeAL[i]).AccountNum)); comboDepositAccount.SelectedIndex = 0; textDepositAccount.Text = ((JournalEntry)jeAL[i]).DateDisplayed.ToShortDateString() + " " + ((JournalEntry)jeAL[i]).DebitAmt.ToString("c"); break; } } } } textDate.Text = DepositCur.DateDeposit.ToShortDateString(); textAmount.Text = DepositCur.Amount.ToString("F"); textBankAccountInfo.Text = DepositCur.BankAccountInfo; FillGrids(); if (IsNew) { gridPat.SetSelected(true); gridIns.SetSelected(true); } ComputeAmt(); }
///<summary>Saves the selected rows to database. MUST close window after this.</summary> private bool SaveToDB() { if (textDate.errorProvider1.GetError(textDate) != "") { MsgBox.Show(this, "Please fix data entry errors first."); return(false); } //Prevent backdating---------------------------------------------------------------------------------------- DateTime date = PIn.PDate(textDate.Text); if (IsNew) { if (!Security.IsAuthorized(Permissions.DepositSlips, date)) { return(false); } } else { //We enforce security here based on date displayed, not date entered if (!Security.IsAuthorized(Permissions.DepositSlips, date)) { return(false); } } DepositCur.DateDeposit = PIn.PDate(textDate.Text); //amount already handled. DepositCur.BankAccountInfo = PIn.PString(textBankAccountInfo.Text); if (IsNew) { Deposits.Insert(DepositCur); if (Accounts.DepositsLinked() && DepositCur.Amount > 0) { //create a transaction here Transaction trans = new Transaction(); trans.DepositNum = DepositCur.DepositNum; trans.UserNum = Security.CurUser.UserNum; Transactions.Insert(trans); //first the deposit entry JournalEntry je = new JournalEntry(); je.AccountNum = DepositAccounts[comboDepositAccount.SelectedIndex]; je.CheckNumber = Lan.g(this, "DEP"); je.DateDisplayed = DepositCur.DateDeposit; //it would be nice to add security here. je.DebitAmt = DepositCur.Amount; je.Memo = Lan.g(this, "Deposit"); je.Splits = Accounts.GetDescript(PrefB.GetInt("AccountingIncomeAccount")); je.TransactionNum = trans.TransactionNum; JournalEntries.Insert(je); //then, the income entry je = new JournalEntry(); je.AccountNum = PrefB.GetInt("AccountingIncomeAccount"); //je.CheckNumber=; je.DateDisplayed = DepositCur.DateDeposit; //it would be nice to add security here. je.CreditAmt = DepositCur.Amount; je.Memo = Lan.g(this, "Deposit"); je.Splits = Accounts.GetDescript(DepositAccounts[comboDepositAccount.SelectedIndex]); je.TransactionNum = trans.TransactionNum; JournalEntries.Insert(je); } } else { Deposits.Update(DepositCur); } if (IsNew) //never allowed to change or attach more checks after initial creation of deposit slip { for (int i = 0; i < gridPat.SelectedIndices.Length; i++) { PatPayList[gridPat.SelectedIndices[i]].DepositNum = DepositCur.DepositNum; Payments.Update(PatPayList[gridPat.SelectedIndices[i]]); } for (int i = 0; i < gridIns.SelectedIndices.Length; i++) { ClaimPayList[gridIns.SelectedIndices[i]].DepositNum = DepositCur.DepositNum; ClaimPayments.Update(ClaimPayList[gridIns.SelectedIndices[i]]); } } if (IsNew) { SecurityLogs.MakeLogEntry(Permissions.DepositSlips, 0, DepositCur.DateDeposit.ToShortDateString() + " New " + DepositCur.Amount.ToString("c")); } else { SecurityLogs.MakeLogEntry(Permissions.AdjustmentEdit, 0, DepositCur.DateDeposit.ToShortDateString() + " " + DepositCur.Amount.ToString("c")); } return(true); }
private void FillGrid() { if (textDateFrom.errorProvider1.GetError(textDateFrom) != "" || textDateTo.errorProvider1.GetError(textDateTo) != "" ) { return; } DateTime dateFrom = PIn.PDate(textDateFrom.Text); DateTime dateTo; if (textDateTo.Text == "") { dateTo = DateTime.MaxValue; } else { dateTo = PIn.PDate(textDateTo.Text); } double filterAmt = 0; if (textAmt.errorProvider1.GetError(textAmt) == "") { filterAmt = PIn.PDouble(textAmt.Text); } JournalList = JournalEntries.GetForAccount(AccountCur.AccountNum); int scroll = gridMain.ScrollValue; gridMain.BeginUpdate(); gridMain.Title = AccountCur.Description + " (" + Lan.g("enumAccountType", AccountCur.AcctType.ToString()) + ")"; gridMain.Columns.Clear(); string str = ""; ODGridColumn col = new ODGridColumn(Lan.g("TableJournal", "Chk #"), 60, HorizontalAlignment.Center); gridMain.Columns.Add(col); col = new ODGridColumn(Lan.g("TableJournal", "Date"), 80); gridMain.Columns.Add(col); if (isPrinting) { col = new ODGridColumn(Lan.g("TableJournal", "Memo"), 200); } else { col = new ODGridColumn(Lan.g("TableJournal", "Memo"), 220); } gridMain.Columns.Add(col); if (isPrinting) { col = new ODGridColumn(Lan.g("TableJournal", "Splits"), 200); } else { col = new ODGridColumn(Lan.g("TableJournal", "Splits"), 220); } gridMain.Columns.Add(col); str = Lan.g("TableJournal", "Debit"); if (Accounts.DebitIsPos(AccountCur.AcctType)) { str += Lan.g("TableJournal", "(+)"); } else { str += Lan.g("TableJournal", "(-)"); } col = new ODGridColumn(str, 65, HorizontalAlignment.Right); gridMain.Columns.Add(col); str = Lan.g("TableJournal", "Credit"); if (Accounts.DebitIsPos(AccountCur.AcctType)) { str += Lan.g("TableJournal", "(-)"); } else { str += Lan.g("TableJournal", "(+)"); } col = new ODGridColumn(str, 65, HorizontalAlignment.Right); gridMain.Columns.Add(col); col = new ODGridColumn(Lan.g("TableJournal", "Balance"), 65, HorizontalAlignment.Right); gridMain.Columns.Add(col); col = new ODGridColumn(Lan.g("TableJournal", "Clear"), 55, HorizontalAlignment.Center); gridMain.Columns.Add(col); gridMain.Rows.Clear(); ODGridRow row; double bal = 0; for (int i = 0; i < JournalList.Length; i++) { if (JournalList[i].DateDisplayed > dateTo) { break; } if (AccountCur.AcctType == AccountType.Income || AccountCur.AcctType == AccountType.Expense) { if (JournalList[i].DateDisplayed < dateFrom) { continue; //for income and expense accounts, previous balances are not included. Only the current timespan. } } if (JournalList[i].DebitAmt != 0) { if (Accounts.DebitIsPos(AccountCur.AcctType)) //this one is used for checking account { bal += JournalList[i].DebitAmt; } else { bal -= JournalList[i].DebitAmt; } } if (JournalList[i].CreditAmt != 0) { if (Accounts.DebitIsPos(AccountCur.AcctType)) //this one is used for checking account { bal -= JournalList[i].CreditAmt; } else { bal += JournalList[i].CreditAmt; } } if (AccountCur.AcctType == AccountType.Asset || AccountCur.AcctType == AccountType.Liability || AccountCur.AcctType == AccountType.Equity) { if (JournalList[i].DateDisplayed < dateFrom) { continue; //for asset, liability, and equity accounts, older entries do affect the current balance. } } if (filterAmt != 0 && filterAmt != JournalList[i].CreditAmt && filterAmt != JournalList[i].DebitAmt) { continue; } if (textFindText.Text != "" && !JournalList[i].Memo.ToUpper().Contains(textFindText.Text.ToUpper()) && !JournalList[i].CheckNumber.ToUpper().Contains(textFindText.Text.ToUpper()) && !JournalList[i].Splits.ToUpper().Contains(textFindText.Text.ToUpper())) { continue; } row = new ODGridRow(); row.Cells.Add(JournalList[i].CheckNumber); row.Cells.Add(JournalList[i].DateDisplayed.ToShortDateString()); row.Cells.Add(JournalList[i].Memo); row.Cells.Add(JournalList[i].Splits); if (JournalList[i].DebitAmt == 0) { row.Cells.Add(""); } else { row.Cells.Add(JournalList[i].DebitAmt.ToString("n")); } if (JournalList[i].CreditAmt == 0) { row.Cells.Add(""); } else { row.Cells.Add(JournalList[i].CreditAmt.ToString("n")); } row.Cells.Add(bal.ToString("n")); if (JournalList[i].ReconcileNum == 0) { row.Cells.Add(""); } else { row.Cells.Add("X"); } row.Tag = JournalList[i].Copy(); gridMain.Rows.Add(row); } gridMain.EndUpdate(); gridMain.ScrollToEnd(); }
///<summary>Saves the selected rows to database. MUST close window after this.</summary> private bool SaveToDB() { if (textDate.errorProvider1.GetError(textDate) != "") { MsgBox.Show(this, "Please fix data entry errors first."); return(false); } //Prevent backdating---------------------------------------------------------------------------------------- DateTime date = PIn.Date(textDate.Text); if (IsNew) { if (!Security.IsAuthorized(Permissions.DepositSlips, date)) { return(false); } } else { //We enforce security here based on date displayed, not date entered if (!Security.IsAuthorized(Permissions.DepositSlips, date)) { return(false); } } DepositCur.DateDeposit = PIn.Date(textDate.Text); //amount already handled. DepositCur.BankAccountInfo = PIn.String(textBankAccountInfo.Text); if (IsNew) { if (gridPat.SelectedIndices.Length + gridIns.SelectedIndices.Length > 18) { if (!MsgBox.Show(this, MsgBoxButtons.YesNo, "No more than 18 items will fit on a QuickBooks deposit slip. Continue anyway?")) { return(false); } } Deposits.Insert(DepositCur); if (Accounts.DepositsLinked() && DepositCur.Amount > 0) { if (PrefC.GetInt(PrefName.AccountingSoftware) == (int)AccountingSoftware.QuickBooks) { //Create a deposit within QuickBooks. try { Cursor.Current = Cursors.WaitCursor; QuickBooks.CreateDeposit(DepositAccountsQB[comboDepositAccount.SelectedIndex] , PrefC.GetString(PrefName.QuickBooksIncomeAccount), DepositCur.Amount); Cursor.Current = Cursors.Default; } catch (Exception ex) { Cursor.Current = Cursors.Default; if (MessageBox.Show(ex.Message + "\r\n\r\nA deposit has not been created in QuickBooks, continue anyway?", "QuickBooks Deposit Create Failed", MessageBoxButtons.YesNo) != DialogResult.Yes) { return(false); } } } else { //create a transaction here Transaction trans = new Transaction(); trans.DepositNum = DepositCur.DepositNum; trans.UserNum = Security.CurUser.UserNum; Transactions.Insert(trans); //first the deposit entry JournalEntry je = new JournalEntry(); je.AccountNum = DepositAccounts[comboDepositAccount.SelectedIndex]; je.CheckNumber = Lan.g(this, "DEP"); je.DateDisplayed = DepositCur.DateDeposit; //it would be nice to add security here. je.DebitAmt = DepositCur.Amount; je.Memo = Lan.g(this, "Deposit"); je.Splits = Accounts.GetDescript(PrefC.GetLong(PrefName.AccountingIncomeAccount)); je.TransactionNum = trans.TransactionNum; JournalEntries.Insert(je); //then, the income entry je = new JournalEntry(); je.AccountNum = PrefC.GetLong(PrefName.AccountingIncomeAccount); //je.CheckNumber=; je.DateDisplayed = DepositCur.DateDeposit; //it would be nice to add security here. je.CreditAmt = DepositCur.Amount; je.Memo = Lan.g(this, "Deposit"); je.Splits = Accounts.GetDescript(DepositAccounts[comboDepositAccount.SelectedIndex]); je.TransactionNum = trans.TransactionNum; JournalEntries.Insert(je); } } } else { Deposits.Update(DepositCur); } if (IsNew) //never allowed to change or attach more checks after initial creation of deposit slip { for (int i = 0; i < gridPat.SelectedIndices.Length; i++) { PatPayList[gridPat.SelectedIndices[i]].DepositNum = DepositCur.DepositNum; Payments.Update(PatPayList[gridPat.SelectedIndices[i]], false); } for (int i = 0; i < gridIns.SelectedIndices.Length; i++) { ClaimPayList[gridIns.SelectedIndices[i]].DepositNum = DepositCur.DepositNum; ClaimPayments.Update(ClaimPayList[gridIns.SelectedIndices[i]]); } } if (IsNew) { SecurityLogs.MakeLogEntry(Permissions.DepositSlips, 0, DepositCur.DateDeposit.ToShortDateString() + " New " + DepositCur.Amount.ToString("c")); } else { SecurityLogs.MakeLogEntry(Permissions.AdjustmentEdit, 0, DepositCur.DateDeposit.ToShortDateString() + " " + DepositCur.Amount.ToString("c")); } return(true); }
///<summary>Only called once from FormPayment when trying to change an amount or an account on a payment that's already linked to the Accounting section or when trying to create a new link. This automates updating the Accounting section. Do not surround with try-catch, because it was already validated in ValidateLinkedEntries above. Use -1 for newAcct to indicate no changed. The name is required to give descriptions to new entries.</summary> public static void AlterLinkedEntries(double oldAmt, double newAmt, bool isNew, int payNum, int newAcct, DateTime payDate, string patName) { if (!Accounts.PaymentsLinked()) { return; //user has not even set up accounting links. } bool amtChanged = false; if (oldAmt != newAmt) { amtChanged = true; } Transaction trans = Transactions.GetAttachedToPayment(payNum); //this gives us the oldAcctNum double absNew = newAmt; //absolute value of the new amount if (newAmt < 0) { absNew = -newAmt; } //if(trans==null && (newAcct==0 || newAcct==-1)) {//then this method will not even be called if (trans == null) //no previous link, but user is trying to create one. //this is the only case where a new trans is required. { trans = new Transaction(); trans.PayNum = payNum; trans.UserNum = Security.CurUser.UserNum; Transactions.Insert(trans); //sets entry date //first the deposit entry JournalEntry je = new JournalEntry(); je.AccountNum = newAcct; //DepositAccounts[comboDepositAccount.SelectedIndex]; je.CheckNumber = Lan.g("Payments", "DEP"); je.DateDisplayed = payDate; //it would be nice to add security here. if (absNew == newAmt) //amount is positive { je.DebitAmt = newAmt; } else { je.CreditAmt = absNew; } je.Memo = Lan.g("Payments", "Payment -") + " " + patName; je.Splits = Accounts.GetDescript(PrefB.GetInt("AccountingCashIncomeAccount")); je.TransactionNum = trans.TransactionNum; JournalEntries.Insert(je); //then, the income entry je = new JournalEntry(); je.AccountNum = PrefB.GetInt("AccountingCashIncomeAccount"); //je.CheckNumber=; je.DateDisplayed = payDate; //it would be nice to add security here. if (absNew == newAmt) //amount is positive { je.CreditAmt = newAmt; } else { je.DebitAmt = absNew; } je.Memo = Lan.g("Payments", "Payment -") + " " + patName; je.Splits = Accounts.GetDescript(newAcct); je.TransactionNum = trans.TransactionNum; JournalEntries.Insert(je); return; } //at this point, we have established that there is a previous transaction. ArrayList jeAL = JournalEntries.GetForTrans(trans.TransactionNum); int oldAcct = 0; JournalEntry jeDebit = null; JournalEntry jeCredit = null; bool signChanged = false; double absOld = oldAmt;//the absolute value of the old amount if (oldAmt < 0) { absOld = -oldAmt; } if (oldAmt < 0 && newAmt > 0) { signChanged = true; } if (oldAmt > 0 && newAmt < 0) { signChanged = true; } for (int i = 0; i < 2; i++) { if (Accounts.GetAccount(((JournalEntry)jeAL[i]).AccountNum).AcctType == AccountType.Asset) { oldAcct = ((JournalEntry)jeAL[i]).AccountNum; } if (((JournalEntry)jeAL[i]).DebitAmt == absOld) { jeDebit = (JournalEntry)jeAL[i]; } //old credit entry if (((JournalEntry)jeAL[i]).CreditAmt == absOld) { jeCredit = (JournalEntry)jeAL[i]; } } //Already validated that both je's are not null, and that oldAcct is not 0. if (newAcct == 0) //detaching it from a linked transaction. We will delete the transaction //we don't care about the amount { Transactions.Delete(trans); //we need to make sure this doesn't throw any exceptions by carefully checking all //possibilities in the validation routine above. return; } //Either the amount or the account changed on an existing linked transaction. bool acctChanged = false; if (newAcct != -1 && oldAcct != newAcct) { acctChanged = true; //changing linked acctNum } if (amtChanged) { if (signChanged) { jeDebit.DebitAmt = 0; jeDebit.CreditAmt = absNew; jeCredit.DebitAmt = absNew; jeCredit.CreditAmt = 0; } else { jeDebit.DebitAmt = absNew; jeCredit.CreditAmt = absNew; } } if (acctChanged) { if (jeDebit.AccountNum == oldAcct) { jeDebit.AccountNum = newAcct; } if (jeCredit.AccountNum == oldAcct) { jeCredit.AccountNum = newAcct; } } JournalEntries.Update(jeDebit); JournalEntries.Update(jeCredit); }
///<summary>This does all the validation before calling AlterLinkedEntries. It had to be separated like this because of the complexity of saving a payment. Surround with try-catch. Will throw an exception if user is trying to change, but not allowed. Will return false if no synch with accounting is needed. Use -1 for newAcct to indicate no change.</summary> public static bool ValidateLinkedEntries(double oldAmt, double newAmt, bool isNew, int payNum, int newAcct) { if (!Accounts.PaymentsLinked()) { return(false); //user has not even set up accounting links, so no need to check any of this. } bool amtChanged = false; if (oldAmt != newAmt) { amtChanged = true; } Transaction trans = Transactions.GetAttachedToPayment(payNum); //this gives us the oldAcctNum if (trans == null && (newAcct == 0 || newAcct == -1)) //if there was no previous link, and there is no attempt to create a link { return(false); //no synch needed } if (trans == null) //no previous link, but user is trying to create one. newAcct>0. { return(true); //new transaction will be required } //at this point, we have established that there is a previous transaction. //If payment is attached to a transaction which is more than 48 hours old, then not allowed to change. if (amtChanged && trans.DateTimeEntry < MiscData.GetNowDateTime().AddDays(-2)) { throw new ApplicationException(Lan.g("Payments", "Not allowed to change amount that is more than 48 hours old. This payment is already attached to an accounting transaction. You will need to detach it from within the accounting section of the program.")); } if (amtChanged && Transactions.IsReconciled(trans)) { throw new ApplicationException(Lan.g("Payments", "Not allowed to change amount. This payment is attached to an accounting transaction that has been reconciled. You will need to detach it from within the accounting section of the program.")); } ArrayList jeAL = JournalEntries.GetForTrans(trans.TransactionNum); int oldAcct = 0; JournalEntry jeDebit = null; JournalEntry jeCredit = null; double absOld = oldAmt; //the absolute value of the old amount if (oldAmt < 0) { absOld = -oldAmt; } for (int i = 0; i < jeAL.Count; i++) //we make sure down below that this count is exactly 2. { if (Accounts.GetAccount(((JournalEntry)jeAL[i]).AccountNum).AcctType == AccountType.Asset) { oldAcct = ((JournalEntry)jeAL[i]).AccountNum; } if (((JournalEntry)jeAL[i]).DebitAmt == absOld) { jeDebit = (JournalEntry)jeAL[i]; } //old credit entry if (((JournalEntry)jeAL[i]).CreditAmt == absOld) { jeCredit = (JournalEntry)jeAL[i]; } } if (jeCredit == null || jeDebit == null) { throw new ApplicationException(Lan.g("Payments", "Not able to automatically make changes in the accounting section to match the change made here. You will need to detach it from within the accounting section.")); } if (oldAcct == 0) //something must have gone wrong. But this should never happen { throw new ApplicationException(Lan.g("Payments", "Could not locate linked transaction. You will need to detach it manually from within the accounting section of the program.")); } if (newAcct == 0) //detaching it from a linked transaction. //We will delete the transaction { return(true); } bool acctChanged = false; if (newAcct != -1 && oldAcct != newAcct) { acctChanged = true; //changing linked acctNum } if (!amtChanged && !acctChanged) { return(false); //no changes being made to amount or account, so no synch required. } if (jeAL.Count != 2) { throw new ApplicationException(Lan.g("Payments", "Not able to automatically change the amount in the accounting section to match the change made here. You will need to detach it from within the accounting section.")); } //Amount or account changed on an existing linked transaction. return(true); }
///<summary>Called from FormPayment when trying to change an amount on payment that's already linked to the Accounting section. This automates updating the Accounting section. Surround with try-catch, because it with throw an exception if not able to alter the link.</summary> public static void AlterLinkedEntries(Payment pay, Double newAmt) { bool amtChanged = false; //bool typeChanged=false; if (pay.PayAmt != newAmt) { amtChanged = true; } //if(PayType!=newPayType){ // typeChanged=true; //} if (!amtChanged) // && !typeChanged){ { return; //no changes being made to amount, so skip the rest. } Transaction trans = Transactions.GetAttachedToPayment(pay.PayNum); if (trans == null) { return; //not linked to any accounting entry. } //If payment is attached to a transaction which is more than 48 hours old, then not allowed to change. if (amtChanged && trans.DateTimeEntry < MiscData.GetNowDateTime().AddDays(-2)) { throw new ApplicationException(Lan.g("Payments", "Not allowed to change amount that is more than 48 hours old. This payment is already attached to an accounting transaction. You will need to detach it from within the accounting section of the program.")); } if (amtChanged && Transactions.IsReconciled(trans)) { throw new ApplicationException(Lan.g("Payments", "Not allowed to change amount. This payment is attached to an accounting transaction that has been reconciled. You will need to detach it from within the accounting section of the program.")); } ArrayList jeAL = JournalEntries.GetForTrans(trans.TransactionNum); if (jeAL.Count != 2) { throw new ApplicationException(Lan.g("Payments", "Not able to automatically change the amount in the accounting section to match the change made here. You will need to detach it from within the accounting section.")); } JournalEntry jeDebit = null; JournalEntry jeCredit = null; bool signChanged = false; double absOld = pay.PayAmt;//the absolute value of the old amount if (pay.PayAmt < 0) { absOld = -pay.PayAmt; } double absNew = newAmt; //absolute value of the new amount if (newAmt < 0) { absNew = -newAmt; } if (pay.PayAmt < 0 && newAmt > 0) { signChanged = true; } if (pay.PayAmt > 0 && newAmt < 0) { signChanged = true; } for (int i = 0; i < 2; i++) { //first the old debit entry if (((JournalEntry)jeAL[i]).DebitAmt == absOld) { jeDebit = (JournalEntry)jeAL[i]; } //then, the old credit entry if (((JournalEntry)jeAL[i]).CreditAmt == absOld) { jeCredit = (JournalEntry)jeAL[i]; } } if (jeCredit == null || jeDebit == null) { throw new ApplicationException(Lan.g("Payments", "Not able to automatically make changes in the accounting section to match the change made here. You will need to detach it from within the accounting section.")); } if (amtChanged) { if (signChanged) { jeDebit.DebitAmt = 0; jeDebit.CreditAmt = absNew; JournalEntries.Update(jeDebit); jeCredit.DebitAmt = absNew; jeCredit.CreditAmt = 0; JournalEntries.Update(jeCredit); } else { jeDebit.DebitAmt = absNew; JournalEntries.Update(jeDebit); jeCredit.CreditAmt = absNew; JournalEntries.Update(jeCredit); } } //if(!typeChanged){ // return; //} //From here on down, we are just altering the type //jeAL=JournalEntries.GetForTrans(trans.TransactionNum); //JournalEntry jeDebit=null; //JournalEntry jeCredit=null; }
private void FillGrid() { if (textDateFrom.errorProvider1.GetError(textDateFrom) != "" || textDateTo.errorProvider1.GetError(textDateTo) != "") { return; } DateTime dateFrom = PIn.Date(textDateFrom.Text); DateTime dateTo = textDateTo.Text != ""?PIn.Date(textDateTo.Text):DateTime.MaxValue; double filterAmt = string.IsNullOrEmpty(textAmt.errorProvider1.GetError(textAmt))?PIn.Double(textAmt.Text):0; List <JournalEntry> listJEntries = JournalEntries.GetForAccount(_acctCur.AccountNum); List <Transaction> listTransactions = Transactions.GetManyTrans(listJEntries.Select(x => x.TransactionNum).ToList()); //Resize grid to fit, important for later resizing gridMain.BeginUpdate(); gridMain.Columns.Clear(); gridMain.Rows.Clear(); gridMain.Width = isPrinting?1050:(this.Width - 16);//gridMain.Location.XPos=0 and the grid is form width - 16 gridMain.HideScrollBars = isPrinting; gridMain.EndUpdate(); gridMain.BeginUpdate(); gridMain.Title = _acctCur.Description + " (" + Lan.g("enumAccountType", _acctCur.AcctType.ToString()) + ")"; gridMain.Columns.Clear(); gridMain.Columns.Add(new ODGridColumn(Lan.g("TableJournal", "Chk #"), 60, HorizontalAlignment.Center)); gridMain.Columns.Add(new ODGridColumn(Lan.g("TableJournal", "Date"), 75)); gridMain.Columns.Add(new ODGridColumn(Lan.g("TableJournal", "Memo"), isPrinting?200:220)); gridMain.Columns.Add(new ODGridColumn(Lan.g("TableJournal", "Splits"), isPrinting?200:220)); int colClearWidth = 40; //because the "clear" column has not been added yet. int colUserWidth = 100; //because the user columns haven't been added yet. //if printing, total size=paper width-margins (1050), otherwise total size=gridWidth-scroll bar width of 19 //divide remaining size, total size - grid col widths, into thirds for the debit, credit, and balance columns int colW = (gridMain.Width - (isPrinting?0:19) - gridMain.WidthAllColumns - colClearWidth - 2 * colUserWidth) / 3; gridMain.Columns.Add(new ODGridColumn(Lan.g("TableJournal", "Debit" + (Accounts.DebitIsPos(_acctCur.AcctType)?"(+)":"(-)")), colW, HorizontalAlignment.Right)); gridMain.Columns.Add(new ODGridColumn(Lan.g("TableJournal", "Credit" + (Accounts.DebitIsPos(_acctCur.AcctType)?"(-)":"(+)")), colW, HorizontalAlignment.Right)); gridMain.Columns.Add(new ODGridColumn(Lan.g("TableJournal", "Balance"), colW, HorizontalAlignment.Right)); gridMain.Columns.Add(new ODGridColumn(Lan.g("TableJournal", "Created By"), colUserWidth)); gridMain.Columns.Add(new ODGridColumn(Lan.g("TableJournal", "Last Edited By"), colUserWidth)); gridMain.Columns.Add(new ODGridColumn(Lan.g("TableJournal", "Clear"), colClearWidth, HorizontalAlignment.Center)); gridMain.Rows.Clear(); ODGridRow row; decimal bal = 0; foreach (JournalEntry jeCur in listJEntries) { if (jeCur.DateDisplayed > dateTo) { break; } if (new[] { AccountType.Income, AccountType.Expense }.Contains(_acctCur.AcctType) && jeCur.DateDisplayed < dateFrom) { continue; //for income and expense accounts, previous balances are not included. Only the current timespan. } //DebitIsPos=true for checking acct, bal+=DebitAmt-CreditAmt bal += (Accounts.DebitIsPos(_acctCur.AcctType)?1:-1) * ((decimal)jeCur.DebitAmt - (decimal)jeCur.CreditAmt); if (new[] { AccountType.Asset, AccountType.Liability, AccountType.Equity }.Contains(_acctCur.AcctType) && jeCur.DateDisplayed < dateFrom) { continue; //for asset, liability, and equity accounts, older entries do affect the current balance. } if (filterAmt != 0 && filterAmt != jeCur.CreditAmt && filterAmt != jeCur.DebitAmt) { continue; } if (textFindText.Text != "" && new[] { jeCur.Memo, jeCur.CheckNumber, jeCur.Splits }.All(x => !x.ToUpper().Contains(textFindText.Text.ToUpper()))) { continue; } row = new ODGridRow(); row.Cells.Add(jeCur.CheckNumber); row.Cells.Add(jeCur.DateDisplayed.ToShortDateString()); row.Cells.Add(jeCur.Memo); row.Cells.Add(jeCur.Splits); row.Cells.Add(jeCur.DebitAmt == 0?"":jeCur.DebitAmt.ToString("n")); row.Cells.Add(jeCur.CreditAmt == 0?"":jeCur.CreditAmt.ToString("n")); row.Cells.Add(bal.ToString("n")); row.Cells.Add(Userods.GetName(listTransactions.FirstOrDefault(x => x.TransactionNum == jeCur.TransactionNum)?.UserNum ?? 0)); row.Cells.Add(Userods.GetName(jeCur.SecUserNumEdit)); row.Cells.Add(jeCur.ReconcileNum == 0?"":"X"); row.Tag = jeCur.Copy(); gridMain.Rows.Add(row); } gridMain.EndUpdate(); gridMain.ScrollToEnd(); }
private void FillGrid(bool isPrinting = false, bool isResizing = false) { if (textDateFrom.errorProvider1.GetError(textDateFrom) != "" || textDateTo.errorProvider1.GetError(textDateTo) != "") { return; } ODGrid gridToFill = isPrinting?gridMainPrint:gridMain; long firstVisibleTransNum = 0; if (!isPrinting && gridToFill.VisibleRows.Count > 0) //don't scroll into view if printing { firstVisibleTransNum = (long)gridToFill.VisibleRows[0].Tag; } long selectedTransNum = 0; if (!isPrinting && gridToFill.GetSelectedIndex() > -1) //no need to reselect an index if printing { selectedTransNum = gridToFill.SelectedTag <long>(); } //Resize grid to fit, important for later resizing gridToFill.BeginUpdate(); gridToFill.Title = _acctCur.Description + " (" + Lan.g("enumAccountType", _acctCur.AcctType.ToString()) + ")"; FillColumns(isPrinting, isResizing); DateTime dateFrom = PIn.Date(textDateFrom.Text); DateTime dateTo = string.IsNullOrEmpty(textDateTo.Text)?DateTime.MaxValue:PIn.Date(textDateTo.Text); double filterAmt = string.IsNullOrEmpty(textAmt.errorProvider1.GetError(textAmt))?PIn.Double(textAmt.Text):0; if (!isResizing || _listJEntries == null || _dictTransUsers == null) { _listJEntries = JournalEntries.GetForAccount(_acctCur.AccountNum); _dictTransUsers = Transactions.GetManyTrans(_listJEntries.Select(x => x.TransactionNum).ToList()) .ToDictionary(x => x.TransactionNum, x => x.UserNum); } gridToFill.ListGridRows.Clear(); GridRow row; decimal bal = 0; int firstVisibleRowIndex = -1; int selectedIndex = -1; foreach (JournalEntry jeCur in _listJEntries) { if (jeCur.DateDisplayed > dateTo) { break; } if (new[] { AccountType.Income, AccountType.Expense }.Contains(_acctCur.AcctType) && jeCur.DateDisplayed < dateFrom) { continue; //for income and expense accounts, previous balances are not included. Only the current timespan. } //DebitIsPos=true for checking acct, bal+=DebitAmt-CreditAmt bal += (Accounts.DebitIsPos(_acctCur.AcctType)?1:-1) * ((decimal)jeCur.DebitAmt - (decimal)jeCur.CreditAmt); if (new[] { AccountType.Asset, AccountType.Liability, AccountType.Equity }.Contains(_acctCur.AcctType) && jeCur.DateDisplayed < dateFrom) { continue; //for asset, liability, and equity accounts, older entries do affect the current balance. } if (filterAmt != 0 && filterAmt != jeCur.CreditAmt && filterAmt != jeCur.DebitAmt) { continue; } if (textFindText.Text != "" && new[] { jeCur.Memo, jeCur.CheckNumber, jeCur.Splits }.All(x => !x.ToUpper().Contains(textFindText.Text.ToUpper()))) { continue; } row = new GridRow(); row.Cells.Add(jeCur.CheckNumber); row.Cells.Add(jeCur.DateDisplayed.ToShortDateString()); row.Cells.Add(jeCur.Memo); row.Cells.Add(jeCur.Splits); row.Cells.Add(jeCur.DebitAmt == 0?"":jeCur.DebitAmt.ToString("n")); row.Cells.Add(jeCur.CreditAmt == 0?"":jeCur.CreditAmt.ToString("n")); row.Cells.Add(bal.ToString("n")); long userNum; row.Cells.Add(Userods.GetName(_dictTransUsers.TryGetValue(jeCur.TransactionNum, out userNum)?userNum:0)); row.Cells.Add(Userods.GetName(jeCur.SecUserNumEdit)); row.Cells.Add(jeCur.ReconcileNum == 0?"":"X"); row.Tag = jeCur.TransactionNum; gridToFill.ListGridRows.Add(row); if (firstVisibleTransNum > 0 && jeCur.TransactionNum == firstVisibleTransNum) { firstVisibleRowIndex = gridToFill.ListGridRows.Count - 1; } if (selectedTransNum > 0 && jeCur.TransactionNum == selectedTransNum) { selectedIndex = gridToFill.ListGridRows.Count - 1; } } gridToFill.EndUpdate(); if (selectedIndex > -1) { gridToFill.SetSelected(selectedIndex, true); } if (firstVisibleRowIndex > -1) { gridToFill.ScrollToIndex(firstVisibleRowIndex); } else { gridToFill.ScrollToEnd(); } }