public static AjaxUploadCallResult UploadBankStatement(string guid, string itemId) { AuthenticationData authData = GetAuthenticationDataAndCulture(); if (!authData.Authority.HasAccess(new Access(authData.CurrentOrganization, AccessAspect.BookkeepingDetails))) { throw new UnauthorizedAccessException(); } string[] parts = itemId.Split('-'); FinancialAccount account = FinancialAccount.FromIdentity(Int32.Parse(parts[1])); int yearMonth = Int32.Parse(parts[2]); DateTime statementStart = new DateTime(yearMonth / 100, yearMonth % 100, 1); if (account.OrganizationId != authData.CurrentOrganization.Identity) { throw new UnauthorizedAccessException(); } Documents documents = Documents.RecentFromDescription(guid); FinancialAccountDocument accountDoc = FinancialAccountDocument.Create(account, FinancialAccountDocumentType.BankStatement, authData.CurrentUser, statementStart, statementStart.AddMonths(1), string.Empty); documents.SetForeignObjectForAll(accountDoc); return(new AjaxUploadCallResult { Success = true, StillProcessing = false }); }
protected void Page_Load(object sender, EventArgs e) { this.PageAccessRequired = new Access(this.CurrentOrganization, AccessAspect.BookkeepingDetails); this.PageTitle = this.Title = this.LabelHeader.Text = String.Format(Resources.Pages.Ledgers.EndOfMonth_Title, DateTime.UtcNow.AddMonths(-1)); this.InfoBoxLiteral = Resources.Pages.Ledgers.EndOfMonth_Info; // Check which reports are required ItemGroups = new List <EomItemGroup>(); // Group I: External data & accounts EomItemGroup group1 = new EomItemGroup(); group1.Header = Resources.Pages.Ledgers.EndOfMonth_Header_ExternalData; group1.Id = "ExternalData"; string lastUploadItemId = string.Empty; // Iterate over all Balance accounts and check for automation; // if so, add it to an upload sequence FinancialAccounts assetAccounts = FinancialAccounts.ForOrganization(this.CurrentOrganization, FinancialAccountType.Asset); DateTime lastMonthEndDate = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, 1).AddDays(-1); int lastMonth = lastMonthEndDate.Year * 100 + lastMonthEndDate.Month; bool skippable = true; foreach (FinancialAccount assetAccount in assetAccounts) { if (assetAccount.AutomationProfileId != 0) { // This account has automation // If automation has Bank Account Statement enabled (assume true for now): FinancialAccountDocument lastBankStatement = assetAccount.GetMostRecentDocument(FinancialAccountDocumentType.BankStatement); int lastStatementMonth = (this.CurrentOrganization.FirstFiscalYear - 1) * 100 + 12; // December of the year before if (lastBankStatement != null) { lastStatementMonth = lastBankStatement.ConcernsPeriodStart.Year * 100 + lastBankStatement.ConcernsPeriodStart.Month; skippable = false; } string lastId = string.Empty; int monthIterator = lastStatementMonth; while (monthIterator < lastMonth) { monthIterator++; if (monthIterator % 100 == 13) { monthIterator += 88; } EomItem bankStatement = new EomItem(); bankStatement.DependsOn = lastId; // empty for first record bankStatement.Id = lastId = "BankStatement-" + assetAccount.Identity.ToString(CultureInfo.InvariantCulture) + '-' + monthIterator; bankStatement.Name = string.Format(Resources.Pages.Ledgers.EndOfMonth_UploadBankStatementFor, assetAccount.Name, "PDF", new DateTime(monthIterator / 100, monthIterator % 100, 15).ToString("MMMM yyyy")); bankStatement.Completed = false; // TODO bankStatement.Icon = "upload"; bankStatement.Skippable = skippable; group1.Items.Add(bankStatement); } // Add data upload item // TODO: Check if the last data upload was into the current month EomItem dataUploadItem = new EomItem(); dataUploadItem.Id = "BankTransactionData-" + assetAccount.Identity.ToString(CultureInfo.InvariantCulture); dataUploadItem.Icon = "upload"; dataUploadItem.Completed = false; // todo dataUploadItem.Name = String.Format(Resources.Pages.Ledgers.EndOfMonth_UploadTransactionDataFor, assetAccount.Name, "CSV"); dataUploadItem.Skippable = false; group1.Items.Add(dataUploadItem); // Check if we need to add a resync of the hotwallet's native ledger if (CurrentOrganization.FinancialAccounts.AssetsBitcoinHot != null) // has hotwallet { Int64 cashSatoshisInLedger = CurrentOrganization.FinancialAccounts.AssetsBitcoinHot.GetForeignCurrencyBalanceDeltaCents( Constants.DateTimeLow, Constants.DateTimeHigh).Cents; Int64 cashSatoshisInHotwallet = HotBitcoinAddresses.GetSatoshisInHotwallet(CurrentOrganization)[BitcoinChain.Cash]; if (cashSatoshisInHotwallet != cashSatoshisInLedger) { // Resync required EomItem resyncSatoshiCountItem = new EomItem(); resyncSatoshiCountItem.Id = "ResyncSatoshisInLedger"; resyncSatoshiCountItem.Icon = "approve"; resyncSatoshiCountItem.Completed = false; resyncSatoshiCountItem.Skippable = false; resyncSatoshiCountItem.Callback = "ResyncSatoshisInLedger"; resyncSatoshiCountItem.Name = Resources.Pages.Ledgers.EndOfMonth_CheckLedgerAgainstHotWallet; group1.Items.Add(resyncSatoshiCountItem); } } } } // If there are any items in Group 1, OR if an account matching is necessary, then // add that as an action item if (group1.Items.Count() > 0 || FinancialTransactions.GetUnbalanced(this.CurrentOrganization).Count() > 0) { EomItem matchAccounts = new EomItem(); matchAccounts.DependsOn = lastUploadItemId; // may be empty if there's nothing to upload and that's ok matchAccounts.Id = "MatchAccounts"; matchAccounts.Completed = false; // we already know there's at least one unbalanced matchAccounts.Icon = "wrench"; matchAccounts.Skippable = false; matchAccounts.Name = Resources.Pages.Ledgers.EndOfMonth_MatchAccounts; group1.Items.Add(matchAccounts); } if (group1.Items.Count > 0) { ItemGroups.Add(group1); } // Group: Payroll and Taxes EomItemGroup group2 = new EomItemGroup(); group2.Header = Resources.Pages.Ledgers.EndOfMonth_Header_PayrollTaxes; group2.Id = "PayrollTaxes"; ReportRequirement vatRequired = VatReport.IsRequired(this.CurrentOrganization); if (vatRequired == ReportRequirement.Required || vatRequired == ReportRequirement.Completed) { EomItem vatReport = new EomItem(); vatReport.Id = "VatReport"; vatReport.Callback = "CreateVatReport"; vatReport.Completed = (vatRequired == ReportRequirement.Completed ? true : false); vatReport.Name = String.Format(Resources.Pages.Ledgers.EndOfMonth_CreateVatReport, (vatReport.Completed ? VatReport.LastReportDescription(this.CurrentOrganization) : VatReport.NextReportDescription(this.CurrentOrganization))); vatReport.Icon = "document"; group2.Items.Add(vatReport); } Payroll payroll = Payroll.ForOrganization(this.CurrentOrganization); if (payroll.Any()) { // There is active payroll // TODO: Taxes for last month and processing for this month } else { EomItem payrollInactive = new EomItem(); payrollInactive.Id = "PayrollInactive"; payrollInactive.Completed = true; payrollInactive.Name = Resources.Pages.Ledgers.EndOfMonth_PayrollInactive; payrollInactive.Icon = "document"; group2.Items.Add(payrollInactive); } if (group2.Items.Count > 0) { ItemGroups.Add(group2); } // Group: Closure of Ledgers and Annual Reports int lastClosedYear = CurrentOrganization.Parameters.FiscalBooksClosedUntilYear; if (lastClosedYear - 1 < DateTime.UtcNow.Year) { EomItemGroup groupReports = new EomItemGroup(); groupReports.Header = Resources.Pages.Ledgers.EndOfMonth_Header_AnnualReports; EomItem itemCloseYear = new EomItem(); itemCloseYear.Id = "CloseLedgers"; itemCloseYear.Callback = "CloseLedgers"; itemCloseYear.Icon = "document"; itemCloseYear.Name = String.Format(Resources.Pages.Ledgers.EndOfMonth_CloseLedgersFor, lastClosedYear + 1); groupReports.Items.Add(itemCloseYear); ItemGroups.Add(groupReports); } }