private void PopulateCashAdvances() { CashAdvances advances = CashAdvances.ForOrganization(CurrentOrganization); foreach (CashAdvance advance in advances) { if (this._attestationRights.ContainsKey(advance.BudgetId) || advance.Budget.OwnerPersonId == Person.NobodyId) { AttestableItem item = new AttestableItem( "A" + advance.Identity.ToString(CultureInfo.InvariantCulture), advance.Person.Name, advance.AmountCents, advance.Budget, advance.Description, "Financial_CashAdvance", false, advance); if (advance.Attested) { this._attestedItems.Add(item); } else { this._items.Add(item); } } } }
private void PopulateCashAdvances() { CashAdvances advances = CashAdvances.ForOrganization(CurrentOrganization); foreach (CashAdvance advance in advances) { if (this._approvalRights.ContainsKey(advance.BudgetId) || advance.Budget.OwnerPersonId == Person.NobodyId) { ApprovableCost cost = new ApprovableCost( "A" + advance.Identity.ToString(CultureInfo.InvariantCulture), advance.Person.Name, advance.AmountCents, advance.Budget, advance.Description, "Financial_CashAdvance", false, advance); if (!advance.Attested) // if not attested { this._approvableCosts.Add(cost); } else if (!advance.PaidOut) // if attested, but still reversible { this._approvedCosts.Add(cost); } } } }
private void AddCashAdvanceAttestations(Person person, Organization organization) { CashAdvances advances = CashAdvances.ForOrganization(organization); List <int> cashAdvanceIds = new List <int>(); bool isPersonOrgAdmin = false; if (person.Identity == 1) { isPersonOrgAdmin = true; // TODO: Make more advanced, obviously } foreach (CashAdvance advance in advances) { if (advance.Attested) { continue; } bool attestable = false; if (advance.Budget.OwnerPersonId == 0 && isPersonOrgAdmin) { attestable = true; } else if (advance.Budget.OwnerPersonId == person.Identity) { attestable = true; } if (attestable) { cashAdvanceIds.Add(advance.Identity); } } if (cashAdvanceIds.Count > 0) { DashboardTodo todo = new DashboardTodo(); if (cashAdvanceIds.Count > 1) { todo.Description = String.Format(Logic_Swarm_DashboardTodos.Attest_CashAdvance_Many, Formatting.GenerateRangeString(cashAdvanceIds)); } else { todo.Description = String.Format(Logic_Swarm_DashboardTodos.Attest_CashAdvance_One, cashAdvanceIds[0]); } todo.Icon = "/Images/PageIcons/iconshock-stamped-paper-16px.png"; todo.Url = "/Pages/v5/Financial/AttestCosts.aspx"; Add(todo); } }
private OutstandingAccounts GetOutstandingCashAdvances(bool renderPresentTime, DateTime targetDateTime) { OutstandingAccounts outstandingAccounts = new OutstandingAccounts(); // This is a very expensive op. We need to load ALL the cash advances, and determine the opening date from its associated // payout. Then, we need to determine when it was paid pack through another associated payout (or invoice payment) which // I don't know how to find at the time of writing this comment, and if the target date is in between those two, then the // cash advance was outstanding on the target date (or is outstanding now) // A possible optimization could be to load the payouts into a hash table initially instead of looking them up // with two dbroundtrips per expense claim. It should be more efficient to have three dbroundtrips to load expenses, // payouts, and the relevant transactions, then stuff it all into hash tables keyed by identity and process it // in-memory. // A future optimization involves adding "ClosedDateTime" to some tables. // Load all (ALL) cash advances for org CashAdvances allCashAdvances = CashAdvances.ForOrganization(_authenticationData.CurrentOrganization, true); // includes closed // For each advance, determine whether it was open or not at targetDateTime foreach (CashAdvance cashAdvance in allCashAdvances) { // if it wasn't opened until after target datetime, discard (optimization) if (cashAdvance.CreatedDateTime > targetDateTime) { continue; } // At this point, we are iterating over full set of cash advances opened before targetDateTime, but not necessarily // paid out before targetDateTime. We want the set of advances that had been paid out, and had not been paid back, // as determined by the ledger account Cash Advances - on targetDateTime. bool includeThisAdvance = false; DateTime dateTimePaidBack = DateTime.MinValue; DateTime dateTimePaidOut = DateTime.MaxValue; if (!cashAdvance.PaidOut) { // This cash advance hasn't entered the ledger yet continue; } Payout payoutOut = cashAdvance.PayoutOut; Payout payoutBack = cashAdvance.PayoutBack; if (payoutOut == null) { continue; // This cash advance has not been paid out yet } try { dateTimePaidOut = payoutOut.FinancialTransaction.DateTime; } catch (ArgumentException) { // It's possible the payout exists, but hasn't found its transaction yet. If so, this will throw // an ArgumentException here. In either case, it's not in the ledger, so don't include it. continue; } if (dateTimePaidOut > targetDateTime) { // This cash advance falls outside the scope of our window, so ignore continue; } if (payoutBack != null) { try { dateTimePaidBack = payoutBack.FinancialTransaction.DateTime; } catch (ArgumentException) { // as above continue; } if (dateTimePaidBack > targetDateTime) { includeThisAdvance = true; } } else { // As there is no payback, this advance is paid out and still open. includeThisAdvance = true; // TODO: If there is no payout where the cash advance is deducted, it may be // invoiced to close it. // TODO: Find OutboundInvoiceItem that depends on this CashAdvance. Look at the invoice date. That's our PaidBack datetime. } if (includeThisAdvance) { outstandingAccounts.Add(OutstandingAccount.FromCashAdvance(cashAdvance, dateTimePaidOut)); } } return(outstandingAccounts); }