View Javadoc
1   /*
2    * Copyright (c) Patrick Magauran 2018.
3    *   Licensed under the AGPLv3. All conditions of said license apply.
4    *       This file is part of ABOS.
5    *
6    *       ABOS is free software: you can redistribute it and/or modify
7    *       it under the terms of the GNU Affero General Public License as published by
8    *       the Free Software Foundation, either version 3 of the License, or
9    *       (at your option) any later version.
10   *
11   *       ABOS is distributed in the hope that it will be useful,
12   *       but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   *       GNU Affero General Public License for more details.
15   *
16   *       You should have received a copy of the GNU Affero General Public License
17   *       along with ABOS.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package Utilities;/*
21   * Copyright (c) Patrick Magauran 2018.
22   *   Licensed under the AGPLv3. All conditions of said license apply.
23   *       This file is part of ABOS.
24   *
25   *       ABOS is free software: you can redistribute it and/or modify
26   *       it under the terms of the GNU Affero General Public License as published by
27   *       the Free Software Foundation, either version 3 of the License, or
28   *       (at your option) any later version.
29   *
30   *       ABOS is distributed in the hope that it will be useful,
31   *       but WITHOUT ANY WARRANTY; without even the implied warranty of
32   *       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33   *       GNU Affero General Public License for more details.
34   *
35   *       You should have received a copy of the GNU Affero General Public License
36   *       along with ABOS.  If not, see <http://www.gnu.org/licenses/>.
37   */
38  
39  import Exceptions.CustomerNotFoundException;
40  import javafx.beans.property.ReadOnlyDoubleProperty;
41  import javafx.beans.property.ReadOnlyDoubleWrapper;
42  import javafx.beans.property.ReadOnlyStringProperty;
43  import javafx.beans.property.ReadOnlyStringWrapper;
44  import javafx.scene.control.Alert;
45  import javafx.scene.control.ButtonType;
46  
47  import java.math.BigDecimal;
48  import java.sql.Connection;
49  import java.sql.PreparedStatement;
50  import java.sql.ResultSet;
51  import java.sql.SQLException;
52  import java.util.Objects;
53  import java.util.Optional;
54  
55  /**
56   * Created by patrick on 7/26/16.
57   */
58  @SuppressWarnings("unused")
59  public class Customer {
60      private Utilities.Settable<String> name = new Utilities.Settable<>("");
61      private final ReadOnlyDoubleWrapper progress = new ReadOnlyDoubleWrapper(this, "progress");
62      private final ReadOnlyStringWrapper message = new ReadOnlyStringWrapper(this, "message");
63      private Utilities.Settable<Integer> ID = new Utilities.Settable(-1, -1);
64      private Utilities.Settable<Integer> orderID = new Utilities.Settable(-1, -1);
65      private Utilities.Settable<String> nameEdited = new Utilities.Settable("");
66      private Utilities.Settable<String> year = new Utilities.Settable("");
67      private Utilities.Settable<String> address = new Utilities.Settable("");
68      private Utilities.Settable<String> town = new Utilities.Settable("");
69      private Utilities.Settable<String> state = new Utilities.Settable("");
70      private Utilities.Settable<String> zipCode = new Utilities.Settable("");
71      private Utilities.Settable<Double> lat = new Utilities.Settable<>();
72      private Utilities.Settable<Double> lon = new Utilities.Settable<>();
73      private Utilities.Settable<String> phone = new Utilities.Settable("");
74      private Utilities.Settable<BigDecimal> paid = new Utilities.Settable();
75      private Utilities.Settable<Boolean> delivered = new Utilities.Settable();
76      private Utilities.Settable<String> email = new Utilities.Settable();
77      private Utilities.Settable<String> user = new Utilities.Settable("");
78      private Utilities.Settable<BigDecimal> Donation = new Utilities.Settable();
79      private Utilities.Settable<Order.orderArray> orders = new Utilities.Settable();
80  
81      public Customer(Integer ID, String name, String year, String address,
82                      String town,
83                      String state,
84                      String zipCode,
85                      Double lat,
86                      Double lon,
87                      String phone,
88                      BigDecimal paid,
89                      Boolean delivered,
90                      String email,
91                      String nameEdited,
92                      BigDecimal Donation) {
93          this(ID, name, year, address, town, state, zipCode, lat, lon, phone, paid, delivered, email, nameEdited, Donation, DbInt.getUserName());
94      }
95  
96      /**
97       * @param ID         The ID of the customer. If creating a new customer, set this to -1
98       * @param name       The name of the customer
99       * @param year       The Year the customer is to be added to
100      * @param address    The street address of the customer
101      * @param town       The town of the customer
102      * @param state      The state of the customer
103      * @param zipCode    The 5 digit zip code of the customer
104      * @param lat        The latitude of the customer
105      * @param lon        The longitude of the customer
106      * @param phone      THe phone number of the customer
107      * @param paid       A boolean that specifies where the customer paid
108      * @param delivered  A boolean that specifies whether the order was delivered
109      * @param email      The email of the customer
110      * @param nameEdited The new name of the customer to update to
111      * @param Donation   The amount the customer donated
112      * @param user       The user to add the customer as
113      */
114     public Customer(Integer ID, String name, String year, String address,
115                     String town,
116                     String state,
117                     String zipCode,
118                     Double lat,
119                     Double lon,
120                     String phone,
121                     BigDecimal paid,
122                     Boolean delivered,
123                     String email,
124                     String nameEdited,
125                     BigDecimal Donation,
126                     String user) {
127         this.ID.set(ID);
128         this.name.set(name);
129         this.year.set(year);
130         this.address.set(address);
131         this.town.set(town);
132         this.state.set(state);
133         this.zipCode.set(zipCode);
134         this.lat.set(lat);
135         this.lon.set(lon);
136         this.phone.set(phone);
137         this.paid.set(paid);
138         this.delivered.set(delivered);
139         this.email.set(email);
140         this.Donation.set(Donation);
141         this.nameEdited.set(nameEdited);
142         this.user.set(user);
143     }
144 
145     public Customer(String name, String year) {
146         this(-1, name, year, null, null, null, null, null, null, null, BigDecimal.ZERO, false, null, null, null, DbInt.getUserName());
147     }
148 
149     /** Gets customer information using ID and year from the databse
150      * @param ID ID of the customer
151      * @param year The year to retrieve from
152      * @throws CustomerNotFoundException Thrown if the specified ID is not found within the database
153      */
154     public Customer(int ID, String year) throws CustomerNotFoundException {
155         String ret = "";
156         try (Connection con = DbInt.getConnection(year);
157              PreparedStatement prep = con.prepareStatement("SELECT Name, uName FROM customerview WHERE idcustomers=?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
158             prep.setInt(1, ID);
159             try (ResultSet rs = prep.executeQuery()) {
160 
161                 while (rs.next()) {
162 
163                     ret = rs.getString("Name");
164                     this.user.set(rs.getString("uName"));
165                 }
166             }
167             ////Utilities.DbInt.pCon.close()
168 
169         } catch (SQLException e) {
170             LogToFile.log(e, Severity.SEVERE, CommonErrors.returnSqlMessage(e));
171         }
172 
173         if (!Objects.equals(ret, "")) {
174             this.ID.set(ID);
175             this.name.set(ret);
176             this.year.set(year);
177             this.nameEdited = name;
178         } else {
179             throw new CustomerNotFoundException();
180         }
181     }
182 
183     /** Gets customer information using ID, Name and year from the databse
184      * @param ID ID of the customer
185      * @param name The name of the customer
186      * @param year The year to retrieve from
187      *
188      */
189     public Customer(int ID, String name, String year) {
190 
191         this.ID.set(ID);
192         this.name.set(name);
193         this.year.set(year);
194         this.nameEdited.set(name);
195         try (Connection con = DbInt.getConnection(year);
196              PreparedStatement prep = con.prepareStatement("SELECT uName FROM customerview WHERE idcustomers=?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
197             prep.setInt(1, ID);
198             try (ResultSet rs = prep.executeQuery()) {
199 
200                 while (rs.next()) {
201 
202                     this.user.set(rs.getString("uName"));
203                 }
204             }
205             ////Utilities.DbInt.pCon.close()
206 
207         } catch (SQLException e) {
208             LogToFile.log(e, Severity.SEVERE, CommonErrors.returnSqlMessage(e));
209         }
210 
211     }
212 
213     public Customer() {
214         this(null, null, null, null, null, null, null, null, null, null, BigDecimal.ZERO, false, null, null, null, DbInt.getUserName());
215     }
216 
217     /**
218      * @param fail A callback for if the method fails. Used in workers.
219      * @return An integer representing success
220      * @throws Exception Throws an exception so the caller can handle appropriately.
221      */
222     public int updateValues(failCallback fail) throws Exception {
223         if (Objects.equals(DbInt.getCustInf(year.get(), ID.get(), "name", ""), "")) {
224             //Insert Mode
225             double progressIncrement = (100 - getProgress()) / 3;
226             progress.set(getProgress() + progressIncrement);
227             fail.doAction();
228             message.set("Adding Customer");
229             try (Connection con = DbInt.getConnection(year.get());
230                  PreparedStatement writeCust = con.prepareStatement("INSERT INTO customerview (uName, Name, streetAddress, City, State, Zip, Lat, Lon, Phone, Email, Donation) VALUES (?,?,?,?,?,?,?,?,?,?,?)", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
231                 writeCust.setString(1, this.user.get());
232                 writeCust.setString(2, this.nameEdited.get());
233                 writeCust.setString(3, this.address.get());
234                 writeCust.setString(4, this.town.get());
235                 writeCust.setString(5, this.state.get());
236                 writeCust.setString(6, this.zipCode.get());
237                 writeCust.setDouble(7, lat.get());
238                 writeCust.setDouble(8, lon.get());
239                 writeCust.setString(9, this.phone.get());
240                 //writeCust.setString(9, this.orderId);
241                 //writeCust.setString(10, this.paid);
242                 //writeCust.setString(11, this.delivered);
243                 writeCust.setString(10, this.email.get());
244                 writeCust.setString(11, this.Donation.orElseGetAndSet(() -> {return BigDecimal.ZERO;}).toPlainString());
245                 fail.doAction();
246                 writeCust.execute();
247             }
248             progress.set(getProgress() + progressIncrement);
249      /*       try (PreparedStatement prep1 = Utilities.DbInt.getPrep("Set", "INSERT INTO CUSTOMERS(ADDRESS, TOWN, STATE, ZIPCODE, Lat, Lon, ORDERED, NI, NH) VALUES(?,?,?,?,?,?, 'True','False','False')")) {
250                 prep1.setString(1, this.address.get());
251                 prep1.setString(2, this.town.get());
252                 prep1.setString(3, this.state.get());
253                 prep1.setString(4, this.zipCode.get());
254                 prep1.setDouble(5, lat);
255                 prep1.setDouble(6, lon);
256                 fail.doAction();
257 
258                 prep1.execute();
259             }*/
260             progress.set(getProgress() + progressIncrement);
261 
262 
263         } else {
264 
265             progress.set(10);
266 
267             //Updates customer table in Utilities.Year DB with new info.
268             try (Connection con = DbInt.getConnection(year.get());
269                  PreparedStatement CustomerUpdate = con.prepareStatement("UPDATE customerview SET Name=?, streetAddress=?, City=?, State=?, Zip=?, Lat=?, Lon=?, Phone=?,Email=?, Donation=? WHERE idCustomers = ?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
270                 CustomerUpdate.setString(1, this.nameEdited.get());
271                 CustomerUpdate.setString(2, this.address.get());
272                 CustomerUpdate.setString(3, this.town.get());
273                 CustomerUpdate.setString(4, this.state.get());
274                 CustomerUpdate.setString(5, this.zipCode.get());
275                 CustomerUpdate.setDouble(6, lat.get());
276                 CustomerUpdate.setDouble(7, lon.get());
277                 CustomerUpdate.setString(8, this.phone.get());
278                 CustomerUpdate.setString(9, this.email.get());
279                 CustomerUpdate.setString(10, this.Donation.orElseGetAndSet(() -> {
280                     return BigDecimal.ZERO;
281                 }).toPlainString());
282                 CustomerUpdate.setInt(11, ID.get());
283                 fail.doAction();
284 
285                 CustomerUpdate.execute();
286             }
287             progress.set(20);
288 
289         }
290         Integer cID = 0;
291         try (Connection con = DbInt.getConnection(year.get());
292              PreparedStatement prep = con.prepareStatement("SELECT idcustomers FROM customerview WHERE Name=?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
293             prep.setString(1, nameEdited.get());
294             try (ResultSet rs = prep.executeQuery()) {
295                 while (rs.next()) {
296 
297                     cID = rs.getInt(1);
298 
299                 }
300             }
301         }
302         this.ID.setIfNot(cID);
303         return cID;
304     }
305 
306     public void deleteCustomer() {
307         Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
308         alert.setTitle("WARNING!");
309         alert.setHeaderText("BY CONTINUING YOU ARE PERMANENTLY REMOVING A CUSTOMER! ALL DATA MUST BE REENTERED!");
310         alert.setContentText("Would you like to continue?");
311 
312 
313         Optional<ButtonType> result = alert.showAndWait();
314         if (result.get() == ButtonType.OK) {
315 
316             try (Connection con = DbInt.getConnection(year.get());
317                  PreparedStatement prep = con.prepareStatement("DELETE FROM customerview WHERE idCustomers=?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
318                 prep.setInt(1, ID.get());
319                 prep.execute();
320             } catch (SQLException e) {
321                 LogToFile.log(e, Severity.SEVERE, "Error deleting customer. Try again or contact support.");
322             }
323         }
324     }
325 
326     public String[] getCustAddressFrmName() {
327 
328         String city = getTown();
329         String State = getState();
330         String zCode = getZip();
331         String strtAddress = getAddr();
332         String[] address = new String[4];
333         address[0] = city;
334         address[1] = State;
335         address[2] = zCode;
336         address[3] = strtAddress;
337         return address;
338     }
339 
340     public Order.orderArray getOrderArray() {
341         return this.orders.orElseGetAndSet(() -> Order.createOrderArray(year.get(), ID.get(), true));
342     }
343     /**
344      * Loops through Table to get total amount of Bulk Mulch ordered.
345      *
346      * @return The amount of Bulk mulch ordered
347      */
348     public int getNoMulchOrdered() {
349         Order.orderArray order = getOrderArray();
350         int quantMulchOrdered = 0;
351         for (formattedProduct productOrder : order.orderData) {
352             if ((productOrder.productName.contains("Mulch")) && (productOrder.productName.contains("Bulk"))) {
353                 quantMulchOrdered += productOrder.orderedQuantity;
354             }
355         }
356 
357         return quantMulchOrdered;
358     }
359 
360     private BigDecimal getCommission(BigDecimal totalCost) {
361         BigDecimal commision = BigDecimal.ZERO;
362         if ((totalCost.compareTo(new BigDecimal("299.99")) > 0) && (totalCost.compareTo(new BigDecimal("500.01")) < 0)) {
363             commision = totalCost.multiply(new BigDecimal("0.05"));
364         } else if ((totalCost.compareTo(new BigDecimal("500.01")) > 0) && (totalCost.compareTo(new BigDecimal("1000.99")) < 0)) {
365             commision = totalCost.multiply(new BigDecimal("0.1"));
366         } else if (totalCost.compareTo(new BigDecimal("1000")) >= 0) {
367             commision = totalCost.multiply(new BigDecimal("0.15"));
368         }
369         return commision;
370     }
371 
372     /**
373      * Loops through Table to get total amount of Lawn and Garden Products ordered.
374      *
375      * @return The amount of Lawn and Garden Products ordered
376      */
377     public int getNoLivePlantsOrdered() {
378         Order.orderArray order = getOrderArray();
379         int livePlantsOrdered = 0;
380         for (formattedProduct productOrder : order.orderData) {
381             if ((productOrder.productName.contains("-P")) && (productOrder.productName.contains("-FV"))) {
382                 livePlantsOrdered += productOrder.orderedQuantity;
383             }
384         }
385 
386         return livePlantsOrdered;
387     }
388 
389     /**
390      * Loops through Table to get total amount of Lawn Products ordered.
391      *
392      * @return The amount of Live Plants ordered
393      */
394     public int getNoLawnProductsOrdered() {
395         Order.orderArray order = getOrderArray();
396         int lawnProductsOrdered = 0;
397         for (formattedProduct productOrder : order.orderData) {
398             if (productOrder.productName.contains("-L")) {
399                 lawnProductsOrdered += productOrder.orderedQuantity;
400             }
401         }
402         return lawnProductsOrdered;
403     }
404 
405     public Double getLat() {
406         return this.lat.orElseGetAndSet(() -> {
407             Double ret = lat.get();
408             try (Connection con = DbInt.getConnection(year.get());
409                  PreparedStatement prep = con.prepareStatement("SELECT Lat FROM customerview WHERE idCustomers=?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
410                 prep.setInt(1, ID.get());
411                 try (ResultSet rs = prep.executeQuery()) {
412 
413                     while (rs.next()) {
414 
415                         ret = rs.getDouble("Lat");
416 
417                     }
418                 }
419                 ////Utilities.DbInt.pCon.close()
420 
421             } catch (SQLException e) {
422                 LogToFile.log(e, Severity.SEVERE, CommonErrors.returnSqlMessage(e));
423             }
424 
425             return ret;
426         });
427     }
428 
429     public void setLat(Double lat) {
430         this.lat.set(lat);
431     }
432 
433     public Double getLon() {
434         return this.lon.orElseGetAndSet(() -> {
435             Double ret = lon.get();
436             try (Connection con = DbInt.getConnection(year.get());
437                  PreparedStatement prep = con.prepareStatement("SELECT Lon FROM customerview WHERE idCustomers=?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
438                 prep.setInt(1, ID.get());
439                 try (ResultSet rs = prep.executeQuery()) {
440 
441                     while (rs.next()) {
442 
443                         ret = rs.getDouble("Lon");
444 
445                     }
446                 }
447                 ////Utilities.DbInt.pCon.close()
448 
449             } catch (SQLException e) {
450                 LogToFile.log(e, Severity.SEVERE, CommonErrors.returnSqlMessage(e));
451             }
452 
453             return ret;
454         });
455     }
456 
457     public void setLon(Double lon) {
458         this.lon.set(lon);
459     }
460 
461     public void setAddress(String address) {
462         this.address.set(address);
463     }
464 
465     public void setZipCode(String zipCode) {
466         this.zipCode.set(zipCode);
467     }
468 
469     public void setDonation(BigDecimal donation) {
470         Donation.set(donation);
471     }
472 
473     public Integer getId() {
474         return this.ID.orElseGetAndSet(() -> {
475             Integer ret = 0;
476             try (Connection con = DbInt.getConnection(year.get());
477                  PreparedStatement prep = con.prepareStatement("SELECT idcustomers FROM customerview WHERE Name=?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
478                 prep.setString(1, name.get());
479                 try (ResultSet rs = prep.executeQuery()) {
480 
481                     while (rs.next()) {
482 
483                         ret = rs.getInt("idcustomers");
484 
485                     }
486                 }
487                 ////Utilities.DbInt.pCon.close()
488 
489             } catch (SQLException e) {
490                 LogToFile.log(e, Severity.SEVERE, CommonErrors.returnSqlMessage(e));
491             }
492             return ret;
493         });
494 
495     }
496 
497     public String getAddr() {
498         return this.address.orElseGetAndSet(() -> {
499             return DbInt.getCustInf(year.get(), ID.get(), "streetAddress", address.get());
500         });
501     }
502 
503     public String getFormattedAddress() {
504         return getAddr() + " " + getTown() + ", " + getState() + " " + getZip();
505     }
506 
507     public String getTown() {
508         return this.town.orElseGetAndSet(() -> { return DbInt.getCustInf(year.get(), ID.get(), "City", town.get());});
509     }
510 
511     public void setTown(String town) {
512         this.town.set(town);
513     }
514 
515     public String getState() {
516         return this.state.orElseGetAndSet(() -> {
517             return DbInt.getCustInf(year.get(), ID.get(), "State", state.get());
518         });
519     }
520 
521     public void setState(String state) {
522         this.state.set(state);
523     }
524 
525     public String getZip() {
526         return this.zipCode.orElseGetAndSet(() -> {
527             return DbInt.getCustInf(year.get(), ID.get(), "Zip", zipCode.get());
528         });
529     }
530 
531     public String getName() {
532         return name.get();
533     }
534 
535     public void setName(String name) {
536         this.nameEdited.set(name);
537     }
538 
539     public String getUser() {
540         return user.get();
541     }
542 
543     /**
544      * Return Phone number of the customer whose name has been specified.
545      *
546      * @return The Phone number of the specified customer
547      */
548     public String getPhone() {
549         return this.phone.orElseGetAndSet(() -> {
550             return DbInt.getCustInf(year.get(), ID.get(), "Phone", phone.get());
551         });
552     }
553 
554     public void setPhone(String phone) {
555         this.phone.set(phone);
556     }
557 
558     /**
559      * Returns if the customer has paid.
560      *
561      * @return The Payment status of the specified customer
562      */
563     public BigDecimal getPaid() {
564         return this.paid.orElseGetAndSet(() -> { return Order.getOrder(year.get(), ID.get()).paid;});
565     }
566 
567     public void setPaid(BigDecimal paid) {
568         this.paid.set(paid);
569     }
570 
571     public String getYear() {
572         return year.get();
573     }
574 
575     public void setYear(String year) {
576         this.year.set(year);
577     }
578 
579     /**
580      * Return Delivery status of the customer whose name has been specified.
581      *
582      * @return The Delivery status of the specified customer
583      */
584 
585     public Boolean getDelivered() {
586         return this.delivered.orElseGetAndSet(() -> { return Order.getOrder(year.get(), ID.get()).delivered;});
587     }
588 
589     public void setDelivered(Boolean delivered) {
590         this.delivered.set(delivered);
591     }
592 
593     /**
594      * Return Email Address of the customer whose name has been specified.
595      *
596      * @return The Email Address of the specified customer
597      */
598     public String getEmail() {
599         return this.email.orElseGetAndSet(() -> {
600             return DbInt.getCustInf(year.get(), ID.get(), "Email", email.get());
601         });
602     }
603 
604     public void setEmail(String email) {
605         this.email.set(email);
606     }
607 
608     /**
609      * Return Utilities.Order ID of the customer whose name has been specified.
610      *
611      * @return The Utilities.Order ID of the specified customer
612      */
613     public int getOrderId() {
614         return this.orderID.orElseGetAndSet(() -> {
615             int ret = 0;
616             try (Connection con = DbInt.getConnection(year.get());
617                  PreparedStatement prep = con.prepareStatement("SELECT orderID FROM customerview WHERE idCustomers=?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
618                 prep.setInt(1, ID.get());
619                 try (ResultSet rs = prep.executeQuery()) {
620 
621                     while (rs.next()) {
622 
623                         ret = rs.getInt("orderID");
624 
625                     }
626                 }
627                 ////Utilities.DbInt.pCon.close()
628 
629             } catch (SQLException e) {
630                 LogToFile.log(e, Severity.SEVERE, CommonErrors.returnSqlMessage(e));
631             }
632 
633             return ret;
634         });
635     }
636 
637 
638 
639     /**
640      * Return Donation amount of the customer whose name has been specified.
641      *
642      * @return The Donation Amount of the specified customer
643      */
644     public BigDecimal getDontation() {
645         return this.Donation.orElseGetAndSet(() -> {
646             BigDecimal ret = BigDecimal.ZERO;
647             try (Connection con = DbInt.getConnection(year.get());
648                  PreparedStatement prep = con.prepareStatement("SELECT Donation FROM customerview WHERE idCustomers=?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
649                 prep.setInt(1, ID.get());
650                 try (ResultSet rs = prep.executeQuery()) {
651 
652                     while (rs.next()) {
653 
654                         ret = rs.getBigDecimal("Donation");
655 
656                     }
657                 }
658                 ////Utilities.DbInt.pCon.close()
659 
660             } catch (SQLException e) {
661                 LogToFile.log(e, Severity.SEVERE, CommonErrors.returnSqlMessage(e));
662             }
663 
664             return ret;
665         });
666     }
667 
668     public void refreshData() {
669 
670         address.clear();
671         town.clear();
672         state.clear();
673         zipCode.clear();
674         lat.clear();
675         lon.clear();
676         phone.clear();
677         paid.clear();
678         delivered.clear();
679         email.clear();
680         Donation.clear();
681         orders.clear();
682     }
683 
684     public double getProgress() {
685         return progress.get();
686     }
687 
688     public ReadOnlyDoubleProperty progressProperty() {
689         return progress.getReadOnlyProperty();
690     }
691 
692     public String getMessage() {
693         return message.get();
694     }
695 
696     public ReadOnlyStringProperty messageProperty() {
697         return message.getReadOnlyProperty();
698     }
699 
700     public boolean equals(Object obj) {
701         if (obj == this) {
702             return true;
703         }
704         if (!(obj instanceof Customer)) {
705             return false;
706         }
707         Customer other = (Customer) obj;
708         return this.address.get().equals(other.address.get());
709     }
710 
711     public int hashCode() {
712         return address.hashCode();
713     }
714 
715 
716     public interface failCallback {
717         void doAction() throws InterruptedException;
718     }
719 
720 
721 }