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