Dépôt officiel du code source de l'ERP OpenConcerto
Rev 156 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.erp.core.supplychain.stock.element;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.SQLSelectJoin;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.SQLTableEvent;
import org.openconcerto.sql.model.SQLTableEvent.Mode;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.request.UpdateBuilder;
import org.openconcerto.sql.utils.SQLUtils;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.cc.ITransformer;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.dbutils.ResultSetHandler;
public class ComposedItemStockUpdater {
private final List<StockItem> itemsUpdated;
private final DBRoot root;
/// FIXME mettre à jour les stocks des kits à partir des feuilles
/**
* Met à jour les stocks des nomenclature composé par un des articles de itemsUpdated
*
* @param root
* @param itemsUpdated liste des StockItem non composés qui ont été mis à jour
*/
public ComposedItemStockUpdater(DBRoot root, List<StockItem> itemsUpdated) {
this.itemsUpdated = itemsUpdated;
this.root = root;
}
/**
* Mise à jour des stocks en fonction des composants de l'article
*
* @throws SQLException
*/
public void update() throws SQLException {
// Liste des nomenclatures dépendantes des itemsUpdated
List<StockItem> items = getAllComposedItemToUpdate();
updateNomenclature(items);
}
public void updateNomenclature(List<StockItem> items) throws SQLException {
// Fecth des articles liés
getAllChildren(items);
List<StockItem> removedBadItem = new ArrayList<>();
// Mise à jour des stocks
for (StockItem stockItem : items) {
if (!stockItem.updateQtyFromChildren()) {
removedBadItem.add(stockItem);
}
}
items.removeAll(removedBadItem);
SQLTable stockTable = root.getTable("STOCK");
List<String> requests = new ArrayList<String>();
for (StockItem stockItem : items) {
if (stockItem.isStockInit()) {
UpdateBuilder update = new UpdateBuilder(stockTable);
update.setWhere(new Where(stockTable.getKey(), "=", stockItem.stock.getID()));
update.setObject("QTE_REEL", stockItem.getRealQty());
update.setObject("QTE_TH", stockItem.getVirtualQty());
update.setObject("QTE_LIV_ATTENTE", stockItem.getDeliverQty());
update.setObject("QTE_RECEPT_ATTENTE", stockItem.getReceiptQty());
requests.add(update.asString());
} else {
SQLRowValues rowVals = new SQLRowValues(stockTable);
rowVals.put("QTE_REEL", stockItem.getRealQty());
rowVals.put("QTE_TH", stockItem.getVirtualQty());
rowVals.put("QTE_LIV_ATTENTE", stockItem.getDeliverQty());
rowVals.put("QTE_RECEPT_ATTENTE", stockItem.getReceiptQty());
rowVals.put("ID_ARTICLE", stockItem.getArticle().getID());
rowVals.put("ID_DEPOT_STOCK", stockItem.stock.getForeignID("ID_DEPOT_STOCK"));
rowVals.commit();
if (stockItem.getArticle().getForeignID("ID_DEPOT_STOCK") == stockItem.stock.getForeignID("ID_DEPOT_STOCK")) {
SQLRowValues rowValsArt = stockItem.getArticle().createEmptyUpdateRow();
rowValsArt.put("ID_STOCK", rowVals);
rowValsArt.commit();
}
}
}
List<? extends ResultSetHandler> handlers = new ArrayList<ResultSetHandler>(requests.size());
for (String s : requests) {
handlers.add(null);
}
SQLUtils.executeMultiple(stockTable.getDBSystemRoot(), requests, handlers);
stockTable.fire(new SQLTableEvent(stockTable, SQLRow.NONEXISTANT_ID, Mode.ROW_UPDATED));
}
/**
* Associe les StockItems liés aux items passés en parametres
*
* @param items liste des stockitems d'article composé
*/
private void getAllChildren(List<StockItem> items) {
final SQLTable tableArticle = this.root.getTable("ARTICLE");
final int undefDepot = tableArticle.getTable("DEPOT_STOCK").getUndefinedID();
final SQLRowValues rowValsArt = new SQLRowValues(tableArticle);
rowValsArt.put(tableArticle.getKey().getName(), null);
SQLRowValues rowValsStock = new SQLRowValues(this.root.getTable("STOCK"));
rowValsStock.put("QTE_REEL", null);
rowValsStock.put("QTE_TH", null);
rowValsStock.put("QTE_RECEPT_ATTENTE", null);
rowValsStock.put("QTE_LIV_ATTENTE", null);
rowValsStock.put("ID_DEPOT_STOCK", null);
rowValsStock.put("ID_ARTICLE", rowValsArt);
final SQLTable tableArticleElt = this.root.getTable("ARTICLE_ELEMENT");
SQLRowValues rowValsArtItem = new SQLRowValues(tableArticleElt);
rowValsArtItem.put("ID_ARTICLE", rowValsArt);
rowValsArtItem.put("QTE", null);
rowValsArtItem.put("QTE_UNITAIRE", null);
rowValsArtItem.put("ID_ARTICLE_PARENT", null);
final List<Integer> ids = new ArrayList<Integer>();
Map<Tuple2<Integer, Integer>, StockItem> mapItem = new HashMap<Tuple2<Integer, Integer>, StockItem>();
for (StockItem stockItem : items) {
final int id = stockItem.getArticle().getID();
ids.add(id);
if (stockItem.stock.getForeignID("ID_DEPOT_STOCK") != undefDepot) {
mapItem.put(Tuple2.create(id, stockItem.stock.getForeignID("ID_DEPOT_STOCK")), stockItem);
}
}
SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowValsArtItem);
fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
@Override
public SQLSelect transformChecked(SQLSelect input) {
Where w = new Where(tableArticleElt.getField("ID_ARTICLE_PARENT"), ids);
input.setWhere(w);
return input;
}
});
List<SQLRowValues> values = fetcher.fetch();
for (SQLRowValues sqlRowValues : values) {
final SQLRowAccessor article = sqlRowValues.getForeign("ID_ARTICLE");
final SQLRowAccessor articleParent = sqlRowValues.getForeign("ID_ARTICLE_PARENT");
if (article != null && !article.isUndefined()) {
final Collection<? extends SQLRowAccessor> referentStockRows = article.getReferentRows(this.root.getTable("STOCK"));
{
// Init Stock if no depot
if (referentStockRows.size() == 0) {
// init default stock depot
SQLRowValues rowVals = new SQLRowValues(article.getTable().getTable("STOCK"));
rowVals.put("ID_ARTICLE", article.getID());
rowVals.put("ID_DEPOT_STOCK", DepotStockSQLElement.DEFAULT_ID);
try {
SQLRow rowStock = rowVals.commit();
article.createEmptyUpdateRow().put("ID_STOCK", rowStock.getID()).commit();
System.err.println("NO DEPOT STOCK FOR ITEM " + articleParent.getID() + " -- PARENT " + articleParent.getID());
StockItem stockItem = mapItem.get(Tuple2.create(articleParent.getID(), DepotStockSQLElement.DEFAULT_ID));
if (stockItem != null) {
stockItem.addItemComponent(new StockItemComponent(new StockItem(article, rowStock), sqlRowValues.getBigDecimal("QTE_UNITAIRE"), sqlRowValues.getInt("QTE")));
} else {
System.err.println("Unable to find stock of item ARTICLE " + articleParent.getID() + " DEPOT " + DepotStockSQLElement.DEFAULT_ID);
}
} catch (SQLException e) {
ExceptionHandler.handle("Erreur lors de l'initialisation du stock de l'article", e);
}
}
}
for (SQLRowAccessor sqlRowAccessor : referentStockRows) {
StockItem stockItem = mapItem.get(Tuple2.create(articleParent.getID(), sqlRowAccessor.getForeignID("ID_DEPOT_STOCK")));
if (stockItem != null) {
stockItem.addItemComponent(new StockItemComponent(new StockItem(article, sqlRowAccessor), sqlRowValues.getBigDecimal("QTE_UNITAIRE"), sqlRowValues.getInt("QTE")));
} else if (sqlRowAccessor.getForeignID("ID_DEPOT_STOCK") == sqlRowAccessor.getTable().getForeignTable("ID_DEPOT_STOCK").getUndefinedID()) {
stockItem = mapItem.get(Tuple2.create(articleParent.getID(), DepotStockSQLElement.DEFAULT_ID));
stockItem.addItemComponent(new StockItemComponent(new StockItem(article, sqlRowAccessor), sqlRowValues.getBigDecimal("QTE_UNITAIRE"), sqlRowValues.getInt("QTE")));
} else {
System.err.println("Unable to find stock of item ARTICLE " + articleParent.getID() + " DEPOT " + sqlRowAccessor.getForeignID("ID_DEPOT_STOCK"));
}
}
}
}
}
/**
* @return l'ensemble des stockItems composés à mettre à jour
*/
private List<StockItem> getAllComposedItemToUpdate() {
// Liste des ids des artciles non composé mis à jour
Set<Integer> ids = new HashSet<Integer>(itemsUpdated.size());
for (StockItem stockItem : itemsUpdated) {
ids.add(stockItem.getArticle().getID());
}
// Liste des nomenclatures dépendantes des itemsUpdated
List<SQLRowValues> list = getComposedItemToUpdate(ids);
int size = list.size();
Map<Integer, SQLRowValues> result = new HashMap<Integer, SQLRowValues>(ids.size());
for (SQLRowValues sqlRowValues : list) {
result.put(sqlRowValues.getID(), sqlRowValues);
}
// Liste des nomenclatures dépendantes des nomenclatures (kit dans kits)
while (size > 0) {
List<SQLRowValues> l = getComposedItemToUpdate(ids);
for (SQLRowValues sqlRowValues : l) {
result.put(sqlRowValues.getID(), sqlRowValues);
}
size = l.size();
if (size > 0) {
ids.clear();
for (SQLRowValues r : l) {
ids.add(r.getForeignID("ID_ARTICLE"));
}
}
}
List<StockItem> items = new ArrayList<StockItem>(result.size());
for (SQLRowValues rowVals : result.values()) {
StockItem item = new StockItem(rowVals.getForeign("ID_ARTICLE"), rowVals);
items.add(item);
}
return items;
}
/**
*
* @param ids
* @return l'ensemble des Articles composés avec un des articles en parametres
*/
private List<SQLRowValues> getComposedItemToUpdate(final Set<Integer> ids) {
final SQLTable tableArticle = this.root.getTable("ARTICLE");
final SQLRowValues rowValsArt = new SQLRowValues(tableArticle);
rowValsArt.put(tableArticle.getKey().getName(), null);
SQLRowValues rowValsStock = new SQLRowValues(this.root.getTable("STOCK"));
rowValsStock.put("QTE_REEL", null);
rowValsStock.put("QTE_TH", null);
rowValsStock.put("QTE_RECEPT_ATTENTE", null);
rowValsStock.put("QTE_LIV_ATTENTE", null);
rowValsStock.put("ID_ARTICLE", rowValsArt);
rowValsStock.put("ID_DEPOT_STOCK", null);
final SQLTable tableArticleElt = this.root.getTable("ARTICLE_ELEMENT");
// SQLRowValues rowValsArtItem = new SQLRowValues(tableArticleElt);
// rowValsArtItem.put("ID_ARTICLE_PARENT", rowValsArt);
// rowValsArtItem.put("QTE", null);
// rowValsArtItem.put("QTE_UNITAIRE", null);
SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowValsStock);
fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
@Override
public SQLSelect transformChecked(SQLSelect input) {
SQLSelectJoin joinFromField = input.addJoin("RIGHT", tableArticleElt, new Where(tableArticleElt.getField("ID_ARTICLE_PARENT"), "=", input.getTable("STOCK").getField("ID_ARTICLE")));
Where w = new Where(joinFromField.getJoinedTable().getField("ID_ARTICLE"), ids);
joinFromField.setWhere(w);
input.clearOrder();
input.setDistinct(true);
return input;
}
});
return fetcher.fetch();
}
}