public static Payout CreateFromProtoIdentity(Person creator, string protoIdentity) { string[] components = protoIdentity.Split('|'); int payoutId = 0; // The components can EITHER be a series of expense claims OR a single invoice. if (components.Length == 0) { // nothing to construct. Exception or return null? return(null); } if (components[0][0] == 'A') { // Cash advance(s) to be paid out. string bank = string.Empty; string account = string.Empty; List <int> identityList = new List <int>(); Int64 amountCents = 0; int organizationId = 0; foreach (string component in components) { int advanceId = Int32.Parse(component.Substring(1)); CashAdvance advance = CashAdvance.FromIdentity(advanceId); identityList.Add(advanceId); organizationId = advance.OrganizationId; Organization organization = Organization.FromIdentity(advance.OrganizationId); if (bank.Length < 1) { Person asker = advance.Person; bank = asker.BankName; account = asker.BankAccount; } amountCents += advance.AmountCents; advance.PaidOut = true; // advance.Open remains true until the advance is repaid SwarmopsLogEntry.Create(creator, new PayoutCreatedLogEntry(creator, advance.Person, organization, organization.Currency, amountCents / 100.0, "Cash Advance Paid Out"), advance.Person, advance); OutboundComm.CreateNotificationOfFinancialValidation(advance.Budget, advance.Person, advance.AmountCents / 100.0, advance.Description, NotificationResource.CashAdvance_PaidOut); } string referenceString = string.Empty; if (identityList.Count == 1) { referenceString = "Cash Advance #" + identityList[0].ToString(CultureInfo.InvariantCulture); } else { identityList.Sort(); referenceString = "Cash Advances " + Formatting.GenerateRangeString(identityList); } payoutId = SwarmDb.GetDatabaseForWriting().CreatePayout(organizationId, bank, account, referenceString, amountCents, DateTime.Today.AddDays(1), creator.Identity); foreach (int advanceId in identityList) { SwarmDb.GetDatabaseForWriting() .CreatePayoutDependency(payoutId, FinancialDependencyType.CashAdvance, advanceId); } } else if (components[0][0] == 'C') { // Expense claims, possibly followed up by cash advance paybacks Person beneficiaryPerson = null; Organization organization = null; string bank = string.Empty; string account = string.Empty; List <int> claimIdentityList = new List <int>(); List <int> advancePaybackIdentityList = new List <int>(); Int64 amountCents = 0; int organizationId = 0; foreach (string component in components) { int foreignId = Int32.Parse(component.Substring(1)); if (component[0] == 'C') { ExpenseClaim claim = ExpenseClaim.FromIdentity(foreignId); claimIdentityList.Add(foreignId); if (bank.Length < 1) { Person claimer = claim.Claimer; bank = claimer.BankName; account = claimer.BankAccount; organizationId = claim.OrganizationId; } beneficiaryPerson = claim.Claimer; organization = claim.Organization; amountCents += claim.AmountCents; claim.Repaid = true; claim.Close(); OutboundComm.CreateNotificationOfFinancialValidation(claim.Budget, claim.Claimer, claim.AmountCents / 100.0, claim.Description, NotificationResource.ExpenseClaim_PaidOut); } else if (component[0] == 'a') { CashAdvance advancePayback = CashAdvance.FromIdentity(foreignId); advancePaybackIdentityList.Add(foreignId); amountCents -= advancePayback.AmountCents; advancePayback.Open = false; } } string referenceString = string.Empty; if (claimIdentityList.Count == 1) { referenceString = "Expense Claim #" + claimIdentityList[0].ToString(CultureInfo.InvariantCulture); } else { claimIdentityList.Sort(); referenceString = "Expense Claims " + Formatting.GenerateRangeString(claimIdentityList); } SwarmopsLogEntry.Create(creator, new PayoutCreatedLogEntry(creator, beneficiaryPerson, organization, organization.Currency, amountCents / 100.0, referenceString), beneficiaryPerson); payoutId = SwarmDb.GetDatabaseForWriting().CreatePayout(organizationId, bank, account, referenceString, amountCents, DateTime.Today.AddDays(1), creator.Identity); foreach (int claimId in claimIdentityList) { SwarmDb.GetDatabaseForWriting() .CreatePayoutDependency(payoutId, FinancialDependencyType.ExpenseClaim, claimId); } foreach (int advancePaybackId in advancePaybackIdentityList) { SwarmDb.GetDatabaseForWriting() .CreatePayoutDependency(payoutId, FinancialDependencyType.CashAdvancePayback, advancePaybackId); } } else if (components[0][0] == 'I') { // There is just one invoice per payout InboundInvoice invoice = InboundInvoice.FromIdentity(Int32.Parse(components[0].Substring(1))); DateTime expectedPayment = invoice.DueDate; if (expectedPayment < DateTime.Today) { expectedPayment = DateTime.Today; } payoutId = SwarmDb.GetDatabaseForWriting() .CreatePayout(invoice.OrganizationId, string.Empty, invoice.PayToAccount, invoice.Ocr.Length > 0 ? "OCR " + invoice.Ocr : "Ref# " + invoice.InvoiceReference, invoice.AmountCents, expectedPayment, creator.Identity); SwarmDb.GetDatabaseForWriting() .CreatePayoutDependency(payoutId, FinancialDependencyType.InboundInvoice, invoice.Identity); invoice.Open = false; } else if (components[0][0] == 'S') { // Salary, net payment Salary salary = Salary.FromIdentity(Int32.Parse(components[0].Substring(1))); payoutId = SwarmDb.GetDatabaseForWriting() .CreatePayout(salary.PayrollItem.OrganizationId, salary.PayrollItem.Person.BankName, salary.PayrollItem.Person.BankAccount, "Salary " + salary.PayoutDate.ToString("yyyy-MMM"), salary.NetSalaryCents, salary.PayoutDate, creator.Identity); SwarmDb.GetDatabaseForWriting().CreatePayoutDependency(payoutId, FinancialDependencyType.Salary, salary.Identity); salary.NetPaid = true; } else if (components[0][0] == 'T') { // Tax payment for multiple salaries. List <int> identityList = new List <int>(); Int64 amountCents = 0; int organizationId = 0; DateTime payDay = DateTime.Today.AddDays(1); foreach (string component in components) { int salaryId = Int32.Parse(component.Substring(1)); Salary salary = Salary.FromIdentity(salaryId); identityList.Add(salaryId); if (organizationId == 0) { organizationId = salary.PayrollItem.OrganizationId; payDay = salary.PayoutDate; } amountCents += salary.TaxTotalCents; salary.TaxPaid = true; } Organization organization = Organization.FromIdentity(organizationId); identityList.Sort(); payoutId = SwarmDb.GetDatabaseForWriting() .CreatePayout(organization.Identity, "The Tax Man", organization.Parameters.TaxAccount, organization.Parameters.TaxOcr, amountCents, payDay, creator.Identity); foreach (int salaryId in identityList) { SwarmDb.GetDatabaseForWriting().CreatePayoutDependency(payoutId, FinancialDependencyType.SalaryTax, salaryId); } } else { throw new NotImplementedException(); } return(FromIdentity(payoutId)); }
public static Payout CreateBitcoinPayoutFromPrototype(Organization organization, Payout prototype, string transactionHash) { string[] components = prototype.ProtoIdentity.Split('|'); int payoutId = 0; // This function is made for complex bitcoin payouts and will typically take many different types of payouts to many people at once. if (components.Length == 0) { // nothing to construct. Exception or return null? return(null); } payoutId = SwarmDb.GetDatabaseForWriting().CreatePayout(organization.Identity, "Bitcoin network", "Multiple", transactionHash, prototype.AmountCents, DateTime.UtcNow, 0); foreach (string component in components) { int foreignId = Int32.Parse(component.Substring(1)); switch (component[0]) { case 'A': // Cash advance CashAdvance advance = CashAdvance.FromIdentity(foreignId); advance.PaidOut = true; SwarmopsLogEntry.Create(null, new PayoutCreatedLogEntry(null, advance.Person, organization, organization.Currency, advance.AmountCents / 100.0, "Cash Advance Paid Out"), advance.Person, advance); OutboundComm.CreateNotificationOfFinancialValidation(advance.Budget, advance.Person, advance.AmountCents / 100.0, advance.Description, NotificationResource.CashAdvance_PaidOut); SwarmDb.GetDatabaseForWriting() .CreatePayoutDependency(payoutId, FinancialDependencyType.CashAdvance, foreignId); break; case 'a': // This is a negative record - payback of cash advance CashAdvance advancePayback = CashAdvance.FromIdentity(foreignId); advancePayback.Open = false; SwarmDb.GetDatabaseForWriting() .CreatePayoutDependency(payoutId, FinancialDependencyType.CashAdvancePayback, foreignId); break; case 'C': // Expense claim ExpenseClaim claim = ExpenseClaim.FromIdentity(foreignId); claim.Repaid = true; claim.Close(); OutboundComm.CreateNotificationOfFinancialValidation(claim.Budget, claim.Claimer, claim.AmountCents / 100.0, claim.Description, NotificationResource.ExpenseClaim_PaidOut); SwarmDb.GetDatabaseForWriting() .CreatePayoutDependency(payoutId, FinancialDependencyType.ExpenseClaim, foreignId); break; case 'I': // Invoice InboundInvoice invoice = InboundInvoice.FromIdentity(foreignId); DateTime expectedPayment = invoice.DueDate; if (expectedPayment < DateTime.Today) { expectedPayment = DateTime.Today; } SwarmDb.GetDatabaseForWriting() .CreatePayoutDependency(payoutId, FinancialDependencyType.InboundInvoice, invoice.Identity); // TODO: NOTIFY PAID? invoice.Open = false; break; case 'S': // Salary net Salary salaryNet = Salary.FromIdentity(foreignId); SwarmDb.GetDatabaseForWriting().CreatePayoutDependency(payoutId, FinancialDependencyType.Salary, salaryNet.Identity); salaryNet.NetPaid = true; break; case 'T': // Tax payout, typically for multiple salaries Salary salaryTax = Salary.FromIdentity(foreignId); SwarmDb.GetDatabaseForWriting().CreatePayoutDependency(payoutId, FinancialDependencyType.SalaryTax, salaryTax.Identity); salaryTax.TaxPaid = true; break; default: throw new NotImplementedException(); } } // Return the new object by reloading it from database return(Payout.FromIdentity(payoutId)); }