///<summary></summary> public static void Delete(JournalEntry je) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),je); return; } string command= "DELETE FROM journalentry WHERE JournalEntryNum = "+POut.Long(je.JournalEntryNum); Db.NonQ(command); }
///<summary></summary> public static void Update(JournalEntry je) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),je); return; } if(je.DebitAmt<0 || je.CreditAmt<0) { throw new ApplicationException(Lans.g("JournalEntries","Error. Credit and debit must both be positive.")); } Crud.JournalEntryCrud.Update(je); }
///<summary></summary> public static long Insert(JournalEntry je) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { je.JournalEntryNum=Meth.GetLong(MethodBase.GetCurrentMethod(),je); return je.JournalEntryNum; } if(je.DebitAmt<0 || je.CreditAmt<0){ throw new ApplicationException(Lans.g("JournalEntries","Error. Credit and debit must both be positive.")); } return Crud.JournalEntryCrud.Insert(je); }
///<summary></summary> public static void Delete(JournalEntry je) { if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) { Meth.GetVoid(MethodBase.GetCurrentMethod(),je); return; } //This method is only used once in synch below. Validation needs to be done, but doing it inside the loop would be dangerous. //So validation is done in the UI as follows: //1. Deleting an entire transaction is validated in business layer. //2. When editing a transaction attached to reconcile, simple view is blocked. //3. Double clicking on grid lets you change JEs not attached to reconcile. //4. Double clicking on grid lets you change notes even if attached to reconcile. string command= "DELETE FROM journalentry WHERE JournalEntryNum = "+POut.Long(je.JournalEntryNum); Db.NonQ(command); }
/*//<summary>If the journalList is 0 or 1 in length, then this function creates either 1 or 2 entries so that the simple view can display properly.</summary> private void CreateTwoEntries() { JournalEntry entry; if(JournalList.Count>=2) { return; } if(JournalList.Count==0) { //first, for account of origin entry=new JournalEntry(); entry.TransactionNum=TransCur.TransactionNum; if(textDate.Text=="" || textDate.errorProvider1.GetError(textDate)!="") { entry.DateDisplayed=DateTime.Today; } else { entry.DateDisplayed=PIn.PDate(textDate.Text); } entry.AccountNum=AccountOfOrigin.AccountNum; JournalList.Add(entry); //then, for the other entry=new JournalEntry(); entry.TransactionNum=TransCur.TransactionNum; if(textDate.Text=="" || textDate.errorProvider1.GetError(textDate)!="") { entry.DateDisplayed=DateTime.Today; } else { entry.DateDisplayed=PIn.PDate(textDate.Text); } entry.AccountNum=0; JournalList.Add(entry); return; } //otherwise, count=1 entry=new JournalEntry(); entry.TransactionNum=TransCur.TransactionNum; entry.DateDisplayed=((JournalEntry)JournalList[0]).DateDisplayed; if(((JournalEntry)JournalList[0]).AccountNum==AccountOfOrigin.AccountNum) { entry.AccountNum=0; } else { entry.AccountNum=AccountOfOrigin.AccountNum; } entry.DebitAmt=((JournalEntry)JournalList[0]).CreditAmt; entry.CreditAmt=((JournalEntry)JournalList[0]).DebitAmt; JournalList.Add(entry); }*/ ///<summary>When leaving simple view, this function takes the info from the screen and creates two journal entries. Never fails. One of the journal entries might accountNum=0, and they might both have amounts of 0. This is all in preparation for either saving or for viewing as compound.</summary> private void CreateTwoEntries(){ JournalEntry entry; //first, for account of origin entry=new JournalEntry(); entry.TransactionNum=TransCur.TransactionNum; if(textDate.Text=="" || textDate.errorProvider1.GetError(textDate)!="") { entry.DateDisplayed=DateTime.Today; } else { entry.DateDisplayed=PIn.Date(textDate.Text); } entry.AccountNum=AccountOfOrigin.AccountNum; double amt=0; if(textAmount.errorProvider1.GetError(textAmount)==""){//if no error amt=PIn.Double(textAmount.Text); } //if amt==0, then both credit and debit remain 0 if(amt>0){ if(Accounts.DebitIsPos(AccountOfOrigin.AcctType)) {//used for checking entry.DebitAmt=amt; } else { entry.CreditAmt=amt; } } else if(amt<0){ if(Accounts.DebitIsPos(AccountOfOrigin.AcctType)) {//used for checking entry.CreditAmt=-amt; } else { entry.DebitAmt=-amt; } } entry.Memo=textMemo.Text; entry.CheckNumber=textCheckNumber.Text; JournalList.Add(entry); //then, for the other entry=new JournalEntry(); entry.TransactionNum=TransCur.TransactionNum; entry.DateDisplayed=((JournalEntry)JournalList[0]).DateDisplayed; entry.DebitAmt=((JournalEntry)JournalList[0]).CreditAmt; entry.CreditAmt=((JournalEntry)JournalList[0]).DebitAmt; if(AccountPicked==null){ entry.AccountNum=0; } else{ entry.AccountNum=AccountPicked.AccountNum; } entry.Memo=textMemo.Text; entry.CheckNumber=textCheckNumber.Text; JournalList.Add(entry); }
private void butAdd_Click(object sender,EventArgs e) { JournalEntry entry=new JournalEntry(); entry.TransactionNum=TransCur.TransactionNum; if(checkMemoSame.Checked && JournalList.Count>0){ entry.Memo=((JournalEntry)JournalList[0]).Memo; } //date gets set when closing. Everthing else gets set within following form. FormJournalEntryEdit FormJ=new FormJournalEntryEdit(); FormJ.IsNew=true; FormJ.EntryCur=entry; FormJ.ShowDialog(); if(FormJ.DialogResult==DialogResult.OK) { JournalList.Add(FormJ.EntryCur); if(checkMemoSame.Checked) { for(int i=0;i<JournalList.Count;i++) { ((JournalEntry)JournalList[i]).Memo=FormJ.EntryCur.Memo; } } } FillCompound(); }
private void butCancel_Click(object sender, System.EventArgs e) { if(IsNew){ EntryCur=null; } DialogResult=DialogResult.Cancel; }
private void butDelete_Click(object sender,System.EventArgs e) { EntryCur=null; if(IsNew) { DialogResult=DialogResult.Cancel; return; } DialogResult=DialogResult.OK; }
///<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, long payNum, long newAcct,DateTime payDate, string patName) { //No need to check RemotingRole; no call to db. 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=Lans.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=Lans.g("Payments","Payment -")+" "+patName; je.Splits=Accounts.GetDescript(PrefC.GetLong(PrefName.AccountingCashIncomeAccount)); je.TransactionNum=trans.TransactionNum; JournalEntries.Insert(je); //then, the income entry je=new JournalEntry(); je.AccountNum=PrefC.GetLong(PrefName.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=Lans.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. List<JournalEntry> jeL=JournalEntries.GetForTrans(trans.TransactionNum); long 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(jeL[i].AccountNum).AcctType==AccountType.Asset) { oldAcct=jeL[i].AccountNum; } if(jeL[i].DebitAmt==absOld) { jeDebit=jeL[i]; } //old credit entry if(jeL[i].CreditAmt==absOld) { jeCredit=jeL[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>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); //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); DepositCur.Memo=PIn.String(textMemo.Text); if(IsNew){ if(gridPat.SelectedIndices.Length+gridIns.SelectedIndices.Length>18 && IsQuickBooks) { if(!MsgBox.Show(this,MsgBoxButtons.YesNo,"No more than 18 items will fit on a QuickBooks deposit slip. Continue anyway?")) { return false; } } else if(gridPat.SelectedIndices.Length+gridIns.SelectedIndices.Length>32) { if(!MsgBox.Show(this,MsgBoxButtons.YesNo,"No more than 32 items will fit on a deposit slip. Continue anyway?")) { return false; } } //Deposits.Insert(DepositCur); if(Accounts.DepositsLinked() && DepositCur.Amount>0) { if(IsQuickBooks) {//Create a deposit in QuickBooks. if(!CreateDepositQB(true)) { return false; } Deposits.Insert(DepositCur); } else { Deposits.Insert(DepositCur); //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 are not linked or deposit amount is not greater than 0. Deposits.Insert(DepositCur); } } 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, long payNum, long newAcct, DateTime payDate, string patName) { //No need to check RemotingRole; no call to db. 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 = Lans.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 = Lans.g("Payments", "Payment -") + " " + patName; je.Splits = Accounts.GetDescript(PrefC.GetLong(PrefName.AccountingCashIncomeAccount)); je.TransactionNum = trans.TransactionNum; JournalEntries.Insert(je); //then, the income entry je = new JournalEntry(); je.AccountNum = PrefC.GetLong(PrefName.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 = Lans.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. List <JournalEntry> jeL = JournalEntries.GetForTrans(trans.TransactionNum); long 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(jeL[i].AccountNum).AcctType == AccountType.Asset) { oldAcct = jeL[i].AccountNum; } if (jeL[i].DebitAmt == absOld) { jeDebit = jeL[i]; } //old credit entry if (jeL[i].CreditAmt == absOld) { jeCredit = jeL[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, long payNum, long newAcct) { //No need to check RemotingRole; no call to db. 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(Lans.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(Lans.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.")); } List <JournalEntry> jeL = JournalEntries.GetForTrans(trans.TransactionNum); long 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 < jeL.Count; i++) //we make sure down below that this count is exactly 2. { if (Accounts.GetAccount(jeL[i].AccountNum).AcctType == AccountType.Asset) { oldAcct = jeL[i].AccountNum; } if (jeL[i].DebitAmt == absOld) { jeDebit = jeL[i]; } //old credit entry if (jeL[i].CreditAmt == absOld) { jeCredit = jeL[i]; } } if (jeCredit == null || jeDebit == null) { throw new ApplicationException(Lans.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(Lans.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 (jeL.Count != 2) { throw new ApplicationException(Lans.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); }