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.receipt.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 * A general 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));
208 // Return redirect outcome
209 return "add_receipt_item?faces-redirect=true"; //NOI18N
213 * Observes events being fired when a new receipt has been added
215 * @param event Event being fired
217 public void afterAddedReceiptEvent (@Observes final ObservableReceiptAddedEvent event) {
218 // Validate parameter
221 throw new NullPointerException("event is null"); //NOI18N
222 } else if (event.getReceipt() == null) {
224 throw new NullPointerException("event.receipt is null"); //NOI18N
225 } else if (event.getReceipt().getReceiptId() == null) {
227 throw new NullPointerException("event.receipt.receiptId is null"); //NOI18N
228 } else if (event.getReceipt().getReceiptId() < 1) {
230 throw new IllegalArgumentException(MessageFormat.format("event.receipt.receiptId={0} is invalid", event.getReceipt().getReceiptId())); //NOI18N
233 // Add to cache and general list
234 this.receiptCache.put(event.getReceipt().getReceiptId(), event.getReceipt());
235 this.allReceipts.add(event.getReceipt());
238 if (this.userLoginController.isUserLoggedIn() && Objects.equals(event.getReceipt().getReceiptUser(), this.userLoginController.getLoggedInUser())) {
239 // Same user, then add it
240 this.userReceipts.add(event.getReceipt());
245 * Event observer for logged-in user
247 * @param event Event instance
249 public void afterUserLoginEvent (@Observes final ObservableUserLoggedInEvent event) {
250 // event should not be null
253 throw new NullPointerException("event is null"); //NOI18N
254 } else if (event.getLoggedInUser() == null) {
256 throw new NullPointerException("event.loggedInUser is null"); //NOI18N
257 } else if (event.getLoggedInUser().getUserId() == null) {
259 throw new NullPointerException("event.loggedInUser.userId is null"); //NOI18N
260 } else if (event.getLoggedInUser().getUserId() < 1) {
262 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLoggedInUser(), event.getLoggedInUser().getUserId())); //NOI18N
265 // Fill cache with all found user's receipts
266 for (final BillableReceipt receipt : this.allReceipts) {
268 if (Objects.equals(receipt.getReceiptUser(), event.getLoggedInUser())) {
270 this.userReceipts.add(receipt);
276 * Returns all receipts
278 * @return All receipts
280 @SuppressWarnings ("ReturnOfCollectionOrArrayField")
281 public List<BillableReceipt> allReceipts () {
282 return this.allReceipts;
286 * Getter for filtered receipts
288 * @return Filtered receipts
290 @SuppressWarnings ("ReturnOfCollectionOrArrayField")
291 public List<BillableReceipt> getFilteredReceipts () {
292 return this.filteredReceipts;
296 * Setter for filtered receipts
298 * @param filteredReceipts Filtered receipts
300 @SuppressWarnings ("AssignmentToCollectionOrArrayFieldFromParameter")
301 public void setFilteredReceipts (final List<BillableReceipt> filteredReceipts) {
302 this.filteredReceipts = filteredReceipts;
306 * Getter for receipt's bar-code number
308 * @return Receipt's bar-code number
310 public Long getReceiptBarCodeNumber () {
311 return this.receiptBarCodeNumber;
315 * Setter for receipt's bar-code number
317 * @param receiptBarCodeNumber Receipt's bar-code number
319 public void setReceiptBarCodeNumber (final Long receiptBarCodeNumber) {
320 this.receiptBarCodeNumber = receiptBarCodeNumber;
324 * Getter for receipt issuing branch office
326 * @return Receipt issuing branch office
328 public BranchOffice getReceiptBranchOffice () {
329 return this.receiptBranchOffice;
333 * Setter for receipt issuing branch office
335 * @param receiptBranchOffice Receipt issuing branch office
337 public void setReceiptBranchOffice (final BranchOffice receiptBranchOffice) {
338 this.receiptBranchOffice = receiptBranchOffice;
342 * Getter for receipt issue date and time
344 * @return Receipt issue date and time
346 @SuppressWarnings ("ReturnOfDateField")
347 public Date getReceiptIssued () {
348 return this.receiptIssued;
352 * Setter for receipt issue date and time
354 * @param receiptIssued Receipt issue date and time
356 @SuppressWarnings ("AssignmentToDateFieldFromParameter")
357 public void setReceiptIssued (final Date receiptIssued) {
358 this.receiptIssued = receiptIssued;
362 * Getter for receipt number
364 * @return Receipt number
366 public Long getReceiptNumber () {
367 return this.receiptNumber;
371 * Setter for receipt number
373 * @param receiptNumber Receipt number
375 public void setReceiptNumber (final Long receiptNumber) {
376 this.receiptNumber = receiptNumber;
380 * Getter for payment type
382 * @return Payment type
384 public PaymentType getReceiptPaymentType () {
385 return this.receiptPaymentType;
389 * Setter for payment type
391 * @param receiptPaymentType Payment type
393 public void setReceiptPaymentType (final PaymentType receiptPaymentType) {
394 this.receiptPaymentType = receiptPaymentType;
398 * Getter for receipt register's number
400 * @return Receipt register's number
402 public Long getReceiptRegisterNumber () {
403 return this.receiptRegisterNumber;
407 * Setter for receipt register's number
409 * @param receiptRegisterNumber Receipt register's number
411 public void setReceiptRegisterNumber (final Long receiptRegisterNumber) {
412 this.receiptRegisterNumber = receiptRegisterNumber;
416 * Getter for receipt seller employee
418 * @return Receipt seller employee
420 public Employee getReceiptSellerEmployee () {
421 return this.receiptSellerEmployee;
425 * Setter for receipt seller employee
427 * @param receiptSellerEmployee Receipt seller employee
429 public void setReceiptSellerEmployee (final Employee receiptSellerEmployee) {
430 this.receiptSellerEmployee = receiptSellerEmployee;
434 public void initCache () {
436 if (!this.receiptCache.iterator().hasNext()) {
438 final List<BillableReceipt> receipts = this.receiptBean.allReceipts();
441 for (final BillableReceipt receipt : receipts) {
443 this.receiptCache.put(receipt.getReceiptId(), receipt);
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);
481 private void clear () {
483 this.setReceiptBarCodeNumber(null);
484 this.setReceiptBranchOffice(null);
485 this.setReceiptIssued(null);
486 this.setReceiptNumber(null);
487 this.setReceiptPaymentType(null);
488 this.setReceiptRegisterNumber(null);
489 this.setReceiptSellerEmployee(null);
493 * Returns a fully created receipt instance (except primary key, of course)
495 * @return Receipt instance
497 private BillableReceipt createReceiptInstance () {
498 // Init receipt instance
499 final BillableReceipt receipt = new FinancialReceipt(this.getReceiptPaymentType(), this.getReceiptBranchOffice(), this.userLoginController.getLoggedInUser(), this.getReceiptIssued());
501 // Set optional fields
502 receipt.setReceiptNumber(this.getReceiptNumber());
503 receipt.setReceiptBarCodeNumber(this.getReceiptBarCodeNumber());
504 receipt.setReceiptRegisterNumber(this.getReceiptRegisterNumber());
505 receipt.setReceiptSellerEmployee(this.getReceiptSellerEmployee());