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