001    package market;
002    
003    import java.awt.Rectangle;
004    
005    import market.event.OfferEventListener;
006    import market.stdform.ButtonIDs;
007    import market.stdform.FSCustomerDefault;
008    import market.stdform.MSLogOff;
009    import sale.Action;
010    import sale.FormSheet;
011    import sale.FormSheetContentCreator;
012    import sale.MenuSheet;
013    import sale.SaleProcess;
014    import sale.SalesPoint;
015    import sale.Shop;
016    import users.User;
017    import data.CountingStock;
018    import data.DataBasketCondition;
019    import data.DataBasketEntry;
020    import data.DataBasketEntryDestination;
021    import data.DataBasketEntrySource;
022    
023    /**
024     * SalesPoint used by the {@link UCustomer}.
025     */
026    public class SPCustomer extends SPListenable implements OfferEventListener{
027    
028        /**
029             * ID for serialization.
030             */
031            private static final long serialVersionUID = -4380520617845209584L;
032            /**
033         * Array with all SPCustomers used to fire events to
034         */
035        private static OfferEventListener[] oel = new OfferEventListener[0];
036    
037        /**
038         * @param user the User of this SPCustomer
039         */
040        public SPCustomer(User user){
041            super("Kundenterminal - "+((UPerson)user).getFullName());
042            this.attach(user);
043            this.setSalesPointFrameBounds(new Rectangle(0,0,640,540));
044            SMarket.addEventListener((market.event.MarketEventListener)this);
045            SPCustomer.addEventListener(this);
046            Shop.getTheShop().addSalesPoint(this);
047        }
048    
049    
050        //###################################### SalesPoint #############################################
051    
052        /**
053         * @return <code>true</code> if no SaleProcess is running, otherwise <code>false</code>.
054         * This forces the user to quit the SaleProcess before he closes the SalesPoint.
055         */
056        protected boolean onCanQuit(){
057            return getCurrentProcess() == null;
058        }
059    
060        /**
061         * Removes this SPSustomer from the array of OfferEventListeners.
062         */
063        public void quit() {
064            SPCustomer.removeEventListener(this);
065            super.quit();
066        }
067    
068        /**
069         * @return the default FormSheet
070         */
071        protected FormSheet getDefaultFormSheet() {
072            FormSheet sheet = new FSCustomerDefault();
073            sheet.addContentCreator(new FormSheetContentCreator(){
074                            private static final long serialVersionUID = 1146704984018039866L;
075                            protected void createFormSheetContent(FormSheet fs) {
076                    fs.getButton(ButtonIDs.BTN_BUY).setAction(buyAction());
077                    fs.getButton(ButtonIDs.BTN_EDIT).setAction(editAction());
078                }
079            });
080            return sheet;
081        }
082    
083        /**
084         * @return the default MenuSheet
085         */
086        protected MenuSheet getDefaultMenuSheet() {
087            return new MSLogOff();
088        }
089    
090    
091        //################################### our methods ######################################################
092    
093        /**
094         * @return an Action that initiates a SProcessBuy on this Salespoint,
095         * if the customer already contains to the till-queue or the market is to be closed
096         * it will pop up an error-message.
097         */
098        private Action buyAction(){
099            return new Action(){
100                            private static final long serialVersionUID = 3439946422782505800L;
101                            public void doAction(SaleProcess p, SalesPoint sp) throws Throwable {
102                    User user = sp.getUser();
103                    boolean error = false;
104                    String errorMsg = "";
105                    String errorCaption = "";
106                    if (SMarket.isToBeClosed()) {
107                        error = true;
108                        errorMsg = SMarket.MARKET_CLOSES_LONG;
109                        errorCaption = "Feierabend";
110                    }
111                    if(SMarket.getTillQueue().contains(user.getName(), null)) {
112                        error = true;
113                        errorMsg = "Sie haben bereits eine Auswahl von Artikeln in Auftrag gegeben!\n"+
114                                "Bitte begeben Sie sich zunächst zur Kasse, um diesen Autrag abzuschliessen!";
115                        errorCaption = "Auftrag abschließen";
116                    }
117                    if (error) {
118                        JDDShowMessage.showMessageDialog(sp.getDisplay().getFormSheet(), errorMsg,
119                               errorCaption);
120                    } else {
121                        sp.runProcess(new SProcessCustomer(user));
122                    }
123                }
124            };
125        }
126    
127        /**
128         * @return an Action that initiates a SProcessCustomerEditProfile on this SalesPoint,
129         * taking the customer attached to this SPCustomer as argument.
130         */
131        private Action editAction(){
132            return new Action(){
133                            private static final long serialVersionUID = 8721124416084580882L;
134                            public void doAction(SaleProcess p, SalesPoint sp) throws Throwable {
135                    boolean error = false;
136                    String errorMsg = "";
137                    String errorCaption = "";
138                    if (SMarket.isToBeClosed()) {
139                        error = true;
140                        errorMsg = SMarket.MARKET_CLOSES_LONG;
141                        errorCaption = "Feierabend";
142                    }
143                    if (error) {
144                        JDDShowMessage.showMessageDialog(sp.getDisplay().getFormSheet(), errorMsg,
145                               errorCaption);
146                    } else {
147                        sp.runProcess(new SProcessCustomerEditProfile(sp.getUser()));
148                    }
149                }
150            };
151        }
152    
153    
154        ////////////////////////////////////////////////////////////////
155        // Event handling
156        ////////////////////////////////////////////////////////////////
157    
158        /**
159         * Adds an OfferEventListener to the array of listeners.
160         *
161         * @param e the OfferEventListener that will be added.
162         */
163        public static void addEventListener(OfferEventListener e){
164            int len = oel.length;
165            boolean exists = false;
166            for (int i = 0; i < len; i++) {
167                exists = exists || (oel[i] == e);
168            }
169            if (!exists) {
170                OfferEventListener[] temp = new OfferEventListener[len+1];
171                System.arraycopy(oel, 0, temp, 0, len);
172                temp[len] = e;
173                oel = temp;
174            }
175        }
176    
177        /**
178         * Removes an OfferEventListener from the array of listeners.
179         *
180         * @param e the OfferEventListener that will be removed.
181         */
182        public static void removeEventListener(OfferEventListener e){
183            for (int i = 0; i < oel.length; i++) {
184                if (oel[i] == e) {
185                    OfferEventListener[] temp = new OfferEventListener[oel.length-1];
186                    if (i > 0) System.arraycopy(oel,0,temp,0,i);
187                    if (i < oel.length-1) System.arraycopy(oel,i+1,temp,i,oel.length-1-i);
188                    oel = temp;
189                    break;
190                }
191            }
192        }
193    
194        /**
195         * Fires an event to all listeners: this article is empty.
196         *
197         * @param articleKey the key of the unavailable article.
198         */
199        public static void fireOfferIsEmpty(String articleKey) {
200            for (int i = 0; i < oel.length; i++) {
201                if (oel[i] != null) oel[i].offerEmpty(articleKey);
202            }
203        }
204    
205        /**
206         * Fires an event to all listeners: count this article.
207         *
208         * @param articleKey the key of the article to count.
209         * @param spw the SProcessWorker which has sended the request.
210         */
211        public static void fireCountArticles(String articleKey, SProcessWorker spw){
212            for (int i = 0; i < oel.length; i++) {
213                if (oel[i] != null) oel[i].countArticles(articleKey, spw);
214            }
215        }
216    
217        /**
218         * Reaction on event: An article is unavailable.
219         *
220         * @param articleKey the unavailable article.
221         */
222        public void offerEmpty(final String articleKey) {
223            CountingStock cs = ((UCustomer)this.getUser()).getShoppingBasket();
224            if(this.getCurrentProcess() instanceof SProcessCustomer &&
225               cs.contains(articleKey, this.getBasket())){
226                this.getBasket().rollback(new DataBasketCondition(){
227                            private static final long serialVersionUID = 2899752284804079449L;
228                            public String getMainKey() {
229                    return null;
230                }
231                public String getSecondaryKey() {
232                    return null;
233                }
234                public DataBasketEntrySource getSource() {
235                    return null;
236                }
237                public DataBasketEntryDestination getDestination() {
238                    return null;
239                }
240                public Object getValue() {
241                    return null;
242                }
243                public boolean match(DataBasketEntry dbe) {
244                    if(dbe.getSecondaryKey().compareTo(articleKey)==0) return true;
245                    return false;
246                }
247                });
248                try {
249                    this.getCurrentProcess().suspend();
250                } catch (InterruptedException e) {
251                }
252                JDDShowMessage.showMessageDialog(getDisplay().getFormSheet(),
253                            "Aufgrund einer Bestandskorrektur musste folgender Artikel: "+
254                            SMarket.getArticleCatalog().get(articleKey).getArticleName()+
255                            " aus ihrem Einkaufskorb entfernt werden.\n" +
256                            "Bitte wählen sie neu.", "Artikel nicht verfügbar! "+
257                            ((UPerson)this.getUser()).getFullName());
258            }
259        }
260    
261        /**
262         * Empty implementation of the OfferEventListener Interface.
263         */
264        public void wakeUpOrders() {
265        }
266    
267        /**
268         * Reaction on event: a SProcessWorker needs the count of all existing articles.
269         *
270         * @param articleKey the name of the article.
271         * @param spw the SProcessWorker that sends the request.
272         */
273        public void countArticles(String articleKey, SProcessWorker spw) {
274            int count = 0;
275            if(this.getCurrentProcess() instanceof SProcessCustomer &&
276                ((UCustomer)this.getUser()).getShoppingBasket().contains(articleKey, this.getBasket())){
277                count = ((UCustomer)this.getUser()).getShoppingBasket().countItems(articleKey, this.getBasket());
278                spw.addDatabaseCount(count, SProcessWorker.BUYPROCESS);
279            }
280        }
281    }