Ejemplo n.º 1
0
        public static void RebudgetItem(string recordId, int newAccountId)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();

            IPayable         payable    = PayableFromRecordId(recordId);
            FinancialAccount newAccount = FinancialAccount.FromIdentity(newAccountId);

            if (payable.Budget.OrganizationId != authData.CurrentOrganization.Identity ||
                payable.Budget.OwnerPersonId != authData.CurrentUser.Identity ||
                newAccount.OrganizationId != authData.CurrentOrganization.Identity)
            {
                throw new UnauthorizedAccessException();
            }

            payable.SetBudget(newAccount, authData.CurrentUser);
        }
    protected void ButtonAutoBalance_Click(object sender, EventArgs e)
    {
        Person    currentUser = Person.FromIdentity(Int32.Parse(HttpContext.Current.User.Identity.Name));
        Authority authority   = currentUser.GetAuthority();

        if (!authority.HasPermission(Permission.CanDoEconomyTransactions, Int32.Parse(this.DropOrganizations.SelectedValue), -1, Authorization.Flag.ExactOrganization))
        {
            ScriptManager.RegisterStartupScript(this, Page.GetType(), "validationfailed",
                                                "alert ('You do not have access to changing financial records.');",
                                                true);
            return;
        }


        if (this.DropAutoBalanceAccount.SelectedValue == "0")
        {
            ScriptManager.RegisterStartupScript(this, Page.GetType(), "validationfailed",
                                                "alert ('Please select an account to auto-balance against.');",
                                                true);
            return;
        }

        FinancialAccount autoBalanceAccount = FinancialAccount.FromIdentity(Int32.Parse(this.DropAutoBalanceAccount.SelectedValue));

        if (this.GridTransactions.SelectedIndexes.Count == 0)
        {
            ScriptManager.RegisterStartupScript(this, Page.GetType(), "validationfailed",
                                                "alert ('Please select one or more transactions to auto-balance.');",
                                                true);

            return;
        }

        foreach (string indexString in this.GridTransactions.SelectedIndexes)
        {
            int index         = Int32.Parse(indexString);
            int transactionId = (int)this.GridTransactions.MasterTableView.DataKeyValues[index]["Identity"];

            FinancialTransaction transaction = FinancialTransaction.FromIdentity(transactionId);

            transaction.AddRow(autoBalanceAccount, -transaction.Rows.AmountCentsTotal, currentUser);
        }

        PopulateGrid();
        this.GridTransactions.Rebind();
        this.DropAutoBalanceAccount.SelectedValue = "0";
    }
        private static ExpensifyOutputRecord[] FormatExpensifyOutputRecords(List <ExpensifyRecord> recordList)
        {
            List <ExpensifyOutputRecord> outputRecords = new List <ExpensifyOutputRecord>();

            const string doxString =
                "<img src='/Images/Icons/iconshock-search-256px.png' onmouseover=\"this.src='/Images/Icons/iconshock-search-hot-256px.png';\" onmouseout=\"this.src='/Images/Icons/iconshock-search-256px.png';\" firstDocId='{0}' class='LocalIconViewDoc' style='cursor:pointer' height='20' width='20' />";

            const string editString =
                "<img src='/Images/Icons/iconshock-wrench-128x96px-centered.png' height='18' width='24' class='LocalEditExpenseClaim' data-guid='{0}' />";

            foreach (ExpensifyRecord record in recordList)
            {
                ExpensifyOutputRecord newRecord = new ExpensifyOutputRecord
                {
                    Description     = record.CategoryCustom + " / " + record.Description,
                    CreatedDateTime = record.Timestamp.ToString("MMM dd"),
                    Amount          = (record.AmountCents / 100.0).ToString("N2"),
                    AmountVat       = (record.VatCents / 100.0).ToString("N2"),
                    Actions         =
                        String.Format(doxString,
                                      "D" + record.Documents[0].Identity.ToString(CultureInfo.InvariantCulture)) +
                        String.Format(editString, record.Guid),
                    Guid = record.Guid
                };

                if (record.BudgetId != 0)
                {
                    FinancialAccount account = FinancialAccount.FromIdentity(record.BudgetId);
                    newRecord.BudgetText = account.Name;

                    if (account.ParentIdentity != 0)
                    {
                        newRecord.BudgetText = account.Parent.Name + " &raquo; " + account.Name;
                    }
                }
                else
                {
                    newRecord.BudgetText =
                        "<span class='LocalEditExpenseClaim' data-guid='" + record.Guid + "'>" +
                        Resources.Global.Global_DropInits_SelectFinancialAccount + "</span>";
                }

                outputRecords.Add(newRecord);
            }

            return(outputRecords.ToArray());
        }
Ejemplo n.º 4
0
    protected void DropBudgets_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (this.DropBudgets.SelectedValue != "0")
        {
            FinancialAccount selectedBudget = FinancialAccount.FromIdentity(Int32.Parse(this.DropBudgets.SelectedValue));

            if (selectedBudget.GetTree().Count > 1)
            {
                this.DropSubBudget.Populate(selectedBudget);
                this.DropMethod.Items[4].Enabled = true;
            }
            else
            {
                this.DropMethod.Items[4].Enabled = false;
            }
        }
    }
Ejemplo n.º 5
0
    private string ProcessTransferSubBudget()
    {
        int year = DateTime.Today.Year;
        FinancialAccount fromAccount = FinancialAccount.FromIdentity(Int32.Parse(this.DropBudgets.SelectedValue));
        FinancialAccount toAccount   = this.DropSubBudget.SelectedFinancialAccount;
        double           amount      = Double.Parse(this.TextAmount.Text, NumberStyles.Float, new CultureInfo("sv-SE"));
        string           description = this.TextDescription.Text;

        // Transfer the budget

        fromAccount.SetBudget(year, fromAccount.GetBudget(year) + amount); // budgets are negative -- this decreases the budget
        toAccount.SetBudget(year, toAccount.GetBudget(year) - amount);     // budgets are negative -- this increases the budget

        // Set result

        return(amount.ToString("N2") + " was transferred from " + fromAccount.Name + " to " + toAccount.Name + ".");
    }
Ejemplo n.º 6
0
        public static ChangeAccountDataResult SetAccountBudget(int accountId, string budget)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();
            FinancialAccount   account  = FinancialAccount.FromIdentity(accountId);

            if (!PrepareAccountChange(account, authData, false))
            {
                return(new ChangeAccountDataResult
                {
                    Result = ChangeAccountDataOperationsResult.NoPermission
                });
            }

            Int64 newTreeBudget;

            budget = budget.Replace("%A0", "%20"); // some very weird browser space-to-otherspace translation weirds out number parsing
            budget = HttpContext.Current.Server.UrlDecode(budget);

            if (budget.Trim().Length > 0 && Int64.TryParse(budget, NumberStyles.Currency, CultureInfo.CurrentCulture, out newTreeBudget))
            {
                newTreeBudget *= 100; // convert to cents

                int year = DateTime.Today.Year;
                FinancialAccounts accountTree         = account.GetTree();
                Int64             currentTreeBudget   = accountTree.GetBudgetSumCents(year);
                Int64             currentSingleBudget = account.GetBudgetCents(year);
                Int64             suballocatedBudget  = currentTreeBudget - currentSingleBudget;

                Int64 newSingleBudget = newTreeBudget - suballocatedBudget;

                account.SetBudgetCents(DateTime.Today.Year, newSingleBudget);
                return(new ChangeAccountDataResult
                {
                    Result = ChangeAccountDataOperationsResult.Changed,
                    NewData = (newTreeBudget / 100).ToString("N0", CultureInfo.CurrentCulture)
                });
            }
            else
            {
                return(new ChangeAccountDataResult
                {
                    Result = ChangeAccountDataOperationsResult.Invalid
                });
            }
        }
Ejemplo n.º 7
0
    private string ProcessExpenseClaim()
    {
        int year = DateTime.Today.Year;
        FinancialAccount account     = FinancialAccount.FromIdentity(Int32.Parse(this.DropBudgets.SelectedValue));
        string           expenseName = this.TextDescription.Text;
        Person           claimer     = this.ComboClaimPerson.SelectedPerson;
        Int64            amountCents = (Int64)(Double.Parse(this.TextAmount.Text, NumberStyles.Float, new CultureInfo("sv-SE")) * 100);

        // Create the expense claim record

        ExpenseClaim newClaim = ExpenseClaim.Create(claimer, Organization.PPSE, account, DateTime.Today, expenseName, amountCents);

        newClaim.Claimed = false;
        newClaim.Attest(_currentUser);

        return("The claim was created and pre-attested. " + claimer.Canonical +
               " has it in the list of approved expenses.");
    }
Ejemplo n.º 8
0
        public static JsonAccountData GetAccountData(int accountId)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();

            FinancialAccount account = FinancialAccount.FromIdentity(accountId);

            if (account.OrganizationId != authData.CurrentOrganization.Identity)
            {
                throw new UnauthorizedAccessException("A million nopes");
            }

            FinancialAccounts accountTree = account.GetTree();
            int year = DateTime.Today.Year;

            JsonAccountData result = new JsonAccountData();

            result.AccountName       = account.Name;
            result.ParentAccountId   = account.ParentIdentity;
            result.ParentAccountName = account.ParentFinancialAccountId == 0
                                           ? Resources.Global.ResourceManager.GetString("Financial_" +
                                                                                        account.AccountType.ToString())
                                           : account.Parent.Name;
            result.Expensable            = account.Expensable;
            result.Administrative        = account.Administrative;
            result.Active                = account.Active;
            result.Open                  = account.Open;
            result.AccountOwnerName      = account.OwnerPersonId != 0 ? account.Owner.Name : Resources.Global.Global_NoOwner;
            result.AccountOwnerAvatarUrl = account.OwnerPersonId != 0
                                               ? account.Owner.GetSecureAvatarLink(24)
                                               : "/Images/Icons/iconshock-warning-24px.png";
            result.Budget = (accountTree.GetBudgetSumCents(year) / 100L).ToString("N0", CultureInfo.CurrentCulture);

            if (account.AccountType == FinancialAccountType.Asset || account.AccountType == FinancialAccountType.Debt)
            {
                result.Balance = (accountTree.GetDeltaCents(new DateTime(1900, 1, 1), new DateTime(year + 1, 1, 1)) / 100L).ToString("N0");
            }
            else
            {
                result.Balance = (-accountTree.GetDeltaCents(new DateTime(year, 1, 1), new DateTime(year + 1, 1, 1)) / 100L).ToString("N0");
            }
            result.CurrencyCode = account.Organization.Currency.Code;

            return(result);
        }
Ejemplo n.º 9
0
    private void RedrawForNewAccount()
    {
        if (!_authority.HasPermission(Permission.CanDoEconomyTransactions, _organizationId, -1, Authorization.Flag.ExactOrganization))
        {
            CreateTransactionPanel.Visible = false;
            ScriptManager.RegisterStartupScript(this, Page.GetType(), "getlost",
                                                "alert ('You do not have access to financial records.');", true);
            return;
        }
        int accountId = Int32.Parse(this.DropAccounts.SelectedValue);

        if (this.DateStart.SelectedDate > this.DateEnd.SelectedDate)
        {
            DateTime largerDate = (DateTime)this.DateStart.SelectedDate;
            this.DateStart.SelectedDate = this.DateEnd.SelectedDate;
            this.DateEnd.SelectedDate   = largerDate;
        }

        PopulateGrid(accountId, (DateTime)this.DateStart.SelectedDate, (DateTime)this.DateEnd.SelectedDate);
        this.GridTransactions.Rebind();

        if (accountId != 0)
        {
            FinancialAccount account = FinancialAccount.FromIdentity(accountId);

            this.LabelTransactionsTitle.Text = "Transactions in account '" + account.Name + "'";


            // Hide the accounts dropdown in "Create Transaction" and replace it with a static account name

            this.DropAccountsCreate.Visible       = false;
            this.LabelAccountCreate.Visible       = true;
            this.DropAccountsCreate.SelectedValue = accountId.ToString();
            this.LabelAccountCreate.Text          = account.Name;
        }
        else
        {
            this.LabelTransactionsTitle.Text = "No account selected.";
            this.DropAccountsCreate.Visible  = true;
            this.LabelAccountCreate.Visible  = false;
            this.LabelAccountCreate.Text     = "";
        }
    }
Ejemplo n.º 10
0
        public static bool SetAccountName(int accountId, string name)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();
            FinancialAccount   account  = FinancialAccount.FromIdentity(accountId);

            if (account.Name == name)
            {
                // no change
                return(true);
            }

            if (!PrepareAccountChange(account, authData, true))
            {
                return(false);
            }

            account.Name = name;
            return(true);
        }
Ejemplo n.º 11
0
    protected void ButtonSelectBudget_Click(object sender, EventArgs e)
    {
        ViewState[this.ClientID + "_BudgetId"] = this.DropBudgets.SelectedValue;
        this.HiddenInitBudgetId.Value          = this.DropBudgets.SelectedValue;
        ViewState[this.ClientID + "_Year"]     = this.DropYears.SelectedValue;
        this.HiddenInitYear.Value = this.DropYears.SelectedValue;

        _account = FinancialAccount.FromIdentity(Int32.Parse(this.DropBudgets.SelectedValue));
        _year    = Int32.Parse(this.DropYears.SelectedValue);

        PopulateBudgetData();

        bool enableChanges = Int32.Parse(this.DropYears.SelectedValue) >= DateTime.Today.Year;

        this.ButtonReallocate.Enabled  = enableChanges;
        this.ButtonSavePredict.Enabled = enableChanges;

        RebindTooltips();
    }
Ejemplo n.º 12
0
    protected void Page_Load(object sender, EventArgs e)
    {
        attestationRights = GetAttestationRights();
        this.ComboClaimPerson.Authority  = _currentUser.GetAuthority();
        this.ComboBudgetPerson.Authority = _currentUser.GetAuthority();

        if (!Page.IsPostBack)
        {
            this.DropMethod.Style [HtmlTextWriterStyle.Width] = "300px";

            // Populate

            foreach (int budgetId in attestationRights.Keys)
            {
                this.DropBudgets.Items.Add(new ListItem(FinancialAccount.FromIdentity(budgetId).Name, budgetId.ToString()));
            }

            this.LabelForTheItem.Text = "for the expense claim, purchase order, budget, or transfer order";
        }
    }
    protected void DropOrganizations_SelectedIndexChanged(object sender, EventArgs e)
    {
        int          organizationId = Int32.Parse(this.DropOrganizations.SelectedValue);
        Organization organization   = Organization.FromIdentity(organizationId);

        // TODO: Security parsing
        this.DropAssetAccount.Items.Clear();
        this.DropAutoDeposits.Items.Clear();
        this.DropAutoWithdrawals.Items.Clear();

        if (organizationId == PPOrgId && _authority.HasPermission(Permission.CanDoEconomyTransactions, PPOrgId, -1, Authorization.Flag.ExactOrganization))
        {
            // TODO: Populate from a database table instead

            FinancialAccount assetAccount  = organization.FinancialAccounts.AssetsBankAccountMain;
            FinancialAccount incomeAccount = organization.FinancialAccounts.IncomeDonations;
            FinancialAccount costAccount   = organization.FinancialAccounts.CostsBankFees;

            this.DropAssetAccount.Items.Add(new ListItem(assetAccount.Name, assetAccount.Identity.ToString()));
            this.DropAssetAccount.Items.Add(new ListItem("Paypal", organization.FinancialAccounts.AssetsPaypal.Identity.ToString()));
            this.DropAutoDeposits.Items.Add(new ListItem(incomeAccount.Name, incomeAccount.Identity.ToString()));
            this.DropAutoWithdrawals.Items.Add(new ListItem(costAccount.Name, costAccount.Identity.ToString()));
            this.TextDepositLimit.Text    = "1000";
            this.TextWithdrawalLimit.Text = "0";
        }

        else if (organizationId == 55)
        {
            // Rick's sandbox. Please leave in code for the time being.

            FinancialAccount assetAccount  = FinancialAccount.FromIdentity(60);
            FinancialAccount incomeAccount = FinancialAccount.FromIdentity(63);
            FinancialAccount costAccount   = FinancialAccount.FromIdentity(65);

            this.DropAssetAccount.Items.Add(new ListItem(assetAccount.Name, assetAccount.Identity.ToString()));
            this.DropAutoDeposits.Items.Add(new ListItem(incomeAccount.Name, incomeAccount.Identity.ToString()));
            this.DropAutoWithdrawals.Items.Add(new ListItem(costAccount.Name, costAccount.Identity.ToString()));
            this.TextDepositLimit.Text    = "7500";
            this.TextWithdrawalLimit.Text = "0";
        }
    }
Ejemplo n.º 14
0
    protected void Page_Init(object sender, EventArgs e)
    {
        // In case we're in a postback, we need to recreate the suballocation controls in order for the viewstate to be recaptured.
        // But we don't have the viewstate in Init, yet. Still, we must have it here to recapture ViewState.
        //
        // The solution is to use hidden fields with the information we need to recreate the controls and then read them directly
        // from the Request object.

        string accountIdString = Request["ctl00$BodyContent$HiddenInitBudgetId"];
        string yearString      = Request["ctl00$BodyContent$HiddenInitYear"];

        if (!string.IsNullOrEmpty(accountIdString))
        {
            _account = FinancialAccount.FromIdentity(Int32.Parse(accountIdString));
            _year    = Int32.Parse(yearString);

            InitSuballocation(false);
        }

        // If these are not present in the Request objects, the suballocation controls will be created in Page_Load without postback values.
    }
Ejemplo n.º 15
0
        public static bool SetAccountOwner(int accountId, int newOwnerId)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();
            FinancialAccount   account  = FinancialAccount.FromIdentity(accountId);

            if (!PrepareAccountChange(account, authData, false))
            {
                return(false);
            }

            Person newOwner = Person.FromIdentity(newOwnerId);

            // Verify that authdata.AuthenticatedPerson can see personId, or this can be exploited to enumerate all people

            if (!authData.Authority.CanSeePerson(newOwner))
            {
                throw new ArgumentException("No such person identity");
            }

            account.Owner = newOwner;
            return(true);
        }
Ejemplo n.º 16
0
    private string ProcessCreateSubBudget()
    {
        int year = DateTime.Today.Year;

        FinancialAccount parentAccount = FinancialAccount.FromIdentity(Int32.Parse(this.DropBudgets.SelectedValue));
        string           budgetName    = this.TextDescription.Text;
        Person           owner         = this.ComboBudgetPerson.SelectedPerson;
        double           currentBudget = parentAccount.GetBudget(year);
        double           amount        = Double.Parse(this.TextAmount.Text, NumberStyles.Float, new CultureInfo("sv-SE"));

        FinancialAccount account = FinancialAccount.Create(Organization.PPSEid, budgetName, FinancialAccountType.Cost,
                                                           parentAccount.Identity);

        account.Owner = owner;
        account.SetBudget(year, -amount);                      // cost accounts have a negative budget
        parentAccount.SetBudget(year, currentBudget + amount); // cost accounts have a negative budget -- this will LOWER the budget

        return("The budget " + budgetName + " was created, owned by " + owner.Canonical +
               " and with an initial budget for " + year.ToString() + " of " +
               amount.ToString("N2") + ". Do not forget to instruct " + (owner.IsFemale? "her" : "him") +
               " on the duties associated, such as attesting expenses, etc.");
    }
Ejemplo n.º 17
0
        public static AjaxCallAutomationDataResult SetAccountAutomationProfile(int accountId, int profileId)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();
            FinancialAccount   account  = FinancialAccount.FromIdentity(accountId);


            if (account.OrganizationId != authData.CurrentOrganization.Identity)
            {
                throw new UnauthorizedAccessException("A million nopes");
            }

            if (
                !authData.Authority.HasAccess(new Access(authData.CurrentOrganization, AccessAspect.BookkeepingDetails,
                                                         AccessType.Write)))
            {
                throw new UnauthorizedAccessException("No");
            }

            account.AutomationProfileId = profileId;

            AjaxCallAutomationDataResult result = new AjaxCallAutomationDataResult();

            result.Success = true;
            result.Data    = GetAccountAutomationData(profileId);
            result.Data.NonPresentationCurrency =
                (result.Data.Profile.CurrencyId != authData.CurrentOrganization.Currency.Identity);

            if (result.Data.NonPresentationCurrency)
            {
                account.ForeignCurrency = Currency.FromCode(result.Data.AutomationCurrencyCode);
            }
            else
            {
                account.ForeignCurrency = null;
            }

            return(result);
        }
Ejemplo n.º 18
0
        public static bool AddTransactionRow(int txId, int accountId, string amountString)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();

            if (
                !authData.Authority.HasAccess(new Access(authData.CurrentOrganization,
                                                         AccessAspect.Bookkeeping, AccessType.Write)))
            {
                return(false); // fail
            }

            FinancialTransaction transaction = FinancialTransaction.FromIdentity(txId);

            if (authData.CurrentOrganization.Parameters.FiscalBooksClosedUntilYear >= transaction.DateTime.Year)
            {
                return(false); // can't edit closed books
            }

            FinancialAccount account = FinancialAccount.FromIdentity(accountId);

            Double amountFloat = Double.Parse(amountString);
            Int64  amountCents = (Int64)(amountFloat * 100.0);

            if (account.OrganizationId != authData.CurrentOrganization.Identity)
            {
                throw new InvalidOperationException("Account/Organization mismatch");
            }

            if (amountCents == 0)
            {
                return(false);
            }

            transaction.AddRow(account, amountCents, authData.CurrentUser);

            return(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);
        }
Ejemplo n.º 20
0
        protected void ButtonRequest_Click(object sender, EventArgs e)
        {
            // The data has been validated client-side already. We'll throw unfriendly exceptions if invalid data is passed here.
            // People who choose to disable JavaScript and then submit bad input almost deserve to be hurt.

            Int64 amountCents = (Int64)(this.CurrencyAmount.Value * 100.0);

            string description = this.TextPurpose.Text;

            FinancialAccount budget = FinancialAccount.FromIdentity(Int32.Parse(Request.Form["DropBudgets"]));

            // sanity check

            if (budget.Organization.Identity != CurrentOrganization.Identity)
            {
                throw new InvalidOperationException("Budget-organization mismatch; won't file expense claim");
            }

            // Store bank details for current user

            CurrentUser.BankName     = this.TextBank.Text;
            CurrentUser.BankClearing = this.TextClearing.Text;
            CurrentUser.BankAccount  = this.TextAccount.Text;

            // Get documents; check that documents have been uploaded

            Documents documents = Documents.RecentFromDescription(this.FileUpload.GuidString);

            if (documents.Count == 0)
            {
                throw new InvalidOperationException("No documents uploaded");
            }

            ExpenseClaim claim = ExpenseClaim.Create(CurrentUser, CurrentOrganization, budget, DateTime.UtcNow,
                                                     description, amountCents);

            foreach (int tagSetId in this._tagSetIds)
            {
                string selectedTagString =
                    Request.Form["DropTags" + tagSetId.ToString(CultureInfo.InvariantCulture)];

                if (!String.IsNullOrEmpty(selectedTagString))
                {
                    int selectedTagType = Int32.Parse(selectedTagString);
                    if (selectedTagType != 0)
                    {
                        claim.FinancialTransaction.CreateTag(
                            FinancialTransactionTagType.FromIdentity(selectedTagType),
                            CurrentUser);
                    }
                }
            }

            documents.SetForeignObjectForAll(claim);

            string successMessage = string.Format(Resources.Pages.Financial.FileExpenseClaim_SuccessMessagePartOne,
                                                  CurrentOrganization.Currency.Code,
                                                  amountCents / 100.0,
                                                  budget.Name);

            if (budget.OwnerPersonId != CurrentUser.Identity)
            {
                successMessage += "<br/><br/>" + Resources.Pages.Financial.FileExpenseClaim_SuccessMessagePartTwo +
                                  "<br/>";
            }
            else
            {
                successMessage += "<br/><br/>" +
                                  Resources.Pages.Financial.FileExpenseClaim_SuccessMessagePartTwoOwnBudget +
                                  "<br/>";
                claim.Attest(CurrentUser);
            }

            Response.AppendCookie(new HttpCookie("DashboardMessage", HttpUtility.UrlEncode(successMessage)));

            // Redirect to dashboard

            Response.Redirect("/", true);
        }
Ejemplo n.º 21
0
    protected void Page_Load(object sender, EventArgs e)
    {
        FinancialAccount bankAccount = FinancialAccount.FromIdentity(29);
        Organization     euroPirates = Organization.FromIdentity(7);

        FinancialTransactions unbalancedTransactions = FinancialTransactions.GetUnbalanced(euroPirates);

        // assume all in bank account

        foreach (FinancialTransaction transaction in unbalancedTransactions)
        {
            if (transaction.Description[0] == 'H' && Char.IsDigit(transaction.Description[1]) &&
                transaction.Rows.BalanceCentsDelta > 0)
            {
                // outbound intl invoice. Add an untracked intl invoice 10 days prior, map it to this

                OutboundInvoice newInvoice = OutboundInvoice.Create(euroPirates,
                                                                    transaction.DateTime, euroPirates.FinancialAccounts.IncomeSales, "Untracked",
                                                                    "*****@*****.**", string.Empty, euroPirates.Currency, false, string.Empty, Person.FromIdentity(1));
                newInvoice.AddItem("Untracked item", transaction.Rows.BalanceCentsDelta);

                // Doesn't close

                // Add transaction

                // Create the financial transaction with rows

                FinancialTransaction invoiceTransaction =
                    FinancialTransaction.Create(euroPirates.Identity, transaction.DateTime.AddDays(-10),
                                                "Outbound Invoice #" + newInvoice.Identity);

                invoiceTransaction.AddRow(euroPirates.FinancialAccounts.AssetsOutboundInvoices, newInvoice.AmountCents,
                                          null);
                invoiceTransaction.AddRow(euroPirates.FinancialAccounts.IncomeSales, -newInvoice.AmountCents, null);
                invoiceTransaction.Dependency = newInvoice;

                transaction.AddRow(euroPirates.FinancialAccounts.AssetsOutboundInvoices, -newInvoice.AmountCents, null);

                Payment payment = Payment.CreateSingle(euroPirates, transaction.DateTime, euroPirates.Currency,
                                                       newInvoice.AmountCents, newInvoice, null);

                transaction.Dependency = payment.Group;
                payment.Group.Open     = false;
            }

            if ((transaction.Description == "Kostnad" || transaction.Description == "Bank charges") && transaction.Rows.BalanceCentsDelta < 0 &&
                transaction.Rows.BalanceCentsDelta > -125000)
            {
                // Bank fee.

                transaction.AddRow(euroPirates.FinancialAccounts.CostsBankFees, -transaction.Rows.BalanceCentsDelta,
                                   null);
            }

            if (transaction.Description.StartsWith("Paypal "))
            {
                // Bank fee.

                transaction.AddRow(euroPirates.FinancialAccounts.CostsBankFees, -transaction.Rows.BalanceCentsDelta,
                                   null);
            }
        }

        Payouts.AutomatchAgainstUnbalancedTransactions(euroPirates);
    }
Ejemplo n.º 22
0
        protected static ImportStats ProcessImportedData(ImportResult import, Organization organization, Person importingPerson)
        {
            FinancialAccount paysonAccount = FinancialAccount.FromIdentity(99);   // HACK -- need something more sophisticated long run that allows different accounts for different orgs
            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(2010, 4, 1))
                {
                    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,
                                                                      paysonAccount.Identity, amountCents,
                                                                      row.Comment, importKey,
                                                                      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[paysonAccount.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);
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.ContentType = "application/json";

            string accountIdString = Request.QueryString["AccountId"];
            string yearString      = Request.QueryString["Year"];
            string monthString     = Request.QueryString["Month"];

            string emptyResponse = "[{\"id\":\"-\",\"description\":\"" +
                                   JsonSanitize(Resources.Pages.Ledgers.InspectLedgers_PleaseSelectAccount) + "\"}]";

            if (string.IsNullOrEmpty(accountIdString) || string.IsNullOrEmpty(yearString) ||
                string.IsNullOrEmpty(monthString) || accountIdString == "undefined")
            {
                Response.Output.WriteLine(emptyResponse);
                Response.End();
            }

            int accountId = Int32.Parse(accountIdString);
            int year      = Int32.Parse(yearString);
            int month     = Int32.Parse(monthString);

            DateTime dawnOfMankind = new DateTime(1901, 1, 1);

            // no org will ever import bookkeeping from before this date

            if (accountId <= 0)
            {
                Response.Output.WriteLine(emptyResponse);
                Response.End();
            }

            FinancialAccount account = FinancialAccount.FromIdentity(accountId);

            if (account.OrganizationId != CurrentOrganization.Identity)
            {
                throw new UnauthorizedAccessException("All the nopes in the world");
            }

            if (!CurrentAuthority.HasAccess(new Access(CurrentOrganization, AccessAspect.Bookkeeping, AccessType.Read)))
            {
                throw new UnauthorizedAccessException("Access denied because security tokens say so");
            }

            DateTime periodStart, periodEnd;
            DateTime balanceStart       = dawnOfMankind;
            bool     zeroStart          = false;
            bool     zeroEnd            = false;
            bool     displayDescription = CurrentAuthority.HasAccess(new Access(CurrentOrganization, AccessAspect.BookkeepingDetails, AccessType.Read));
            bool     canSeeAudit        = CurrentAuthority.HasAccess(new Access(CurrentOrganization, AccessAspect.Auditing, AccessType.Read));

            if (month > 0 && month <= 12)
            {
                periodStart = new DateTime(year, month, 1);
                periodEnd   = periodStart.AddMonths(1);
                if (account.AccountType == FinancialAccountType.Income ||
                    account.AccountType == FinancialAccountType.Cost)
                {
                    balanceStart = new DateTime(year, 1, 1);

                    if (month == 1)
                    {
                        zeroStart = true;
                    }
                    if (month == 12)
                    {
                        zeroEnd = true;
                    }
                }
            }
            else if (month > 20 && month < 25) // quarters 1..4 are coded as months 21..24
            {
                periodStart = new DateTime(year, (month - 21) * 3 + 1, 1);
                periodEnd   = periodStart.AddMonths(3);
                if (account.AccountType == FinancialAccountType.Income ||
                    account.AccountType == FinancialAccountType.Cost)
                {
                    balanceStart = new DateTime(year, 1, 1);

                    if (month == 21)
                    {
                        zeroStart = true;
                    }
                    if (month == 24)
                    {
                        zeroEnd = true;
                    }
                }
            }
            else if (month == 31) // "whole year" is coded as month 31
            {
                periodStart = new DateTime(year, 1, 1);
                periodEnd   = new DateTime(year + 1, 1, 1);
                if (account.AccountType == FinancialAccountType.Income ||
                    account.AccountType == FinancialAccountType.Cost)
                {
                    zeroStart = true;
                    zeroEnd   = true;
                }
            }
            else
            {
                throw new ArgumentException("Invalid month supplied: " + month.ToString(CultureInfo.InvariantCulture));
            }


            FinancialAccountRows rows = account.GetRows(periodStart, periodEnd);

            StringBuilder result = new StringBuilder(16384);

            Int64  runningBalance = 0L;
            string startString    = Resources.Pages.Ledgers.InspectLedgers_InboundBalanceZero;
            string endString      = Resources.Pages.Ledgers.InspectLedgers_OutboundBalanceZero;

            if (!zeroStart)
            {
                runningBalance = account.GetDeltaCents(balanceStart, periodStart);
                startString    = Resources.Pages.Ledgers.InspectLedgers_InboundBalance;
            }
            if (!zeroEnd)
            {
                endString = Resources.Pages.Ledgers.InspectLedgers_OutboundBalance;
            }
            else if (periodEnd > DateTime.Now)
            {
                // account is zeroed at end of this period, but we're not yet at end of period, so add a "to date" disclaimer
                endString = Resources.Pages.Ledgers.InspectLedgers_OutboundBalanceZeroToDate;
            }

            result.Append("{" +
                          String.Format("\"description\":\"{0}\",\"balance\":\"{1:N0}\"", JsonSanitize(startString),
                                        runningBalance / 100.0) + "},");

            foreach (FinancialAccountRow row in rows)
            {
                string creditString = string.Empty;
                string debitString  = string.Empty;
                string description  = row.Description;

                if (!displayDescription)
                {
                    description = Resources.Pages.Ledgers.InspectLedgers_TxDetail_DescriptionWithheld;
                }

                if (row.AmountCents < 0)
                {
                    creditString = String.Format("{0:N0}", row.AmountCents / 100.0);
                }
                else if (row.AmountCents > 0)
                {
                    debitString = String.Format("{0:N0}", row.AmountCents / 100.0);
                }

                runningBalance += row.AmountCents;

                string actionHtml = String.Format(
                    "<img src=\"/Images/Icons/iconshock-magnifyingglass-16px.png\" class=\"LocalIconInspect\" txId=\"{0}\" />", row.FinancialTransactionId.ToString(CultureInfo.InvariantCulture));

                if (canSeeAudit)
                {
                    actionHtml +=
                        String.Format(
                            "&nbsp;<img src=\"/Images/Icons/iconshock-flag-white-16px.png\" class=\"LocalIconFlag\" txId=\"{0}\" />",
                            row.FinancialTransactionId.ToString(CultureInfo.InvariantCulture));
                }

                result.Append("{" + String.Format(
                                  "\"id\":\"{0:N0}\",\"datetime\":\"{1:MMM-dd HH:mm}\",\"description\":\"{2}\"," +
                                  "\"deltaPos\":\"{3}\",\"deltaNeg\":\"{4}\",\"balance\":\"{5:N0}\",\"action\":\"{6}\"",
                                  row.FinancialTransactionId,
                                  row.TransactionDateTime,
                                  JsonSanitize(description),
                                  debitString,
                                  creditString,
                                  runningBalance / 100.0,
                                  JsonSanitize(actionHtml)) + "},");
            }

            if (rows.Count == 0)
            {
                // If there are no transactions in this time period, say so

                result.Append("{\"description\":\"" +
                              JsonSanitize(Resources.Pages.Ledgers.InspectLedgers_NoTransactions) + "\"},");
            }

            result.Append("{" +
                          String.Format("\"description\":\"{0}\",\"balance\":\"{1:N0}\"", JsonSanitize(endString),
                                        runningBalance / 100.0) + "},");

            Response.Output.WriteLine("[" + result.ToString().TrimEnd(',') + "]");
            Response.End();
        }
Ejemplo n.º 24
0
    protected void Page_Load(object sender, EventArgs e)
    {
        string documentIdString = Request.QueryString["DocumentId"];
        int    documentId       = Int32.Parse(documentIdString);

        Document document = Document.FromIdentity(documentId);

        //Orgid is needed to safely verify permission
        int orgId = Organization.PPSEid;

        bool hasPermission = false;

        switch (document.DocumentType)
        {
        case DocumentType.FinancialTransaction:
        {
            //TODO: Get the orgId from foreign object
            if (_authority.HasPermission(Permission.CanSeeEconomyDetails, orgId, -1, Authorization.Flag.ExactOrganization))
            {
                hasPermission = true;
            }
        }
        break;

        case DocumentType.ExpenseClaim:
        case DocumentType.InboundInvoice:
        {
            int budgetId = 0;

            if (document.DocumentType == DocumentType.ExpenseClaim)
            {
                ExpenseClaim claim = (ExpenseClaim)document.ForeignObject;
                orgId    = claim.Budget.OrganizationId;
                budgetId = claim.BudgetId;
            }
            else
            {
                InboundInvoice invoice = (InboundInvoice)document.ForeignObject;
                orgId    = invoice.Budget.OrganizationId;
                budgetId = invoice.BudgetId;
            }

            if (_authority.HasPermission(Permission.CanSeeEconomyDetails, orgId, -1, Authorization.Flag.ExactOrganization))
            {
                hasPermission = true;
                break;
            }

            if (FinancialAccount.FromIdentity(budgetId).OwnerPersonId == _currentUser.Identity)
            {
                hasPermission = true;
            }
            break;
        }

        case DocumentType.PaperLetter:
        {
            PaperLetter letter = (PaperLetter)document.ForeignObject;

            if (letter.Recipient.Identity == _currentUser.Identity)
            {
                hasPermission = true;     // A letter to the viewer
            }

            // Otherwise, are there overriding permissions, if not addressed to him/her?

            else if (!letter.Personal)
            {
                // Unpersonal paper letter, like a rally permit. Note that bank statements should
                // be considered personal as they contain donors' information in the transaction info.

                if (_authority.HasPermission(Permission.CanSeeInsensitivePaperLetters, letter.OrganizationId, -1, Authorization.Flag.Default))
                {
                    hasPermission = true;
                }
            }
            else if (letter.ToPersonId == 0)
            {
                // Addressed to the organization, not to a specific person, but still personal.
                // Typical examples include political inquiries from private citizens written on
                // paper.

                if (_authority.HasPermission(Permission.CanSeeSensitivePaperLetters, letter.OrganizationId, -1, Authorization.Flag.Default))
                {
                    hasPermission = true;
                }
            }
            else
            {
                // Addressed to a specific individual that is not the viewer, and it's personal.
                // INVOCATION OF THIS CODE IS A BREACH OF THE POSTAL SECRET and should ONLY EVER
                // be done for technical, not operational, reasons and preferably NEVER.

                if (_authority.HasPermission(Permission.CanBreachPostalSecretPaperLetters, letter.OrganizationId, -1, Authorization.Flag.Default))
                {
                    hasPermission = true;
                }
            }
        }
        break;

        case DocumentType.PersonPhoto:
        {
            // These are public

            hasPermission = true;
        }
        break;
        }

        if (!hasPermission)
        {
            throw new Exception("Access is not allowed");
        }

        string serverPath = @"C:\Data\Uploads\PirateWeb"; // TODO: Read from web.config

        string contentType = string.Empty;

        if (document.ServerFileName.EndsWith(".pdf"))
        {
            contentType = MediaTypeNames.Application.Pdf;
        }
        else if (document.ServerFileName.EndsWith(".png"))
        {
            contentType = "image/png"; // why isn't this in MediaTypeNames?
        }
        else if (document.ServerFileName.EndsWith(".jpg"))
        {
            contentType = MediaTypeNames.Image.Jpeg;
        }

        Response.ContentType = contentType + "; filename=" + document.ClientFileName;
        Response.TransmitFile(serverPath + Path.DirectorySeparatorChar + document.ServerFileName);
    }
        protected void Page_Load(object sender, EventArgs e)
        {
            string documentIdString = Request.QueryString["DocId"];
            int    documentId       = Int32.Parse(documentIdString);

            string documentDownloadName = Request.QueryString["DocName"];

            documentDownloadName = documentDownloadName.Replace("\"", "'");

            Document document = Document.FromIdentity(documentId);

            //Orgid is needed to safely verify permission
            int orgId = 0; // initialize to invalid

            bool   hasPermission  = false;
            string serverFileName = document.ServerFileName;

            if (document.UploadedByPersonId == this.CurrentAuthority.Person.Identity)
            {
                hasPermission = true; // can always view documents you yourself uploaded
            }

            if (CurrentOrganization.HasOpenLedgers)
            {
                hasPermission = true;
            }


            if (!hasPermission)
            {
                switch (document.DocumentType)
                {
                case DocumentType.FinancialTransaction:
                {
/*
 *                      //TODO: Get the orgId from foreign object
 *                      if (this.CurrentAuthority.HasPermission(Permission.CanSeeEconomyDetails, orgId, -1, Authorization.Flag.ExactOrganization))
 *                      {
 *                          hasPermission = true;
 *                      }*/
                }
                break;

                case DocumentType.ExpenseClaim:
                case DocumentType.InboundInvoice:
                case DocumentType.OutboundInvoice:
                {
                    int budgetId = 0;

                    if (document.DocumentType == DocumentType.ExpenseClaim)
                    {
                        ExpenseClaim claim = (ExpenseClaim)document.ForeignObject;
                        orgId    = claim.Budget.OrganizationId;
                        budgetId = claim.BudgetId;
                    }
                    else if (document.DocumentType == DocumentType.InboundInvoice)
                    {
                        InboundInvoice invoice = (InboundInvoice)document.ForeignObject;
                        orgId    = invoice.Budget.OrganizationId;
                        budgetId = invoice.BudgetId;
                    }
                    else
                    {
                        OutboundInvoice invoice = (OutboundInvoice)document.ForeignObject;
                        orgId    = invoice.OrganizationId;
                        budgetId = invoice.BudgetId;
                    }


                    FinancialAccount budget = FinancialAccount.FromIdentity(budgetId);

                    if (budget.OwnerPersonId == CurrentUser.Identity || budget.OwnerPersonId == 0)
                    {
                        hasPermission = true;
                        break;
                    }

                    // TODO: Security leak - check CurrentOrganization against Document's org

                    if (
                        CurrentAuthority.HasAccess(new Access(CurrentOrganization, AccessAspect.Financials,
                                                              AccessType.Write)))
                    {
                        hasPermission = true;
                    }

                    /*
                     * if (this.CurrentAuthority.HasPermission(Permission.CanSeeEconomyDetails, orgId, -1, Authorization.Flag.ExactOrganization))
                     * {
                     *  hasPermission = true;
                     *  break;
                     * }*/

                    break;
                }

                case DocumentType.PaperLetter:
                {
                    PaperLetter letter = (PaperLetter)document.ForeignObject;

                    if (letter.Recipient.Identity == CurrentUser.Identity)
                    {
                        hasPermission = true;     // A letter to the viewer
                    }

                    /*
                     * // Otherwise, are there overriding permissions, if not addressed to him/her?
                     *
                     * else if (!letter.Personal)
                     * {
                     *  // Unpersonal paper letter, like a rally permit. Note that bank statements should
                     *  // be considered personal as they contain donors' information in the transaction info.
                     *
                     *  if (this.CurrentAuthority.HasPermission(Permission.CanSeeInsensitivePaperLetters, letter.OrganizationId, -1, Authorization.Flag.Default))
                     *  {
                     *      hasPermission = true;
                     *  }
                     * }
                     * else if (letter.ToPersonId == 0)
                     * {
                     *  // Addressed to the organization, not to a specific person, but still personal.
                     *  // Typical examples include political inquiries from private citizens written on
                     *  // paper.
                     *
                     *  if (this.CurrentAuthority.HasPermission(Permission.CanSeeSensitivePaperLetters, letter.OrganizationId, -1, Authorization.Flag.Default))
                     *  {
                     *      hasPermission = true;
                     *  }
                     * }
                     * else
                     * {
                     *  // Addressed to a specific individual that is not the viewer, and it's personal.
                     *  // INVOCATION OF THIS CODE IS A BREACH OF THE POSTAL SECRET and should ONLY EVER
                     *  // be done for technical, not operational, reasons and preferably NEVER.
                     *
                     *  if (this.CurrentAuthority.HasPermission(Permission.CanBreachPostalSecretPaperLetters, letter.OrganizationId, -1, Authorization.Flag.Default))
                     *  {
                     *      hasPermission = true;
                     *  }
                     * }*/
                }
                break;

                case DocumentType.PersonPhoto:
                case DocumentType.Logo:
                case DocumentType.Artwork:
                {
                    // These are public

                    hasPermission = true;
                }
                break;
                }
            }

            if (!hasPermission)
            {
                throw new Exception("Access is not allowed");
            }

            string contentType = string.Empty;

            string clientFileNameLower = document.ClientFileName.ToLowerInvariant().Trim();
            string serverFileNameLower = document.ServerFileName.ToLowerInvariant().Trim();

            // The "Filename.Contains" here instead of "Filename.EndsWith" is because page counts are added to file names

            if (serverFileNameLower.EndsWith(".png") && clientFileNameLower.Contains(".pdf"))
            {
                // Converted PDF, so cut filename to raw GUID length

                serverFileName        = serverFileName.Substring(0, serverFileName.Length - "-0001.png".Length);
                documentDownloadName += ".pdf";
                contentType           = MediaTypeNames.Application.Pdf;
            }
            else if (clientFileNameLower.EndsWith(".png"))
            {
                contentType           = "image/png"; // why isn't this in MediaTypeNames?
                documentDownloadName += ".png";
            }
            else if (clientFileNameLower.EndsWith(".jpg") || clientFileNameLower.EndsWith(".jpeg"))
            {
                contentType           = MediaTypeNames.Image.Jpeg;
                documentDownloadName += ".jpg";
            }
            else
            {
                int lastDot = clientFileNameLower.LastIndexOf('.');

                if (lastDot > 0)
                {
                    documentDownloadName += clientFileNameLower.Substring(lastDot); // Adds original client extension
                }
            }

            if (documentDownloadName.EndsWith(" 2_1") || documentDownloadName.EndsWith(" 2/1"))
            {
                // Mystery bug

                documentDownloadName = documentDownloadName.Substring(0, documentDownloadName.Length - 4);
            }



            string legacyMarker = string.Empty;

            if (!File.Exists(Document.StorageRoot + serverFileName))
            {
                legacyMarker = "legacy/"; // for some legacy installations, all older files are placed here
            }

            // TODO: If still doesn't exist, perhaps return a friendly error image instead?

            if (!File.Exists(Document.StorageRoot + legacyMarker + serverFileName))
            {
                if (!Debugger.IsAttached) // if running live; ignore FNF errors when debugging
                {
                    throw new FileNotFoundException(Document.StorageRoot + legacyMarker + serverFileName);
                }
                else
                {
                    Response.StatusCode = 404;
                    Response.End();
                    return;
                }
            }

            Response.ContentType = contentType;
            Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + documentDownloadName + "\"");
            Response.TransmitFile(Document.StorageRoot + legacyMarker + serverFileName);
        }
Ejemplo n.º 26
0
        public static ChangeAccountDataResult SetAccountBudget(int accountId, string budget)
        {
            try
            {
                AuthenticationData authData = GetAuthenticationDataAndCulture();
                FinancialAccount   account  = FinancialAccount.FromIdentity(accountId);

                if (!PrepareAccountChange(account, authData, false))
                {
                    return(new ChangeAccountDataResult
                    {
                        Result = ChangeAccountDataOperationsResult.NoPermission
                    });
                }

                Int64 newTreeBudget;
                budget = budget.Replace("%A0", "%20");
                // some very weird browser space-to-otherspace translation weirds out number parsing
                budget = HttpContext.Current.Server.UrlDecode(budget);

                if (budget.Trim().Length > 0 &&
                    Int64.TryParse(budget, NumberStyles.Currency, CultureInfo.CurrentCulture, out newTreeBudget))
                {
                    newTreeBudget *= 100; // convert to cents

                    int year = DateTime.Today.Year;
                    FinancialAccounts accountTree         = account.ThisAndBelow();
                    Int64             currentTreeBudget   = accountTree.GetBudgetSumCents(year);
                    Int64             currentSingleBudget = account.GetBudgetCents(year);
                    Int64             suballocatedBudget  = currentTreeBudget - currentSingleBudget;

                    Int64 newSingleBudget = newTreeBudget - suballocatedBudget;

                    account.SetBudgetCents(DateTime.Today.Year, newSingleBudget);

                    // Once we've set the budget, also update the "yearly result" budget.
                    // The "yearly result" budget isn't shown in the account plan, but is
                    // abstracted to "projected loss" or "projected gain" pseudobudgets.

                    int thisYear = DateTime.UtcNow.Year;
                    FinancialAccounts allProfitLossAccounts   = FinancialAccounts.ForOrganization(authData.CurrentOrganization);
                    Int64             newProfitLossProjection = allProfitLossAccounts.Where(queryAccount => queryAccount.Identity != authData.CurrentOrganization.FinancialAccounts.CostsYearlyResult.Identity).Sum(queryAccount => queryAccount.GetBudgetCents(thisYear));

                    authData.CurrentOrganization.FinancialAccounts.CostsYearlyResult.SetBudgetCents(thisYear, -newProfitLossProjection);

                    return(new ChangeAccountDataResult
                    {
                        Result = ChangeAccountDataOperationsResult.Changed,
                        NewData = (newTreeBudget / 100).ToString("N0", CultureInfo.CurrentCulture)
                    });
                }

                return(new ChangeAccountDataResult
                {
                    Result = ChangeAccountDataOperationsResult.Invalid
                });
            }
            catch (Exception weirdException)
            {
                // Exceptions are happening here in deployment ONLY. We're logging it to find which one and why.
                // TODO: This really needs to be in Logic. DO NOT DO NOT DO NOT call Database layer directly from Site layer.

                SwarmDb.GetDatabaseForWriting()
                .CreateExceptionLogEntry(DateTime.UtcNow, "AccountPlan-SetBudget", weirdException);

                throw;
            }
        }
Ejemplo n.º 27
0
        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;
            }
        }
Ejemplo n.º 28
0
        public static JsonAccountData GetAccountData(int accountId)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();

            FinancialAccount account = FinancialAccount.FromIdentity(accountId);

            if (account.OrganizationId != authData.CurrentOrganization.Identity)
            {
                throw new UnauthorizedAccessException("A million nopes");
            }

            FinancialAccounts accountTree = account.ThisAndBelow();
            int year = DateTime.Today.Year;

            JsonAccountData result = new JsonAccountData();

            if (account.ParentIdentity == 0)
            {
                // if this is a root account, put it under the category root node, which has negative the type id
                result.ParentAccountId = -(int)account.AccountType;
            }
            else
            {
                result.ParentAccountId = account.ParentIdentity;
            }

            result.AccountName = account.Name;

            result.ParentAccountName = account.ParentFinancialAccountId == 0
                ? Global.ResourceManager.GetString("Financial_" +
                                                   account.AccountType)
                : account.Parent.Name;
            result.Expensable            = account.Expensable;
            result.Administrative        = account.Administrative;
            result.Active                = account.Active;
            result.Open                  = account.Open;
            result.AccountOwnerName      = account.OwnerPersonId != 0 ? account.Owner.Name : Global.Global_NoOwner;
            result.AccountOwnerAvatarUrl = account.OwnerPersonId != 0
                ? account.Owner.GetSecureAvatarLink(24)
                : "/Images/Icons/iconshock-warning-24px.png";
            result.Budget = (accountTree.GetBudgetSumCents(year) / 100L).ToString("N0", CultureInfo.CurrentCulture);

            if (account.AccountType == FinancialAccountType.Asset || account.AccountType == FinancialAccountType.Debt)
            {
                result.Balance =
                    (accountTree.GetDeltaCents(new DateTime(1900, 1, 1), new DateTime(year + 1, 1, 1)) / 100L).ToString
                    (
                        "N0");
                result.InitialBalance =
                    ((accountTree.GetDeltaCents(new DateTime(1900, 1, 1),
                                                new DateTime(authData.CurrentOrganization.FirstFiscalYear, 1, 1)) / 100.0).ToString("N2"));
            }
            else
            {
                result.Balance =
                    (-accountTree.GetDeltaCents(new DateTime(year, 1, 1), new DateTime(year + 1, 1, 1)) / 100L)
                    .ToString(
                        "N0");
                result.InitialBalance = "N/A"; // unused
            }
            result.CurrencyCode = account.Organization.Currency.DisplayCode;

            return(result);
        }
Ejemplo n.º 29
0
        public static AjaxCallResult MarkDirectPurchase(int transactionId, int budgetId, string vatAmountString,
                                                        string newDescription, string guid)
        {
            if (transactionId == 0 | budgetId == 0)
            {
                return(new AjaxCallResult {
                    Success = false
                });
            }

            AuthenticationData authData = GetAuthenticationDataAndCulture();

            if (
                !authData.Authority.HasAccess(new Access(authData.CurrentOrganization,
                                                         AccessAspect.BookkeepingDetails)))
            {
                throw new UnauthorizedAccessException();
            }

            FinancialAccount budget = FinancialAccount.FromIdentity(budgetId);

            if (authData.CurrentOrganization.Identity != budget.Organization.Identity)
            {
                throw new UnauthorizedAccessException();
            }

            newDescription = newDescription.Trim();
            if (newDescription.Length < 1)
            {
                return(new AjaxCallResult
                {
                    Success = false,
                    DisplayMessage = Resources.Pages.Ledgers.BalanceTransactions_Error_NeedDescription
                });
            }

            Documents docs = Documents.RecentFromDescription(guid).WhereNotAssociated;

            if (docs.Count < 1)
            {
                return(new AjaxCallResult
                {
                    Success = false,
                    DisplayMessage = Resources.Pages.Ledgers.BalanceTransactions_Error_NeedDocumentation
                });
            }

            Int64 vatCents   = 0;
            bool  vatEnabled = authData.CurrentOrganization.VatEnabled;

            if (vatEnabled)
            {
                try
                {
                    vatCents = Swarmops.Logic.Support.Formatting.ParseDoubleStringAsCents(vatAmountString);
                }
                catch (ArgumentException)
                {
                    return(new AjaxCallResult
                    {
                        Success = false,
                        DisplayMessage = Resources.Pages.Ledgers.BalanceTransactions_Error_VatAmountParseError
                    });

                    throw;
                }
            }

            // We're FINALLY ready to update the transaction

            FinancialTransaction tx = FinancialTransaction.FromIdentity(transactionId);

            tx.Description = newDescription;
            docs.SetForeignObjectForAll(tx);

            Int64 centsDiff = tx.Rows.AmountCentsTotal;

            if (vatEnabled)
            {
                tx.AddRow(authData.CurrentOrganization.FinancialAccounts.AssetsVatInboundUnreported, vatCents, authData.CurrentUser);
                tx.AddRow(budget, (-centsDiff) - vatCents, authData.CurrentUser);
            }
            else
            {
                tx.AddRow(budget, -centsDiff, authData.CurrentUser);
            }

            return(new AjaxCallResult {
                Success = true
            });
        }
Ejemplo n.º 30
0
        public static AjaxUploadCallResult UploadBankTransactionData(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]));

            if (account.OrganizationId != authData.CurrentOrganization.Identity)
            {
                throw new UnauthorizedAccessException();
            }

            Documents documents = Documents.RecentFromDescription(guid);

            // Safeguard 2019-Dec-23: Abort if more than one document (code below needs hardening against concurrent-threads race conditions)

            if (documents.Count != 1)
            {
                throw new NotImplementedException();
            }

            // Load documents and process them as loaded strings, one by one

            foreach (Document document in documents)
            {
                string documentData                = document.GetReader().ReadToEnd();
                ExternalBankDataProfile profile    = account.ExternalBankDataProfile;
                ExternalBankData        loadedData = new ExternalBankData();
                loadedData.Profile = profile;

                try
                {
                    loadedData.LoadData(documentData, authData.CurrentOrganization, account.Currency);
                }
                catch (Exception)
                {
                    return(new AjaxUploadCallResult {
                        Success = false, DisplayMessage = "ERROR_FILEDATAFORMAT"
                    });
                }

                // Start async thread to import the data to the SQL database; the caller must
                // check the status of the import

                string identifier = guid + "-" + itemId + "-" + Guid.NewGuid().ToString();

                /* Thread processThread = new Thread((ThreadStart) AsyncProcesses.ImportExternalTransactionDataThreadStart);
                 * processThread.Start(new AsyncProcesses.ImportExternalTransactionDataArgs {}); */

                return(new AjaxUploadCallResult
                {
                    Success = true,
                    StillProcessing = true,
                    Identifier = identifier
                });
            }

            return(new AjaxUploadCallResult {
                Success = true, StillProcessing = true
            });
        }