Exemple #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();
        }
Exemple #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());
                }
            }
        }
Exemple #3
0
        /// <summary>
        ///     Processes all payroll for all organizations system-wide. Should run on the 1st of every month.
        /// </summary>
        public static void ProcessMonthly()
        {
            DateTime today = DateTime.UtcNow;

            string lastRun = Persistence.Key["LastSalaryRun"];

            string expectedLastRun = today.ToString("yyyyMM", CultureInfo.InvariantCulture);

            if (lastRun != null &&
                String.Compare(lastRun, expectedLastRun, CultureInfo.InvariantCulture, CompareOptions.IgnoreCase) >= 0)
            {
                // nothing to do, return

                return;
            }

            Persistence.Key["LastSalaryRun"] = expectedLastRun;

            // Process the payroll for all organizations. Assume payday is 25th.
            // TODO: Different payday per organization?

            Payroll  payroll = GetAll();
            DateTime payday  = new DateTime(today.Year, today.Month, 25);

            foreach (PayrollItem payrollItem in payroll)
            {
                Salary salary = Salary.Create(payrollItem, payday);
                SwarmopsLog.CreateEntry(payrollItem.Person, new SalaryCreatedLogEntry(salary));

                // TODO: CREATE SALARY SPECIFICATION, SEND TO PERSON
            }

            // If this is January, also send the annual statements for last year

            if (today.Month == 1)
            {
                Salaries.CreateAnnualStatements(today.Year - 1);
            }
        }
        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);
        }
Exemple #5
0
        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);
            }
        }
Exemple #6
0
        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);
            }
        }