/// <summary> /// Fills the AccountAddress object. /// </summary> /// <param name="baseResponse"></param> public void Fill(Account account) { try { // get address. this.Fill((AccountAddress)account); DalAccount dalAccount = new DalAccount(); // now get statement informatin. CustomerAccountSchema.CustomerStatementsDataTable statements = dalAccount.GetCustomerStatements(_siteId, _siteCode, _accountNumber.AccountNumber9); // the customer statement data table returns back 1 record for each statementCode // and serviceCode. However, our return sums up these results. this means we need // to track when we have a new statement code. int previousStatementCode = -1; Statement statement = null; for (int i = 0; i < statements.Count; i++) { CustomerAccountSchema.CustomerStatement stmnt = statements[i]; int statementCode = (int)stmnt.StatementCode; // these values only change when the statement code changes. if (previousStatementCode != statementCode) { // create a new statement and add it to the account. double amountBilled = (double)stmnt.AmountBilled; Icoms1900Date lastStatementDate = new Icoms1900Date((int)stmnt.LastStatementDate); eStatementStatus statementStatus = (eStatementStatus)TypeDescriptor.GetConverter( typeof(eStatementStatus)).ConvertFrom(stmnt.Status); // ok, we care about all statements, except... if (statementStatus == eStatementStatus.Cancelled || statementStatus == eStatementStatus.Disconnect) { //we want to show cancelled or disconnected //statements that have been billed within the //last 100 days or if the statement still has //a balance. Otherwise we get the next statement if ((!lastStatementDate.SpecialDate && (DateTime.Now - lastStatementDate).Days > __statementDays) && amountBilled <= 0) { continue; //get the next statement } } // set this first off. previousStatementCode = statementCode; // need this for later. string paddedStatementCode = statementCode.ToString().PadLeft(3, '0'); // create new statement object and add it to collection. statement = new Statement(); account.Statements.Add(statement); statement.AccountNumber16 = paddedStatementCode + _accountNumber.AccountNumber13; statement.StatementCode = paddedStatementCode; statement.AmountBilled = amountBilled; statement.BillingOption = (eBillingOption)TypeDescriptor.GetConverter( typeof(eBillingOption)).ConvertFrom(stmnt.BillHandlingCode); // this is the balance outstanding net of any charges not billed. Icoms1900Date dueDate = new Icoms1900Date((int)stmnt.DueDate); statement.DueOnReceipt = dueDate.SpecialDate; statement.DueDate = dueDate.SpecialDate == true?DateTime.MinValue:(DateTime)dueDate; int mopCode = (int)stmnt.MopCode; statement.EasyPayFlag = mopCode != 0; statement.EasyPayMopType = statement.EasyPayFlag ? (ePaymentType) new MopPaymentType(_userName, mopCode) : ePaymentType.Unknown; statement.LastStatementDate = new Icoms1900Date((int)stmnt.LastStatementDate); // adjustment amounts UnappliedAmounts unappliedAmounts = dalAccount.GetUnappliedPaymentAmount( _siteId, _siteCode, _accountNumber.AccountNumber9, statementCode); statement.UnappliedPaymentAmount = unappliedAmounts.Payments; statement.UnappliedAdjustmentAmount = unappliedAmounts.NetAdjustments; statement.UnappliedDebitAdjustmentAmount = unappliedAmounts.DebitAdjustments; statement.UnappliedCreditAdjustmentAmount = unappliedAmounts.CreditAdjustments; // pending amount statement.PendingPaymentAmount = dalAccount.GetPendingPaymentAmount( _siteId, _siteCode, _accountNumber.AccountNumber9, statementCode); // now. let's start setting the fields that are a calculation of 1-N // other fields. however, we only want to set that portion of the value // that is calculated once per statement (remember GetCustomerStatements() // may return multiple records for a single statement we return to a customer) // This means if the calculated value of the field depends upon the following // items, we want to include it in our calculation here: // a) A PendingPayment // b) UnappliedDebitAdjustment // c) UnappliedCreditAdjustment // d) UnappliedNetAdjustment(net of debit and credit). // e) Any field that includes BALANCE_LAST_STATEMENT // f) Any field that includes LAST_PAYMENT_AMOUNT1,2 or 3 statement.Status = statementStatus; if (stmnt.LastPaymentDate1 > 0) { statement.RecentPayments.Add( new PaymentItem((double)stmnt.LastPaymentAmount1, new Icoms1900Date((int)stmnt.LastPaymentDate1))); } if (stmnt.LastPaymentDate2 > 0) { statement.RecentPayments.Add( new PaymentItem((double)stmnt.LastPaymentAmount2, new Icoms1900Date((int)stmnt.LastPaymentDate2))); } if (stmnt.LastPaymentDate3 > 0) { statement.RecentPayments.Add( new PaymentItem((double)stmnt.LastPaymentAmount3, new Icoms1900Date((int)stmnt.LastPaymentDate3))); } } // HERE WE WANT TO SET THOSE VALUES THAT CHANGE ON A PER RECORD // BASIS. REMEMBER THAT GetCustomerStatements() CAN RETURN MULTIPLE // RECORDS PER STATEMENT DUE TO AR AGING TRACKING AMOUNTS AT THE // PRODUCT LEVEL (E.G. CABLE, DATA, CALLING CARD, TELEPHONE). // add service code to service code collection. statement.ServiceCategories.Add((eServiceCategory)TypeDescriptor.GetConverter( typeof(eServiceCategory)).ConvertFrom(stmnt.ServiceCode)); // modify deposit due. statement.DepositDueAmount += (double)stmnt.DepositDueAmount; // next writeoffamount. statement.WriteOffAmount += (double)stmnt.WriteOffAmount; // current ar balance. statement.CurrentBalance += (double)stmnt.ArBalanceAmount; // next adjust the current bucket. statement.CurrentBucket += (double)stmnt.CurrentArBalanceAmount; // are 1-30 bucket. statement.AR1To30Amount += (double)stmnt.Ar1To30Amount; // are 31-60 bucket. statement.AR31To60Amount += (double)stmnt.Ar31To60Amount; // are 61-90 bucket. statement.AR61To90Amount += (double)stmnt.Ar61To90Amount; // are 91-120 bucket. statement.AR91To120Amount += (double)stmnt.Ar91To120Amount; // are 121-150 bucket. statement.AR121To150Amount += (double)stmnt.Ar121To150Amount; // are 150 plus bucket. statement.AR150PlusAmount += (double)stmnt.Ar150PlusAmount; } for (int j = 0; j < account.Statements.Count; j++) { Statement baseStatement = account.Statements[j]; double totalPending = baseStatement.UnappliedPaymentAmount + baseStatement.PendingPaymentAmount; // set current balance baseStatement.CurrentBalance = Math.Round(baseStatement.CurrentBalance + baseStatement.DepositDueAmount + baseStatement.WriteOffAmount + baseStatement.UnappliedAdjustmentAmount - totalPending, 2); // now set the different ar aging buckets. NOTE: I know that I am not // using all of these fields at this time; however, we are trying to // mimic the green screens and our needs may change down the road. So, // I am calculating them now so some other poor soul doesn't have to // go through it again. Also, I have set XmlIgnoreAttribute() on many // of these fields to prevent them from being streamed to our SOA clients. // if you want them to be streamed to the client merely change XmlIgnore() // to XmlAttribute("NameOfProperty"). if (totalPending > 0) { double amt = baseStatement.DepositDueAmount; bool keepGoing = netOutAmounts(ref amt, ref totalPending); baseStatement.DepositDueAmount = Math.Round(amt, 2); if (keepGoing) { amt = baseStatement.AR150PlusAmount; keepGoing = netOutAmounts(ref amt, ref totalPending); baseStatement.AR150PlusAmount = Math.Round(amt, 2); } if (keepGoing) { amt = baseStatement.AR121To150Amount; keepGoing = netOutAmounts(ref amt, ref totalPending); baseStatement.AR121To150Amount = Math.Round(amt, 2); } if (keepGoing) { amt = baseStatement.AR91To120Amount; keepGoing = netOutAmounts(ref amt, ref totalPending); baseStatement.AR91To120Amount = Math.Round(amt, 2); } if (keepGoing) { amt = baseStatement.AR61To90Amount; keepGoing = netOutAmounts(ref amt, ref totalPending); baseStatement.AR61To90Amount = Math.Round(amt, 2); } if (keepGoing) { amt = baseStatement.AR31To60Amount; keepGoing = netOutAmounts(ref amt, ref totalPending); baseStatement.AR31To60Amount = Math.Round(amt, 2); } if (keepGoing) { amt = baseStatement.AR1To30Amount; keepGoing = netOutAmounts(ref amt, ref totalPending); baseStatement.AR1To30Amount = Math.Round(amt, 2); } if (keepGoing) { baseStatement.CurrentBucket -= totalPending; } } // now modify current bucket by unapplied debit adjustments. baseStatement.CurrentBucket = Math.Round( baseStatement.CurrentBucket + baseStatement.UnappliedDebitAdjustmentAmount, 2); // now set minimumDue. baseStatement.MinimumDue = Math.Round(baseStatement.CurrentBalance - baseStatement.CurrentBucket - baseStatement.AR1To30Amount, 2); // make sure it doesn't go below 0 if (baseStatement.MinimumDue < 0) { statement.MinimumDue = 0; } } } catch (BusinessLogicLayerException) { // already handled throw; } catch (DataSourceException dse) { // not handled. need to handle throw new DataSourceUnavailableException(dse); } catch (Exception ex) { // not handled. need to handle throw new UnexpectedSystemException(ex); } }