Esempio n. 1
0
    private void AddInboundInvoiceEvent(int parentId, InboundInvoice invoice)
    {
        int newId = transactionEvents.Count + 1;

        transactionEvents.Add(new TransactionEvent(newId, parentId, "Invoice #" + invoice.Identity.ToString()));
        transactionEvents.Add(
            new TransactionEvent(newId + 1, newId,
                                 "Supplier: " + invoice.Supplier));
        transactionEvents.Add(
            new TransactionEvent(newId + 2, newId,
                                 "Received: " +
                                 invoice.CreatedDateTime.ToString("yyyy-MM-dd HH:mm")));

        transactionEvents.Add(
            new TransactionEvent(newId + 3, newId,
                                 "Budget: " +
                                 invoice.Budget.Name));

        AddValidations(newId, invoice);

        foreach (Document document in invoice.Documents)
        {
            AddDocumentEvent(newId, document);
        }
    }
Esempio n. 2
0
    protected void GridInvoices_ItemCreated(object sender, GridItemEventArgs e)
    {
        if (e.Item is GridDataItem)
        {
            InboundInvoice invoice = (InboundInvoice)e.Item.DataItem;

            if (invoice == null)
            {
                return;
            }

            Label labelBudgetYear = (Label)e.Item.FindControl("LabelBudgetYear");

            if (invoice.BudgetId == 0)
            {
                labelBudgetYear.Text = "UNBUDGETED!";
            }
            else
            {
                labelBudgetYear.Text = invoice.Budget.Name + ", " + invoice.CreatedDateTime.Year.ToString();
            }


            Controls_v4_DocumentList docList = (Controls_v4_DocumentList)e.Item.FindControl("DocListInvoice");

            docList.Documents = invoice.Documents;


            HyperLink editLink = (HyperLink)e.Item.FindControl("LinkEdit");
            editLink.Attributes["href"]    = "#";
            editLink.Attributes["onclick"] = String.Format("return ShowInboundInvoiceForm('{0}','{1}');",
                                                           invoice.Identity, e.Item.ItemIndex);
        }
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        _invoice = InboundInvoice.FromIdentity(Int32.Parse(Request.QueryString["InboundInvoiceId"]));

        // TODO: Verify authority (economy assistant or budget owner)

        if (!Page.IsPostBack)
        {
            this.LabelInvoiceFrom.Text         = _invoice.Supplier;
            this.LabelInvoiceReceivedDate.Text = _invoice.CreatedDateTime.ToString("yyyy-MM-dd");
            this.LabelAttested.Text            = _invoice.Attested ? "Yes." : "No.";

            this.DropAccounts.Populate(_invoice.Organization, FinancialAccountType.Cost);

            if (_invoice.BudgetId != 0)
            {
                this.DropAccounts.SelectedFinancialAccount = _invoice.Budget;
            }

            this.DateInvoiceDue.SelectedDate = _invoice.DueDate;
            this.TextAmount.Text             = _invoice.Amount.ToString("N2", new CultureInfo("sv-SE"));
        }

        // The DocumentList control does not hold state - yet - so must be initialized always

        this.DocumentList.Documents = Documents.ForObject(_invoice);
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        _invoice = InboundInvoice.FromIdentity(Int32.Parse(Request.QueryString["InboundInvoiceId"]));

        // TODO: Verify authority (economy assistant or budget owner)

        if (!Page.IsPostBack)
        {
            this.LabelInvoiceFrom.Text = _invoice.Supplier;
            this.LabelInvoiceReceivedDate.Text = _invoice.CreatedDateTime.ToString("yyyy-MM-dd");
            this.LabelAttested.Text = _invoice.Attested ? "Yes." : "No.";

            this.DropAccounts.Populate(_invoice.Organization, FinancialAccountType.Cost);

            if (_invoice.BudgetId != 0)
            {
                this.DropAccounts.SelectedFinancialAccount = _invoice.Budget;
            }

            this.DateInvoiceDue.SelectedDate = _invoice.DueDate;
            this.TextAmount.Text = _invoice.Amount.ToString("N2", new CultureInfo("sv-SE"));
        }

        // The DocumentList control does not hold state - yet - so must be initialized always

        this.DocumentList.Documents = Documents.ForObject(_invoice);
    }
Esempio n. 5
0
 public TaskInboundInvoice(InboundInvoice invoice)
     : base(
         invoice.Identity, "Inbound Invoice #" + invoice.Identity, invoice.CreatedDateTime,
         invoice.DueDate.AddDays(-7))
 {
     // empty ctor
 }
Esempio n. 6
0
        private static string GetObjectDetails(IHasIdentity identifiableObject)
        {
            switch (identifiableObject.GetType().Name)
            {
            case "ExpenseClaim":
                ExpenseClaim claim = (ExpenseClaim)identifiableObject;

                return("<strong>" +
                       String.Format(Global.Financial_ExpenseClaimLongSpecification, claim.Identity) +
                       ":</strong> " + claim.Organization.Currency.Code + " " +
                       (claim.AmountCents / 100.0).ToString("N2") + ". " +
                       HttpUtility.HtmlEncode(GetValidationDetails(claim.Validations)) + " " +
                       GetDocumentDetails(claim.Documents, claim));

            case "CashAdvance":
                CashAdvance advance = (CashAdvance)identifiableObject;

                return("<strong>" +
                       String.Format(Global.Financial_CashAdvanceSpecification, advance.Identity) +
                       ":</strong> " + advance.Organization.Currency.Code + " " +
                       (advance.AmountCents / 100.0).ToString("N2") + ". " +
                       HttpUtility.HtmlEncode(GetValidationDetails(advance.Validations)));

            case "InboundInvoice":
                InboundInvoice invoice = (InboundInvoice)identifiableObject;

                return("<strong>" +
                       String.Format(Global.Financial_InboundInvoiceSpecification, invoice.Identity) +
                       ":</strong> " + invoice.Organization.Currency.Code + " " +
                       (invoice.AmountCents / 100.0).ToString("N2") + ". " +
                       GetValidationDetails(invoice.Validations) + " " +
                       GetDocumentDetails(invoice.Documents, invoice));

            case "Salary":
                Salary salary = (Salary)identifiableObject;

                return("<strong>" +
                       String.Format(Global.Financial_SalaryIdentity, salary.Identity) +
                       ":</strong> " +
                       String.Format(Resources.Pages.Ledgers.InspectLedgers_TxDetail_SalaryDetail,
                                     salary.PayrollItem.Organization.Currency.Code,
                                     salary.BaseSalaryCents / 100.0,                             // base salary
                                     (salary.GrossSalaryCents - salary.BaseSalaryCents) / 100.0, // before-tax adjustments
                                     salary.GrossSalaryCents / 100.0,                            // before-tax adjusted salary
                                     salary.SubtractiveTaxCents / 100.0,                         // tax deduction
                                     (salary.NetSalaryCents + salary.SubtractiveTaxCents -
                                      salary.GrossSalaryCents) / 100.0,                          // after-tax adjustments
                                     salary.NetSalaryCents / 100.0) +                            // actual payout amount
                       " " + GetValidationDetails(salary.Validations));

            default:
                throw new NotImplementedException("Unhandled object type in GetObjectDetails: " +
                                                  identifiableObject.GetType().Name);
            }
        }
    protected void GridInvoices_ItemCreated(object sender, GridItemEventArgs e)
    {
        // Set the images for the status indicators.

        const string imageUrlTodo = "~/Images/Public/Fugue/icons-shadowless/minus-small.png";
        const string imageUrlTick = "~/Images/Public/Fugue/icons-shadowless/tick.png";
        const string imageUrlFail = "~/Images/Public/Fugue/icons-shadowless/cross-circle-frame.png";

        if (e.Item is GridDataItem)
        {
            InboundInvoice invoice = (InboundInvoice)e.Item.DataItem;

            if (invoice == null)
            {
                return;
            }

            Controls_v4_DocumentList docList = (Controls_v4_DocumentList)e.Item.FindControl("DocumentList");

            if (docList != null)
            {
                docList.Documents = Documents.ForObject(invoice);
            }

            Image imageAttested = (Image)e.Item.FindControl("ImageAttested");
            Image imagePaid     = (Image)e.Item.FindControl("ImageClosedPaid");

            imageAttested.ImageUrl = invoice.Attested ? imageUrlTick : imageUrlTodo;

            if (invoice.Open == false)
            {
                imagePaid.ImageUrl = invoice.Attested ? imageUrlTick : imageUrlFail;
            }
            else
            {
                imagePaid.ImageUrl = imageUrlTodo;
            }

            HyperLink editLink = (HyperLink)e.Item.FindControl("LinkEdit");
            editLink.Attributes["href"] = "#";

            if (invoice.Open)
            {
                editLink.Attributes["onclick"] = String.Format("return ShowInboundInvoiceForm('{0}','{1}');",
                                                               invoice.Identity, e.Item.ItemIndex);
            }
            else
            {
                editLink.Visible = false;
            }
        }
    }
        static protected IPayable PayableFromRecordId(string recordId)
        {
            char recordType = recordId[0];
            int  itemId     = Int32.Parse(recordId.Substring(1));

            switch (recordType)
            {
            case 'E':     // Expense claim
                return(ExpenseClaim.FromIdentity(itemId));

            case 'A':     // Cash advance
                return(CashAdvance.FromIdentity(itemId));

            case 'I':     // Inbound invoice
                return(InboundInvoice.FromIdentity(itemId));

            default:
                throw new NotImplementedException("Unknown record type");
            }
        }
 private void AddInboundInvoiceToDebug(InboundInvoice invoice)
 {
     debugLookup[Organization.PPSE.FinancialAccounts.DebtsInboundInvoices.Identity].Invoices -= invoice.Amount;
 }
Esempio n. 10
0
        static public object FromBasic(IHasIdentity basic)
        {
            string argumentType = basic.GetType().ToString();

            switch (argumentType)
            {
            // ----- Is there any way to make self-writing code here through replication or similar, so
            // ----- that every case doesn't need to be listed?


            // ------------ COMMUNICATION CLASSES ------------

            case "Swarmops.Basic.Types.BasicCommunicationTurnaround":
                return(CommunicationTurnaround.FromBasic((BasicCommunicationTurnaround)basic));

            case "Swarmops.Basic.Types.Communications.BasicOutboundComm":
                return(OutboundComm.FromBasic((BasicOutboundComm)basic));

            case "Swarmops.Basic.Types.Communications.BasicOutboundCommRecipient":
                return(OutboundCommRecipient.FromBasic((BasicOutboundCommRecipient)basic));


            // ----------- FINANCIAL CLASSES ----------

            case "Swarmops.Basic.Types.BasicExpenseClaim":
                return(ExpenseClaim.FromBasic((BasicExpenseClaim)basic));

            case "Swarmops.Basic.Types.Financial.BasicCashAdvance":
                return(CashAdvance.FromBasic((BasicCashAdvance)basic));

            case "Swarmops.Basic.Types.BasicInboundInvoice":
                return(InboundInvoice.FromBasic((BasicInboundInvoice)basic));

            case "Swarmops.Basic.Types.Financial.BasicFinancialAccount":
                return(FinancialAccount.FromBasic((BasicFinancialAccount)basic));

            case "Swarmops.Basic.Types.Financial.BasicFinancialTransaction":
                return(FinancialTransaction.FromBasic((BasicFinancialTransaction)basic));

            case "Swarmops.Basic.Types.BasicFinancialValidation":
                return(FinancialValidation.FromBasic((BasicFinancialValidation)basic));

            case "Swarmops.Basic.Types.BasicOutboundInvoice":
                return(OutboundInvoice.FromBasic((BasicOutboundInvoice)basic));

            case "Swarmops.Basic.Types.BasicOutboundInvoiceItem":
                return(OutboundInvoiceItem.FromBasic((BasicOutboundInvoiceItem)basic));

            case "Swarmops.Basic.Types.BasicPayment":
                return(Payment.FromBasic((BasicPayment)basic));

            case "Swarmops.Basic.Types.BasicPaymentGroup":
                return(PaymentGroup.FromBasic((BasicPaymentGroup)basic));

            case "Swarmops.Basic.Types.BasicPayout":
                return(Payout.FromBasic((BasicPayout)basic));

            case "Swarmops.Basic.Types.BasicPayrollAdjustment":
                return(PayrollAdjustment.FromBasic((BasicPayrollAdjustment)basic));

            case "Swarmops.Basic.Types.BasicPayrollItem":
                return(PayrollItem.FromBasic((BasicPayrollItem)basic));

            case "Swarmops.Basic.Types.BasicSalary":
                return(Salary.FromBasic((BasicSalary)basic));

            case "Swarmops.Basic.Types.Financial.BasicFinancialTransactionTagSet":
                return(FinancialTransactionTagSet.FromBasic((BasicFinancialTransactionTagSet)basic));

            case "Swarmops.Basic.Types.Financial.BasicFinancialTransactionTagType":
                return(FinancialTransactionTagType.FromBasic((BasicFinancialTransactionTagType)basic));

            // ------------ GOVERNANCE CLASSES ------------

            case "Swarmops.Basic.Types.BasicBallot":
                return(Ballot.FromBasic((BasicBallot)basic));

            case "Swarmops.Basic.Types.BasicMeetingElectionCandidate":
                return(MeetingElectionCandidate.FromBasic((BasicInternalPollCandidate)basic));

            case "Swarmops.Basic.Types.BasicMeetingElection":
                return(MeetingElection.FromBasic((BasicInternalPoll)basic));

            case "Swarmops.Basic.Types.BasicMeetingElectionVote":
                return(MeetingElectionVote.FromBasic((BasicInternalPollVote)basic));

            case "Swarmops.Basic.Types.Governance.BasicMotion":
                return(Motion.FromBasic((BasicMotion)basic));

            case "Swarmops.Basic.Types.Governance.BasicMotionAmendment":
                return(MotionAmendment.FromBasic((BasicMotionAmendment)basic));


            // ------------ PARLEY/ACTIVISM CLASSES ------------

            case "Swarmops.Basic.Types.BasicExternalActivity":
                return(ExternalActivity.FromBasic((BasicExternalActivity)basic));

            case "Swarmops.Basic.Types.BasicParley":
                return(Parley.FromBasic((BasicParley)basic));

            case "Swarmops.Basic.Types.BasicParleyAttendee":
                return(ParleyAttendee.FromBasic((BasicParleyAttendee)basic));

            case "Swarmops.Basic.Types.BasicParleyOption":
                return(ParleyOption.FromBasic((BasicParleyOption)basic));

            case "Swarmops.Basic.Types.BasicPerson":
                return(Person.FromBasic((BasicPerson)basic));

            // ------------------ FAIL ----------------

            default:
                throw new NotImplementedException("Unimplemented argument type: " + argumentType);
            }
        }
        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);
        }
Esempio n. 12
0
 private void AddAttestableItem(AttestableItems items, InboundInvoice invoice)
 {
     items.Add(new AttestableItem("I" + invoice.Identity.ToString(), invoice.Supplier, (decimal)invoice.Amount, invoice.Budget, "See scans:", "Inbound Invoice #" + invoice.Identity, invoice));
 }
 private static int SortInvoicesByDueDateReverse(InboundInvoice a, InboundInvoice b)
 {
     return(DateTime.Compare(b.DueDate, a.DueDate));
 }
Esempio n. 14
0
 public TaskAttestationLate(InboundInvoice invoice)
     : base(invoice.Identity, "Invoice #" + invoice.Identity, invoice.CreatedDateTime, invoice.DueDate)
 {
 }
Esempio n. 15
0
        private static string GetTrackingDetails(object someObject)
        {
            string objectType = someObject.GetType().Name;

            switch (objectType)
            {
            case "Payout":
                Payout payout = (Payout)someObject;
                string result =
                    String.Format(Resources.Pages.Ledgers.InspectLedgers_TxDetail_ThisIsPayoutX, payout.Identity) +
                    " ";

                List <string> subValidations = new List <string>();
                List <string> subResults     = new List <string>();

                if (payout.DependentExpenseClaims.Count > 0)
                {
                    if (payout.DependentExpenseClaims.Count == 1)
                    {
                        subResults.Add("<strong>" +
                                       String.Format(Global.Financial_ExpenseClaimSpecificationWithClaimer,
                                                     payout.DependentExpenseClaims[0].Identity,
                                                     HttpUtility.HtmlEncode(payout.DependentExpenseClaims[0].Claimer.Name)) +
                                       ".</strong>");
                    }
                    else
                    {
                        subResults.Add("<strong>" +
                                       String.Format(Global.Financial_ExpenseClaimsSpecificationWithClaimer,
                                                     Formatting.GenerateRangeString(payout.DependentExpenseClaims.Identities),
                                                     HttpUtility.HtmlEncode(payout.DependentExpenseClaims[0].Claimer.Name)) +
                                       ".</strong>");
                    }

                    foreach (ExpenseClaim claim in payout.DependentExpenseClaims)
                    {
                        subValidations.Add(GetObjectDetails(claim));
                    }
                }

                if (payout.DependentCashAdvancesPayback.Count > 0)
                {
                    if (payout.DependentCashAdvancesPayback.Count == 1)
                    {
                        subResults.Add("<strong>" +
                                       String.Format(Global.Financial_CashAdvancePaybackSpecification,
                                                     payout.DependentCashAdvancesPayback[0].Identity) + ".</strong>");
                    }
                    else
                    {
                        subResults.Add("<strong>" +
                                       String.Format(Global.Financial_CashAdvancePaybacksSpecification,
                                                     Formatting.GenerateRangeString(payout.DependentExpenseClaims.Identities)) +
                                       ".</strong>");
                    }
                }

                if (payout.DependentCashAdvancesPayout.Count > 0)
                {
                    CashAdvance advance0 = payout.DependentCashAdvancesPayout[0];

                    if (payout.DependentCashAdvancesPayout.Count == 1)
                    {
                        subResults.Add("<strong>" +
                                       String.Format(Global.Financial_CashAdvanceLongSpecificationWithRecipient,
                                                     advance0.Identity, advance0.Person.Name) + ".</strong>");
                    }
                    else
                    {
                        subResults.Add("<strong>" +
                                       String.Format(Global.Financial_CashAdvancesLongSpecificationWithRecipient,
                                                     Formatting.GenerateRangeString(payout.DependentExpenseClaims.Identities),
                                                     advance0.Person.Name) + ".</strong>");
                    }

                    foreach (CashAdvance advance in payout.DependentCashAdvancesPayout)
                    {
                        subValidations.Add(GetObjectDetails(advance));
                    }
                }

                if (payout.DependentInvoices.Count > 0)
                {
                    // Assume _one_ invoice

                    InboundInvoice invoice = payout.DependentInvoices[0];

                    subResults.Add("<strong>" + String.Format(
                                       Global.Financial_InboundInvoiceSpecificationWithSender, invoice.Identity,
                                       invoice.Supplier) + "</strong>");

                    subValidations.Add(GetObjectDetails(invoice));
                }

                if (payout.DependentSalariesNet.Count > 0)
                {
                    // Assume one salary

                    Salary salary = payout.DependentSalariesNet[0];

                    subResults.Add("<strong>" +
                                   String.Format(Global.Financial_SalaryDualSpecificationWithRecipient,
                                                 salary.Identity, salary.PayoutDate,
                                                 HttpUtility.HtmlEncode(salary.PayrollItem.PersonCanonical)) +
                                   "</strong>");

                    subValidations.Add(GetObjectDetails(salary));
                }

                if (payout.DependentSalariesTax.Count > 0)
                {
                    Salary salary0 = payout.DependentSalariesTax[0];

                    if (payout.DependentSalariesTax.Count == 1)
                    {
                        subResults.Add("<strong>" +
                                       String.Format(Global.Financial_SalaryTaxDualSpecification, salary0.Identity,
                                                     salary0.PayoutDate) + "</strong>");
                    }
                    else
                    {
                        subResults.Add("<strong>" +
                                       String.Format(Global.Financial_SalariesTaxSpecification, salary0.PayoutDate) +
                                       "</strong>");
                    }
                }


                result +=
                    String.Join(" " + Resources.Pages.Ledgers.InspectLedgers_TxDetail_CombinedWith + " ",
                                subResults) + ". " +
                    String.Format(Resources.Pages.Ledgers.InspectLedgers_TxDetail_PaidOutBy,
                                  payout.CreatedByPerson.Canonical);

                return("<p>" + result + "</p><p>" + String.Join("</p><p>", subValidations) + "</p>");

            case "ExpenseClaim":
            case "CashAdvance":
            case "InboundInvoice":
            case "Salary":
                return("<p>" + GetObjectDetails((IHasIdentity)someObject) + "</p>");

            default:
                return("Unimplemented dependency type: " + objectType);
            }
        }
Esempio n. 16
0
        protected void ButtonCreate_Click(object sender, EventArgs e)  // TODO
        {
            // 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.

            double amount = Double.Parse(this.TextAmount.Text, NumberStyles.Number);
            // parses in current culture - intentional
            Int64 amountCents = (Int64)amount * 100;

            string description = this.TextPurpose.Text;

            DateTime dueDate = DateTime.Parse(this.TextDueDate.Text);


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

            // sanity check

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


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

            InboundInvoice invoice = InboundInvoice.Create(CurrentOrganization, dueDate, amountCents, budget,
                                                           this.TextSupplier.Text, this.TextPurpose.Text, this.TextAccount.Text, string.Empty,
                                                           this.TextReference.Text, CurrentUser);

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

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

            documents.SetForeignObjectForAll(invoice);

            // Display success message

            this.LiteralSuccess.Text = HttpUtility.UrlEncode(String.Format(Resources.Pages.Financial.CreateInboundInvoice_SuccessMessage,
                                                                           invoice.Identity)).Replace("+", "%20");

            // Reset all fields for next invoice

            this.FileUpload.Reset();
            this.TextSupplier.Text  = String.Empty;
            this.TextAccount.Text   = String.Empty;
            this.TextPurpose.Text   = String.Empty;
            this.TextReference.Text = String.Empty;
            this.TextAmount.Text    = 0.ToString("N2");
            this.TextDueDate.Text   = DateTime.Today.AddDays(30).ToShortDateString(); // Use current culture

            // the easyUI combo fields should reset automatically on form submission unless we explicitly reconstruct

            this.TextSupplier.Focus();
        }
Esempio n. 17
0
        public static PaymentTransferInfoResult GetPaymentTransferInfo(string prototypeId)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();

            // TODO: Authentication check

            string[] payoutComponents = prototypeId.Split('|');

            if (payoutComponents.Length < 1)
            {
                throw new InvalidOperationException("Prototype ID can't be empty");
            }

            PaymentTransferInfo info = new PaymentTransferInfo();

            // Some payouts are composites of multiple objects, but all these will share the same
            // payout data, so we can safely use just the first object to determine payment
            // target information
            //
            // with one exception -- we need to determine the amount by adding all the objects
            // together, if applicable

            DateTime paymentDueBy = Constants.DateTimeLow;

            switch (Char.ToUpperInvariant(payoutComponents[0][0]))
            {
            case 'C':     // expense claim
                info =
                    PaymentTransferInfo.FromObject(
                        ExpenseClaim.FromIdentity(Int32.Parse(payoutComponents[0].Substring(1))),
                        new Money(GetSumCentsTotal(prototypeId), authData.CurrentOrganization.Currency));
                break;

            case 'A':     // cash advance (payout or payback, same logic either way)
                info =
                    PaymentTransferInfo.FromObject(
                        CashAdvance.FromIdentity(Int32.Parse(payoutComponents[0].Substring(1))),
                        new Money(GetSumCentsTotal(prototypeId), authData.CurrentOrganization.Currency));
                break;

            case 'S':     // salary
                Salary salary = Salary.FromIdentity(Int32.Parse(payoutComponents[0].Substring(1)));
                info         = PaymentTransferInfo.FromObject(salary);
                paymentDueBy = salary.PayoutDate;
                break;

            case 'I':     // inbound invoice
                InboundInvoice invoice = InboundInvoice.FromIdentity(Int32.Parse(payoutComponents[0].Substring(1)));
                info         = PaymentTransferInfo.FromObject(invoice);
                paymentDueBy = invoice.DueDate;
                break;

            default:
                throw new NotImplementedException("Unrecognized payment type");
            }

            PaymentTransferInfoResult result = new PaymentTransferInfoResult
            {
                Success        = true,
                CurrencyAmount = info.CurrencyAmount,
                DisplayMessage = string.Empty,
                Recipient      = info.Recipient,
                Reference      = info.Reference,
                TransferMethod = info.LocalizedPaymentMethodName
            };

            if (paymentDueBy < Constants.DateTimeLowThreshold)
            {
                result.DueBy = Resources.Global.Global_ASAP;
            }
            else
            {
                DateTime nowUtc = DateTime.UtcNow;

                if (paymentDueBy.Year != nowUtc.Year || paymentDueBy < nowUtc.AddMonths(-3))
                {
                    result.DueBy = paymentDueBy.ToString(Resources.Global.Global_DateFormatLongSansWeekday);
                }
                else
                {
                    result.DueBy = paymentDueBy.ToString(Resources.Global.Global_DateFormatLongDateMonth);
                }

                if (paymentDueBy < nowUtc.AddDays(-1))
                {
                    result.DueBy += " - " + Resources.Pages.Financial.PayOutMoney_PaymentLate;
                }
            }

            List <string> listTransferMethodLabels = new List <string>();
            List <string> listTransferMethodData   = new List <string>();

            foreach (string label in info.LocalizedPaymentInformation.Keys)
            {
                listTransferMethodLabels.Add(HttpUtility.HtmlEncode(label));
                listTransferMethodData.Add(HttpUtility.HtmlEncode(info.LocalizedPaymentInformation [label]));
            }

            result.TransferMethodLabels = listTransferMethodLabels.ToArray();
            result.TransferMethodData   = listTransferMethodData.ToArray();
            result.OcrData = info.OcrData;  // can be null and that's ok

            return(result);
        }
Esempio n. 18
0
    protected void ButtonSubmitClaim_Click(object sender, EventArgs e)
    {
        // First, if there's an upload that the user hasn't processed, process it first.

        if (this.Upload.UploadedFiles.Count > 0)
        {
            ProcessUpload();
        }

        // If args were invalid, abort

        if (!Page.IsValid)
        {
            return;
        }



        // Read the form data

        string supplier    = this.TextSupplier.Text;
        string bankAccount = this.TextAccount.Text;

        int temporaryId = Int32.Parse(this.TemporaryDocumentIdentity.Text);

        int              organizationId = Int32.Parse(this.DropOrganizations.SelectedValue);
        Organization     org            = Organization.FromIdentity(organizationId);
        Int64            amountCents    = (Int64)(Double.Parse(this.TextAmount.Text, new CultureInfo("sv-SE")) * 100);
        FinancialAccount budget         = this.DropBudgets.SelectedFinancialAccount;
        DateTime         dueDate        = (DateTime)this.DatePicker.SelectedDate;

        string ocr           = string.Empty;
        string invoiceNumber = string.Empty;

        if (this.DropReferenceType.SelectedValue == "OCR")
        {
            ocr = this.TextReference.Text;
        }
        else
        {
            invoiceNumber = this.TextReference.Text;
        }

        // Create the invoice record

        InboundInvoice newInvoice = InboundInvoice.Create(org, dueDate,
                                                          amountCents, budget, supplier, bankAccount, ocr, invoiceNumber, _currentUser);

        // Move documents to the new invoice

        Documents.ForObject(new TemporaryIdentity(temporaryId)).SetForeignObjectForAll(newInvoice);

        // Create the event for PirateBot-Mono to send off mails

        Activizr.Logic.Support.PWEvents.CreateEvent(EventSource.PirateWeb, EventType.InboundInvoiceReceived,
                                                    _currentUser.Identity, organizationId, 1, _currentUser.Identity,
                                                    newInvoice.Identity, string.Empty);

        Page.ClientScript.RegisterStartupScript(typeof(Page), "OkMessage", @"alert ('The invoice was registered.');", true);

        // Clear the text fields

        this.TextSupplier.Text  = string.Empty;
        this.TextAccount.Text   = string.Empty;
        this.TextReference.Text = string.Empty;
        this.DropReferenceType.SelectedIndex = 0;
        this.TemporaryDocumentIdentity.Text  = "0";
        this.TextAmount.Text = "0,00"; // TODO: LOCALIZE BY CULTURE

        // PopulateGrid();
    }
Esempio n. 19
0
        protected void Page_Load(object sender, EventArgs e)
        {
            string documentIdString = Request.QueryString["DocId"];
            int    documentId       = Int32.Parse(documentIdString);

            Document document = Document.FromIdentity(documentId);

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

            bool hasPermission = false;

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


                FinancialAccount budget = FinancialAccount.FromIdentity(budgetId);

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

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

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

                /*
                 * 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 == this.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:
            {
                // These are public

                hasPermission = true;
            }
            break;
            }

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

            string contentType = string.Empty;

            string fileNameLower = document.ClientFileName.ToLowerInvariant();

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

            string legacyMarker = string.Empty;

            if (!File.Exists(StorageRoot + document.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(StorageRoot + legacyMarker + document.ServerFileName))
            {
                throw new FileNotFoundException(StorageRoot + legacyMarker + document.ServerFileName);
            }

            Response.ContentType = contentType + "; filename=" + document.ClientFileName;
            Response.TransmitFile(StorageRoot + legacyMarker + document.ServerFileName);
        }
Esempio n. 20
0
    protected void ButtonAttest_Click(object sender, EventArgs e)
    {
        List <string> identityStrings = new List <string>();

        foreach (string indexString in this.GridAttestables.SelectedIndexes)
        {
            int    index = Int32.Parse(indexString);
            string itemIdentityString = (string)this.GridAttestables.MasterTableView.DataKeyValues[index]["Identity"];
            int    itemIdentity       = Int32.Parse(itemIdentityString.Substring(1));


            // Mark items as attested

            switch (itemIdentityString[0])
            {
            case 'E':
                ExpenseClaim claim = ExpenseClaim.FromIdentity(itemIdentity);

                if (attestationRights.ContainsKey(claim.BudgetId))
                {
                    claim.Attest(_currentUser);
                    Activizr.Logic.Support.PWEvents.CreateEvent(
                        EventSource.PirateWeb, EventType.ExpenseAttested, _currentUser.Identity,
                        claim.OrganizationId, 0, claim.ClaimingPersonId, claim.Identity, string.Empty);
                }
                break;

            case 'I':
                InboundInvoice invoice = InboundInvoice.FromIdentity(itemIdentity);

                if (attestationRights.ContainsKey(invoice.BudgetId))
                {
                    invoice.Attest(_currentUser);
                    Activizr.Logic.Support.PWEvents.CreateEvent(
                        EventSource.PirateWeb, EventType.InboundInvoiceAttested, _currentUser.Identity,
                        invoice.OrganizationId, 0, 0, invoice.Identity, string.Empty);
                }
                break;

            case 'S':
                Salary salary = Salary.FromIdentity(itemIdentity);

                // Mark as attested

                bool mayAttest = false;

                if (attestationRights.ContainsKey(salary.PayrollItem.BudgetId) && salary.PayrollItem.PersonId != _currentUser.Identity)
                {
                    mayAttest = true;
                }

                if (salary.PayrollItem.ReportsToPersonId == _currentUser.Identity)
                {
                    mayAttest = true;
                }

                if (mayAttest)
                {
                    salary.Attest(_currentUser);
                    Activizr.Logic.Support.PWEvents.CreateEvent(
                        EventSource.PirateWeb, EventType.SalaryAttested, _currentUser.Identity,
                        salary.PayrollItem.OrganizationId, 0, 0, salary.Identity, string.Empty);
                }
                break;

            case 'P':
                Parley parley = Parley.FromIdentity(itemIdentity);

                if (attestationRights.ContainsKey(parley.BudgetId))
                {
                    parley.Attest(_currentUser);
                }
                break;
            }
        }

        this.GridAttestables.Rebind();
    }
Esempio n. 21
0
 private static int SortGridInvoices(InboundInvoice invoice1, InboundInvoice invoice2)
 {
     return(DateTime.Compare(invoice1.CreatedDateTime, invoice2.CreatedDateTime));
 }
Esempio n. 22
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);
    }
Esempio n. 23
0
    protected void GridAttestables_ItemCreated(object sender, GridItemEventArgs e)
    {
        if (e.Item is GridDataItem)
        {
            AttestableItem item = (AttestableItem)e.Item.DataItem;

            if (item == null)
            {
                return;
            }

            // Set Description field

            Label description = (Label)e.Item.FindControl("LabelDescription");

            description.Text = item.Description;

            if (item.Item is InboundInvoice)
            {
                InboundInvoice invoice = item.Item as InboundInvoice;

                Controls_v4_DocumentList docList = (Controls_v4_DocumentList)e.Item.FindControl("DocList");
                docList.Documents   = invoice.Documents;
                docList.Visible     = true;
                description.Visible = false;

                HyperLink editLink = (HyperLink)e.Item.FindControl("LinkEdit");
                editLink.Attributes["href"]    = "#";
                editLink.Attributes["onclick"] = String.Format("return ShowInboundInvoiceForm('{0}','{1}');",
                                                               invoice.Identity, e.Item.ItemIndex);
            }
            else if (item.Item is ExpenseClaim)
            {
                ExpenseClaim claim = item.Item as ExpenseClaim;

                HyperLink editLink = (HyperLink)e.Item.FindControl("LinkEdit");
                editLink.Attributes["href"]    = "#";
                editLink.Attributes["onclick"] = String.Format("return ShowExpenseClaimForm('{0}','{1}');",
                                                               claim.Identity, e.Item.ItemIndex);
            }

            // Calculate or retrieve remaining budget

            if (!budgetsRemainingLookup.ContainsKey(item.Budget.Identity))
            {
                int year = DateTime.Today.Year; // HACK: Should be item's date

                Int64 budgetCents = (Int64)item.Budget.GetBudget(year) * 100;

                Int64 centsUsed = item.Budget.GetDeltaCents(new DateTime(year, 1, 1), new DateTime(year + 1, 1, 1));

                decimal budgetRemaining = (-budgetCents - centsUsed) / 100.0m;

                budgetsRemainingLookup[item.Budget.Identity] = budgetRemaining;
            }

            Label labelBudgetRemaining = (Label)e.Item.FindControl("LabelBudgetRemaining");

            labelBudgetRemaining.Text = String.Format("{0:N2}", budgetsRemainingLookup[item.Budget.Identity]);
        }


        // Set the images for the status indicators.

        return; // fix later

        if (e.Item is GridDataItem)
        {
            ExpenseClaim claim = (ExpenseClaim)e.Item.DataItem;

            if (claim == null)
            {
                return;
            }

            Label labelBudgetYear = (Label)e.Item.FindControl("LabelBudgetYear");

            if (claim.BudgetId == 0)
            {
                labelBudgetYear.Text = "UNBUDGETED!";
            }
            else
            {
                labelBudgetYear.Text = claim.Budget.Name + ", " + claim.BudgetYear.ToString();
            }

            HyperLink editLink = (HyperLink)e.Item.FindControl("LinkEdit");
            editLink.Attributes["href"]    = "#";
            editLink.Attributes["onclick"] = String.Format("return ShowExpenseClaimForm('{0}','{1}');",
                                                           claim.Identity, e.Item.ItemIndex);
        }
    }
    private void AddInboundInvoiceEvent(int parentId, InboundInvoice invoice)
    {
        int newId = transactionEvents.Count + 1;

        transactionEvents.Add(new TransactionEvent(newId, parentId, "Invoice #" + invoice.Identity.ToString()));
        transactionEvents.Add(
            new TransactionEvent(newId + 1, newId,
                                 "Supplier: " + invoice.Supplier));
        transactionEvents.Add(
            new TransactionEvent(newId + 2, newId,
                                 "Received: " +
                                 invoice.CreatedDateTime.ToString("yyyy-MM-dd HH:mm")));

        transactionEvents.Add(
            new TransactionEvent(newId + 3, newId,
                                 "Budget: " +
                                 invoice.Budget.Name));

        AddValidations(newId, invoice);

        foreach (Document document in invoice.Documents)
        {
            AddDocumentEvent(newId, document);
        }
    }
        protected void ButtonCreate_Click(object sender, EventArgs e)  // TODO
        {
            // 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    = this.CurrencyAmount.Cents;
            Int64 amountVatCents = this.CurrencyVat.Cents;

            string description = this.TextPurpose.Text;

            DateTime dueDate = DateTime.Parse(this.TextDueDate.Text);


            FinancialAccount budget = this.ComboBudgets.SelectedAccount;

            // sanity check

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


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

            InboundInvoice invoice = InboundInvoice.Create(CurrentOrganization, dueDate, amountCents, amountVatCents, budget,
                                                           this.TextSupplier.Text, this.TextPurpose.Text, this.TextAccount.Text, string.Empty,
                                                           this.TextReference.Text, CurrentUser);

            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)
                    {
                        invoice.FinancialTransaction.CreateTag(
                            FinancialTransactionTagType.FromIdentity(selectedTagType), CurrentUser);
                    }
                }
            }

            documents.SetForeignObjectForAll(invoice);

            // If amounts were in a different currency, record the native values for proper payment

            if (this.CurrencyAmount.NonPresentationCurrencyUsed)
            {
                Money currencyEntered = this.CurrencyAmount.NonPresentationCurrencyAmount;
                invoice.NativeCurrencyAmount = currencyEntered;
            }

            // Display success message

            this._invoiceId = invoice.OrganizationSequenceId; // a property returns the localized string

            // Reset all fields for next invoice

            this.FileUpload.Reset();
            this.TextSupplier.Text    = String.Empty;
            this.TextAccount.Text     = String.Empty;
            this.TextPurpose.Text     = String.Empty;
            this.TextReference.Text   = String.Empty;
            this.CurrencyAmount.Cents = 0;
            this.CurrencyVat.Cents    = 0;
            this.TextDueDate.Text     = DateTime.Today.AddDays(30).ToShortDateString(); // Use current culture

            // the easyUI combo fields should reset automatically on form submission unless we explicitly reconstruct

            this.TextSupplier.Focus();
        }
Esempio n. 26
0
        private static AjaxCallResult HandleAttestationDeattestation(string identifier, AttestationMode mode)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();

            IApprovable approvableItem;
            string      attestedTemplate;
            string      deattestedTemplate;

            char   costType = identifier[0];
            int    itemId   = Int32.Parse(identifier.Substring(1));
            Int64  amountCents;
            string beneficiary;
            string result;

            // Find the item we are attesting or deattesting

            switch (costType)
            {
            case 'A':     // Case advance
                CashAdvance advance = CashAdvance.FromIdentity(itemId);
                if (advance.OrganizationId != authData.CurrentOrganization.Identity)
                {
                    throw new InvalidOperationException("Called to attest out-of-org line item");
                }
                if (advance.Budget.OwnerPersonId != authData.CurrentUser.Identity &&
                    advance.Budget.OwnerPersonId != Person.NobodyId)
                {
                    throw new SecurityException("Called without attestation privileges");
                }

                approvableItem     = advance;
                attestedTemplate   = Resources.Pages.Financial.AttestCosts_AdvanceAttested;
                deattestedTemplate = Resources.Pages.Financial.AttestCosts_AdvanceDeattested;
                beneficiary        = advance.Person.Name;
                amountCents        = advance.AmountCents;

                break;

            case 'E':     // Expense claim
                ExpenseClaim expense = ExpenseClaim.FromIdentity(itemId);
                if (expense.OrganizationId != authData.CurrentOrganization.Identity)
                {
                    throw new InvalidOperationException("Called to attest out-of-org line item");
                }
                if (expense.Budget.OwnerPersonId != authData.CurrentUser.Identity &&
                    expense.Budget.OwnerPersonId != Person.NobodyId)
                {
                    throw new SecurityException("Called without attestation privileges");
                }

                approvableItem     = expense;
                attestedTemplate   = Resources.Pages.Financial.AttestCosts_ExpenseAttested;
                deattestedTemplate = Resources.Pages.Financial.AttestCosts_ExpenseDeattested;
                beneficiary        = expense.Claimer.Name;
                amountCents        = expense.AmountCents;

                break;

            case 'I':     // Inbound invoice
                InboundInvoice invoice = InboundInvoice.FromIdentity(itemId);
                if (invoice.OrganizationId != authData.CurrentOrganization.Identity)
                {
                    throw new InvalidOperationException("Called to attest out-of-org line item");
                }
                if (invoice.Budget.OwnerPersonId != authData.CurrentUser.Identity &&
                    invoice.Budget.OwnerPersonId != Person.NobodyId)
                {
                    throw new SecurityException("Called without attestation privileges");
                }

                approvableItem     = invoice;
                attestedTemplate   = Resources.Pages.Financial.AttestCosts_InvoiceAttested;
                deattestedTemplate = Resources.Pages.Financial.AttestCosts_InvoiceDeattested;
                beneficiary        = invoice.Supplier;
                amountCents        = invoice.AmountCents;

                break;

            case 'S':     // Salary payout
                Salary salary = Salary.FromIdentity(itemId);
                if (salary.PayrollItem.OrganizationId != authData.CurrentOrganization.Identity)
                {
                    throw new InvalidOperationException("Called to attest out-of-org line item");
                }
                if (salary.PayrollItem.Budget.OwnerPersonId != authData.CurrentUser.Identity &&
                    salary.PayrollItem.Budget.OwnerPersonId != Person.NobodyId)
                {
                    throw new SecurityException("Called without attestation privileges");
                }

                approvableItem     = salary;
                attestedTemplate   = Resources.Pages.Financial.AttestCosts_SalaryAttested;
                deattestedTemplate = Resources.Pages.Financial.AttestCosts_SalaryDeattested;
                beneficiary        = salary.PayrollItem.PersonCanonical;
                amountCents        = salary.GrossSalaryCents + salary.AdditiveTaxCents;

                break;

            case 'P':     // Parley, aka Conference
                Parley parley = Parley.FromIdentity(itemId);
                if (parley.OrganizationId != authData.CurrentOrganization.Identity)
                {
                    throw new InvalidOperationException("Called to attest out-of-org line item");
                }
                if (parley.Budget.OwnerPersonId != authData.CurrentUser.Identity &&
                    parley.Budget.OwnerPersonId != Person.NobodyId)
                {
                    throw new SecurityException("Called without attestation privileges");
                }

                approvableItem     = parley;
                attestedTemplate   = Resources.Pages.Financial.AttestCosts_ParleyAttested;
                deattestedTemplate = Resources.Pages.Financial.AttestCosts_ParleyDeattested;
                beneficiary        = parley.Person.Name;
                amountCents        = parley.BudgetCents;

                break;

            default:
                throw new InvalidOperationException("Unknown Cost Type in HandleAttestationDeattestation: \"" +
                                                    identifier + "\"");
            }

            // Finally, attest or deattest

            if (mode == AttestationMode.Attestation)
            {
                Int64 budgetRemaining = approvableItem.Budget.GetBudgetCentsRemaining();

                result = string.Empty;

                if (amountCents > -budgetRemaining)
                {
                    if (
                        authData.Authority.HasAccess(new Access(authData.CurrentOrganization,
                                                                AccessAspect.Administration)))
                    {
                        // Admin rights, so allow (forced) overdraft

                        // Unless budget was nonzero and allocated, set protest message

                        if (approvableItem.Budget.Owner != null || approvableItem.Budget.GetBudgetCents() != 0)
                        {
                            result = Resources.Pages.Financial.AttestCosts_Overdrafted + " ";
                        }
                    }
                    else
                    {
                        // Do not allow overdraft

                        return(new AjaxCallResult
                        {
                            DisplayMessage = Resources.Pages.Financial.AttestCosts_OutOfBudget,
                            Success = false
                        });
                    }
                }

                approvableItem.Approve(authData.CurrentUser);
                result += string.Format(attestedTemplate, itemId, beneficiary,
                                        authData.CurrentOrganization.Currency.Code,
                                        amountCents / 100.0);
            }
            else if (mode == AttestationMode.Deattestation)
            {
                approvableItem.RetractApproval(authData.CurrentUser);
                result = string.Format(deattestedTemplate, itemId, beneficiary,
                                       authData.CurrentOrganization.Currency.Code,
                                       amountCents / 100.0);
            }
            else
            {
                throw new InvalidOperationException("Unknown Approval Mode: " + mode);
            }

            FinancialAccount.ClearApprovalAdjustmentsCache(authData.CurrentOrganization);

            return(new AjaxCallResult {
                DisplayMessage = result, Success = true
            });
        }
Esempio n. 27
0
        private static string HandleAttestationDeattestation(string identifier, AttestationMode mode)
        {
            AuthenticationData authData = GetAuthenticationDataAndCulture();

            IAttestable attestableItem     = null;
            string      attestedTemplate   = string.Empty;
            string      deattestedTemplate = string.Empty;

            char   costType = identifier[0];
            int    itemId   = Int32.Parse(identifier.Substring(1));
            Int64  amountCents;
            string beneficiary = string.Empty;
            string result      = string.Empty;

            // Find the item we are attesting or deattesting

            switch (costType)
            {
            case 'A':     // Case advance
                CashAdvance advance = CashAdvance.FromIdentity(itemId);
                if (advance.OrganizationId != authData.CurrentOrganization.Identity)
                {
                    throw new InvalidOperationException("Called to attest out-of-org line item");
                }
                if (advance.Budget.OwnerPersonId != authData.CurrentUser.Identity &&
                    advance.Budget.OwnerPersonId != Person.NobodyId)
                {
                    throw new SecurityAccessDeniedException("Called without attestation privileges");
                }

                attestableItem     = advance;
                attestedTemplate   = Resources.Pages.Financial.AttestCosts_AdvanceAttested;
                deattestedTemplate = Resources.Pages.Financial.AttestCosts_AdvanceDeattested;
                beneficiary        = advance.Person.Name;
                amountCents        = advance.AmountCents;

                break;

            case 'E':     // Expense claim
                ExpenseClaim expense = ExpenseClaim.FromIdentity(itemId);
                if (expense.OrganizationId != authData.CurrentOrganization.Identity)
                {
                    throw new InvalidOperationException("Called to attest out-of-org line item");
                }
                if (expense.Budget.OwnerPersonId != authData.CurrentUser.Identity &&
                    expense.Budget.OwnerPersonId != Person.NobodyId)
                {
                    throw new SecurityAccessDeniedException("Called without attestation privileges");
                }

                attestableItem     = expense;
                attestedTemplate   = Resources.Pages.Financial.AttestCosts_ExpenseAttested;
                deattestedTemplate = Resources.Pages.Financial.AttestCosts_ExpenseDeattested;
                beneficiary        = expense.Claimer.Name;
                amountCents        = expense.AmountCents;

                break;

            case 'I':     // Inbound invoice
                InboundInvoice invoice = InboundInvoice.FromIdentity(itemId);
                if (invoice.OrganizationId != authData.CurrentOrganization.Identity)
                {
                    throw new InvalidOperationException("Called to attest out-of-org line item");
                }
                if (invoice.Budget.OwnerPersonId != authData.CurrentUser.Identity &&
                    invoice.Budget.OwnerPersonId != Person.NobodyId)
                {
                    throw new SecurityAccessDeniedException("Called without attestation privileges");
                }

                attestableItem     = invoice;
                attestedTemplate   = Resources.Pages.Financial.AttestCosts_InvoiceAttested;
                deattestedTemplate = Resources.Pages.Financial.AttestCosts_InvoiceDeattested;
                beneficiary        = invoice.Supplier;
                amountCents        = invoice.AmountCents;

                break;

            case 'S':     // Salary payout
                Salary salary = Salary.FromIdentity(itemId);
                if (salary.PayrollItem.OrganizationId != authData.CurrentOrganization.Identity)
                {
                    throw new InvalidOperationException("Called to attest out-of-org line item");
                }
                if (salary.PayrollItem.Budget.OwnerPersonId != authData.CurrentUser.Identity &&
                    salary.PayrollItem.Budget.OwnerPersonId != Person.NobodyId)
                {
                    throw new SecurityAccessDeniedException("Called without attestation privileges");
                }

                attestableItem     = salary;
                attestedTemplate   = Resources.Pages.Financial.AttestCosts_SalaryAttested;
                deattestedTemplate = Resources.Pages.Financial.AttestCosts_SalaryDeattested;
                beneficiary        = salary.PayrollItem.PersonCanonical;
                amountCents        = salary.GrossSalaryCents;

                break;

            case 'P':     // Parley, aka Conference
                Parley parley = Parley.FromIdentity(itemId);
                if (parley.OrganizationId != authData.CurrentOrganization.Identity)
                {
                    throw new InvalidOperationException("Called to attest out-of-org line item");
                }
                if (parley.Budget.OwnerPersonId != authData.CurrentUser.Identity &&
                    parley.Budget.OwnerPersonId != Person.NobodyId)
                {
                    throw new SecurityAccessDeniedException("Called without attestation privileges");
                }

                attestableItem     = parley;
                attestedTemplate   = Resources.Pages.Financial.AttestCosts_ParleyAttested;
                deattestedTemplate = Resources.Pages.Financial.AttestCosts_ParleyDeattested;
                beneficiary        = parley.Person.Name;
                amountCents        = parley.BudgetCents;

                break;

            default:
                throw new InvalidOperationException("Unknown Cost Type in HandleAttestationDeattestation: \"" +
                                                    identifier + "\"");
            }

            // Finally, attest or deattest

            if (mode == AttestationMode.Attestation)
            {
                attestableItem.Attest(authData.CurrentUser);
                result = string.Format(attestedTemplate, itemId, beneficiary,
                                       authData.CurrentOrganization.Currency.Code,
                                       amountCents / 100.0);
            }
            else if (mode == AttestationMode.Deattestation)
            {
                attestableItem.Deattest(authData.CurrentUser);
                result = string.Format(deattestedTemplate, itemId, beneficiary,
                                       authData.CurrentOrganization.Currency.Code,
                                       amountCents / 100.0);
            }
            else
            {
                throw new InvalidOperationException("Unknown Attestation Mode: " + mode);
            }

            return(result);
        }
    private string GetProgressTicks(InboundInvoice invoice)
    {
        StringBuilder ticks = new StringBuilder(512);

        // The first tick is whether the invoice was even received yet, in anticipation of Purchase Orders
        // For now, it is always filled

        ticks.Append(_greenTick);

        // The second tick is whether the invoice has been attested

        if (invoice.Attested)
        {
            ticks.Append(_greenTick);

            // Is it also paid?

            if (invoice.PaidOut)
            {
                ticks.Append(_greenTick);

                // Is the payout closed, that is, registered closed with the bank?

                try
                {
                    if (Payout.FromDependency(invoice).Open)
                    {
                        ticks.Append(_emptyTick);
                    }
                    else
                    {
                        ticks.Append(_greenTick);
                    }
                }
                catch (ArgumentException)
                {
                    // There was no payout; the invoice was closed another way.

                    ticks.Append(_redCross);
                }
            }
            else
            {
                // attested but not paid yet

                ticks.Append(_emptyTick + _emptyTick);
            }
        }
        else // not attested
        {
            // Is the invoice closed? If so, it was denied entirely

            if (invoice.Open)
            {
                ticks.Append(_emptyTick + _emptyTick + _emptyTick);
            }
            else
            {
                // Closed, and therefore it was denied attestation
                ticks.Append(_redCross + _filler + _filler);
            }
        }

        return(ticks.ToString());
    }
Esempio n. 29
0
 private void AddInboundInvoiceToDebug(InboundInvoice invoice)
 {
     debugLookup[Organization.PPSE.FinancialAccounts.DebtsInboundInvoices.Identity].Invoices -= invoice.Amount;
 }