protected void ButtonConfirmedKill_Click(object sender, EventArgs e)
    {
        if (_invoice.Attested)
        {
            _invoice.Deattest(_currentUser);
        }

        FinancialValidations.Create(FinancialValidationType.Kill, _invoice, _currentUser);

        // Set the state to Closed, Unvalidated

        _invoice.Open = false;

        // Undo all financial transaction changes

        FinancialTransaction transaction = _invoice.FinancialTransaction;

        transaction.RecalculateTransaction(new Dictionary <int, Int64>(), _currentUser);

        // Mark transaction as invalid in description

        transaction.Description = "Inbound Invoice #" + _invoice.Identity.ToString() + " (killed/zeroed)";

        // Finally, close form and rebind

        ClientScript.RegisterStartupScript(Page.GetType(), "mykey", "CloseAndRebind();", true);
    }
Exemple #2
0
        public static ResyncResults ExecuteResync(string guid)
        {
            AuthenticationData authenticationData = GetAuthenticationDataAndCulture();

            if (
                !authenticationData.Authority.HasAccess(new Access(authenticationData.CurrentOrganization,
                                                                   AccessAspect.Bookkeeping, AccessType.Write)))
            {
                throw new UnauthorizedAccessException();
            }

            ResyncResults results = new ResyncResults();

            ExternalBankMismatchingDateTime[] mismatchArray =
                (ExternalBankMismatchingDateTime[])
                HttpContext.Current.Session["LedgersResync" + guid + "MismatchArray"];

            FinancialAccount account =
                (FinancialAccount)HttpContext.Current.Session["LedgersResync" + guid + "Account"];

            long             autoDepositDonationCents = 1000 * 100;
            FinancialAccount autoDonationAccount      = account.Organization.FinancialAccounts.IncomeDonations;

            if (authenticationData.CurrentOrganization.Identity != account.OrganizationId)
            {
                throw new InvalidOperationException("Mismatching org");
            }

            foreach (ExternalBankMismatchingDateTime mismatchDateTime in mismatchArray)
            {
                foreach (
                    ExternalBankMismatchingRecordDescription mismatchingRecord in mismatchDateTime.MismatchingRecords)
                {
                    for (int index = 0; index < mismatchingRecord.MasterCents.Length; index++)
                    {
                        results.RecordsTotal++;
                        long cents = mismatchingRecord.MasterCents[index];

                        bool unhandled = false;
                        bool handlable = true;

                        FinancialTransaction tx = mismatchingRecord.Transactions[index];

                        if (tx != null && tx.Dependency != null)
                        {
                            unhandled = true;

                            IHasIdentity dependency = tx.Dependency;

                            if (dependency is PaymentGroup &&
                                mismatchingRecord.ResyncActions[index] ==
                                ExternalBankMismatchResyncAction.RewriteSwarmops)
                            {
                                if (cents == (dependency as PaymentGroup).SumCents)
                                {
                                    // Amount checks out with dependency; rewrite requested; this is handlable on auto

                                    Dictionary <int, long> newTx = new Dictionary <int, long>();
                                    newTx[account.Identity] = cents;
                                    newTx[account.Organization.FinancialAccounts.AssetsOutboundInvoices.Identity] =
                                        -cents;
                                    tx.RecalculateTransaction(newTx, authenticationData.CurrentUser);
                                    unhandled = false;
                                }
                            }


                            handlable = false; // need to fix this
                        }


                        if (handlable)
                        {
                            switch (mismatchingRecord.ResyncActions[index])
                            {
                            case ExternalBankMismatchResyncAction.DeleteSwarmops:
                                if (tx == null)
                                {
                                    throw new InvalidOperationException(
                                              "Can't have Delete op on a null transaction");
                                }

                                tx.Description = tx.Description + " (killed/zeroed in resync)";
                                tx.RecalculateTransaction(new Dictionary <int, long>(),
                                                          authenticationData.CurrentUser); // zeroes out
                                break;

                            case ExternalBankMismatchResyncAction.RewriteSwarmops:
                                if (tx == null)
                                {
                                    throw new InvalidOperationException(
                                              "Can't have Rewrite op on a null transaction");
                                }

                                Dictionary <int, long> newTx = new Dictionary <int, long>();
                                newTx[account.Identity] = cents;
                                if (cents > 0 && cents < autoDepositDonationCents)
                                {
                                    newTx[autoDonationAccount.Identity] = -cents;     // negative; P&L account
                                }
                                tx.RecalculateTransaction(newTx, authenticationData.CurrentUser);
                                break;

                            case ExternalBankMismatchResyncAction.CreateSwarmops:
                                if (tx != null)
                                {
                                    throw new InvalidOperationException("Transaction seems to already exist");
                                }

                                tx = FinancialTransaction.Create(account.OwnerPersonId, mismatchDateTime.DateTime,
                                                                 mismatchingRecord.Description);
                                tx.AddRow(account, cents, authenticationData.CurrentUser);

                                if (cents > 0 && cents < autoDepositDonationCents)
                                {
                                    tx.AddRow(autoDonationAccount, -cents, authenticationData.CurrentUser);
                                }
                                break;

                            case ExternalBankMismatchResyncAction.NoAction:
                                // no action
                                break;

                            default:
                                // not handled
                                unhandled = true;
                                break;
                            }
                        }

                        if (unhandled)
                        {
                            results.RecordsFail++;
                        }
                        else
                        {
                            results.RecordsSuccess++;
                        }
                    }
                }
            }

            return(results);
        }
Exemple #3
0
        protected static ImportStats ProcessImportedData(ImportResult import, Organization organization,
                                                         Person importingPerson)
        {
            FinancialAccount payPalAccount = organization.FinancialAccounts.AssetsPaypal;
            FinancialAccount bankFees      = organization.FinancialAccounts.CostsBankFees;
            FinancialAccount donations     = organization.FinancialAccounts.IncomeDonations;

            int autoDepositLimit    = 1000; // TODO: Get from organization parameters
            int autoWithdrawalLimit = 0;

            ImportStats result = new ImportStats();

            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;
                }

                Dictionary <int, long> nominalTransaction = new Dictionary <int, long>();

                FinancialTransaction transaction = null;

                try
                {
                    transaction = FinancialTransaction.FromImportKey(organization, importKey);
                }
                catch (Exception)
                {
                    // if we get here, that means the transaction did not yet exist

                    transaction = FinancialTransaction.ImportWithStub(organization.Identity, row.DateTime,
                                                                      payPalAccount.Identity, amountCents,
                                                                      row.Comment, importKey, "" /* new SHA256 field */,
                                                                      importingPerson.Identity);
                    result.ImportedTransactionCount++;

                    if (transaction == null)
                    {
                        // No transaction was created. This is an error condition as it should have been created if it didn't
                        // exist, and the "exist" case is handled in the FromImportKey attempt above. Abort with error.
                        // Throw new exception?

                        continue;
                    }
                }

                result.ProcessedTransactionCount++;

                nominalTransaction[payPalAccount.Identity] = amountCents;

                // The transaction was created. Examine if the autobook criteria are true.

                if (amountCents < 0)
                {
                    if ((-amountCents) < autoWithdrawalLimit * 100)
                    {
                        // Book against autoWithdrawal account.

                        nominalTransaction[bankFees.Identity] = -amountCents;
                    }
                }
                else if (amountCents > 0)
                {
                    if (row.FeeCents < 0)
                    {
                        // This is always an autodeposit, if there is a fee (which is never > 0.0)

                        nominalTransaction[bankFees.Identity]  = -row.FeeCents;
                        nominalTransaction[donations.Identity] = -row.AmountCentsGross;
                    }
                    else if (amountCents < autoDepositLimit * 100)
                    {
                        // Book against autoDeposit account.

                        nominalTransaction[donations.Identity] = -amountCents;
                    }
                }

                if (transaction.Rows.AmountCentsTotal != 0) // If transaction is unbalanced, balance it
                {
                    if (transaction.RecalculateTransaction(nominalTransaction, importingPerson))
                    {
                        result.ModifiedTransactionCount++;
                    }
                }
            }

            return(result);
        }
        public static ChangeAccountDataResult SetAccountInitialBalance(int accountId, string newInitialBalanceString)
        {
            try
            {
                AuthenticationData authData = GetAuthenticationDataAndCulture();
                FinancialAccount   account  = FinancialAccount.FromIdentity(accountId);

                if (!PrepareAccountChange(account, authData, false) || authData.CurrentOrganization.Parameters.FiscalBooksClosedUntilYear >= authData.CurrentOrganization.FirstFiscalYear)
                {
                    return(new ChangeAccountDataResult
                    {
                        Result = ChangeAccountDataOperationsResult.NoPermission
                    });
                }

                Int64 desiredInitialBalanceCents =
                    (Int64)
                    (Double.Parse(newInitialBalanceString,
                                  NumberStyles.AllowThousands | NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint,
                                  CultureInfo.CurrentCulture) * 100.0);

                Int64 currentInitialBalanceCents = account.GetDeltaCents(new DateTime(1900, 1, 1),
                                                                         new DateTime(authData.CurrentOrganization.FirstFiscalYear, 1, 1));

                Int64 deltaCents = desiredInitialBalanceCents - currentInitialBalanceCents;

                // Find or create "Initial Balances" transaction

                FinancialAccountRows testRows = FinancialAccountRows.ForOrganization(authData.CurrentOrganization,
                                                                                     new DateTime(1900, 1, 1), new DateTime(authData.CurrentOrganization.FirstFiscalYear, 1, 1));

                FinancialTransaction initialBalancesTransaction = null;

                foreach (FinancialAccountRow row in testRows)
                {
                    if (row.Transaction.Description == "Initial Balances")
                    {
                        initialBalancesTransaction = row.Transaction;
                        break;
                    }
                }

                if (initialBalancesTransaction == null)
                {
                    // create transaction

                    initialBalancesTransaction = FinancialTransaction.Create(authData.CurrentOrganization.Identity,
                                                                             new DateTime(authData.CurrentOrganization.FirstFiscalYear - 1, 12, 31), "Initial Balances");
                }

                Dictionary <int, Int64> recalcBase = initialBalancesTransaction.GetRecalculationBase();
                int equityAccountId = authData.CurrentOrganization.FinancialAccounts.DebtsEquity.Identity;

                if (!recalcBase.ContainsKey(accountId))
                {
                    recalcBase[accountId] = 0;
                }
                if (!recalcBase.ContainsKey(equityAccountId))
                {
                    recalcBase[equityAccountId] = 0;
                }

                recalcBase[accountId]       += deltaCents;
                recalcBase[equityAccountId] -= deltaCents;
                initialBalancesTransaction.RecalculateTransaction(recalcBase, authData.CurrentUser);
                return(new ChangeAccountDataResult
                {
                    Result = ChangeAccountDataOperationsResult.Changed,
                    NewData = (desiredInitialBalanceCents / 100.0).ToString("N2", CultureInfo.CurrentCulture)
                });
            }
            catch (Exception weirdException)
            {
                SwarmDb.GetDatabaseForWriting()
                .CreateExceptionLogEntry(DateTime.UtcNow, "AccountPlan-SetInitBalance", weirdException);

                throw;
            }
        }