private void LoadDependencies() { this.DependentExpenseClaims = new ExpenseClaims(); this.DependentInvoices = new InboundInvoices(); this.DependentSalariesNet = new Salaries(); this.DependentSalariesTax = new Salaries(); this.DependentCashAdvancesPayout = new CashAdvances(); this.DependentCashAdvancesPayback = new CashAdvances(); BasicFinancialDependency[] dependencies = SwarmDb.GetDatabaseForReading().GetPayoutDependencies(Identity); foreach (BasicFinancialDependency dependency in dependencies) { switch (dependency.DependencyType) { case FinancialDependencyType.ExpenseClaim: this.DependentExpenseClaims.Add(ExpenseClaim.FromIdentity(dependency.ForeignId)); break; case FinancialDependencyType.InboundInvoice: this.DependentInvoices.Add(InboundInvoice.FromIdentity(dependency.ForeignId)); break; case FinancialDependencyType.Salary: Salary salary = Salary.FromIdentity(dependency.ForeignId); if (salary.NetSalaryCents == AmountCents) // HACK: Assumes that tax total is not identical { this.DependentSalariesNet.Add(salary); } else { this.DependentSalariesTax.Add(salary); } break; case FinancialDependencyType.CashAdvance: this.DependentCashAdvancesPayout.Add(CashAdvance.FromIdentity(dependency.ForeignId)); break; case FinancialDependencyType.CashAdvancePayback: this.DependentCashAdvancesPayback.Add(CashAdvance.FromIdentity(dependency.ForeignId)); break; default: throw new NotImplementedException( "Unknown financial dependency type in Payout.LoadDependencies(): " + dependency); } } }
private static void AddUnpaidSalaries(Payouts payoutList, Organization organization) { Int64 taxTotalCents = 0; Salaries salaries = Salaries.ForOrganization(organization); List <int> identityList = new List <int>(); DateTime payDay = Constants.DateTimeHigh; foreach (Salary salary in salaries) { if (!salary.Attested) { continue; } if (!salary.NetPaid) { PayrollItem payrollItem = salary.PayrollItem; Person employee = payrollItem.Person; BasicPayout basicPayout = new BasicPayout(0, organization.Identity, employee.BankName, employee.BankClearing + " / " + employee.BankAccount, "[Loc]Financial_SalarySpecification|[Date]" + salary.PayoutDate.ToString(CultureInfo.InvariantCulture), salary.NetSalaryCents, salary.PayoutDate, false, DateTime.Now, 0); Payout payout = Payout.FromBasic(basicPayout); payout.RecipientPerson = employee; payout.DependentSalariesNet.Add(salary); payoutList.Add(payout); if (payDay > salary.PayoutDate) { payDay = salary.PayoutDate; } } if (!salary.TaxPaid) { taxTotalCents += salary.TaxTotalCents; identityList.Add(salary.Identity); if (payDay > salary.PayoutDate) { payDay = salary.PayoutDate; } } } if (taxTotalCents > 0) { // Add the summarized tax line, too BasicPayout basicPayout = new BasicPayout(0, organization.Identity, "[Loc]Financial_TheTaxMan", "SEBG 5050-1055", // HACK: Get tax account from something organization.TaxPaymentOcr, taxTotalCents, payDay, false, DateTime.Now, 0); Payout payout = Payout.FromBasic(basicPayout); foreach (int salaryId in identityList) { payout.DependentSalariesTax.Add(Salary.FromIdentity(salaryId)); } payoutList.Add(payout); } }
private static void AddUnpaidSalaries(Payouts payoutList, int organizationId) { Int64 taxTotalCents = 0; Salaries salaries = Salaries.ForOrganization(Organization.FromIdentity(organizationId)); List <int> identityList = new List <int>(); DateTime payDay = DateTime.MaxValue; foreach (Salary salary in salaries) { if (!salary.Attested) { continue; } if (!salary.NetPaid) { PayrollItem payrollItem = salary.PayrollItem; Person employee = payrollItem.Person; BasicPayout basicPayout = new BasicPayout(0, organizationId, employee.BankName, employee.BankClearing + " / " + employee.BankAccount, "[Loc]Financial_SalarySpecification|[Date]" + salary.PayoutDate.ToString(CultureInfo.InvariantCulture), salary.NetSalaryCents, salary.PayoutDate, false, DateTime.Now, 0); Payout payout = Payout.FromBasic(basicPayout); payout.DependentSalariesNet.Add(salary); payoutList.Add(payout); if (payDay > salary.PayoutDate) { payDay = salary.PayoutDate; } } if (!salary.TaxPaid) { taxTotalCents += salary.TaxTotalCents; identityList.Add(salary.Identity); if (payDay > salary.PayoutDate) { payDay = salary.PayoutDate; } } } if (taxTotalCents > 0) { // Add the summarized tax line, too string referenceString = string.Empty; if (identityList.Count == 1) { referenceString = "[Loc]Financial_TaxSpecification|" + identityList[0].ToString(); } else { identityList.Sort(); referenceString = "[Loc]Financial_TaxesSpecification|" + Formatting.GenerateRangeString(identityList); } BasicPayout basicPayout = new BasicPayout(0, organizationId, "[Loc]Financial_TheTaxMan", string.Empty, referenceString, taxTotalCents, payDay, false, DateTime.Now, 0); Payout payout = Payout.FromBasic(basicPayout); foreach (int salaryId in identityList) { payout.DependentSalariesTax.Add(Salary.FromIdentity(salaryId)); } payoutList.Add(payout); } }
private void LoadDependencies() { if (this.DependentCashAdvancesPayback != null && Identity == 0) { return; // if inited and identity zero, return } this.DependentExpenseClaims = new ExpenseClaims(); this.DependentInvoices = new InboundInvoices(); this.DependentSalariesNet = new Salaries(); this.DependentSalariesTax = new Salaries(); this.DependentCashAdvancesPayout = new CashAdvances(); this.DependentCashAdvancesPayback = new CashAdvances(); if (Identity == 0) { return; // never progress past here if identity zero } BasicFinancialDependency[] dependencies = SwarmDb.GetDatabaseForReading().GetPayoutDependencies(Identity); foreach (BasicFinancialDependency dependency in dependencies) { switch (dependency.DependencyType) { case FinancialDependencyType.ExpenseClaim: this.DependentExpenseClaims.Add(ExpenseClaim.FromIdentity(dependency.ForeignId)); break; case FinancialDependencyType.InboundInvoice: this.DependentInvoices.Add(InboundInvoice.FromIdentity(dependency.ForeignId)); break; case FinancialDependencyType.Salary: Salary salary = Salary.FromIdentity(dependency.ForeignId); if (salary.NetSalaryCents == AmountCents || this.CreatedDateTime > new DateTime(2015, 11, 1)) { this.DependentSalariesNet.Add(salary); } else // LEGACY { this.DependentSalariesTax.Add(salary); } break; case FinancialDependencyType.SalaryTax: Salary salaryTax = Salary.FromIdentity(dependency.ForeignId); this.DependentSalariesTax.Add(salaryTax); break; case FinancialDependencyType.CashAdvance: this.DependentCashAdvancesPayout.Add(CashAdvance.FromIdentity(dependency.ForeignId)); break; case FinancialDependencyType.CashAdvancePayback: this.DependentCashAdvancesPayback.Add(CashAdvance.FromIdentity(dependency.ForeignId)); break; default: throw new NotImplementedException( "Unknown financial dependency type in Payout.LoadDependencies(): " + dependency); } } }
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)); }