2 * Copyright (C) 2016, 2017 Roland Häder
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation, either version 3 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
14 * You should have received a copy of the GNU Affero General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 package org.mxchange.jfinancials.beans.financial.model.receipt;
19 import fish.payara.cdi.jsr107.impl.NamedCache;
20 import java.text.MessageFormat;
21 import java.util.Comparator;
22 import java.util.Date;
23 import java.util.Iterator;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.Objects;
27 import javax.annotation.PostConstruct;
28 import javax.cache.Cache;
30 import javax.enterprise.context.RequestScoped;
31 import javax.enterprise.event.Event;
32 import javax.enterprise.event.Observes;
33 import javax.enterprise.inject.Any;
34 import javax.faces.view.facelets.FaceletException;
35 import javax.inject.Inject;
36 import javax.inject.Named;
37 import org.mxchange.jcontactsbusiness.model.branchoffice.BranchOffice;
38 import org.mxchange.jcontactsbusiness.model.employee.Employee;
39 import org.mxchange.jfinancials.beans.BaseFinancialsBean;
40 import org.mxchange.jfinancials.beans.user.login.FinancialsUserLoginWebSessionController;
41 import org.mxchange.jfinancials.events.receipt.added.ObservableReceiptAddedEvent;
42 import org.mxchange.jfinancials.events.receipt.added.ReceiptAddedEvent;
43 import org.mxchange.jfinancials.exceptions.ReceiptAlreadyAddedException;
44 import org.mxchange.jfinancials.model.receipt.BillableReceipt;
45 import org.mxchange.jfinancials.model.receipt.FinancialReceipt;
46 import org.mxchange.jfinancials.model.receipt.FinancialReceiptSessionBeanRemote;
47 import org.mxchange.jproduct.model.payment.PaymentType;
48 import org.mxchange.juserlogincore.events.login.ObservableUserLoggedInEvent;
51 * An administrative financial receipt bean (controller)
53 * @author Roland Häder<roland@mxchange.org>
55 @Named ("receiptController")
57 public class FinancialsReceiptWebRequestBean extends BaseFinancialsBean implements FinancialsReceiptWebRequestController {
62 private static final long serialVersionUID = 56_189_028_928_371L;
65 * Event being fired when user has added a new receipt
69 private Event<ObservableReceiptAddedEvent> addedReceiptEvent;
74 private final List<BillableReceipt> allReceipts;
77 * Filtered receipts list
79 private List<BillableReceipt> filteredReceipts;
84 private Long receiptBarCodeNumber;
87 * EJB for general financial receipt purposes
89 @EJB (lookup = "java:global/jfinancials-ejb/financialReceipt!org.mxchange.jfinancials.model.receipt.FinancialReceiptSessionBeanRemote")
90 private FinancialReceiptSessionBeanRemote receiptBean;
93 * Recipient issuing company (for example where the user went shopping to)
95 private BranchOffice receiptBranchOffice;
98 * A list of all branch offices (globally)
101 @NamedCache (cacheName = "receiptCache")
102 private Cache<Long, BillableReceipt> receiptCache;
105 * Date/time the receipt has been issued
107 private Date receiptIssued;
110 * Receipt number (only numbers)
112 private Long receiptNumber;
115 * Payment type being used for this receipt
117 private PaymentType receiptPaymentType;
122 private Long receiptRegisterNumber;
127 private Employee receiptSellerEmployee;
133 private FinancialsUserLoginWebSessionController userLoginController;
138 private final List<BillableReceipt> userReceipts;
143 @SuppressWarnings ("CollectionWithoutInitialCapacity")
144 public FinancialsReceiptWebRequestBean () {
145 // Call super constructor
149 this.allReceipts = new LinkedList<>();
150 this.userReceipts = new LinkedList<>();
154 * Adds the completed receipt to database by calling an EJB business method.
155 * If not all required fields are set, a proper exception is being thrown.
157 * @return Link outcome
159 public String addReceipt () {
160 // Are all required fields set?
161 if (!this.userLoginController.isUserLoggedIn()) {
163 throw new IllegalStateException("User is not logged-in"); //NOI18N
164 } else if (this.getReceiptBranchOffice() == null) {
166 throw new NullPointerException("this.receiptBranchOffice is not set."); //NOI18N
167 } else if (this.getReceiptBranchOffice().getBranchId() == null) {
168 // It must be an already peristed instance
169 throw new NullPointerException("this.receiptBranchOffice.businessContactId is not set."); //NOI18N
170 } else if (this.getReceiptBranchOffice().getBranchId() < 1) {
171 // It must be an already peristed instance
172 throw new IllegalArgumentException(MessageFormat.format("this.receiptBranchOffice.businessContactId={0} is not valid.", this.getReceiptBranchOffice().getBranchId())); //NOI18N
173 } else if (this.getReceiptPaymentType() == null) {
175 throw new NullPointerException("this.receiptPaymentType is not set."); //NOI18N
176 } else if (this.getReceiptIssued() == null) {
178 throw new NullPointerException("this.receiptIssued is not set."); //NOI18N
181 // Prepare receipt instance
182 final BillableReceipt receipt = this.createReceiptInstance();
184 // Is the receipt already there?
185 if (this.isReceiptAdded(receipt)) {
186 // Receipt has already been added
187 throw new FaceletException(MessageFormat.format("Receipt for receiptBranchOffice={0},receiptIssued={1},receiptNumber={2} has already been added.", this.getReceiptBranchOffice().getBranchId(), this.getReceiptIssued().toString(), this.getReceiptNumber())); //NOI18N
191 final BillableReceipt updatedReceipt;
193 // All is set, then try to call EJB
196 updatedReceipt = this.receiptBean.addReceipt(receipt);
197 } catch (final ReceiptAlreadyAddedException ex) {
199 throw new FaceletException(ex);
202 // Fire event with updated instance
203 this.addedReceiptEvent.fire(new ReceiptAddedEvent(updatedReceipt));
205 // Return redirect outcome
206 return "add_receipt_item?faces-redirect=true"; //NOI18N
210 * Observes events being fired when a new receipt has been added
212 * @param event Event being fired
214 public void afterAddedReceiptEvent (@Observes final ObservableReceiptAddedEvent event) {
215 // Validate parameter
218 throw new NullPointerException("event is null"); //NOI18N
219 } else if (event.getReceipt() == null) {
221 throw new NullPointerException("event.receipt is null"); //NOI18N
222 } else if (event.getReceipt().getReceiptId() == null) {
224 throw new NullPointerException("event.receipt.receiptId is null"); //NOI18N
225 } else if (event.getReceipt().getReceiptId() < 1) {
227 throw new IllegalArgumentException(MessageFormat.format("event.receipt.receiptId={0} is invalid", event.getReceipt().getReceiptId())); //NOI18N
230 // Add to cache and general list
231 this.receiptCache.put(event.getReceipt().getReceiptId(), event.getReceipt());
232 this.allReceipts.add(event.getReceipt());
235 if (this.userLoginController.isUserLoggedIn() && Objects.equals(event.getReceipt().getReceiptUser(), this.userLoginController.getLoggedInUser())) {
236 // Same user, then add it
237 this.userReceipts.add(event.getReceipt());
242 * Event observer for logged-in user
244 * @param event Event instance
246 public void afterUserLoginEvent (@Observes final ObservableUserLoggedInEvent event) {
247 // event should not be null
250 throw new NullPointerException("event is null"); //NOI18N
251 } else if (event.getLoggedInUser() == null) {
253 throw new NullPointerException("event.loggedInUser is null"); //NOI18N
254 } else if (event.getLoggedInUser().getUserId() == null) {
256 throw new NullPointerException("event.loggedInUser.userId is null"); //NOI18N
257 } else if (event.getLoggedInUser().getUserId() < 1) {
259 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLoggedInUser(), event.getLoggedInUser().getUserId())); //NOI18N
262 // Fill cache with all found user's receipts
263 for (final BillableReceipt receipt : this.allReceipts) {
265 if (Objects.equals(receipt.getReceiptUser(), event.getLoggedInUser())) {
267 this.userReceipts.add(receipt);
273 * Returns all receipts
275 * @return All receipts
277 @SuppressWarnings ("ReturnOfCollectionOrArrayField")
278 public List<BillableReceipt> allReceipts () {
279 return this.allReceipts;
283 * Getter for filtered receipts
285 * @return Filtered receipts
287 @SuppressWarnings ("ReturnOfCollectionOrArrayField")
288 public List<BillableReceipt> getFilteredReceipts () {
289 return this.filteredReceipts;
293 * Setter for filtered receipts
295 * @param filteredReceipts Filtered receipts
297 @SuppressWarnings ("AssignmentToCollectionOrArrayFieldFromParameter")
298 public void setFilteredReceipts (final List<BillableReceipt> filteredReceipts) {
299 this.filteredReceipts = filteredReceipts;
303 * Getter for receipt's bar-code number
305 * @return Receipt's bar-code number
307 public Long getReceiptBarCodeNumber () {
308 return this.receiptBarCodeNumber;
312 * Setter for receipt's bar-code number
314 * @param receiptBarCodeNumber Receipt's bar-code number
316 public void setReceiptBarCodeNumber (final Long receiptBarCodeNumber) {
317 this.receiptBarCodeNumber = receiptBarCodeNumber;
321 * Getter for receipt issuing branch office
323 * @return Receipt issuing branch office
325 public BranchOffice getReceiptBranchOffice () {
326 return this.receiptBranchOffice;
330 * Setter for receipt issuing branch office
332 * @param receiptBranchOffice Receipt issuing branch office
334 public void setReceiptBranchOffice (final BranchOffice receiptBranchOffice) {
335 this.receiptBranchOffice = receiptBranchOffice;
339 * Getter for receipt issue date and time
341 * @return Receipt issue date and time
343 @SuppressWarnings ("ReturnOfDateField")
344 public Date getReceiptIssued () {
345 return this.receiptIssued;
349 * Setter for receipt issue date and time
351 * @param receiptIssued Receipt issue date and time
353 @SuppressWarnings ("AssignmentToDateFieldFromParameter")
354 public void setReceiptIssued (final Date receiptIssued) {
355 this.receiptIssued = receiptIssued;
359 * Getter for receipt number
361 * @return Receipt number
363 public Long getReceiptNumber () {
364 return this.receiptNumber;
368 * Setter for receipt number
370 * @param receiptNumber Receipt number
372 public void setReceiptNumber (final Long receiptNumber) {
373 this.receiptNumber = receiptNumber;
377 * Getter for payment type
379 * @return Payment type
381 public PaymentType getReceiptPaymentType () {
382 return this.receiptPaymentType;
386 * Setter for payment type
388 * @param receiptPaymentType Payment type
390 public void setReceiptPaymentType (final PaymentType receiptPaymentType) {
391 this.receiptPaymentType = receiptPaymentType;
395 * Getter for receipt register's number
397 * @return Receipt register's number
399 public Long getReceiptRegisterNumber () {
400 return this.receiptRegisterNumber;
404 * Setter for receipt register's number
406 * @param receiptRegisterNumber Receipt register's number
408 public void setReceiptRegisterNumber (final Long receiptRegisterNumber) {
409 this.receiptRegisterNumber = receiptRegisterNumber;
413 * Getter for receipt seller employee
415 * @return Receipt seller employee
417 public Employee getReceiptSellerEmployee () {
418 return this.receiptSellerEmployee;
422 * Setter for receipt seller employee
424 * @param receiptSellerEmployee Receipt seller employee
426 public void setReceiptSellerEmployee (final Employee receiptSellerEmployee) {
427 this.receiptSellerEmployee = receiptSellerEmployee;
431 public void initCache () {
433 if (!this.receiptCache.iterator().hasNext()) {
435 final List<BillableReceipt> list = this.receiptBean.allReceipts();
438 for (final Iterator<BillableReceipt> iterator = list.iterator(); iterator.hasNext();) {
440 final BillableReceipt next = iterator.next();
443 this.receiptCache.put(next.getReceiptId(), next);
447 // Is the list empty, but filled cache?
448 if (this.allReceipts.isEmpty() && this.receiptCache.iterator().hasNext()) {
450 final Iterator<Cache.Entry<Long, BillableReceipt>> iterator = this.receiptCache.iterator();
453 while (iterator.hasNext()) {
455 final Cache.Entry<Long, BillableReceipt> next = iterator.next();
458 this.allReceipts.add(next.getValue());
462 this.allReceipts.sort(new Comparator<BillableReceipt>() {
464 public int compare (final BillableReceipt o1, final BillableReceipt o2) {
465 return o1.getReceiptId() > o2.getReceiptId() ? 1 : o1.getReceiptId() < o2.getReceiptId() ? -1 : 0;
473 public boolean isReceiptAdded (final BillableReceipt receipt) {
474 // Always trust the cache
475 return this.allReceipts.contains(receipt);
479 * Returns a fully created receipt instance (except primary key, of course)
481 * @return Receipt instance
483 private BillableReceipt createReceiptInstance () {
484 // Init receipt instance
485 final BillableReceipt receipt = new FinancialReceipt(this.getReceiptPaymentType(), this.getReceiptBranchOffice(), this.userLoginController.getLoggedInUser(), this.getReceiptIssued());
487 // Set optional fields
488 receipt.setReceiptNumber(this.getReceiptNumber());
489 receipt.setReceiptBarCodeNumber(this.getReceiptBarCodeNumber());
490 receipt.setReceiptRegisterNumber(this.getReceiptRegisterNumber());
491 receipt.setReceiptSellerEmployee(this.getReceiptSellerEmployee());