001    package market;
002    
003    import java.util.Calendar;
004    
005    import market.statistics.CISalesStats;
006    import market.statistics.Statistics;
007    import market.stdform.ButtonIDs;
008    import market.stdform.FSCheckable;
009    import market.stdform.FSEditPersonData;
010    import market.stdform.FSManagerArticleStatsDetail;
011    import market.stdform.FSManagerArticleStatsMain;
012    import market.stdform.FSManagerCustomerOverview;
013    import market.stdform.FSManagerCustomerStatsDetail;
014    import market.stdform.FSManagerCustomerStatsMain;
015    import market.stdform.FSManagerEmployeeOverview;
016    import market.stdform.FSManagerOffer;
017    import market.stdform.FSManagerOpenClose;
018    import market.stdform.FSManagerOpenPurchaseOrderDetail;
019    import market.stdform.FSManagerOpenPurchaseOrderMain;
020    import market.stdform.FSManagerOptions;
021    import market.stdform.FSManagerOverallStats;
022    import market.stdform.FSManagerPurchase;
023    import market.stdform.FSManagerPurchaseConfirm;
024    import market.stdform.MSLogOff;
025    import market.swing.JCTimeRangeBoxes;
026    import sale.Action;
027    import sale.FormSheet;
028    import sale.FormSheetContentCreator;
029    import sale.Gate;
030    import sale.GateChangeTransition;
031    import sale.JDisplayDialog;
032    import sale.MenuSheet;
033    import sale.MenuSheetItem;
034    import sale.SaleProcess;
035    import sale.SalesPoint;
036    import sale.Shop;
037    import sale.Transition;
038    import sale.UIGate;
039    import data.CatalogItemValue;
040    import data.CountingStock;
041    import data.DataBasket;
042    import data.DataBasketConditionImpl;
043    import data.DoubleValue;
044    import data.IntegerValue;
045    import data.Value;
046    import data.events.VetoException;
047    import data.ooimpl.CountingStockImpl;
048    import data.ooimpl.DataBasketImpl;
049    import data.stdforms.SingleTableFormSheet;
050    import data.stdforms.TwoTableFormSheet;
051    
052    /**
053     * The manager process. This process handles all interaction with the manager's {@link SalesPoint}.
054     */
055    public class SProcessManager extends SProcessMarket {
056    
057        /**
058         * Gate for opening and closing the market.
059         */
060        private UIGate gateOpenClose                = new UIGate(null, null);
061    
062        /**
063         * Gate for setting some calculation variables.
064         */
065        private UIGate gateOptions                  = new UIGate(null, null);
066    
067        /**
068         * Gate for purchasing some articles for the market.
069         */
070        private UIGate gatePurchaseMain             = new UIGate(null, null);
071    
072        /**
073         * Gate for confirming a purchase.
074         */
075        private UIGate gatePurchaseConfirm          = new UIGate(null, null);
076    
077        /**
078         * Gate for displaying an overview of orders that have not yet arrived.
079         */
080        private UIGate gateOpoMain                  = new UIGate(null, null);
081    
082        /**
083         * Gate for displaying details of an that has not yet arrived.
084         */
085        private UIGate gateOpoDetail                = new UIGate(null, null);
086    
087        /**
088         * Gate for displaying the market's articles and their amount.
089         */
090        private UIGate gateStockMain                = new UIGate(null, null);
091    
092        /**
093         * Gate for viewing, selecting, adding and removing employees.
094         */
095        private UIGate gateEmplEditMain             = new UIGate(null, null);
096    
097        /**
098         * Gate for editing an employee's data.
099         */
100        private UIGate gateEmplEditDetail           = new UIGate(null, null);
101    
102        /**
103         * Gate for viewing, selecting and removing customers.
104         */
105        private UIGate gateCustEditMain             = new UIGate(null, null);
106    
107        /**
108         * Gate for viewing a customer's personal data.
109         */
110        private UIGate gateCustEditDetail           = new UIGate(null, null);
111    
112        /**
113         * Gate for selecting an article and a range of time for statistics.
114         */
115        private UIGate gateArticleStatsMain         = new UIGate(null, null);
116    
117        /**
118         * Gate for viewing detailed article statistics.
119         */
120        private UIGate gateArticleStatsDetail       = new UIGate(null, null);
121    
122        /**
123         * Gate for selecting a customer whose statistics should be displayed.
124         */
125        private UIGate gateCustomerStatsMain        = new UIGate(null, null);
126    
127        /**
128         * Gate for viewing a customer's statistics.
129         */
130        private UIGate gateCustomerStatsDetail      = new UIGate(null, null);
131    
132        /**
133         * Gate for the overall statistics.
134         */
135        private UIGate gateOverallStats             = new UIGate(null, null);
136        private MenuSheet menu = createManagerMenuSheet();
137        private DataBasket dbPurchase;
138        private CountingStock csPurchase;
139    
140        /**
141         * The last date the manger ordered something. This variable necessary for creating the indexes of
142         * the open purchase orders.
143         */
144        private Calendar dateLastOrder;
145    
146        /**
147         * A counting variable for open purchase orders. If there are more than one orders a day, they are
148         * distinguished by a running number which is created with the help of this variable.
149         */
150        private int intLastOrder = 0;
151    
152        public SProcessManager() {
153            super("Manager");
154        }
155    
156        /**
157         * This method is needed by {@link SaleProcess} to know on which gate to start.
158         * @return the initial gate, i.e. the {@link Gate} where the process starts.
159         */
160        public Gate getInitialGate() {
161            return getStockMainGate();
162        }
163    
164        /**
165         * Attaches {@link FSManagerOpenClose}, its actions and the menu to {@link #gateOpenClose}.
166         * @return the set up {@link #gateOpenClose}.
167         */
168        private UIGate getOpenCloseGate() {
169            final FormSheet fsmoc = new FSManagerOpenClose();
170            fsmoc.addContentCreator(new FormSheetContentCreator() {
171                public void createFormSheetContent(final FormSheet fs) {
172                    //open market
173                    fs.getButton(ButtonIDs.BTN_START).setAction(new Action() {
174                        public void doAction(SaleProcess p, SalesPoint sp) {
175                            SMarket.getTheMarket().setOpen(0);
176                            SMarket.fireMarketOpened();
177                        }
178                    });
179                    //close market (end of day)
180                    fs.getButton(ButtonIDs.BTN_END).setAction(new Action() {
181                        public void doAction(SaleProcess p, SalesPoint sp) {
182                            int error = 0;
183                            if (Shop.getTheShop().getSalesPoints().size() > 1) error = 1;
184                            if (SMarket.getTillQueue().size(null) > 0) error = 2;
185                            switch (error) {
186                                case 1:
187                                    JDDShowMessage.showMessageDialog(fs,
188                                          "Es sind noch nicht alle SalesPoints geschlossen", "Fehler");
189                                    break;
190    
191                                case 2:
192                                    JDDShowMessage.showMessageDialog(fs,
193                                          "Es wurden noch nicht alle Kunden bedient.", "Fehler");
194                                    break;
195                                default:
196                                    SMarket.getTheMarket().setOpen(2);
197                            }
198                        }
199                    });
200                    //next day
201                    fs.getButton(ButtonIDs.BTN_NEXT).setAction(
202                        new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
203                              SMarket.setNextDay();
204                        }
205                    });
206                }
207            });
208    
209            //open market
210            setAction(fsmoc, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
211                        SMarket.getTheMarket().setOpen(0);
212                        SMarket.fireMarketOpened();
213                    }}, ButtonIDs.BTN_START);
214            //close market
215            setAction(fsmoc, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
216                        int error = 0;
217                        if (Shop.getTheShop().getSalesPoints().size() > 1) error = 1;
218                        if (SMarket.getTheMarket().getStock(SMarket.STK_TILLQUEUE).size(null) > 0) error = 2;
219                        switch (error) {
220                            case 1:
221                                JDDShowMessage.showMessageDialog(fsmoc,
222                                      "Es sind noch nicht alle SalesPoints geschlossen", "Fehler");
223                                break;
224    
225                            case 2:
226                                JDDShowMessage.showMessageDialog(fsmoc,
227                                      "Es wurden noch nicht alle Kunden bedient.", "Fehler");
228                                break;
229                            default:
230                                SMarket.getTheMarket().setOpen(2);
231                        }
232                    }}, ButtonIDs.BTN_END);
233            //advance time
234            setAction(fsmoc, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
235                        SMarket.setNextDay();
236                    }}, ButtonIDs.BTN_NEXT);
237    
238            gateOpenClose.setFormSheet(fsmoc);
239            gateOpenClose.setMenuSheet(menu);
240            return gateOpenClose;
241        }
242    
243        /**
244         * Attaches {@link FSManagerOptions}, its actions and the menu to {@link #gateOptions}.
245         * @return the set up {@link #gateOptions}.
246         */
247        private UIGate getOptionsGate() {
248            final FSCheckable fsc = new FSCheckable(new FSManagerOptions());
249            //accept settings
250            setAction(fsc, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
251                        if (fsc.checkTextFields(FSCheckable.ALL_ERRORMESSAGES_AT_ONCE, false)) {
252                            Options options = SMarket.getOptions();
253                            int error = 0;
254                            if (Double.valueOf(Conversions.convertComma(
255                                    fsc.getEntry(FSManagerOptions.JTFC_MAX_DISCOUNT))).doubleValue() > 100)
256                                error = 1;
257                            switch (error) {
258                                case 1:
259                                    JDDShowMessage.showMessageDialog(fsc, "Es können nicht mehr als " +
260                                            "100% Rabatt gewährt werden.", "Zu viel Rabatt");
261                                default:
262                                    options.setDiscountRange(Integer.valueOf(
263                                            fsc.getEntry(FSManagerOptions.JTFC_DISCOUNT_RANGE)).intValue());
264                                    options.setDiscountValue(Integer.valueOf(
265                                            fsc.getEntry(FSManagerOptions.JTFC_DISCOUNT_VALUE)).intValue());
266                                    options.setMaxDiscount(Double.valueOf(Conversions.convertComma(
267                                            fsc.getEntry(FSManagerOptions.JTFC_MAX_DISCOUNT))).
268                                            doubleValue() / 100);
269                                    options.setFractionOfWages(Double.valueOf(Conversions.convertComma(
270                                            fsc.getEntry(FSManagerOptions.JTFC_FRACTION_OF_WAGES))).
271                                            doubleValue() / 100);
272                                    options.setTimeOfEmployment(Double.valueOf(Conversions.convertComma(
273                                            fsc.getEntry(FSManagerOptions.JTFC_SENIORITY))).
274                                            doubleValue() / 100);
275                                    SMarket.getMonthlySalesStats().setCosts(Conversions.currencyToInt(
276                                            fsc.getEntry(FSManagerOptions.JTFC_COSTS), true));
277                            }
278                        }
279                    }}, ButtonIDs.BTN_ACCEPT);
280            gateOptions.setFormSheet(fsc);
281            gateOptions.setMenuSheet(menu);
282            return gateOptions;
283        }
284    
285        /**
286         * Attaches {@link FSManagerOffer} and the menu to {@link #gateStockMain}.
287         * @return the set up {@link #gateStockMain}.
288         */
289        private UIGate getStockMainGate() {
290            final SingleTableFormSheet stfs = FSManagerOffer.create();
291            gateStockMain.setFormSheet(stfs);
292            gateStockMain.setMenuSheet(menu);
293            return gateStockMain;
294        }
295    
296        /**
297         * Attaches {@link FSManagerPurchase}, its actions and the menu to {@link #gatePurchaseMain}.
298         * @param cs the manager's "shopping basket", it can be empty or already filled with articles.
299         * @param db the transaction's DataBasket.
300         * @return the set up {@link #gatePurchaseMain}.
301         */
302        private UIGate getPurchaseMainGate(CountingStock cs, DataBasket db) {
303            //Create FormSheet with saved DataBasket and CountingStock if needed. If not, create new ones.
304            final TwoTableFormSheet ttfs = FSManagerPurchase.create(gatePurchaseMain,
305                    cs == null ? new CountingStockImpl("Einkauf", SMarket.getArticleCatalog()) : cs,
306                    db == null ? new DataBasketImpl() : db);
307            //Buy
308            setAction(ttfs, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
309                        csPurchase = (CountingStock)ttfs.getRightTableSource();
310                        dbPurchase = ttfs.getDataBasket();
311                        //if no items bought, print error message
312                        if (!dbPurchase.contains(DataBasketConditionImpl.ALL_ENTRIES)) {
313                            JDDShowMessage.showMessageDialog(ttfs, "Bitte wählen sie Artikel zum Kauf aus.",
314                                    "Keine Auswahl getroffen");
315                        } else {
316                            //sum up prices of all selected Articles
317                            DoubleValue dv = new DoubleValue(0);
318                            csPurchase.sumStock(dbPurchase, CatalogItemValue.EVALUATE_OFFER, dv);
319                            int toPay = Conversions.currencyToInt(dv.toString(), false);
320                            //Transition to gate purchaseConfirm
321                            gatePurchaseMain.setNextTransition(new GateChangeTransition(
322                                    getPurchaseConfirmGate(toPay)));
323                        }
324                    }}, ButtonIDs.BTN_BUY);
325            gatePurchaseMain.setFormSheet(ttfs);
326            gatePurchaseMain.setMenuSheet(menu);
327            return gatePurchaseMain;
328        }
329    
330        /**
331         * Attaches {@link FSManagerPurchaseConfirm} and its actions to {@link #gatePurchaseConfirm}.
332         * @param toPay the money to pay for the manager's purchase.
333         * @return the set up {@link #gatePurchaseConfirm}.
334         */
335        private UIGate getPurchaseConfirmGate(final int toPay) {
336            final FormSheet fsmpc = new FSManagerPurchaseConfirm(toPay);
337            //buy (commit db, add cs to offerStock) and go back to purchaseMain with right table being empty
338            setAction(fsmpc, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
339                        dbPurchase.commit();
340                        //create id for new order (current date and consecutive number)
341                        Calendar now = SMarket.getTime();
342                        if (dateLastOrder == null) {
343                            dateLastOrder = (Calendar)now.clone();
344                        }
345                        if (dateLastOrder.before(now)) {
346                            dateLastOrder = (Calendar)now.clone();
347                            intLastOrder = 1;
348                        } else {
349                            intLastOrder++;
350                        }
351                        String newIDDate = dateLastOrder.toString();
352                        CIOpenPurchaseOrders opo = new CIOpenPurchaseOrders(newIDDate, intLastOrder,
353                                csPurchase);
354                        SMarket.getOpenPurchaseOrder().add(opo, null);
355                        //add this order to statistics
356                        SMarket.getMonthlySalesStats().updateOrderHistory(opo.getOrders());
357                        gatePurchaseConfirm.setNextTransition(new GateChangeTransition(
358                                getPurchaseMainGate(null, null)));
359                        //subtract purchase from account
360                        SMarket.subtractFromAccount(new IntegerValue(toPay));
361                    }}, ButtonIDs.BTN_OK);
362            //go back to purchaseMain and find right table as it has been left so one can edit his purchase
363            setAction(fsmpc, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
364                        ((UIGate)p.getCurrentGate()).setNextTransition(
365                                new GateChangeTransition(getPurchaseMainGate(csPurchase, dbPurchase)));
366                    }}, ButtonIDs.BTN_BACK);
367            //cancel purchase and go back to purchaseMain with right table being empty
368            setAction(fsmpc, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
369                        dbPurchase.rollback();
370                        gatePurchaseConfirm.setNextTransition(new GateChangeTransition(
371                                getPurchaseMainGate(csPurchase, dbPurchase)));
372                    }}, ButtonIDs.BTN_CANCEL);
373            gatePurchaseConfirm.setFormSheet(fsmpc);
374            return gatePurchaseConfirm;
375        }
376    
377        /**
378         * Attaches {@link FSManagerOpenPurchaseOrderMain}, its actions and the menu to {@link #gateOpoMain}.
379         * @return the set up {@link #gateOpoMain}.
380         */
381        private UIGate getOpoMainGate() {
382            final SingleTableFormSheet stfs = FSManagerOpenPurchaseOrderMain.create();
383            //view details of the selected order
384            setAction(stfs, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
385                        CIOpenPurchaseOrders selRec = (CIOpenPurchaseOrders)stfs.getSelectedRecord();
386                        if (selRec == null)
387                            JDDShowMessage.showMessageDialog(stfs, "Bitte wählen sie eine Lieferung aus.",
388                                    "Auswahl treffen");
389                        else
390                            ((UIGate)p.getCurrentGate()).setNextTransition(new GateChangeTransition(
391                                    getOpoDetailGate(selRec)));
392                    }}, ButtonIDs.BTN_DETAIL);
393            gateOpoMain.setFormSheet(stfs);
394            gateOpoMain.setMenuSheet(menu);
395            return gateOpoMain;
396        }
397    
398        /**
399         * Attaches {@link FSManagerOpenPurchaseOrderDetail}, its actions and the menu to {@link #gateOpoDetail}.
400         * @param opo the open purchase order to be viewed.
401         * @return the set up {@link #gateOpoDetail}.
402         */
403        private UIGate getOpoDetailGate(CIOpenPurchaseOrders opo) {
404            FormSheet fsmopod = FSManagerOpenPurchaseOrderDetail.create(opo);
405            //go back to overview
406            setTransition(fsmopod, new GateChangeTransition(getOpoMainGate()), ButtonIDs.BTN_BACK);
407            gateOpoDetail.setFormSheet(fsmopod);
408            gateOpoDetail.setMenuSheet(menu);
409            return gateOpoDetail;
410        }
411    
412    
413        /**
414         * Attaches {@link FSManagerEmployeeOverview}, its actions and the menu to {@link #gateEmplEditMain}.
415         * @return the set up {@link #gateEmplEditMain}.
416         */
417        private UIGate getEmplEditMainGate() {
418            final FSManagerEmployeeOverview fsmeo = new FSManagerEmployeeOverview();
419            //button add (merely a transition, but defined as action because of circular reference)
420            setAction(fsmeo, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
421                        ((UIGate)p.getCurrentGate()).setNextTransition(
422                                new GateChangeTransition(getEmplEditDetailGate(null)));
423                    }}, ButtonIDs.BTN_ADD);
424            //button edit
425            setAction(fsmeo, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
426                        UStaffer usr = (UStaffer)fsmeo.getSelectedRecord();
427                        if (usr == null) {
428                            JDDShowMessage.showMessageDialog(fsmeo, "Bitte wählen sie einen Mitarbeiter aus.",
429                                    "Auswahl treffen");
430                        } else {
431                            ((UIGate)p.getCurrentGate()).setNextTransition(
432                                    new GateChangeTransition(getEmplEditDetailGate(usr)));
433                        }
434                    }}, ButtonIDs.BTN_EDIT);
435            //button delete
436            setAction(fsmeo, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
437                        final UStaffer usr = (UStaffer)fsmeo.getSelectedRecord();
438                        if (usr == null) {
439                            JDDShowMessage.showMessageDialog(fsmeo, "Bitte wählen sie einen Mitarbeiter aus.",
440                                    "Auswahl treffen");
441                        } else {
442                            final Value dismissalCompensation = usr.computeDismissalCompensation();
443                            JDisplayDialog jdd = JDDShowMessage.showMessageDialog(fsmeo,
444                                    "Soll " + usr.getFullName() + " ein Entlassungsgeld in Höhe von " +
445                                    Conversions.valueToCurrency(dismissalCompensation, " Euro") +
446                                    " gezahlt werden?", "Entlassungsgeld");
447                            jdd.getFormSheet().addContentCreator(new FormSheetContentCreator() {
448                                protected void createFormSheetContent(final FormSheet fs) {
449                                    fs.removeAllButtons();
450                                    fs.addButton("Ja", 1, new Action() {
451                                        public void doAction(SaleProcess p, SalesPoint sp) {
452                                            try {
453                                                UMUserBase.deleteUser(usr);
454                                                SMarket.subtractFromAccount(dismissalCompensation);
455                                            }
456                                            catch (VetoException ex) {
457                                                JDDShowMessage.showMessageDialog(fsmeo, ex.getMessage(),
458                                                        "Eingeloggt");
459                                            }
460                                            fs.cancel();
461                                        }
462                                    });
463                                    fs.addButton("Nein", 2, new Action() {
464                                        public void doAction(SaleProcess p, SalesPoint sp) {
465                                            try {
466                                                UMUserBase.deleteUser(usr);
467                                            }
468                                            catch (VetoException ex) {
469                                                JDDShowMessage.showMessageDialog(fsmeo, ex.getMessage(),
470                                                        "Eingeloggt");
471                                            }
472                                            fs.cancel();
473                                        }
474                                    });
475                                    fs.addButton("Abbrechen", 3, new Action() {
476                                        public void doAction(SaleProcess p, SalesPoint sp) {
477                                            fs.cancel();
478                                        }
479                                    });
480    
481                                }
482    
483                            });
484                        }
485                    }}, ButtonIDs.BTN_DELETE);
486            gateEmplEditMain.setFormSheet(fsmeo);
487            gateEmplEditMain.setMenuSheet(menu);
488    
489            return gateEmplEditMain;
490        }
491    
492        /**
493         * Attaches {@link FSEditPersonData}, its actions and the menu to {@link #gateEmplEditDetail}.
494         * @param usr the employee whose details are to be viewed or edited. If <code>null</code> the
495         * FormSheet's fields will be empty and a new worker can be employed.
496         * @return the set up {@link #gateEmplEditDetail}.
497         */
498        private UIGate getEmplEditDetailGate(final UStaffer usr) {
499            final FSCheckable fsc = FSEditPersonData.getStafferProfile(usr);
500            //button accept
501            setAction(fsc, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
502                        if (fsc.checkTextFields(FSCheckable.ALL_ERRORMESSAGES_AT_ONCE, false)) {
503                            FSEditPersonData fsepd = (FSEditPersonData)fsc.getFormSheet();
504                            char[] pwd = fsepd.getPassword();
505                            //check vor special errors
506                            int error = 0;
507                            if (usr == null) { //if new user is to be added
508                                if (pwd == null)
509                                    error = 1; //the passwords must be set
510                            } else { //if old user is to be edited
511                                if (UMUserBase.getNumberOfManagers() == 1   //last manager mustn't be removed
512                                        && usr.getQualification().equals(UStaffer.MANAGER)
513                                        && !fsepd.getQualification().equals(UStaffer.MANAGER))
514                                    error = 2;  //password does not have to be set, but password and confirmation
515                                                //must at least match
516                                if (!fsepd.passwordsEqual())
517                                    error = 3;
518                            }
519                            switch (error) {
520                                case 1:
521                                    JDDShowMessage.showMessageDialog(fsc,
522                                            "Die Passwörter stimmen nicht überein oder wurden nicht gesetzt.",
523                                            "Passwort überprüfen");
524                                    break;
525                                case 2:
526                                    JDDShowMessage.showMessageDialog(fsc,
527                                            "Dies ist der letzte Manager, er darf seines Postens nicht " +
528                                            "enthoben werden.",
529                                            "Letzter Manager");
530                                    break;
531                                case 3:
532                                    JDDShowMessage.showMessageDialog(fsc,
533                                            "Die Passwörter stimmen nicht überein.",
534                                            "Passwort überprüfen");
535                                    break;
536                            }
537                            if (error == 0) {
538                                UStaffer u = null;
539                                if (usr == null) { //new user
540                                    u = (UStaffer)UMUserBase.createUser(fsc.getEntry(FSEditPersonData.
541                                            JTFC_LOGIN),
542                                            UMUserBase.SELLER,
543                                            fsepd.getQualification());
544                                } else { //existing user
545                                    u = usr;
546                                }
547                                if (u == null) { //new user, but chosen login already exists
548                                    JDDShowMessage.showMessageDialog(fsc,
549                                            "Dieses Login wurde bereits vergeben, wählen sie bitte ein anderes",
550                                            "Doppeltes Login");
551                                } else {
552                                    //both
553                                    u.setSalutation(fsepd.getSalutation());
554                                    u.setSurname(fsc.getEntry(FSEditPersonData.JTFC_NAME));
555                                    u.setFirstName(fsc.getEntry(FSEditPersonData.JTFC_FIRSTNAME));
556                                    u.setTelephone(fsc.getEntry(FSEditPersonData.JTFC_TELEPHONE));
557                                    u.setStreet(fsc.getEntry(FSEditPersonData.JTFC_STREET));
558                                    u.setCity(fsc.getEntry(FSEditPersonData.JTFC_CITY));
559                                    u.setPostcode(new Integer(
560                                            fsc.getEntry(FSEditPersonData.JTFC_POSTCODE)).intValue());
561                                    if (fsepd.isPasswordSet())
562                                        u.setPassWd(UStaffer.garblePassWD(pwd));
563                                    u.setQualification(fsepd.getQualification());
564                                    u.setSalary(Conversions.currencyToInt(
565                                            fsc.getEntry(FSEditPersonData.JTFC_SALARY), true));
566                                    ((UIGate)p.getCurrentGate()).setNextTransition(
567                                            new GateChangeTransition(getEmplEditMainGate()));
568                                }
569                            }
570                        }
571                    }}, ButtonIDs.BTN_ACCEPT);
572    
573            //button back (merely a transition, but defined as action because of circular reference)
574            setAction(fsc, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
575                        ((UIGate)p.getCurrentGate()).setNextTransition(
576                                new GateChangeTransition(getEmplEditMainGate()));
577                    }}, ButtonIDs.BTN_BACK);
578            gateEmplEditDetail.setFormSheet(fsc);
579            gateEmplEditDetail.setMenuSheet(menu);
580            return gateEmplEditDetail;
581        }
582    
583        /**
584         * Attaches {@link FSManagerCustomerOverview}, its actions and the menu to {@link #gateCustEditMain}.
585         * @return the set up {@link #gateCustEditMain}.
586         */
587        private UIGate getCustEditMainGate() {
588            final FSManagerCustomerOverview fsmco = new FSManagerCustomerOverview();
589            //button edit
590            setAction(fsmco, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
591                        UCustomer usr = (UCustomer)fsmco.getSelectedRecord();
592                        if (usr == null) {
593                            JDDShowMessage.showMessageDialog(fsmco, "Bitte wählen sie einen Kunden aus.",
594                                    "Auswahl treffen");
595                        } else {
596                            ((UIGate)p.getCurrentGate()).setNextTransition(
597                                    new GateChangeTransition(getCustEditDetailGate(usr)));
598                        }
599                    }}, ButtonIDs.BTN_EDIT);
600            //button delete
601            setAction(fsmco, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
602                        UCustomer usr = (UCustomer)fsmco.getSelectedRecord();
603                        if (usr == null) {
604                            JDDShowMessage.showMessageDialog(fsmco, "Bitte wählen sie einen Kunden aus.",
605                                    "Auswahl treffen");
606                        } else {
607                            try {
608                                UMUserBase.deleteUser(usr);
609                            }
610                            catch (VetoException ex) {
611                                JDDShowMessage.showMessageDialog(fsmco,
612                                        ex.getMessage(), "Eingeloggt");
613                            }
614                        }
615                    }}, ButtonIDs.BTN_DELETE);
616            gateCustEditMain.setFormSheet(fsmco);
617            gateCustEditMain.setMenuSheet(menu);
618            return gateCustEditMain;
619        }
620    
621        /**
622         * Attaches {@link FSEditPersonData}, its actions and the menu to {@link #gateCustEditDetail}.
623         * @param usr the customer whose details are to be viewed.
624         * @return the set up {@link #gateCustEditDetail}.
625         */
626        private UIGate getCustEditDetailGate(final UCustomer usr) {
627            final FSCheckable fsc = FSEditPersonData.getCustomerProfileForManager(usr);
628            //button accept
629            setAction(fsc, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
630                        if (fsc.checkTextFields(FSCheckable.ALL_ERRORMESSAGES_AT_ONCE, false)) {
631                            FSEditPersonData fsepd = (FSEditPersonData)fsc.getFormSheet();
632                            char[] pwd = fsepd.getPassword();
633                            //password and confirmation do not match
634                            if (!fsepd.passwordsEqual()) {
635                                JDDShowMessage.showMessageDialog(fsc,
636                                        "Die Passwörter stimmen nicht überein.",
637                                        "Passwort überprüfen");
638                            } else {
639                                //save changes
640                                if (fsepd.isPasswordSet()) usr.setPassWd(UStaffer.garblePassWD(pwd));
641                                ((UIGate)p.getCurrentGate()).setNextTransition(
642                                        new GateChangeTransition(getCustEditMainGate()));
643                            }
644                        }
645                    }}, ButtonIDs.BTN_ACCEPT);
646            //button back
647            setTransition(fsc, new GateChangeTransition(getCustEditMainGate()), ButtonIDs.BTN_BACK);
648            fsc.getButton(ButtonIDs.BTN_BACK).setCaption("Kundenübersicht");
649            //button to stats
650            fsc.addContentCreator(new FormSheetContentCreator() {
651                public void createFormSheetContent(final FormSheet fs) {
652                    fsc.addButton("Zur Statistik", 1, new Action() {
653                        public void doAction(SaleProcess p, SalesPoint sp) {
654                            ((UIGate)p.getCurrentGate()).setNextTransition(
655                                    new GateChangeTransition(getCustomerStatsDetailGate(usr)));
656                        }
657                    });
658                }
659            });
660            gateCustEditDetail.setFormSheet(fsc);
661            gateCustEditDetail.setMenuSheet(menu);
662            return gateCustEditDetail;
663        }
664    
665        /**
666         * Attaches {@link FSManagerArticleStatsMain}, its actions and the menu to {@link #gateArticleStatsMain}.
667         * @return the set up {@link #gateArticleStatsMain}.
668         */
669        private UIGate getArticleStatsMainGate(){
670            //instantiation necessary to query ComboBoxes
671            FSManagerArticleStatsMain fsmasm = new FSManagerArticleStatsMain();
672            final JCTimeRangeBoxes jctrb = fsmasm.getTimeRangeBoxes();
673            final SingleTableFormSheet stfs = FSManagerArticleStatsMain.create();
674            //button detail
675            setAction(stfs, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
676                        CISalesStats statsToDisplay = null;
677                        int error = 0;
678                        CIArticle selRec = (CIArticle)stfs.getSelectedRecord();
679                        if (selRec == null) error = 1;
680                        if (!jctrb.isValidTimeRange()) error = 2;
681                        switch (error) {
682                            case 1:
683                                JDDShowMessage.showMessageDialog(stfs, "Bitte wählen sie einen Artikel aus.",
684                                    "Auswahl treffen");
685                                break;
686                            case 2:
687                                JDDShowMessage.showMessageDialog(stfs, "Ungültiger Zeitraum.",
688                                       "Ungültiger Zeitraum");
689                                break;
690                            default:
691                                int mFrom = jctrb.getFromMonth();
692                                int mTo = jctrb.getToMonth();
693                                int yFrom = jctrb.getFromYear();
694                                int yTo = jctrb.getToYear();
695                                ((UIGate)p.getCurrentGate()).setNextTransition(new GateChangeTransition(
696                                        getArticleStatsDetailGate(Statistics.getArticleStats(
697                                        selRec.getName(), mFrom, yFrom, mTo, yTo))));
698                        }
699                    }}, ButtonIDs.BTN_DETAIL);
700            gateArticleStatsMain.setFormSheet(stfs);
701            gateArticleStatsMain.setMenuSheet(menu);
702            return gateArticleStatsMain;
703        }
704    
705        /**
706         * Attaches {@link FSManagerArticleStatsDetail}, its actions and the menu to
707         * {@link #gateArticleStatsDetail}.
708         * @param ciss the precomputed statistics to be displayed.
709         * @return the set up {@link #gateArticleStatsDetail}.
710         */
711        public Gate getArticleStatsDetailGate(CISalesStats ciss) {
712            FormSheet fsasd = new FSManagerArticleStatsDetail(ciss);
713            //button back
714            setTransition(fsasd, new GateChangeTransition(getArticleStatsMainGate()), ButtonIDs.BTN_BACK);
715            gateArticleStatsDetail.setFormSheet(fsasd);
716            gateArticleStatsDetail.setMenuSheet(menu);
717            return gateArticleStatsDetail;
718        }
719    
720        /**
721         * Attaches {@link FSManagerCustomerStatsMain}, its actions and the menu to {@link #gateCustomerStatsMain}.
722         * @return the set up {@link #gateCustomerStatsMain}.
723         */
724        private UIGate getCustomerStatsMainGate() {
725            final FSManagerCustomerStatsMain fsmcsm = new FSManagerCustomerStatsMain();
726            //button detail
727            setAction(fsmcsm, new Action() {public void doAction(SaleProcess p, SalesPoint sp) {
728                        UCustomer selRec = (UCustomer)fsmcsm.getSelectedRecord();
729                        int error = 0;
730                        if (selRec == null) error = 1;
731                        switch (error) {
732                            case 1:
733                                JDDShowMessage.showMessageDialog(fsmcsm, "Bitte wählen sie einen Kunden aus.",
734                                    "Auswahl treffen");
735                                break;
736                            default:
737                                ((UIGate)p.getCurrentGate()).setNextTransition(new GateChangeTransition(
738                                        getCustomerStatsDetailGate(selRec)));
739                        }
740                    }}, ButtonIDs.BTN_DETAIL);
741            gateCustomerStatsMain.setFormSheet(fsmcsm);
742            gateCustomerStatsMain.setMenuSheet(menu);
743            return gateCustomerStatsMain;
744        }
745    
746        /**
747         * Attaches {@link FSManagerCustomerStatsDetail}, its actions and the menu to
748         * {@link #gateCustomerStatsDetail}.
749         * @param uc the customer whose statistics are to be viewed.
750         * @return the set up {@link #gateCustomerStatsDetail}.
751         */
752        private UIGate getCustomerStatsDetailGate(final UCustomer uc) {
753            final FormSheet fscsd = new FSManagerCustomerStatsDetail(uc);
754            fscsd.addContentCreator(new FormSheetContentCreator() {
755                public void createFormSheetContent(final FormSheet fs) {
756                    //button to customer data
757                    fs.addButton("Kundendaten", 1, new Action() {
758                        public void doAction(SaleProcess p, SalesPoint sp) {
759                            ((UIGate)p.getCurrentGate()).setNextTransition(
760                                    new GateChangeTransition(getCustEditDetailGate(uc)));
761                        }
762                    });
763                }
764            });
765            setTransition(fscsd, new GateChangeTransition(getCustomerStatsMainGate()), ButtonIDs.BTN_BACK);
766            fscsd.getButton(ButtonIDs.BTN_BACK).setCaption("Statistikübersicht");
767            gateCustomerStatsDetail.setFormSheet(fscsd);
768            gateCustomerStatsDetail.setMenuSheet(menu);
769            return gateCustomerStatsDetail;
770        }
771    
772        /**
773         * Attaches {@link FSManagerOverallStats} and the menu to {@link #gateOverallStats}.
774         * @return the set up {@link #gateOverallStats}.
775         */
776        private UIGate getOverallStatsGate() {
777            FormSheet fsmos = new FSManagerOverallStats();
778            gateOverallStats.setFormSheet(fsmos);
779            gateOverallStats.setMenuSheet(menu);
780            return gateOverallStats;
781        }
782    
783        /**
784         * Creates the {@link MenuSheet} for the manager process.
785         *
786         * @return the created MenuSheet.
787         */
788        private MenuSheet createManagerMenuSheet() {
789            MenuSheet msMenuBar = new MenuSheet("Bar");
790            MenuSheet msLogOff = new MSLogOff();
791            MenuSheet msWares = new MenuSheet("Waren", null, 'W');
792            MenuSheet msPersons = new MenuSheet("Personen", null, 'P');
793            MenuSheet msStatistics = new MenuSheet("Statistiken", null, 'k');
794            MenuSheetItem msiOpenClose = new MenuSheetItem("Öffnen/Schließen", null, new Action() {
795                public void doAction(SaleProcess p, SalesPoint sp) {
796                    ((UIGate)p.getCurrentGate()).setNextTransition(
797                            new GateChangeTransition(getOpenCloseGate()));
798                }}, 'f');
799            MenuSheetItem msiOptions = new MenuSheetItem("Einstellungen", null, new Action() {
800                public void doAction(SaleProcess p, SalesPoint sp) {
801                    ((UIGate)p.getCurrentGate()).setNextTransition(
802                            new GateChangeTransition(getOptionsGate()));
803                }}, 'E');
804            MenuSheetItem msiStockOverview = new MenuSheetItem("Bestand und Preis", null, new Action() {
805                public void doAction(SaleProcess p, SalesPoint sp) {
806                    ((UIGate)p.getCurrentGate()).setNextTransition(new GateChangeTransition(getStockMainGate()));
807                }}, 'B');
808            MenuSheetItem msiPurchase = new MenuSheetItem("Einkaufen", null, new Action() {
809                public void doAction(SaleProcess p, SalesPoint sp) {
810                    ((UIGate)p.getCurrentGate()).setNextTransition(getToPurchaseMain(null, null));
811                }}, 'E');
812            MenuSheetItem msiOpoMain = new MenuSheetItem("Erwartete Lieferungen", null, new Action() {
813                public void doAction(SaleProcess p, SalesPoint sp) {
814                    ((UIGate)p.getCurrentGate()).setNextTransition(
815                            new GateChangeTransition(getOpoMainGate()));
816                }}, 'L');
817            MenuSheetItem msiEmplEdit = new MenuSheetItem("Angestellte", null, new Action() {
818                public void doAction(SaleProcess p, SalesPoint sp) {
819                    ((UIGate)p.getCurrentGate()).setNextTransition(
820                            new GateChangeTransition(getEmplEditMainGate()));
821                }}, 'A');
822            MenuSheetItem msiCustEdit = new MenuSheetItem("Kunden", null, new Action() {
823                public void doAction(SaleProcess p, SalesPoint sp) {
824                    ((UIGate)p.getCurrentGate()).setNextTransition(
825                            new GateChangeTransition(getCustEditMainGate()));
826                }}, 'K');
827            MenuSheetItem msiArticleStats = new MenuSheetItem("Artikelstatistik", null, new Action() {
828                public void doAction(SaleProcess p, SalesPoint sp) {
829                    ((UIGate)p.getCurrentGate()).setNextTransition(
830                            new GateChangeTransition(getArticleStatsMainGate()));
831                }}, 'A');
832            MenuSheetItem msiCustomerStats = new MenuSheetItem("Kundenstatistik", null, new Action() {
833                public void doAction(SaleProcess p, SalesPoint sp) {
834                    ((UIGate)p.getCurrentGate()).setNextTransition(
835                            new GateChangeTransition(getCustomerStatsMainGate()));
836                }}, 'K');
837            MenuSheetItem msiOverallStats = new MenuSheetItem("Umsatzstatistik", null, new Action() {
838                public void doAction(SaleProcess p, SalesPoint sp) {
839                    ((UIGate)p.getCurrentGate()).setNextTransition(
840                            new GateChangeTransition(getOverallStatsGate()));
841                }}, 'U');
842    
843            msMenuBar.add(msLogOff);
844                msLogOff.add(msiOpenClose);
845                msLogOff.add(msiOptions);
846                msLogOff.add(msLogOff.remove("exit"));
847            msMenuBar.add(msWares);
848                msWares.add(msiStockOverview);
849                msWares.add(msiPurchase);
850                msWares.add(msiOpoMain);
851            msMenuBar.add(msPersons);
852                msPersons.add(msiEmplEdit);
853                msPersons.add(msiCustEdit);
854            msMenuBar.add(msStatistics);
855                msStatistics.add(msiArticleStats);
856                msStatistics.add(msiCustomerStats);
857                msStatistics.add(msiOverallStats);
858            return msMenuBar;
859        }
860    
861      /**
862       * Helper Transition to {@link #gatePurchaseMain}.<br>
863       * <br>
864       * This transition cannot be implemented as a GateChangeTransition.<br>
865       * The reason is that getPurchaseMainGate contains a TTFS-creation method that passes
866       * gatePurchaseMain as necessary parameter for the TTFS.<br>
867       * When a user's current Gate is gatePurchaseMain and he invokes a GateChangeTransition
868       * to gatePurchaseMain via the menu, an exception would occur.<br>
869       * This is because for a GateChangeTransition the setup method for gatePurchaseMain
870       * (and therefore the TTFS-creation method) would be called while gatePurchaseMain
871       * is still active and displaying a TTFS.
872       * This method creates the TTFS after the gatePurchaseMain has already been
873       * left, thus causing no conflicts.
874       *
875       * @param cs the CountingStock containing the manager's purchase.
876       * @param db the transaction's DataBasket.
877       *
878       * @return a Transition to {@link #getPurchaseMainGate(CountingStock, DataBasket)}.
879       */
880        private Transition getToPurchaseMain(final CountingStock cs, final DataBasket db) {
881            return new Transition() {
882                public Gate perform(SaleProcess pOwner, users.User usr) {
883                    return getPurchaseMainGate(cs, db);
884                }
885            };
886        }
887    }