151 lines
5.9 KiB
Java
151 lines
5.9 KiB
Java
package com.pqt.server.module.sale;
|
|
|
|
import com.pqt.core.entities.product.Product;
|
|
import com.pqt.core.entities.sale.Sale;
|
|
import com.pqt.server.module.stock.StockService;
|
|
import com.pqt.server.tools.FileUtil;
|
|
import com.pqt.server.tools.entities.SaleContent;
|
|
import org.apache.commons.io.input.ReversedLinesFileReader;
|
|
|
|
import java.io.*;
|
|
import java.text.DateFormat;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Iterator;
|
|
|
|
/**
|
|
* Implémentation de l'interface {@link ISaleDao} utilisant un fichier comme moyen pour assurer la persistance des
|
|
* données relatives aux commandes validées. <b>Cette implémentation ne supporte pas le rollback de commandes</b>.
|
|
* <p/>.
|
|
* La persistance des données est faite de sorte que ces données soient lisibles par un humain lorsque le fichier est
|
|
* ouvert avecc un éditeur de texte quelconque.
|
|
* <p/>
|
|
* Les identifiants attribués aux commandes validées sont incrémentés à chaque fois, en se basant soit sur la dernière
|
|
* valeur attribuée (lue depuis le fichier de sauvegarde lors de l'instantiation), soit sur une valeur par défaut. Ils
|
|
* sont tous <b>positifs et non-nuls</b>.
|
|
*/
|
|
public class NoRevertFileSaleDao implements ISaleDao {
|
|
|
|
private static final String SALE_LOG_FILE_NAME = "sale_log.txt";
|
|
private static final long DEFAULT_SALE_ID = 0; //équivaut à la valeur du premier id - 1
|
|
private StockService stockService;
|
|
private long nextSaleId;
|
|
private ISaleRenderer renderer;
|
|
|
|
NoRevertFileSaleDao(StockService stockService) {
|
|
this.stockService = stockService;
|
|
this.renderer = getRenderer();
|
|
nextSaleId = readLastSaleIdFromFile()+1;
|
|
}
|
|
|
|
@Override
|
|
public long submitSale(Sale sale) {
|
|
boolean valid = true;
|
|
Iterator<Product> it = sale.getProducts().keySet().iterator();
|
|
while(valid && it.hasNext()){
|
|
Product p = it.next();
|
|
Product product = stockService.getProduct(p.getId());
|
|
valid = product!=null
|
|
&& p.equals(product)
|
|
&& product.isSellable()
|
|
&& product.getAmountRemaining()>=sale.getProducts().get(p);
|
|
}
|
|
|
|
if(!valid)
|
|
return -1;
|
|
|
|
long saleId = nextSaleId;
|
|
stockService.applySale(new SaleContent(sale));
|
|
logSale(sale, saleId);
|
|
generateNextSaleId();
|
|
return saleId;
|
|
}
|
|
|
|
private void generateNextSaleId() {
|
|
nextSaleId++;
|
|
}
|
|
|
|
/**
|
|
* Read the last sale id written in the log file with title {@link #SALE_LOG_FILE_NAME} or a default value if such id has not been found.
|
|
* <p/>
|
|
* Different reasons why this method may not find any id :<br/>
|
|
* - file does not exist<br/>
|
|
* - file is empty<br/>
|
|
* - file does not respect the expected syntax for writing sales' data<br/>
|
|
* <p/>
|
|
* The log file with title {@link #SALE_LOG_FILE_NAME} is not created by this method if it doesn't exist yet.
|
|
* @return last sale id used in the log file, or -1 if none was found.
|
|
*/
|
|
private long readLastSaleIdFromFile(){
|
|
long id = DEFAULT_SALE_ID;
|
|
if(FileUtil.exist(SALE_LOG_FILE_NAME)){
|
|
try(ReversedLinesFileReader rlfr = new ReversedLinesFileReader(new File("SALE_LOG_FILE_NAME"))){
|
|
boolean stop = false;
|
|
do{
|
|
try {
|
|
String line = rlfr.readLine();
|
|
if(line.matches("^[0-9]+$")){
|
|
id = Long.parseLong(line.substring(1));
|
|
stop = true;
|
|
}
|
|
}catch (EOFException e){
|
|
stop = true;
|
|
}
|
|
}while(!stop);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
return id;
|
|
}else{
|
|
return id;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isSaleRevertSupported() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean submitSaleRevert(long id) {
|
|
//TODO Créer un nouveau dao qui supporte le revert
|
|
throw new UnsupportedOperationException("Le revert de commandes n'est pas supporté");
|
|
}
|
|
|
|
private void logSale(Sale sale, long saleId){
|
|
try(FileOutputStream fos = new FileOutputStream(SALE_LOG_FILE_NAME);
|
|
PrintWriter pw = new PrintWriter(fos)){
|
|
|
|
pw.append(renderer.render(sale, saleId));
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private ISaleRenderer getRenderer(){
|
|
return(sale, id)->{
|
|
StringBuffer sb = new StringBuffer("\n#").append(id).append("\n");
|
|
String separator = "-----";
|
|
DateFormat dateFormat = new SimpleDateFormat("<dd/ww/yyyy - HH:mm:ss>");
|
|
|
|
sb.append("type : ").append(sale.getType().name()).append("\n");
|
|
sb.append("at : ").append(dateFormat.format(sale.getOrderedAt())).append("\n");
|
|
if(sale.getOrderedBy()!=null)
|
|
sb.append("by : ").append(sale.getOrderedBy().getUsername()).append("(").append(sale.getOrderedBy().getPermissionLevel().name()).append(")").append("\n");
|
|
if(sale.getOrderedFor()!=null)
|
|
sb.append("for : ").append(sale.getOrderedFor().getUsername()).append("(").append(sale.getOrderedFor().getPermissionLevel().name()).append(")").append("\n");
|
|
sb.append(separator).append("\n");
|
|
sb.append("Products : \n");
|
|
sale.getProducts().keySet().forEach(p->{
|
|
int productAmount = sale.getProducts().get(p);
|
|
sb.append(String.format(" * %s (%du, %f€) : %d remaining in stock", p.getName(), productAmount, p.getPrice()*(double)productAmount, p.getAmountRemaining()-productAmount)).append("\n");
|
|
});
|
|
sb.append(separator);
|
|
return sb.toString();
|
|
};
|
|
}
|
|
|
|
private interface ISaleRenderer{
|
|
String render(Sale sale, long saleId);
|
|
}
|
|
}
|