public decimal OnWin(decimal money, int options = 0) { Console.WriteLine("You won!"); var diff = Payouts.ThirtyFiveToOne(money) - money; return(diff); }
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 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; } }
public void MustBeAbleToFetchSinglePayout() { var config = new MerchantConfig("K500746", "fia'w2ahSheahahc", Server.Playground); var payoutsGetter = new Payouts(); var payout = payoutsGetter.GetSinglePayout("FYCK", config); Assert.IsNotNull(payout); }
protected void ButtonAutoRemap_Click(object sender, EventArgs e) { Payouts.AutomatchAgainstUnbalancedTransactions(Organization.FromIdentity(Int32.Parse(this.DropOrganizations.SelectedValue))); PopulateGrid(); PopulatePayouts(Int32.Parse(this.DropOrganizations.SelectedValue)); this.GridPayouts.Rebind(); this.GridTransactions.Rebind(); }
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()); }
private void AddPayouts(Person person, Organization organization) { TaskGroup group = new TaskGroup(TaskGroupType.Payout); TaskGroup groupUrgent = new TaskGroup(TaskGroupType.PayoutUrgently); TaskGroup groupOverdue = new TaskGroup(TaskGroupType.PayoutOverdue); if ( !person.GetAuthority() .HasPermission(Permission.CanPayOutMoney, organization.Identity, 1, Authorization.Flag.AnyGeographyExactOrganization)) { return; } Payouts payouts = Payouts.Construct(organization); foreach (Payout payout in payouts) { group.Tasks.Add(new TaskPayout(payout)); if (payout.DependentInvoices.Count > 0) { if (payout.ExpectedTransactionDate < DateTime.Today) { groupOverdue.Tasks.Add(new TaskPayout(payout)); } else if (payout.ExpectedTransactionDate < DateTime.Today.AddDays(7)) { groupUrgent.Tasks.Add(new TaskPayout(payout)); } } } if (group.Tasks.Count > 0) { Add(group); } if (groupUrgent.Tasks.Count > 0) { Add(groupUrgent); } if (groupOverdue.Tasks.Count > 0) { Add(groupOverdue); } }
private string FormatPreviousAsJson(Payouts payouts) { StringBuilder result = new StringBuilder(16384); foreach (Payout payout in payouts) { PaymentTransferInfo transferInfo = payout.PaymentTransferInfo; result.Append("{"); result.AppendFormat( "\"itemId\":\"{7}\"," + "\"paid\":\"yes\"," + "\"databaseId\":\"{8}\"," + "\"due\":\"{1}\"," + "\"recipient\":\"{2}\"," + "\"transferInfo\":\"{3}\"," + "\"amount\":\"{6}\"," + "\"ocrAvailable\":\"{4}\"," + "\"action\":\"" + "<img id='IconApproval{7}' class='IconApproval{7} LocalIconApproval LocalPaid action-icon' baseid='{7}' protoid='{0}' databaseid='{8}' data-ocr='{10}' data-fieldcount='{9}' data-reference='{5}' />" + "<img class='IconApproved{7} LocalIconApproved LocalPaid status-icon' baseid='{7}' />" + "<img class='IconWait{7} LocalIconWait LocalPaid status-icon' baseid='{7}' />" + "<img class='IconUndo{7} LocalIconUndo LocalPaid action-icon' baseid='{7}' />" + "<img class='IconDenial{7} LocalIconDenial LocalPaid action-icon' baseid='{7}' />" + "<img class='IconDenied{7} LocalIconDenied LocalPaid status-icon' baseid='{7}' />" + "\"", payout.ProtoIdentity, payout.ExpectedTransactionDate.ToShortDateString(), JsonSanitize(TryLocalize(transferInfo.Recipient)), transferInfo.Currency.Code + ", " + JsonSanitize(transferInfo.LocalizedPaymentMethodName), transferInfo.OcrAvailable ? "<img class='LocalIconOcr status-icon' />" : string.Empty, JsonSanitize(TryLocalize(payout.Reference)), payout.AmountCents / 100.0, payout.ProtoIdentity.Replace("|", ""), payout.Identity, transferInfo.LocalizedPaymentInformation.Count, transferInfo.OcrAvailable ? "yes" : "no"); result.Append("},"); } if (result.Length > 0) { result.Remove(result.Length - 1, 1); // remove last comma, if there are any elements } return(result.ToString()); }
public void MustBePossibleToGetPayouts() { var config = new MerchantConfig("K500746", "fia'w2ahSheahahc", Server.Playground); PayoutRequest req = new PayoutRequest { CurrencyCode = "EUR", EndDate = DateTime.Now.Date.ToShortDateString(), StartDate = DateTime.Now.Subtract(new TimeSpan(1000, 0, 0, 0)).ToShortDateString(), Offset = 0, Size = 10 }; var payoutsGetter = new Payouts(); var listOfPayouts = payoutsGetter.GetPayouts(req, config); Assert.IsNotNull(listOfPayouts); }
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 payouts = Payouts.Construct(CurrentOrganization); // Format as JSON and return Response.ContentType = "application/json"; string json = FormatAsJson(payouts); Response.Output.WriteLine(json); Response.End(); }
private string FormatPreviousAsJson(Payouts payouts) { StringBuilder result = new StringBuilder(16384); DateTime today = DateTime.Today; foreach (Payout payout in payouts) { result.Append("{"); result.AppendFormat( "\"itemId\":\"{0}\"," + "\"databaseId\":\"{8}\"," + "\"due\":\"{1}\"," + "\"recipient\":\"{2}\"," + "\"bank\":\"{3}\"," + "\"account\":\"{4}\"," + "\"reference\":\"{5}\"," + "\"amount\":\"{6:N2}\"," + "\"action\":\"" + "<img id=\\\"IconApproval{7}\\\" class=\\\"IconApproval{7} LocalIconApproval LocalPrevious\\\" databaseid=\\\"{8}\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconApproved{7} LocalIconApproved LocalPrevious\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconDenial{7} LocalIconDenial LocalPrevious\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconDenied{7} LocalIconDenied LocalPrevious\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconUndo{7} LocalIconUndo LocalPrevious\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "\"", payout.ProtoIdentity, payout.ExpectedTransactionDate.ToShortDateString(), JsonSanitize(TryLocalize(payout.Recipient)), JsonSanitize(payout.Bank), JsonSanitize(payout.Account), JsonSanitize(TryLocalize(payout.Reference)), payout.AmountCents / 100.0, payout.ProtoIdentity.Replace("|", ""), payout.Identity); result.Append("},"); } if (result.Length > 0) { result.Remove(result.Length - 1, 1); // remove last comma, if there are any elements } return(result.ToString()); }
private string FormatAsJson(Payouts payouts) { StringBuilder result = new StringBuilder(16384); string hasDoxString = "<img src=\\\"/Images/PageIcons/iconshock-battery-drill-16px.png\\\" onmouseover=\\\"this.src='/Images/PageIcons/iconshock-battery-drill-16px.png';\\\" onmouseout=\\\"this.src='/Images/PageIcons/iconshock-battery-drill-16px.png';\\\" onclick=\\\"alert('Under construction');\\\" style=\\\"cursor:pointer\\\" />"; result.Append("{\"rows\":["); DateTime today = DateTime.Today; foreach (Payout payout in payouts) { result.Append("{"); result.AppendFormat( "\"itemId\":\"{0}\"," + "\"due\":\"{1}\"," + "\"recipient\":\"{2}\"," + "\"bank\":\"{3}\"," + "\"account\":\"{4}\"," + "\"reference\":\"{5}\"," + "\"amount\":\"{6:N2}\"," + "\"action\":\"" + "<img id=\\\"IconApproval{7}\\\" class=\\\"LocalIconApproval\\\" baseid=\\\"{0}\\\" height=\\\"16\\\" width=\\\"16\\\" />" + "<img id=\\\"IconApproved{7}\\\" class=\\\"LocalIconApproved\\\" baseid=\\\"{0}\\\" height=\\\"16\\\" width=\\\"16\\\" />\"", payout.ProtoIdentity, (payout.ExpectedTransactionDate <= today? Resources.Global.Global_ASAP: payout.ExpectedTransactionDate.ToShortDateString()), JsonSanitize(TryLocalize(payout.Recipient)), JsonSanitize(payout.Bank), JsonSanitize(payout.Account), JsonSanitize(TryLocalize(payout.Reference)), payout.AmountCents/100.0, payout.ProtoIdentity.Replace("|", "")); result.Append("},"); } result.Remove(result.Length - 1, 1); // remove last comma result.Append("]}"); return result.ToString(); }
public decimal OnWin(decimal money, int option) { decimal diff = 0; Console.WriteLine("You won!"); if (option == 17) { diff += Payouts.SeventeenToOne(money) - money; } else if (option == 11) { diff += Payouts.ElevenToOne(money) - money; } else if (option == 8) { diff += Payouts.EightToOne(money) - money; } return(diff); }
private string FormatAsJson(Payouts payouts) { StringBuilder result = new StringBuilder(16384); result.Append("{\"rows\":["); DateTime today = DateTime.Today; foreach (Payout payout in payouts) { result.Append("{"); result.AppendFormat( "\"itemId\":\"{0}\"," + "\"due\":\"{1}\"," + "\"recipient\":\"{2}\"," + "\"bank\":\"{3}\"," + "\"account\":\"{4}\"," + "\"reference\":\"{5}\"," + "\"amount\":\"{6:N2}\"," + "\"action\":\"" + "<img id=\\\"IconApproval{7}\\\" class=\\\"LocalIconApproval\\\" baseid=\\\"{0}\\\" height=\\\"16\\\" width=\\\"16\\\" />" + "<img id=\\\"IconApproved{7}\\\" class=\\\"LocalIconApproved\\\" baseid=\\\"{0}\\\" height=\\\"16\\\" width=\\\"16\\\" />\"", payout.ProtoIdentity, (payout.ExpectedTransactionDate <= today ? Global.Global_ASAP : payout.ExpectedTransactionDate.ToShortDateString()), JsonSanitize(TryLocalize(payout.Recipient)), JsonSanitize(payout.Bank), JsonSanitize(payout.Account), JsonSanitize(TryLocalize(payout.Reference)), payout.AmountCents / 100.0, payout.ProtoIdentity.Replace("|", "")); result.Append("},"); } result.Remove(result.Length - 1, 1); // remove last comma result.Append("]}"); return(result.ToString()); }
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(); }
protected void Page_Load(object sender, EventArgs e) { this.PageAccessRequired = new Access(this.CurrentOrganization, AccessAspect.Bookkeeping, AccessType.Write); this.PageTitle = "Debug Ledgers"; this.PageIcon = "iconshock-tester"; // Initialize by mapping all // TODO: If this O(n^2) matching becomes teh suckage, optimize using hashtables over amounts Payouts.AutomatchAgainstUnbalancedTransactions(this.CurrentOrganization); // Iterate over all open payment groups and try to map them to unbalanced transactions FinancialTransactions unbalancedTransactions = FinancialTransactions.GetUnbalanced(this.CurrentOrganization); // TODO: this fn should move to Organization PaymentGroups openGroups = PaymentGroups.ForOrganization(this.CurrentOrganization, false); foreach (PaymentGroup openGroup in openGroups) { openGroup.MapTransaction(unbalancedTransactions); } }
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; }
protected void ProcessImportedData(ImportResult import) { FinancialAccount assetAccount = FinancialAccount.FromIdentity(Int32.Parse(this.DropAssetAccount.SelectedValue)); FinancialAccount autoDepositAccount = FinancialAccount.FromIdentity(Int32.Parse(this.DropAutoDeposits.SelectedValue)); FinancialAccount autoWithdrawalAccount = FinancialAccount.FromIdentity(Int32.Parse(this.DropAutoWithdrawals.SelectedValue)); int autoDepositLimit = Int32.Parse(this.TextDepositLimit.Text); int autoWithdrawalLimit = Int32.Parse(this.TextWithdrawalLimit.Text); int organizationId = Int32.Parse(this.DropOrganizations.SelectedValue); Organization organization = Organization.FromIdentity(organizationId); int importedTransactionCount = 0; foreach (ImportedRow row in import.Rows) { // Each row is at least a stub, probably more. // If too old, ignore. if (row.DateTime < new DateTime(2008, 12, 4)) { continue; } string importKey = row.SuppliedTransactionId; // If importKey is empty, construct a hash from the data fields. if (string.IsNullOrEmpty(importKey)) { string hashKey = row.HashBase + row.Comment + (row.AmountCentsNet / 100.0).ToString(CultureInfo.InvariantCulture) + row.CurrentBalance.ToString(CultureInfo.InvariantCulture) + row.DateTime.ToString("yyyy-MM-dd-hh-mm-ss"); importKey = SHA1.Hash(hashKey).Replace(" ", ""); } if (importKey.Length > 30) { importKey = importKey.Substring(0, 30); } Int64 amountCents = row.AmountCentsNet; if (amountCents == 0) { amountCents = row.AmountCentsGross; } FinancialTransaction transaction = FinancialTransaction.ImportWithStub(organizationId, row.DateTime, assetAccount.Identity, amountCents, row.Comment, importKey, _currentUser.Identity); if (transaction != null) { // The transaction was created. Examine if the autobook criteria are true. importedTransactionCount++; FinancialAccounts accounts = FinancialAccounts.FromBankTransactionTag(row.Comment); if (accounts.Count == 1) { // This is a labelled local donation. Geography geography = accounts[0].AssignedGeography; FinancialAccount localAccount = accounts[0]; transaction.AddRow(organization.FinancialAccounts.IncomeDonations, -amountCents, _currentUser); transaction.AddRow(organization.FinancialAccounts.CostsLocalDonationTransfers, amountCents, _currentUser); transaction.AddRow(localAccount, -amountCents, _currentUser); Activizr.Logic.Support.PWEvents.CreateEvent(EventSource.PirateWeb, EventType.LocalDonationReceived, _currentUser.Identity, organizationId, geography.Identity, 0, transaction.Identity, localAccount.Identity.ToString()); } else if (row.Comment.ToLowerInvariant().StartsWith("bg 451-0061 ")) // TODO: Organization.Parameters.FinancialTrackedTransactionPrefix { // Check for previously imported payment group PaymentGroup group = PaymentGroup.FromTag(organization, "SEBGM" + DateTime.Today.Year.ToString() + // TODO: Get tagging from org row.Comment.Substring(11)); if (group != null) { // There was a previously imported and not yet closed payment group matching this transaction // Close the payment group and match the transaction against accounts receivable transaction.Dependency = group; group.Open = false; transaction.AddRow(organization.FinancialAccounts.AssetsOutboundInvoices, -amountCents, _currentUser); } } else if (amountCents < 0) { if ((-amountCents) < autoWithdrawalLimit * 100) { // Book against autoWithdrawal account. transaction.AddRow(autoWithdrawalAccount, -amountCents, _currentUser); } } else if (amountCents > 0) { if (row.Fee < 0) { // This is always an autodeposit, if there is a fee (which is never > 0.0) transaction.AddRow(organization.FinancialAccounts.CostsBankFees, -row.Fee, _currentUser); transaction.AddRow(autoDepositAccount, -row.AmountCentsGross, _currentUser); } else if (amountCents < autoDepositLimit * 100) { // Book against autoDeposit account. transaction.AddRow(autoDepositAccount, -amountCents, _currentUser); } } } } // Import complete. Examine if we expect more transactions -- if the imported balance differs from // the database balance: double databaseAccountBalance = assetAccount.BalanceTotal; bool mismatch = false; if (databaseAccountBalance != import.CurrentBalance) { mismatch = true; } string message = importedTransactionCount.ToString() + " transactions were imported."; if (importedTransactionCount == 0) { message = "No transactions were imported. "; } else if (importedTransactionCount == 1) { message = "One transaction was imported. "; } if (import.CurrentBalance > 0) { if (mismatch) { message += " Transactions are missing from the database. Import more transactions."; } else { message += " The account balance is up to date. No further import is necessary."; ScriptManager.RegisterStartupScript(this, Page.GetType(), "alldone", "alert ('The account balance is up to date. No further import is necessary.');", true); // Auto-match open payouts against new transactions Payouts.AutomatchAgainstUnbalancedTransactions(organization); } } this.LabelImportResultText.Text = message; }
protected void PopulatePayouts(int organizationId) { this.GridPayouts.DataSource = Payouts.ForOrganization(Organization.FromIdentity(organizationId)); }
private string FormatPrototypesAsJson(Payouts payouts) { StringBuilder result = new StringBuilder(16384); DateTime today = DateTime.Today; bool bitcoinHotWalletActive = (this.CurrentOrganization.FinancialAccounts.AssetsBitcoinHot != null ? true : false); foreach (Payout payout in payouts) { if (bitcoinHotWalletActive && payout.RecipientPerson != null && payout.RecipientPerson.BitcoinPayoutAddress.Length > 0 && payout.Account.Length < 4) // 4 because an empty account will be " / ", length 3 { // This is a person who will be paid in bitcoin per personal preferences, so don't show for manual payout continue; } if (bitcoinHotWalletActive && payout.Account.StartsWith("bitcoin:")) { // This is a payout registered to be paid in bitcoin, so don't show for manual payout continue; } result.Append("{"); result.AppendFormat( "\"itemId\":\"{0}\"," + "\"due\":\"{1}\"," + "\"recipient\":\"{2}\"," + "\"bank\":\"{3}\"," + "\"account\":\"{4}\"," + "\"reference\":\"{5}\"," + "\"amount\":\"{6:N2}\"," + "\"action\":\"" + "<img id=\\\"IconApproval{7}\\\" class=\\\"IconApproval{7} LocalIconApproval LocalPrototype\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconApproved{7} LocalIconApproved LocalPrototype\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconDenial{7} LocalIconDenial LocalPrototype\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconDenied{7} LocalIconDenied LocalPrototype\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconUndo{7} LocalIconUndo LocalPrototype\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "\"", payout.ProtoIdentity, (payout.ExpectedTransactionDate <= today ? Global.Global_ASAP : payout.ExpectedTransactionDate.ToShortDateString()), JsonSanitize(TryLocalize(payout.Recipient)), JsonSanitize(TryLocalize(payout.Bank)), JsonSanitize(payout.Account), JsonSanitize(TryLocalize(payout.Reference)), payout.AmountCents / 100.0, payout.ProtoIdentity.Replace("|", "")); result.Append("},"); } if (result.Length > 0) { result.Remove(result.Length - 1, 1); // remove last comma, if there are any elements } return(result.ToString()); }
private string FormatPrototypesAsJson(Payouts payouts) { StringBuilder result = new StringBuilder(16384); DateTime today = DateTime.Today; bool bitcoinHotWalletActive = (this.CurrentOrganization.FinancialAccounts.AssetsBitcoinHot != null ? true : false); foreach (Payout payout in payouts) { if (bitcoinHotWalletActive && payout.RecipientPerson != null && payout.RecipientPerson.BitcoinPayoutAddress.Length > 0 && payout.Account.Length < 4) // 4 because an empty account will be " / ", length 3 { // This is a person who will be paid in bitcoin per personal preferences, so don't show for manual payout continue; } if (bitcoinHotWalletActive && payout.Account.StartsWith("bitcoin:")) { // This is a payout registered to be paid in bitcoin, so don't show for manual payout continue; } if (payout.Reference.Length < 2) { continue; // must have at least a reference and a checksum - two digits minimum } if (!Formatting.CheckLuhnChecksum(payout.Reference)) { // invalid checksum continue; } if (!Formatting.CheckLuhnChecksum(payout.Account)) { continue; } result.Append("{"); result.AppendFormat( "\"itemId\":\"{0}\"," + "\"due\":\"{1}\"," + "\"reference\":\"<span class='ocrFont'>{2}</span>\"," + "\"amount\":\"<span class='ocrFont'>{3}</span>\"," + "\"account\":\"<span class='ocrFont'>{4}</span>\"," + "\"action\":\"" + "<img class=\\\"IconApproval{5} LocalIconApproval LocalPrototype\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconApproved{5} LocalIconApproved LocalPrototype\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconDenial{5} LocalIconDenial LocalPrototype\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconDenied{5} LocalIconDenied LocalPrototype\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "<img class=\\\"IconUndo{5} LocalIconUndo LocalPrototype\\\" baseid=\\\"{0}\\\" height=\\\"18\\\" width=\\\"24\\\" />" + "\"", payout.ProtoIdentity, (payout.ExpectedTransactionDate <= today ? Global.Global_ASAP : payout.ExpectedTransactionDate.ToShortDateString()), GetReferenceOcr(payout), GetAmountOcr(payout), GetAccountOcr(payout), payout.ProtoIdentity.Replace("|", "")); result.Append("},"); } if (result.Length > 0) { result.Remove(result.Length - 1, 1); // remove last comma, if there are any elements } return(result.ToString()); }
private void PopulateGrid() { Payouts payouts = Payouts.Construct(Organization.PPSEid); this.GridPayouts.DataSource = payouts; }
private static string GetDependencyString(params object[] payoutParams) { // This should be moved to some sort of interface layer for localization. List <int> expenseClaimIdentities = new List <int>(); List <int> invoiceIdentities = new List <int>(); List <int> salaryNetIdentities = new List <int>(); List <int> salaryTaxIdentities = new List <int>(); Payouts allPayouts = new Payouts(); foreach (object parameter in payoutParams) { if (parameter is Payout) { allPayouts.Add((Payout)parameter); } if (parameter is Payouts) { foreach (Payout payout in (Payouts)parameter) { allPayouts.Add(payout); } } } foreach (Payout payout in allPayouts) { expenseClaimIdentities.AddRange(payout.DependentExpenseClaims.Identities); invoiceIdentities.AddRange(payout.DependentInvoices.Identities); salaryNetIdentities.AddRange(payout.DependentSalariesNet.Identities); salaryTaxIdentities.AddRange(payout.DependentSalariesTax.Identities); } List <string> parts = new List <string>(); if (expenseClaimIdentities.Count > 0) { parts.Add(GenerateDependencyPart("Expense Claim", "Expense Claims", expenseClaimIdentities)); } if (invoiceIdentities.Count > 0) { parts.Add(GenerateDependencyPart("Invoice", "Invoices", invoiceIdentities)); } if (salaryNetIdentities.Count > 0) { parts.Add(GenerateDependencyPart("Salary Net", "Salaries Net", salaryNetIdentities)); } if (salaryTaxIdentities.Count > 0) { parts.Add(GenerateDependencyPart("Salary Tax", "Salaries Tax", salaryTaxIdentities)); } if (parts.Count == 0) { return("Nothing"); } string result = string.Empty; for (int index = 0; index < parts.Count - 1; index++) { result += ", " + parts[index]; } if (parts.Count > 2) { result += ","; } if (parts.Count > 1) { result = result.Substring(2) + " and "; } result += parts[parts.Count - 1]; return(result); }
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 static void OnEveryHour() { try { BotLog.Write(0, "MainCycle", "One-hour entry"); try { // This will upgrade the database schema if and only if we failed to do so on entry. if (SwarmDb.DbVersion < SwarmDb.DbVersionExpected) { BotLog.Write(1, "OneHour", "Entering DbUpgrade"); DatabaseMaintenance.UpgradeSchemata(); BotLog.Write(1, "OneHour", "Exited DbUpgrade"); } } catch (Exception e) { TraceAndReport(e); } try { BotLog.Write(1, "OneHour", "Entering Automatch"); Organizations organizations = Organizations.GetAll(); foreach (Organization organization in organizations) { if (organization.IsEconomyEnabled) { BotLog.Write(1, "OneHour", "Automatching org #" + organization.Identity.ToString(CultureInfo.InvariantCulture)); Payouts.AutomatchAgainstUnbalancedTransactions(organization); } } BotLog.Write(1, "OneHour", "Exited Automatch"); /*TestTrace("Running PaymentGroupMapper.Run()..."); * PaymentGroupMapper.Run(); * TestTrace(" done.\r\n");*/ } catch (Exception e) { TraceAndReport(e); } try { /*TestTrace("Running BlogTop50Scraper.Run()..."); * BlogTop50Scraper.Run(); * TestTrace(" done.\r\n");*/ } catch (Exception e) { TraceAndReport(e); } try { /*TestTrace("Running Mappery.CreatePiratpartietOrganizationStrengthCircuitMap()..."); * Mappery.CreatePiratpartietOrganizationStrengthCircuitMap(); * TestTrace(" done.\r\n");*/ } catch (Exception e) { TraceAndReport(e); } try { /*TestTrace("Running Mappery.CreatePiratpartietOrganizationStrengthCityMap()..."); * Mappery.CreatePiratpartietOrganizationStrengthCityMap(); * TestTrace(" done.\r\n");*/ } catch (Exception e) { TraceAndReport(e); } BotLog.Write(0, "MainCycle", "One-hour exit"); } catch (Exception e) { TraceAndReport(e); } }
protected void Page_Load(object sender, EventArgs e) { FinancialAccount bankAccount = FinancialAccount.FromIdentity(29); Organization euroPirates = Organization.FromIdentity(7); FinancialTransactions unbalancedTransactions = FinancialTransactions.GetUnbalanced(euroPirates); // assume all in bank account foreach (FinancialTransaction transaction in unbalancedTransactions) { if (transaction.Description[0] == 'H' && Char.IsDigit(transaction.Description[1]) && transaction.Rows.BalanceCentsDelta > 0) { // outbound intl invoice. Add an untracked intl invoice 10 days prior, map it to this OutboundInvoice newInvoice = OutboundInvoice.Create(euroPirates, transaction.DateTime, euroPirates.FinancialAccounts.IncomeSales, "Untracked", "*****@*****.**", string.Empty, euroPirates.Currency, false, string.Empty, Person.FromIdentity(1)); newInvoice.AddItem("Untracked item", transaction.Rows.BalanceCentsDelta); // Doesn't close // Add transaction // Create the financial transaction with rows FinancialTransaction invoiceTransaction = FinancialTransaction.Create(euroPirates.Identity, transaction.DateTime.AddDays(-10), "Outbound Invoice #" + newInvoice.Identity); invoiceTransaction.AddRow(euroPirates.FinancialAccounts.AssetsOutboundInvoices, newInvoice.AmountCents, null); invoiceTransaction.AddRow(euroPirates.FinancialAccounts.IncomeSales, -newInvoice.AmountCents, null); invoiceTransaction.Dependency = newInvoice; transaction.AddRow(euroPirates.FinancialAccounts.AssetsOutboundInvoices, -newInvoice.AmountCents, null); Payment payment = Payment.CreateSingle(euroPirates, transaction.DateTime, euroPirates.Currency, newInvoice.AmountCents, newInvoice, null); transaction.Dependency = payment.Group; payment.Group.Open = false; } if ((transaction.Description == "Kostnad" || transaction.Description == "Bank charges") && transaction.Rows.BalanceCentsDelta < 0 && transaction.Rows.BalanceCentsDelta > -125000) { // Bank fee. transaction.AddRow(euroPirates.FinancialAccounts.CostsBankFees, -transaction.Rows.BalanceCentsDelta, null); } if (transaction.Description.StartsWith("Paypal ")) { // Bank fee. transaction.AddRow(euroPirates.FinancialAccounts.CostsBankFees, -transaction.Rows.BalanceCentsDelta, null); } } Payouts.AutomatchAgainstUnbalancedTransactions(euroPirates); }
public string[] GetSelectedPayouts(PayoutState state) { return(Payouts.Where(model => model.Selected).Select(model => model.PayoutId) .ToArray()); }
private int GetOpenCount() { return(Payouts.ForOrganization(CurrentOrganization).Count); }
private string FormatPrototypesAsJson(Payouts payouts) { StringBuilder result = new StringBuilder(16384); DateTime today = DateTime.Today; bool bitcoinHotWalletActive = (this.CurrentOrganization.FinancialAccounts.AssetsBitcoinHot != null ? true : false); foreach (Payout payout in payouts) { if (bitcoinHotWalletActive && payout.RecipientPerson != null && payout.RecipientPerson.BitcoinPayoutAddress.Length > 0 && payout.Account.Length < 4) // 4 because an empty account will be " / ", length 3 { // This is a person who will be paid in bitcoin per personal preferences, so don't show for manual payout continue; } if (bitcoinHotWalletActive && payout.Account.StartsWith("bitcoin:")) { // This is a payout registered to be paid in bitcoin, so don't show for manual payout continue; } PaymentTransferInfo transferInfo = payout.PaymentTransferInfo; result.Append("{"); result.AppendFormat( "\"itemId\":\"{7}\"," + "\"due\":\"{1}\"," + "\"recipient\":\"{2}\"," + "\"transferInfo\":\"{3}\"," + "\"amount\":\"{6}\"," + "\"ocrAvailable\":\"{4}\"," + "\"action\":\"" + "<img id='IconApproval{7}' class='IconApproval{7} LocalIconApproval LocalPrototype action-icon' baseid='{7}' protoid='{0}' data-ocr='{10}' data-fieldcount='{9}' data-reference='{5}' />" + "<img id='IconApproved{7}' class='LocalIconApproved LocalPrototype status-icon' baseid='{7}' />" + "<img id='IconWait{7}' class='LocalIconWait LocalPrototype status-icon' baseid='{7}' />" + "<img id='IconUndo{7}' class='LocalIconUndo LocalPrototype action-icon' baseid='{7}' />" + "<img id='IconDenial{7}' class='LocalIconDenial LocalPrototype action-icon' baseid='{7}' />" + "<img id='IconDenied{7}' class='LocalIconDenied LocalPrototype status-icon' baseid='{7}' />" + "\"", payout.ProtoIdentity, (payout.ExpectedTransactionDate <= today ? Global.Global_ASAP : payout.ExpectedTransactionDate.ToShortDateString()), JsonSanitize(TryLocalize(transferInfo.Recipient)), transferInfo.Currency.Code + ", " + JsonSanitize(transferInfo.LocalizedPaymentMethodName), transferInfo.OcrAvailable? "<img class='LocalIconOcr status-icon' />": string.Empty, JsonSanitize(TryLocalize(payout.Reference)), payout.HasNativeAmount? payout.NativeAmountString : (payout.AmountCents / 100.0).ToString("N2"), payout.ProtoIdentity.Replace("|", ""), string.Empty, // this is here to match the databaseid field below transferInfo.LocalizedPaymentInformation.Count, transferInfo.OcrAvailable? "yes": "no"); result.Append("},"); } if (result.Length > 0) { result.Remove(result.Length - 1, 1); // remove last comma, if there are any elements } return(result.ToString()); }
private static void OnEveryFiveMinutes() { try { BotLog.Write(0, "MainCycle", "Five-minute entry"); try { // BotLog.Write(1, "FiveMinute", "Starting automated payout processing"); Payouts.PerformAutomated(BitcoinChain.Cash); } catch (Exception e) { TraceAndReport(e); } try { /*BotLog.Write(1, "FiveMinute", "Starting newsletter checker"); * TestTrace("Running NewsletterChecker.Run()..."); * NewsletterChecker.Run(); * TestTrace(" done.\r\n");*/ } catch (Exception e) { TraceAndReport(e); } try { /*BotLog.Write(1, "FiveMinute", "Starting turnaround tracker"); * TestTrace("Running TurnaroundTracker.Run()..."); * TurnaroundTracker.Run(); * TestTrace(" done.\r\n");*/ } catch (Exception e) { TraceAndReport(e); } try { // TestTrace(" done.\r\nRunning UpdateStatsCache.Run()..."); // UpdateStatsCache.Run(); /*TestTrace(" done.\r\nRunning TranslateUrls()..."); * TranslateUrls();*/ // Added during election rush 2010: clean up support database every five minutes instead of once a day // SMS notifications for bounces are turned off, so people don't get SMS notifications in the middle of the night } catch (Exception e) { TraceAndReport(e); } try { /*BotLog.Write(1, "FiveMinute", "Closing delay warnings"); * TestTrace("Running SupportDatabase.CloseDelayWarnings()..."); * SupportDatabase.CloseDelayWarnings(); * TestTrace(" done.\r\n");*/ } catch (Exception e) { TraceAndReport(e); } try { /*TestTrace("Running SupportDatabase.NotifyBouncingEmails()..."); * BotLog.Write(1, "FiveMinute", "Notifying bouncing emails"); * SupportDatabase.NotifyBouncingEmails(); * TestTrace(" done.\r\n");*/ } catch (Exception e) { TraceAndReport(e); } try { /*TestTrace("Running SupportMailReview.Run()..."); * BotLog.Write(1, "FiveMinute", "Running support mail review"); * SupportMailReview.Run(); * TestTrace(" done.\r\n");*/ } catch (Exception e) { TraceAndReport(e); } BotLog.Write(0, "MainCycle", "Five-minute exit"); } catch (Exception e) { ExceptionMail.Send(e, true); TestTrace(e.ToString()); } }
private void AddPayouts(Person person, Organization organization) { if (!person.HasAccess(new Access(organization, AccessAspect.Financials, AccessType.Write))) { return; // do not add this if can't pay out } DashboardTodo todoNormal = new DashboardTodo(); DashboardTodo todoUrgent = new DashboardTodo(); DashboardTodo todoOverdue = new DashboardTodo(); todoNormal.Url = todoUrgent.Url = todoOverdue.Url = "/Pages/v5/Financial/PayOutMoney.aspx"; todoNormal.Icon = todoUrgent.Icon = todoOverdue.Icon = "/Images/PageIcons/iconshock-money-envelope-16px.png"; int payoutCount = 0; int urgentPayoutCount = 0; int overduePayoutCount = 0; Payouts payouts = Payouts.Construct(organization); foreach (Payout payout in payouts) { payoutCount++; if (payout.DependentInvoices.Count > 0) { if (payout.ExpectedTransactionDate < DateTime.Today) { overduePayoutCount++; } else if (payout.ExpectedTransactionDate < DateTime.Today.AddDays(7)) { urgentPayoutCount++; } } } if (payoutCount > 0) { todoNormal.Description = payoutCount > 1 ? String.Format(App_GlobalResources.Logic_Swarm_DashboardTodos.Payout_Many, payoutCount) : App_GlobalResources.Logic_Swarm_DashboardTodos.Payout_One; this.Add(todoNormal); } if (overduePayoutCount > 0) { todoOverdue.Description = overduePayoutCount > 1 ? String.Format(App_GlobalResources.Logic_Swarm_DashboardTodos.Payout_Overdue_Many, payoutCount) : App_GlobalResources.Logic_Swarm_DashboardTodos.Payout_Overdue_One; todoOverdue.Urgency = TodoUrgency.Red; this.Add(todoOverdue); } if (urgentPayoutCount > 0) { todoUrgent.Description = overduePayoutCount > 1 ? String.Format(App_GlobalResources.Logic_Swarm_DashboardTodos.Payout_Urgent_Many, payoutCount) : App_GlobalResources.Logic_Swarm_DashboardTodos.Payout_Urgent_One; todoUrgent.Urgency = TodoUrgency.Yellow; this.Add(todoUrgent); } }
private static string GetDependencyString(params object[] payoutParams) { // This should be moved to some sort of interface layer for localization. List<int> expenseClaimIdentities = new List<int>(); List<int> invoiceIdentities = new List<int>(); List<int> salaryNetIdentities = new List<int>(); List<int> salaryTaxIdentities = new List<int>(); Payouts allPayouts = new Payouts(); foreach (object parameter in payoutParams) { if (parameter is Payout) { allPayouts.Add((Payout) parameter); } if (parameter is Payouts) { foreach (Payout payout in (Payouts)parameter) { allPayouts.Add(payout); } } } foreach (Payout payout in allPayouts) { expenseClaimIdentities.AddRange(payout.DependentExpenseClaims.Identities); invoiceIdentities.AddRange(payout.DependentInvoices.Identities); salaryNetIdentities.AddRange(payout.DependentSalariesNet.Identities); salaryTaxIdentities.AddRange(payout.DependentSalariesTax.Identities); } List<string> parts = new List<string>(); if (expenseClaimIdentities.Count > 0) { parts.Add(GenerateDependencyPart("Expense Claim", "Expense Claims", expenseClaimIdentities)); } if (invoiceIdentities.Count > 0) { parts.Add(GenerateDependencyPart("Invoice", "Invoices", invoiceIdentities)); } if (salaryNetIdentities.Count > 0) { parts.Add(GenerateDependencyPart("Salary Net", "Salaries Net", salaryNetIdentities)); } if (salaryTaxIdentities.Count > 0) { parts.Add(GenerateDependencyPart("Salary Tax", "Salaries Tax", salaryTaxIdentities)); } if (parts.Count == 0) { return "Nothing"; } string result = string.Empty; for (int index = 0; index < parts.Count - 1; index++) { result += ", " + parts[index]; } if (parts.Count > 2) { result += ","; } if (parts.Count > 1) { result = result.Substring(2) + " and "; } result += parts[parts.Count - 1]; return result; }