Esempio n. 1
0
        public void MigrateDependenciesTo(Payout migrationTarget)
        {
            if (Identity > 0 && migrationTarget.Identity > 0)
            {
                // Persisted payout migration

                SwarmDb.GetDatabaseForWriting().MovePayoutDependencies(Identity, migrationTarget.Identity);
            }
            else
            {
                // In-memory migration: this payout isn't in database yet

                this.DependentCashAdvancesPayback.ForEach(item => migrationTarget.DependentCashAdvancesPayback.Add(item));
                this.DependentCashAdvancesPayout.ForEach(item => migrationTarget.DependentCashAdvancesPayout.Add(item));
                this.DependentExpenseClaims.ForEach(item => migrationTarget.DependentExpenseClaims.Add(item));
                this.DependentInvoices.ForEach(item => migrationTarget.DependentInvoices.Add(item));
                this.DependentSalariesNet.ForEach(item => migrationTarget.DependentSalariesNet.Add(item));
                this.DependentSalariesTax.ForEach(item => migrationTarget.DependentSalariesTax.Add(item));

                this.DependentCashAdvancesPayback = new CashAdvances();
                this.DependentCashAdvancesPayout  = new CashAdvances();
                this.DependentExpenseClaims       = new ExpenseClaims();
                this.DependentInvoices            = new InboundInvoices();
                this.DependentSalariesNet         = new Salaries();
                this.DependentSalariesTax         = new Salaries();
            }
            migrationTarget.RecalculateAmount();
            RecalculateAmount();
        }
Esempio n. 2
0
        private void LoadDependencies()
        {
            DependentExpenseClaims       = new ExpenseClaims();
            DependentInvoices            = new InboundInvoices();
            DependentSalariesNet         = new Salaries();
            DependentSalariesTax         = new Salaries();
            DependentCashAdvancesPayout  = new CashAdvances();
            DependentCashAdvancesPayback = new CashAdvances();

            BasicFinancialDependency[] dependencies = SwarmDb.GetDatabaseForReading().GetPayoutDependencies(this.Identity);

            foreach (BasicFinancialDependency dependency in dependencies)
            {
                switch (dependency.DependencyType)
                {
                case FinancialDependencyType.ExpenseClaim:
                    DependentExpenseClaims.Add(ExpenseClaim.FromIdentity(dependency.ForeignId));
                    break;

                case FinancialDependencyType.InboundInvoice:
                    DependentInvoices.Add(InboundInvoice.FromIdentity(dependency.ForeignId));
                    break;

                case FinancialDependencyType.Salary:
                    Salary salary = Salary.FromIdentity(dependency.ForeignId);
                    if (salary.NetSalaryCents == this.AmountCents)      // HACK: Assumes that tax total is not identical
                    {
                        DependentSalariesNet.Add(salary);
                    }
                    else
                    {
                        DependentSalariesTax.Add(salary);
                    }
                    break;

                case FinancialDependencyType.CashAdvance:
                    DependentCashAdvancesPayout.Add(CashAdvance.FromIdentity(dependency.ForeignId));
                    break;

                case FinancialDependencyType.CashAdvancePayback:
                    DependentCashAdvancesPayback.Add(CashAdvance.FromIdentity(dependency.ForeignId));
                    break;

                default:
                    throw new NotImplementedException("Unknown financial dependency type in Payout.LoadDependencies(): " + dependency.ToString());
                }
            }
        }
Esempio n. 3
0
        public static Dictionary <int, Int64> GetBudgetAttestationSpaceAdjustments(Organization organization)
        {
            // This function returns a dictionary for the cents that are either accounted for but not attested,
            // or attested but accounted for, to be used to understand how much is really left in budget

            // Positive adjustment means more [cost] budget available, negative less [cost] budget available

            if (_organizationBudgetAttestationSpaceLookup.ContainsKey(organization.Identity))
            {
                return(_organizationBudgetAttestationSpaceLookup [organization.Identity]);
            }

            // TODO: This is expensive research, we should cache this result and clear cache on any attestation or create op

            Dictionary <int, Int64> result = new Dictionary <int, long>();

            // Cash advances are accounted for when paid out. Make sure they count toward the budget when attested.

            CashAdvances advances = CashAdvances.ForOrganization(organization);

            foreach (CashAdvance advance in advances)
            {
                if (!result.ContainsKey(advance.BudgetId))
                {
                    result[advance.BudgetId] = 0;
                }

                if (advance.Attested)
                {
                    result[advance.BudgetId] -= advance.AmountCents;
                }
            }

            // Expense claims, Inbound invoices, and Salaries are accounted for when filed. Make sure they DON'T
            // count toward the budget while they are NOT attested.

            ExpenseClaims claims = ExpenseClaims.ForOrganization(organization); // gets all open claims

            foreach (ExpenseClaim claim in claims)
            {
                if (!result.ContainsKey(claim.BudgetId))
                {
                    result[claim.BudgetId] = 0;
                }

                if (!claim.Attested)
                {
                    result[claim.BudgetId] += claim.AmountCents;
                }
            }

            InboundInvoices invoices = InboundInvoices.ForOrganization(organization);

            foreach (InboundInvoice invoice in invoices)
            {
                if (!result.ContainsKey(invoice.BudgetId))
                {
                    result[invoice.BudgetId] = 0;
                }

                if (!invoice.Attested)
                {
                    result[invoice.BudgetId] += invoice.AmountCents;
                }
            }

            Salaries salaries = Salaries.ForOrganization(organization);

            foreach (Salary salary in salaries)
            {
                if (!result.ContainsKey(salary.PayrollItem.BudgetId))
                {
                    result[salary.PayrollItem.BudgetId] = 0;
                }

                if (!salary.Attested)
                {
                    result[salary.PayrollItem.BudgetId] += (salary.GrossSalaryCents + salary.AdditiveTaxCents);
                }
            }

            _organizationBudgetAttestationSpaceLookup[organization.Identity] = result;

            return(result);
        }
Esempio n. 4
0
        private static void AddUnpaidExpenseClaims(Payouts payoutList, Organization organization)
        {
            ExpenseClaims claims = ExpenseClaims.FromOrganization(organization);

            Dictionary <int, Payout> payoutLookup = new Dictionary <int, Payout>();

            foreach (ExpenseClaim claim in claims)
            {
                // If ready for payout, add to list.

                if (claim.Open)
                {
                    if (claim.Attested && claim.Validated && !claim.Repaid && !claim.KeepSeparate)
                    {
                        // this should be added to the list. Check if we already have pending payouts
                        // for this person:

                        if (payoutLookup.ContainsKey(claim.ClaimingPersonId))
                        {
                            // Yes. Add claim to list.

                            payoutLookup[claim.ClaimingPersonId].DependentExpenseClaims.Add(claim);
                        }
                        else
                        {
                            // No. Create a new payout for this person.

                            BasicPayout basicPayout = new BasicPayout(0, organization.Identity, claim.Claimer.BankName,
                                                                      claim.Claimer.BankClearing + " / " + claim.Claimer.BankAccount, string.Empty, 0,
                                                                      Constants.DateTimeLow, false, DateTime.Now, 0);
                            Payout payout = Payout.FromBasic(basicPayout);
                            payout.RecipientPerson = claim.Claimer;

                            payout.DependentExpenseClaims.Add(claim);

                            payoutLookup[claim.ClaimingPersonId] = payout;
                        }
                    }
                }
            }

            // At this point, all the expense claims have been added - but we need to add the open
            // cash advances and deduct them.

            CashAdvances cashAdvances = CashAdvances.ForOrganization(organization);

            cashAdvances = cashAdvances.WherePaid;

            // At this point, only open and paid cash advances are in the list: they're debts to the org

            foreach (CashAdvance cashAdvance in cashAdvances)
            {
                if (payoutLookup.ContainsKey(cashAdvance.PersonId))
                {
                    // there's a payout prepared to this person - we need to deduct the cash advance from it.

                    payoutLookup[cashAdvance.PersonId].DependentCashAdvancesPayback.Add(cashAdvance);
                }
            }

            // We now have the list of payouts and the associated claims, but the amounts aren't set on the
            // payouts. This will be the next step, as we assemble the list.

            foreach (Payout payout in payoutLookup.Values)
            {
                Int64      newAmountCents = 0;
                List <int> claimIds       = new List <int>();

                foreach (ExpenseClaim claim in payout.DependentExpenseClaims)
                {
                    newAmountCents += claim.AmountCents;
                    claimIds.Add(claim.Identity);
                }

                foreach (CashAdvance previousAdvance in payout.DependentCashAdvancesPayback)
                {
                    newAmountCents -= previousAdvance.AmountCents;
                }

                string lessAdvancesIndicator = payout.DependentCashAdvancesPayback.Count > 0
                    ? "LessAdvances"
                    : string.Empty;

                payout.AmountCents = newAmountCents;

                if (claimIds.Count == 1)
                {
                    payout.Reference = "[Loc]Financial_ExpenseClaimSpecification" + lessAdvancesIndicator + "|" +
                                       claimIds[0].ToString(CultureInfo.InvariantCulture);
                }
                else
                {
                    claimIds.Sort();
                    payout.Reference = "[Loc]Financial_ExpenseClaimsSpecification" + lessAdvancesIndicator + "|" +
                                       Formatting.GenerateRangeString(claimIds);
                }

                if (newAmountCents > 0)
                {
                    payoutList.Add(payout);
                }
            }
        }
Esempio n. 5
0
        private static void AddUnpaidCashAdvances(Payouts payoutList, Organization organization)
        {
            CashAdvances advances = CashAdvances.ForOrganization(organization);

            advances = advances.WhereAttested;
            advances = advances.WhereUnpaid;

            Dictionary <int, Payout> payoutLookup = new Dictionary <int, Payout>();

            foreach (CashAdvance advance in advances)
            {
                // If ready for payout, add to list.

                if (!advance.Open || !advance.Attested || advance.PaidOut)
                {
                    throw new InvalidOperationException(
                              "Got into loop with closed/unattested/paid-out cash advances - this is not a possible state");
                }

                if (payoutLookup.ContainsKey(advance.PersonId))
                {
                    // Yes. Add claim to list.

                    payoutLookup[advance.PersonId].DependentCashAdvancesPayout.Add(advance);
                }
                else
                {
                    // No. Create a new payout for this person.

                    BasicPayout basicPayout = new BasicPayout(0, organization.Identity, advance.Person.BankName,
                                                              advance.Person.BankClearing + " / " + advance.Person.BankAccount, string.Empty, 0,
                                                              Constants.DateTimeLow, false, DateTime.Now, 0);
                    Payout payout = Payout.FromBasic(basicPayout);
                    payout.RecipientPerson = advance.Person;

                    payout.DependentCashAdvancesPayout.Add(advance);

                    payoutLookup[advance.PersonId] = payout;
                }
            }

            // We now have the list of payouts and the associated claims, but the amounts aren't set on the
            // payouts. This will be the next step, as we assemble the list.

            foreach (Payout payout in payoutLookup.Values)
            {
                Int64      newAmountCents = 0;
                List <int> advanceIds     = new List <int>();

                foreach (CashAdvance advance in payout.DependentCashAdvancesPayout)
                {
                    newAmountCents += advance.AmountCents;
                    advanceIds.Add(advance.Identity);
                }

                payout.AmountCents = newAmountCents;

                if (advanceIds.Count == 1)
                {
                    payout.Reference = "[Loc]Financial_CashAdvanceSpecification|" +
                                       advanceIds[0].ToString(CultureInfo.InvariantCulture);
                }
                else
                {
                    advanceIds.Sort();
                    payout.Reference = "[Loc]Financial_CashAdvancesSpecification|" +
                                       Formatting.GenerateRangeString(advanceIds);
                }

                if (newAmountCents > 0)
                {
                    payoutList.Add(payout);
                }
            }
        }