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 }