public static void InitializeProcessing(string guid, string accountIdString) { // Start an async thread that does all the work, then return AuthenticationData authData = GetAuthenticationDataAndCulture(); int accountId = Int32.Parse(accountIdString); FinancialAccount account = FinancialAccount.FromIdentity(accountId); if (account.Organization.Identity != authData.CurrentOrganization.Identity || !authData.Authority.HasAccess(new Access(authData.CurrentOrganization, AccessAspect.Bookkeeping, AccessType.Write))) { throw new UnauthorizedAccessException(); } Thread initThread = new Thread(ProcessUploadThread); ProcessThreadArguments args = new ProcessThreadArguments { Guid = guid, Organization = authData.CurrentOrganization, Account = account }; initThread.Start(args); }
public static AjaxCallResult InitializeExpensifyProcessing(string guidFiles, string guidProgress) { // Start an async thread that does all the work, then return AuthenticationData authData = GetAuthenticationDataAndCulture(); ProgressBarBackend progress = new ProgressBarBackend(guidProgress); progress.Set(0); // Set to 0 first, esp. in case of previous files progress.Set(1); // Then to 1, just to indicate life Thread initThread = new Thread(ProcessExpensifyUploadThread); ProcessThreadArguments args = new ProcessThreadArguments { GuidFiles = guidFiles, GuidProgress = guidProgress, Organization = authData.CurrentOrganization, CurrentUser = authData.CurrentUser }; initThread.Start(args); return(new AjaxCallResult { Success = true }); }
public static void InitializeProcessing(string guid, string accountIdString) { // Start an async thread that does all the work, then return AuthenticationData authData = GetAuthenticationDataAndCulture(); int accountId = Int32.Parse(accountIdString); FinancialAccount account = FinancialAccount.FromIdentity(accountId); if (account.Organization.Identity != authData.CurrentOrganization.Identity || !authData.CurrentUser.HasAccess(new Access(authData.CurrentOrganization, AccessAspect.Bookkeeping, AccessType.Write))) { throw new UnauthorizedAccessException(); } Thread initThread = new Thread(ProcessUploadThread); ProcessThreadArguments args = new ProcessThreadArguments {Guid = guid, Organization = authData.CurrentOrganization, Account = account}; initThread.Start(args); }
static private ImportResults ProcessImportedData(ExternalBankData import, ProcessThreadArguments args) { FinancialAccount assetAccount = args.Account; FinancialAccount autoDepositAccount = args.Organization.FinancialAccounts.IncomeDonations; int autoDepositLimit = 1000; // TODO: this.CurrentOrganization.Parameters.AutoDonationLimit; ImportResults result = new ImportResults(); int count = 0; int progressUpdateInterval = import.Records.Length/40; if (progressUpdateInterval > 100) { progressUpdateInterval = 100; } foreach (ExternalBankDataRecord row in import.Records) { // Update progress. count++; if (progressUpdateInterval < 2 || count % progressUpdateInterval == 0) { int percent = (count*99)/import.Records.Length; GuidCache.Set(args.Guid + "-Progress", percent); } // Update high- and low-water marks. if (row.DateTime < result.EarliestTransaction) { result.EarliestTransaction = row.DateTime; } if (row.DateTime > result.LatestTransaction) { result.LatestTransaction = row.DateTime; } string importKey = row.ImportHash; Int64 amountCents = row.TransactionNetCents; if (amountCents == 0) // defensive programming - these _should_ be duplicated in the interpreter if no "fee" field { amountCents = row.TransactionGrossCents; } if (args.Organization.Identity == 1 && assetAccount.Identity == 1 && PilotInstallationIds.IsPilot(PilotInstallationIds.PiratePartySE)) { // This is an ugly-as-f**k hack that sorts under the category "just bring our pilots the f**k back to operational // status right f*****g now". // This code can and should be safely removed once the pilot's books are closed for 2014, which should be some time mid-2015. if (row.DateTime < new DateTime(2014,03,22)) { result.DuplicateTransactions++; continue; } } FinancialTransaction transaction = FinancialTransaction.ImportWithStub(args.Organization.Identity, row.DateTime, assetAccount.Identity, amountCents, row.Description, importKey, args.CurrentUser.Identity); if (transaction != null) { // The transaction was created. Examine if the autobook criteria are true. result.TransactionsImported++; FinancialAccounts accounts = FinancialAccounts.FromBankTransactionTag(row.Description); if (accounts.Count == 1) { // This is a labelled local donation. Geography geography = accounts[0].AssignedGeography; FinancialAccount localAccount = accounts[0]; transaction.AddRow(args.Organization.FinancialAccounts.IncomeDonations, -amountCents, args.CurrentUser); transaction.AddRow(args.Organization.FinancialAccounts.CostsLocalDonationTransfers, amountCents, args.CurrentUser); transaction.AddRow(localAccount, -amountCents, args.CurrentUser); PWEvents.CreateEvent(EventSource.PirateWeb, EventType.LocalDonationReceived, args.CurrentUser.Identity, args.Organization.Identity, geography.Identity, 0, transaction.Identity, localAccount.Identity.ToString()); } else if (row.Description.ToLowerInvariant().StartsWith(args.Organization.IncomingPaymentTag)) { // Check for previously imported payment group // TODO: MAKE FLEXIBLE - CALL PAYMENTREADERINTERFACE! // HACK HACK HACK HACK PaymentGroup group = PaymentGroup.FromTag(args.Organization, "SEBGM" + DateTime.Today.Year.ToString() + // TODO: Get tags from org row.Description.Substring(args.Organization.IncomingPaymentTag.Length).Trim()); if (group != null && group.Open) { // There was a previously imported and not yet closed payment group matching this transaction // Close the payment group and match the transaction against accounts receivable transaction.Dependency = group; group.Open = false; transaction.AddRow(args.Organization.FinancialAccounts.AssetsOutboundInvoices, -amountCents, args.CurrentUser); } } else if (amountCents < 0) { // Autowithdrawal mechanisms removed, condition kept because of downstream else-if conditions } else if (amountCents > 0) { if (row.FeeCents < 0) { // This is always an autodeposit, if there is a fee (which is never > 0.0) transaction.AddRow(args.Organization.FinancialAccounts.CostsBankFees, -row.FeeCents, args.CurrentUser); transaction.AddRow(autoDepositAccount, -row.TransactionGrossCents, args.CurrentUser); } else if (amountCents < autoDepositLimit * 100) { // Book against autoDeposit account. transaction.AddRow(autoDepositAccount, -amountCents, args.CurrentUser); } } } else { // Transaction was not imported; assume duplicate result.DuplicateTransactions++; } } // Import complete. Return true if the bookkeeping account matches the bank data. Int64 databaseAccountBalanceCents = assetAccount.BalanceTotalCents; // Subtract any transactions made after the most recent imported transaction. // This is necessary in case of Paypal and others which continuously feed the // bookkeeping account with new transactions; it will already have fed transactions // beyond the end-of-file. Int64 beyondEofCents = assetAccount.GetDeltaCents(result.LatestTransaction.AddSeconds(1), DateTime.Now.AddDays(2)); // Caution: the "AddSeconds(1)" is not foolproof, there may be other new txs on the same second. if (databaseAccountBalanceCents - beyondEofCents == import.LatestAccountBalanceCents) { Payouts.AutomatchAgainstUnbalancedTransactions(args.Organization); result.AccountBalanceMatchesBank = true; result.BalanceMismatchCents = 0; } else { result.AccountBalanceMatchesBank = false; result.BalanceMismatchCents = (databaseAccountBalanceCents - beyondEofCents) - import.LatestAccountBalanceCents; } result.CurrencyCode = args.Organization.Currency.Code; return result; }