private void PopulateDropPayouts() { int orgId = thisPayout.OrganizationId; Payouts openPayouts = Payouts.ForOrganization(Organization.FromIdentity(orgId)); this.DropPayouts.Items.Clear(); this.DropPayouts.Items.Add(new ListItem("-- Select a payout --", "0")); foreach (Payout payout in openPayouts) { if (payout.Identity != thisPayout.Identity) { this.DropPayouts.Items.Add( new ListItem( String.Format(new CultureInfo("sv-SE"), "#{0}, {1}, {2:N2}", payout.Identity, payout.Recipient, payout.Amount), payout.Identity.ToString())); } } if (openPayouts.Count < 2) { this.DropPayouts.Items.Add(new ListItem("No other open payout.", "0")); this.RadioManualMerge.Enabled = false; } }
protected void Page_Load(object sender, EventArgs e) { // Access required is change access to financials PageAccessRequired = new Access(CurrentOrganization, AccessAspect.Financials, AccessType.Write); // Get all payable items Payouts prototypePayouts = Payouts.Construct(CurrentOrganization); Payouts previousPayouts = Payouts.ForOrganization(CurrentOrganization); // gets all currently open payouts - enabled for undoing // Format as JSON and return string prototypes = FormatPrototypesAsJson(prototypePayouts); string previous = FormatPreviousAsJson(previousPayouts); string elements = (prototypes.Length > 0 && previous.Length > 0 ? prototypes + "," + previous // if both have elements, add a comma between them : prototypes + previous); // one or both strings are empty, so no comma Response.ContentType = "application/json"; string json = "{\"rows\":[" + elements + "]}"; Response.Output.WriteLine(json); Response.End(); }
private static DropdownOption[] GetOpenPayoutData(FinancialTransaction transaction) { DateTime transactionDateTime = transaction.DateTime; Int64 matchAmount = transaction.Rows.AmountCentsTotal; DropdownOptions result = new DropdownOptions(); List <DropdownOption> listExact = new List <DropdownOption>(); List <DropdownOption> listTolerant = new List <DropdownOption>(); Payouts openPayouts = Payouts.ForOrganization(transaction.Organization); foreach (Payout payout in openPayouts) { if (payout.AmountCents > -matchAmount * 95 / 100 && payout.AmountCents < -matchAmount * 105 / 100) { string description = String.Format(Resources.Pages.Ledgers.BalanceTransactions_PayoutMatch, payout.Identity, payout.ExpectedTransactionDate, payout.Recipient, payout.Organization.Currency.DisplayCode, payout.AmountCents / 100.0, payout.Specification); if (payout.AmountCents == -matchAmount) { listExact.Add(new DropdownOption { id = payout.Identity.ToString(CultureInfo.InvariantCulture), @group = Resources.Pages.Ledgers.BalanceTransactions_ExactMatches, text = description }); } else { listTolerant.Add(new DropdownOption { id = payout.Identity.ToString(CultureInfo.InvariantCulture), @group = Resources.Pages.Ledgers.BalanceTransactions_FivePercentMatches, text = description }); } } } List <DropdownOption> listCombined = new List <DropdownOption>(); listCombined.AddRange(listExact); listCombined.AddRange(listTolerant); return(listCombined.ToArray()); }
protected void Page_Load(object sender, EventArgs e) { // Access required is change access to financials PageAccessRequired = new Access(CurrentOrganization, AccessAspect.Financials, AccessType.Write); // Get all payable items Payouts prototypePayouts = Payouts.Construct(CurrentOrganization); Payouts previousPayouts = Payouts.ForOrganization(CurrentOrganization); // gets all currently open payouts - enabled for undoing // Format as JSON and return string elements = FormatPrototypesAsJson(prototypePayouts); Response.ContentType = "application/json"; string json = "{\"rows\":[" + elements + "]}"; Response.Output.WriteLine(json); Response.End(); }
private int GetOpenCount() { return(Payouts.ForOrganization(CurrentOrganization).Count); }
protected void PopulatePayouts(int organizationId) { this.GridPayouts.DataSource = Payouts.ForOrganization(Organization.FromIdentity(organizationId)); }
private OutstandingAccounts GetOutstandingExpenseClaims(bool renderPresentTime, DateTime targetDateTime) { OutstandingAccounts outstandingAccounts = new OutstandingAccounts(); if (renderPresentTime) { ExpenseClaims claims = ExpenseClaims.ForOrganization(_authenticationData.CurrentOrganization); Payouts payouts = Payouts.ForOrganization(_authenticationData.CurrentOrganization); foreach (ExpenseClaim claim in claims) { outstandingAccounts.Add(OutstandingAccount.FromExpenseClaim(claim, DateTime.MinValue)); } foreach (Payout payout in payouts) { foreach (ExpenseClaim claim in payout.DependentExpenseClaims) { outstandingAccounts.Add(OutstandingAccount.FromExpenseClaim(claim, payout.ExpectedTransactionDate)); } } } else { // This is a very expensive op. We need to load all expense claims and process them in logic, looking at their // payouts and end financial transactions, as the traceability was built to be efficient backwards (tracing money // paid out to its documentation), rather than forwards. // 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 ExpenseClaims and Payouts at the database level. // Load all (ALL) expense claims for org ExpenseClaims allClaims = ExpenseClaims.ForOrganization(_authenticationData.CurrentOrganization, true); // includes closed // For each claim, determine whether it was open or not at targetDateTime foreach (ExpenseClaim claim in allClaims) { // if it wasn't opened until after target datetime, discard if (claim.CreatedDateTime > targetDateTime) { continue; } // At this point, we are iterating over full set of expense claims opened before targetDateTime. We want the // set of claims that were still open - as determined by the ledger account Expense Claims - on targetDateTime. // // For the expense claims that are still open, this is trivially true. // // However, for others, we need to look at the corresponding Payout and its FinancialTransaction to determine // whetherthe transaction's date is on the other side of targetDateTime. bool includeThisClaim = false; DateTime dateTimeClosed = DateTime.MinValue; if (claim.Open) { includeThisClaim = true; } else { // claim is closed. This is where we need to look first at payout then at financial transaction. Payout payout = claim.Payout; if (payout == null) { // TODO: Find outbound invoice item that depends on this expense claim continue; // some legacy from when Swarmops was primitive - earliest claims don't have payouts } if (payout.Open) { // Transaction is not yet closed. Include this claim, set closed to expected-closed. includeThisClaim = true; dateTimeClosed = payout.ExpectedTransactionDate; } else { FinancialTransaction transaction = payout.FinancialTransaction; if (transaction == null) { throw new InvalidOperationException( "This should not happen (transaction not found on closed payout)"); } if (transaction.DateTime > targetDateTime) { // yes, the claim was opened before targetDateTime and closed after it. This should be included. includeThisClaim = true; dateTimeClosed = transaction.DateTime; } } // TODO: An expense claim can also be closed through an outbound invoice, in case there was a larger cash // advance that wasn't fully covered, and where the two are added together. Check for this condition as well. // // OutboundInvoiceItem should have a dependency on the expense claim if this is the case. } if (includeThisClaim) { outstandingAccounts.Add(OutstandingAccount.FromExpenseClaim(claim, dateTimeClosed)); } } } return(outstandingAccounts); }
private void PopulateDebugInfo() { debugLookup = new Dictionary <int, DebugInfoLine>(); ExpenseClaims expenseClaims = ExpenseClaims.FromOrganization(Organization.PPSE); InboundInvoices inboundInvoices = InboundInvoices.ForOrganization(Organization.PPSE); Salaries salaries = Salaries.ForOrganization(Organization.PPSE); Payouts payouts = Payouts.ForOrganization(Organization.PPSE); debugLookup[Organization.PPSE.FinancialAccounts.DebtsExpenseClaims.Identity] = new DebugInfoLine(); debugLookup[Organization.PPSE.FinancialAccounts.DebtsInboundInvoices.Identity] = new DebugInfoLine(); debugLookup[Organization.PPSE.FinancialAccounts.CostsAllocatedFunds.Identity] = new DebugInfoLine(); debugLookup[Organization.PPSE.FinancialAccounts.DebtsSalary.Identity] = new DebugInfoLine(); debugLookup[Organization.PPSE.FinancialAccounts.DebtsTax.Identity] = new DebugInfoLine(); foreach (Payout payout in payouts) { foreach (ExpenseClaim claim in payout.DependentExpenseClaims) { debugLookup[Organization.PPSE.FinancialAccounts.DebtsExpenseClaims.Identity].Payouts -= claim.Amount; } foreach (InboundInvoice invoice in payout.DependentInvoices) { debugLookup[Organization.PPSE.FinancialAccounts.DebtsInboundInvoices.Identity].Payouts -= (decimal)invoice.Amount; } foreach (Salary salary in payout.DependentSalariesNet) { debugLookup[Organization.PPSE.FinancialAccounts.DebtsSalary.Identity].Payouts -= salary.NetSalaryDecimal; } foreach (Salary salary in payout.DependentSalariesTax) { debugLookup[Organization.PPSE.FinancialAccounts.DebtsTax.Identity].Payouts -= salary.TaxTotalDecimal; } } foreach (ExpenseClaim claim in expenseClaims) { if (claim.Open) { AddExpenseToDebug(claim); } } foreach (InboundInvoice invoice in inboundInvoices) { AddInboundInvoiceToDebug(invoice); } foreach (Salary salary in salaries) { AddSalaryNetToDebug(salary); AddSalaryTaxToDebug(salary); } List <DebugInfoLine> debugInfoLines = new List <DebugInfoLine>(); foreach (int accountId in debugLookup.Keys) { debugLookup[accountId].AccountId = accountId; debugLookup[accountId].Actual = FinancialAccount.FromIdentity(accountId).GetDelta(new DateTime(2006, 1, 1), DateTime.Today.AddDays(2)); // two days to account for all possible time zones } foreach (DebugInfoLine line in debugLookup.Values) { debugInfoLines.Add(line); } this.GridDebug.DataSource = debugInfoLines; }