1 package org.paneris.jammyjoes.model;
2
3 import java.sql.Date;
4 import java.util.Enumeration;
5
6 import org.melati.poem.AccessPoemException;
7 import org.melati.poem.Persistent;
8 import org.melati.poem.ValidationPoemException;
9 import org.melati.util.StringUtils;
10 import org.paneris.jammyjoes.model.generated.ProductBase;
11 import org.paneris.jammyjoes.util.JammyJoesUtil;
12
13 public class Product extends ProductBase {
14
15 private Double quantitySold;
16 private Double quantityPurchased;
17 private Double quantityShopSale;
18 private Double quantityInternetSale;
19 private Double quantityTelephoneSale;
20 private Double quantityStockCheckIncrease;
21 private Double quantityStockCheckDecrease;
22 private Double quantityCorrectLevel;
23 private Double quantityAjustmentRequired;
24
25 public void setVatexempt(Boolean cooked) throws AccessPoemException, ValidationPoemException {
26 super.setVatexempt(cooked);
27 setRetailpriceincvat(getRetailpriceincvat());
28 }
29
30 public Product() {
31 }
32
33 public boolean hasStatus(ProductStatus status) {
34 if (getStatus().equals(status)) {
35 return true;
36 }
37 return false;
38 }
39
40 public boolean getHasStock() {
41 if (getStocklevel().intValue() > 0) {
42 return true;
43 }
44 return false;
45 }
46
47 public boolean getDoWeSellIt() {
48 if (getHasStock()) {
49 return true;
50 }
51 ProductStatusTable statuses = getJammyjoesDatabaseTables().getProductStatusTable();
52 if (hasStatus(statuses.getNew()) || hasStatus(statuses.getNormallyStocked())) {
53 return true;
54 }
55 return false;
56 }
57
58 public boolean getDiscontinued() {
59 if (getStatus().equals(getJammyjoesDatabaseTables().getProductStatusTable().getDiscontinued())){
60 return true;
61 }
62 return false;
63 }
64
65 public Double getPreSaleprice() {
66 return getSaleprice();
67 }
68
69
70 public Double getCostpriceIncVat() {
71 if (isVatexempt()) {
72 return new Double(getCostprice().doubleValue());
73 } else {
74 return new Double(getCostprice().doubleValue() * 1.175);
75 }
76 }
77
78 public void setRetailpriceincvat(Double cooked)
79 throws AccessPoemException, ValidationPoemException {
80 if (cooked != null) {
81 if (isVatexempt()) {
82 setRetailprice(cooked.doubleValue());
83 } else {
84 setRetailprice(cooked.doubleValue() / 1.175);
85 }
86 }
87 super.setRetailpriceincvat(cooked);
88 }
89
90 private boolean isVatexempt() {
91 return getVatexempt().booleanValue();
92 }
93
94 public void setRetailprice(Double cooked) throws AccessPoemException, ValidationPoemException {
95 calculateMargin(cooked, getCostprice());
96 super.setRetailprice(cooked);
97 }
98
99 public void setCostprice(Double cooked) throws AccessPoemException, ValidationPoemException {
100 calculateMargin(getRetailprice(), cooked);
101 super.setCostprice(cooked);
102 }
103
104 public void calculateMargin(Double retailprice, Double costprice) {
105 if (retailprice != null && costprice != null) {
106 double margin = retailprice.doubleValue() - costprice.doubleValue();
107 setMargin(margin);
108 setMarginpercent(margin / retailprice.doubleValue() * 100);
109 setMarkuppercent(margin / costprice.doubleValue() * 100);
110 }
111 }
112
113 public void clearQuantities() {
114 quantitySold = null;
115 quantityPurchased = null;
116 quantityShopSale = null;
117 quantityInternetSale = null;
118 quantityTelephoneSale = null;
119 quantityStockCheckIncrease = null;
120 quantityStockCheckDecrease = null;
121 quantityCorrectLevel = null;
122 quantityAjustmentRequired = null;
123 }
124
125 private void calculateQuantities() {
126 StockTransactionTypeTable st = getJammyjoesDatabaseTables().getStockTransactionTypeTable();
127 quantityPurchased = calculateQuantity(st.getPurchase());
128 quantityShopSale = calculateQuantity(st.getShopSale());
129 quantityInternetSale = calculateQuantity(st.getInternetSale());
130 quantityTelephoneSale = calculateQuantity(st.getTelephoneSale());
131 quantityStockCheckIncrease = calculateQuantity(st.getStockCheckIncreasee());
132 quantityStockCheckDecrease = calculateQuantity(st.getStockCheckDecrease());
133 quantitySold = new Double(quantityShopSale.doubleValue() + quantityInternetSale.doubleValue() + quantityTelephoneSale.doubleValue());
134 quantityCorrectLevel =
135 new Double(
136 quantityPurchased.doubleValue()
137 - quantitySold.doubleValue()
138 + quantityStockCheckIncrease.doubleValue()
139 - quantityStockCheckDecrease.doubleValue());
140 quantityAjustmentRequired = quantityCorrectLevel;
141 if (getStocklevel() != null)
142 quantityAjustmentRequired =
143 new Double(quantityCorrectLevel.doubleValue() - getStocklevel().doubleValue());
144 }
145
146 private Double calculateQuantity(StockTransactionType type) {
147 return calculateQuantityToDate(type, null);
148 }
149
150 private Double calculateQuantityToDate(StockTransactionType type, Date date) {
151 return calculateQuantity(type, date, true);
152 }
153
154 private Double calculateQuantityFromDate(StockTransactionType type, Date date) {
155 return calculateQuantity(type, date, false);
156 }
157
158 private Double calculateQuantity(StockTransactionType type, Date date, boolean to) {
159 double total = 0;
160 String selection =
161 q("product") + " = " + getTroid() + " AND " + q("type") + " = " + type.getTroid();
162
163 if (date != null) {
164 selection += " AND " + q("date");
165 if (to) {
166 selection += " < ";
167 } else {
168 selection += " >= ";
169 }
170 selection += JammyJoesUtil.formatDateForSQL(getDatabase(), date);
171 }
172 Enumeration e =
173 getJammyjoesDatabaseTables()
174 .getStockTransactionTable()
175 .cachedSelection(selection, null)
176 .objects();
177 while (e.hasMoreElements()) {
178 StockTransaction t = (StockTransaction) e.nextElement();
179 total += t.getQuantity().doubleValue();
180 }
181 return new Double(total);
182 }
183
184 private String q(String name) {
185 StringBuffer b = new StringBuffer();
186 StringUtils.appendQuoted(b, name, '"');
187 return b.toString();
188 }
189
190 public double getQuantityPurchased() {
191 if (quantityPurchased == null)
192 calculateQuantities();
193 return quantityPurchased.doubleValue();
194 }
195
196 public double getQuantityShopSale() {
197 if (quantityShopSale == null)
198 calculateQuantities();
199 return quantityShopSale.doubleValue();
200 }
201
202 public double getQuantityInternetSale() {
203 if (quantityInternetSale == null)
204 calculateQuantities();
205 return quantityInternetSale.doubleValue();
206 }
207
208 public double getQuantityTelephoneSale() {
209 if (quantityTelephoneSale == null)
210 calculateQuantities();
211 return quantityTelephoneSale.doubleValue();
212 }
213
214 public double getQuantityStockCheckIncrease() {
215 if (quantityStockCheckIncrease == null)
216 calculateQuantities();
217 return quantityStockCheckIncrease.doubleValue();
218 }
219
220 public double getQuantityStockCheckDecrease() {
221 if (quantityStockCheckDecrease == null)
222 calculateQuantities();
223 return quantityStockCheckDecrease.doubleValue();
224 }
225
226 public double getQuantitySold() {
227 if (quantitySold == null)
228 calculateQuantities();
229 return quantitySold.doubleValue();
230 }
231
232 public double getQuantityCorrectLevel() {
233 if (quantityCorrectLevel == null)
234 calculateQuantities();
235 return quantityCorrectLevel.doubleValue();
236 }
237
238 public int getQuantityAjustmentRequired() {
239 if (quantityAjustmentRequired == null)
240 calculateQuantities();
241 return quantityAjustmentRequired.intValue();
242 }
243
244 public double getRequiredOrderValue() {
245 return getCostprice().doubleValue() * getReorderquantity().intValue();
246 }
247
248 /**
249 * when duplicating, the new Persistent needs a zero stock level
250 */
251 public Persistent duplicated() throws AccessPoemException {
252 Product prod = (Product) super.duplicated();
253 prod.setStocklevel(0);
254 return prod;
255 }
256
257 public Double getStockLevel(Date date) {
258 StockTransactionTypeTable st = getJammyjoesDatabaseTables().getStockTransactionTypeTable();
259 Double quantityPurchased = calculateQuantityToDate(st.getPurchase(), date);
260 Double quantityStockCheckIncrease = calculateQuantityToDate(st.getStockCheckIncreasee(), date);
261 Double quantityStockCheckDecrease = calculateQuantityToDate(st.getStockCheckDecrease(), date);
262 Double quantitySold = getQuantitySoldToDate(date);
263 return new Double(
264 quantityPurchased.doubleValue()
265 - quantitySold.doubleValue()
266 + quantityStockCheckIncrease.doubleValue()
267 - quantityStockCheckDecrease.doubleValue());
268 }
269
270 public Double getQuantitySoldToDate(Date date) {
271 StockTransactionTypeTable st = getJammyjoesDatabaseTables().getStockTransactionTypeTable();
272 Double quantityShopSale = calculateQuantityToDate(st.getShopSale(), date);
273 Double quantityInternetSale = calculateQuantityToDate(st.getInternetSale(), date);
274 Double quantityTelephoneSale = calculateQuantityToDate(st.getTelephoneSale(), date);
275 Double quantitySold =
276 new Double(quantityShopSale.doubleValue() + quantityInternetSale.doubleValue() + quantityTelephoneSale.doubleValue());
277 return quantitySold;
278 }
279
280 public Double getQuantitySoldFromDate(Date date) {
281 StockTransactionTypeTable st = getJammyjoesDatabaseTables().getStockTransactionTypeTable();
282 Double quantityShopSale = calculateQuantityFromDate(st.getShopSale(), date);
283 Double quantityTelephoneSale = calculateQuantityToDate(st.getTelephoneSale(), date);
284 Double quantityInternetSale = calculateQuantityFromDate(st.getInternetSale(), date);
285 Double quantitySold =
286 new Double(quantityShopSale.doubleValue() + quantityInternetSale.doubleValue() + quantityTelephoneSale.doubleValue());
287 return quantitySold;
288 }
289
290 public StockValues getStockLevels(Date date) {
291 double stockLevel = 0;
292 if (getStocklevel() != null)
293 stockLevel = getStocklevel().doubleValue();
294 if (date != null)
295 stockLevel = getStockLevel(date).doubleValue();
296 return new StockValues(this, stockLevel);
297 }
298
299 public class StockValues {
300 private Product product;
301 private double stockLevel = 0;
302
303 public StockValues(Product p, double sl) {
304 product = p;
305 stockLevel = sl;
306 }
307
308 public double getValue(Double price) {
309 if (price == null)
310 return 0;
311 return stockLevel * price.doubleValue();
312 }
313
314 public double getLevel() {
315 return stockLevel;
316 }
317
318 public double getCostPriceExVat() {
319 return getValue(product.getCostprice());
320 }
321
322 public double getCostPriceIncVat() {
323 return product.getCostpriceIncVat().doubleValue();
324 }
325
326 public double getRetailPriceExVat() {
327 return getValue(product.getRetailprice());
328 }
329
330 public double getRetailPriceIncVat() {
331 return getValue(product.getRetailpriceincvat());
332 }
333 }
334
335 public Boolean getNew() {
336 if (getStatus().equals(getJammyjoesDatabaseTables().getProductStatusTable().getNew()))
337 return Boolean.TRUE;
338 return Boolean.FALSE;
339 }
340
341 public StockTransaction newStockTransaction(Date date, StockTransactionType type, Integer quantity) {
342 StockTransaction st = (StockTransaction)getJammyjoesDatabaseTables().getStockTransactionTable().newPersistent();
343 st.setProduct(this);
344 st.setDate(date);
345 st.setType(type);
346 st.setQuantity(quantity);
347 st.setCostprice(getCostprice());
348 st.setRetailpriceincvat(getRetailpriceincvat());
349 st.setVatexempt(getVatexempt());
350 return st;
351 }
352 }