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.Employable;
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.receipt.ReceiptAlreadyAddedException;
44 import org.mxchange.jfinancials.exceptions.receipt.ReceiptNotFoundException;
45 import org.mxchange.jfinancials.model.receipt.BillableReceipt;
46 import org.mxchange.jfinancials.model.receipt.FinancialReceipt;
47 import org.mxchange.jfinancials.model.receipt.FinancialReceiptSessionBeanRemote;
48 import org.mxchange.jproduct.model.payment.PaymentType;
49 import org.mxchange.juserlogincore.events.login.ObservableUserLoggedInEvent;
52 * A general financial receipt bean (controller)
54 * @author Roland Häder<roland@mxchange.org>
56 @Named ("receiptController")
58 public class FinancialsReceiptWebRequestBean extends BaseFinancialsBean implements FinancialsReceiptWebRequestController {
63 private static final long serialVersionUID = 56_189_028_928_371L;
66 * Event being fired when user has added a new receipt
70 private Event<ObservableReceiptAddedEvent> addedReceiptEvent;
75 private final List<BillableReceipt> allReceipts;
78 * Filtered receipts list
80 private List<BillableReceipt> filteredReceipts;
85 private Long receiptBarCodeNumber;
88 * EJB for general financial receipt purposes
90 @EJB (lookup = "java:global/jfinancials-ejb/financialReceipt!org.mxchange.jfinancials.model.receipt.FinancialReceiptSessionBeanRemote")
91 private FinancialReceiptSessionBeanRemote receiptBean;
94 * Recipient issuing company (for example where the user went shopping to)
96 private BranchOffice receiptBranchOffice;
99 * A list of all branch offices (globally)
102 @NamedCache (cacheName = "receiptCache")
103 private Cache<Long, BillableReceipt> receiptCache;
106 * Date/time the receipt has been issued
108 private Date receiptIssued;
111 * Receipt number (only numbers)
113 private Long receiptNumber;
116 * Payment type being used for this receipt
118 private PaymentType receiptPaymentType;
123 private Long receiptRegisterNumber;
128 private Employable receiptSellerEmployee;
134 private FinancialsUserLoginWebSessionController userLoginController;
139 private final List<BillableReceipt> userReceipts;
144 @SuppressWarnings ("CollectionWithoutInitialCapacity")
145 public FinancialsReceiptWebRequestBean () {
146 // Call super constructor
150 this.allReceipts = new LinkedList<>();
151 this.userReceipts = new LinkedList<>();
155 * Adds the completed receipt to database by calling an EJB business method.
156 * If not all required fields are set, a proper exception is being thrown.
158 * @return Link outcome
160 public String addReceipt () {
161 // Are all required fields set?
162 if (!this.userLoginController.isUserLoggedIn()) {
164 throw new IllegalStateException("User is not logged-in"); //NOI18N
165 } else if (this.getReceiptBranchOffice() == null) {
167 throw new NullPointerException("this.receiptBranchOffice is not set."); //NOI18N
168 } else if (this.getReceiptBranchOffice().getBranchId() == null) {
169 // It must be an already peristed instance
170 throw new NullPointerException("this.receiptBranchOffice.businessContactId is not set."); //NOI18N
171 } else if (this.getReceiptBranchOffice().getBranchId() < 1) {
172 // It must be an already peristed instance
173 throw new IllegalArgumentException(MessageFormat.format("this.receiptBranchOffice.businessContactId={0} is not valid.", this.getReceiptBranchOffice().getBranchId())); //NOI18N
174 } else if (this.getReceiptPaymentType() == null) {
176 throw new NullPointerException("this.receiptPaymentType is not set."); //NOI18N
177 } else if (this.getReceiptIssued() == null) {
179 throw new NullPointerException("this.receiptIssued is not set."); //NOI18N
182 // Prepare receipt instance
183 final BillableReceipt receipt = this.createReceiptInstance();
185 // Is the receipt already there?
186 if (this.isReceiptAdded(receipt)) {
187 // Receipt has already been added
188 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
192 final BillableReceipt updatedReceipt;
194 // All is set, then try to call EJB
197 updatedReceipt = this.receiptBean.addReceipt(receipt);
198 } catch (final ReceiptAlreadyAddedException ex) {
200 throw new FaceletException(ex);
203 // Fire event with updated instance
204 this.addedReceiptEvent.fire(new ReceiptAddedEvent(updatedReceipt));
209 // Return redirect outcome
210 return "add_receipt_item?faces-redirect=true"; //NOI18N
214 * Observes events being fired when a new receipt has been added
216 * @param event Event being fired
218 public void afterAddedReceiptEvent (@Observes final ObservableReceiptAddedEvent event) {
219 // Validate parameter
222 throw new NullPointerException("event is null"); //NOI18N
223 } else if (event.getReceipt() == null) {
225 throw new NullPointerException("event.receipt is null"); //NOI18N
226 } else if (event.getReceipt().getReceiptId() == null) {
228 throw new NullPointerException("event.receipt.receiptId is null"); //NOI18N
229 } else if (event.getReceipt().getReceiptId() < 1) {
231 throw new IllegalArgumentException(MessageFormat.format("event.receipt.receiptId={0} is invalid", event.getReceipt().getReceiptId())); //NOI18N
234 // Add to cache and general list
235 this.receiptCache.put(event.getReceipt().getReceiptId(), event.getReceipt());
236 this.allReceipts.add(event.getReceipt());
239 if (this.userLoginController.isUserLoggedIn() && Objects.equals(event.getReceipt().getReceiptUser(), this.userLoginController.getLoggedInUser())) {
240 // Same user, then add it
241 this.userReceipts.add(event.getReceipt());
246 * Event observer for logged-in user
248 * @param event Event instance
250 public void afterUserLoginEvent (@Observes final ObservableUserLoggedInEvent event) {
251 // event should not be null
254 throw new NullPointerException("event is null"); //NOI18N
255 } else if (event.getLoggedInUser() == null) {
257 throw new NullPointerException("event.loggedInUser is null"); //NOI18N
258 } else if (event.getLoggedInUser().getUserId() == null) {
260 throw new NullPointerException("event.loggedInUser.userId is null"); //NOI18N
261 } else if (event.getLoggedInUser().getUserId() < 1) {
263 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLoggedInUser(), event.getLoggedInUser().getUserId())); //NOI18N
266 // Fill cache with all found user's receipts
267 for (final BillableReceipt receipt : this.allReceipts) {
269 if (Objects.equals(receipt.getReceiptUser(), event.getLoggedInUser())) {
271 this.userReceipts.add(receipt);
277 * Returns all receipts
279 * @return All receipts
281 @SuppressWarnings ("ReturnOfCollectionOrArrayField")
282 public List<BillableReceipt> allReceipts () {
283 return this.allReceipts;
287 public BillableReceipt findReceiptById (final Long receiptId) throws ReceiptNotFoundException {
288 // Validate parameter
289 if (null == receiptId) {
291 throw new NullPointerException("receiptId is null"); //NOI18N
292 } else if (receiptId < 1) {
294 throw new IllegalArgumentException("receiptId=" + receiptId + " is invalid."); //NOI18N
295 } else if (!this.receiptCache.containsKey(receiptId)) {
297 throw new ReceiptNotFoundException(receiptId);
301 final BillableReceipt receipt = this.receiptCache.get(receiptId);
308 * Getter for filtered receipts
310 * @return Filtered receipts
312 @SuppressWarnings ("ReturnOfCollectionOrArrayField")
313 public List<BillableReceipt> getFilteredReceipts () {
314 return this.filteredReceipts;
318 * Setter for filtered receipts
320 * @param filteredReceipts Filtered receipts
322 @SuppressWarnings ("AssignmentToCollectionOrArrayFieldFromParameter")
323 public void setFilteredReceipts (final List<BillableReceipt> filteredReceipts) {
324 this.filteredReceipts = filteredReceipts;
328 * Getter for receipt's bar-code number
330 * @return Receipt's bar-code number
332 public Long getReceiptBarCodeNumber () {
333 return this.receiptBarCodeNumber;
337 * Setter for receipt's bar-code number
339 * @param receiptBarCodeNumber Receipt's bar-code number
341 public void setReceiptBarCodeNumber (final Long receiptBarCodeNumber) {
342 this.receiptBarCodeNumber = receiptBarCodeNumber;
346 * Getter for receipt issuing branch office
348 * @return Receipt issuing branch office
350 public BranchOffice getReceiptBranchOffice () {
351 return this.receiptBranchOffice;
355 * Setter for receipt issuing branch office
357 * @param receiptBranchOffice Receipt issuing branch office
359 public void setReceiptBranchOffice (final BranchOffice receiptBranchOffice) {
360 this.receiptBranchOffice = receiptBranchOffice;
364 * Getter for receipt issue date and time
366 * @return Receipt issue date and time
368 @SuppressWarnings ("ReturnOfDateField")
369 public Date getReceiptIssued () {
370 return this.receiptIssued;
374 * Setter for receipt issue date and time
376 * @param receiptIssued Receipt issue date and time
378 @SuppressWarnings ("AssignmentToDateFieldFromParameter")
379 public void setReceiptIssued (final Date receiptIssued) {
380 this.receiptIssued = receiptIssued;
384 * Getter for receipt number
386 * @return Receipt number
388 public Long getReceiptNumber () {
389 return this.receiptNumber;
393 * Setter for receipt number
395 * @param receiptNumber Receipt number
397 public void setReceiptNumber (final Long receiptNumber) {
398 this.receiptNumber = receiptNumber;
402 * Getter for payment type
404 * @return Payment type
406 public PaymentType getReceiptPaymentType () {
407 return this.receiptPaymentType;
411 * Setter for payment type
413 * @param receiptPaymentType Payment type
415 public void setReceiptPaymentType (final PaymentType receiptPaymentType) {
416 this.receiptPaymentType = receiptPaymentType;
420 * Getter for receipt register's number
422 * @return Receipt register's number
424 public Long getReceiptRegisterNumber () {
425 return this.receiptRegisterNumber;
429 * Setter for receipt register's number
431 * @param receiptRegisterNumber Receipt register's number
433 public void setReceiptRegisterNumber (final Long receiptRegisterNumber) {
434 this.receiptRegisterNumber = receiptRegisterNumber;
438 * Getter for receipt seller employee
440 * @return Receipt seller employee
442 public Employable getReceiptSellerEmployee () {
443 return this.receiptSellerEmployee;
447 * Setter for receipt seller employee
449 * @param receiptSellerEmployee Receipt seller employee
451 public void setReceiptSellerEmployee (final Employable receiptSellerEmployee) {
452 this.receiptSellerEmployee = receiptSellerEmployee;
456 public void initCache () {
458 if (!this.receiptCache.iterator().hasNext()) {
460 final List<BillableReceipt> receipts = this.receiptBean.allReceipts();
463 for (final BillableReceipt receipt : receipts) {
465 this.receiptCache.put(receipt.getReceiptId(), receipt);
469 // Is the list empty, but filled cache?
470 if (this.allReceipts.isEmpty() && this.receiptCache.iterator().hasNext()) {
472 final Iterator<Cache.Entry<Long, BillableReceipt>> iterator = this.receiptCache.iterator();
475 while (iterator.hasNext()) {
477 final Cache.Entry<Long, BillableReceipt> next = iterator.next();
480 this.allReceipts.add(next.getValue());
484 this.allReceipts.sort(new Comparator<BillableReceipt>() {
486 public int compare (final BillableReceipt o1, final BillableReceipt o2) {
487 return o1.getReceiptId() > o2.getReceiptId() ? 1 : o1.getReceiptId() < o2.getReceiptId() ? -1 : 0;
495 public boolean isReceiptAdded (final BillableReceipt receipt) {
496 // Always trust the cache
497 return this.allReceipts.contains(receipt);
503 private void clear () {
505 this.setReceiptBarCodeNumber(null);
506 this.setReceiptBranchOffice(null);
507 this.setReceiptIssued(null);
508 this.setReceiptNumber(null);
509 this.setReceiptPaymentType(null);
510 this.setReceiptRegisterNumber(null);
511 this.setReceiptSellerEmployee(null);
515 * Returns a fully created receipt instance (except primary key, of course)
517 * @return Receipt instance
519 private BillableReceipt createReceiptInstance () {
520 // Init receipt instance
521 final BillableReceipt receipt = new FinancialReceipt(this.getReceiptPaymentType(), this.getReceiptBranchOffice(), this.userLoginController.getLoggedInUser(), this.getReceiptIssued());
523 // Set optional fields
524 receipt.setReceiptNumber(this.getReceiptNumber());
525 receipt.setReceiptBarCodeNumber(this.getReceiptBarCodeNumber());
526 receipt.setReceiptRegisterNumber(this.getReceiptRegisterNumber());
527 receipt.setReceiptSellerEmployee(this.getReceiptSellerEmployee());