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 }