View Javadoc
1   /*
2    * *************************************************************************************************************************************************************
3    *
4    * blueHour: open source accounting
5    * http://tidalwave.it/projects/bluehour
6    *
7    * Copyright (C) 2013 - 2024 by Tidalwave s.a.s. (http://tidalwave.it)
8    *
9    * *************************************************************************************************************************************************************
10   *
11   * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12   * You may obtain a copy of the License at
13   *
14   *     http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17   * CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License.
18   *
19   * *************************************************************************************************************************************************************
20   *
21   * git clone https://bitbucket.org/tidalwave/bluehour-src
22   * git clone https://github.com/tidalwave-it/bluehour-src
23   *
24   * *************************************************************************************************************************************************************
25   */
26  package it.tidalwave.accounting.ui.projectexplorer.impl;
27  
28  import javax.annotation.Nonnull;
29  import java.util.Collection;
30  import it.tidalwave.accounting.model.spi.CustomerSpi;
31  import it.tidalwave.accounting.model.spi.ProjectSpi;
32  import it.tidalwave.accounting.model.types.Money;
33  import it.tidalwave.role.Aggregate;
34  import it.tidalwave.role.ui.Displayable;
35  import it.tidalwave.role.ui.Presentable;
36  import it.tidalwave.role.ui.PresentationModel;
37  import it.tidalwave.role.ui.PresentationModelAggregate;
38  import it.tidalwave.role.ui.Styleable;
39  import it.tidalwave.dci.annotation.DciRole;
40  import lombok.RequiredArgsConstructor;
41  import static it.tidalwave.accounting.commons.Styleables.RIGHT_ALIGNED;
42  import static it.tidalwave.accounting.model.spi.util.Formatters.*;
43  import static it.tidalwave.util.Parameters.r;
44  
45  /***************************************************************************************************************************************************************
46   *
47   * @author  Fabrizio Giudici
48   *
49   **************************************************************************************************************************************************************/
50  @DciRole(datumType = ProjectSpi.class)
51  @RequiredArgsConstructor
52  public class ProjectPresentable implements Presentable
53    {
54      @Nonnull
55      private final ProjectSpi project;
56  
57      @Override @Nonnull
58      public PresentationModel createPresentationModel (@Nonnull final Collection<Object> instanceRoles)
59        {
60          return PresentationModel.of(project, r(aggregatePresentationModel(), instanceRoles));
61        }
62  
63      @Nonnull
64      protected Aggregate<PresentationModel> aggregatePresentationModel()
65        {
66          final var budget           = project.getBudget();
67          // FIXME: these are dynamically computed, can be slow - should be also cached? Here or in the data objects?
68          final var earnings         = project.getEarnings();
69          final var invoicedEarnings = project.getInvoicedEarnings();
70  
71          // FIXME: uses the column header names, should be an internal id instead
72          return PresentationModelAggregate.newInstance()
73                  .withPmOf("Client",     r(Displayable.of(((CustomerSpi)project.getCustomer()).getName())))
74                  .withPmOf("Status",     r(Displayable.of(project.getStatus().name())))
75                  .withPmOf("#",          r(Displayable.of(project::getNumber)))
76                  .withPmOf("Name",       r(Displayable.of(project::getName)))
77                  .withPmOf("Start Date", r(Displayable.of(DATE_FORMATTER::format, project.getStartDate()),
78                                                   RIGHT_ALIGNED))
79                  .withPmOf("Due Date",   r(Displayable.of(DATE_FORMATTER::format, project.getEndDate()),
80                                                   RIGHT_ALIGNED))
81                  .withPmOf("Notes",      r(Displayable.of(project::getNotes)))
82                  .withPmOf("Time",       r(Displayable.of(DURATION_FORMATTER::format, project.getDuration()),
83                                                   RIGHT_ALIGNED))
84                  .withPmOf("Budget",     r(Displayable.of(MONEY_FORMATTER::format, budget),
85                        Styleable.of("right-aligned", budget.isEqualTo(Money.ZERO) ? "alerted" : "")))
86                  .withPmOf("Earnings",   r(Displayable.of(MONEY_FORMATTER::format, earnings),
87                        Styleable.of("right-aligned", earnings.greaterThan(budget) ? "alerted" : "",
88                                                      earnings.isEqualTo(budget) ? "green" : "")))
89                  .withPmOf("Invoiced",   r(Displayable.of(MONEY_FORMATTER::format, invoicedEarnings),
90                        Styleable.of("right-aligned", invoicedEarnings.greaterThan(earnings) ? "alerted" :
91                                                      invoicedEarnings.isEqualTo(earnings) ? "green" : "")));
92        }
93    }