package book.rebate.qty; import java.math.BigDecimal; import java.util.Date; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import book.BookResult; import book.FlowTable; import book.FreezeCondition; import book.QtyCommand; import book.RecordOperator; import book.rebate.BookCommand; import book.rebate.BookCommandBucket; import book.rebate.BookCommandMeta; import foundation.action.ActionProvider; import foundation.dao.DataPackage; import foundation.dao.DataSource; import foundation.dao.Filter; import foundation.data.entity.Entity; import foundation.data.entity.EntitySet; import foundation.data.object.DataObject; import foundation.data.object.EntitySaver; import foundation.io.IOContext; import foundation.persist.NamedSQL; import foundation.persist.SQLRunner; import foundation.util.ID; import foundation.util.Util; public class BookWriter extends ActionProvider { private static Logger logger; public static final String FieldName_BatchMark = "batch_mark"; static { logger = LogManager.getLogger(BookWriter.class); } public BookWriter() { } @Override protected void publishMethod() { //1. 获取库存记账描述列表 addMethod("getBookCommandList"); //2. 获取库存记账描述 addMethod("getBookCommand"); //3. 记账 addMethod("write"); } public void getBookCommandList() { BookCommandBucket bucket = BookCommandBucket.getInstance(); dataWriter.addValue("data", bucket); } public void getBookCommand() { String commandCode = dataReader.getString("code"); List metas = BookCommandBucket.getMeta(commandCode); if (metas == null) { logger.error("book command [{}] can not find: ", commandCode); return; } dataWriter.addValue("data", metas); } public void write() throws Exception { String commandCode = context.getStepParam(); if (Util.isEmpty(commandCode)) { commandCode = context.getParam(); } List bookCommands = BookCommandBucket.get(commandCode); if (bookCommands == null || (bookCommands.isEmpty())) { throw new Exception("book command [{" + commandCode + "}] can not find: "); } //2. 获取公司及仓库 for (BookCommand bookCommand: bookCommands) { getOrgAndWarehouse(bookCommand); } //3. 账本加锁 lockStockBook(bookCommands); //4. 创建流水表(FlowTable)并进行校验 boolean isContinue = true; for (BookCommand bookCommand: bookCommands) { isContinue = isContinue && getFlowTableAndValidate(bookCommand, bookCommand.getDataSource()); } if (!isContinue) { logger.error("validate not success, skip..."); return; } //5. 根据Command和FlowTable记账 for (BookCommand bookCommand: bookCommands) { doWriteBook(bookCommand); } } private void getOrgAndWarehouse(BookCommand bookCommand) throws Exception { IOContext ioContext = context.getContext(IOContext.class); //2.批量导入设置批号 if(ioContext != null ) { bookCommand.setIoBatchId(ioContext.getIoBatchId()); bookCommand.setBatchDocument(ioContext.getToDateObject()); bookCommand.setBatchDocumentDetail(ioContext.getToTempDateObject()); bookCommand.setOperate("import"); }else { bookCommand.setDocument(dataReader.getDataPackage()); bookCommand.setOperate(dataReader.getOperator()); } } private void lockStockBook(List bookCommands) throws Exception { for (BookCommand bookCommand: bookCommands) { NamedSQL lockRebateBook = NamedSQL.getInstance("lockRebateBook"); lockRebateBook.setParam("documentTable", bookCommand.getDocumentTableName()); lockRebateBook.setParam("document_id", bookCommand.getDocumentId()); SQLRunner.execSQL(lockRebateBook); } } private boolean getFlowTableAndValidate(BookCommand bookCommand, DataSource dataSource) throws Exception { if (DataSource.Request == dataSource) { return getFlowTableAndValidateFromRequest(bookCommand); } return getFlowTableAndValidate(bookCommand); } private boolean getFlowTableAndValidateFromRequest(BookCommand bookCommand) throws Exception { boolean result = true; FlowTable flowTable = bookCommand.getFlowTable(); //1. 根据【单据】+【明细账】获取记账工作表 DataPackage dataPackage = bookCommand.getDocument(); EntitySet detailSet = dataPackage.getItemEntitySet(bookCommand.getDocumentDetailTableName(), DataSource.Request); //2. 获取数据 NamedSQL getRebateQtyBookFlow = NamedSQL.getInstance("getRebateQtyBookFlowBasicFields"); getRebateQtyBookFlow.setParam("tableName", bookCommand.getDocumentTableName()); getRebateQtyBookFlow.setParam("detailTableName", bookCommand.getDocumentDetailTableName()); getRebateQtyBookFlow.setParam("batch_mark", bookCommand.getBatchMark()); getRebateQtyBookFlow.setParam("rebateId", bookCommand.getRebateId()); getRebateQtyBookFlow.setParam("documentDetailParentId", "document_detail.parent_id" ); getRebateQtyBookFlow.setParam("documentTypeCode" ,bookCommand.getConfigDocTypeSegment()); for (Entity entity: detailSet) { getRebateQtyBookFlow.setParam("document_num", bookCommand.getDocumentQtySegment()); Filter filter = new Filter(); filter.add(bookCommand.getFilter()); filter.add("document_detail.id", entity.getString("id")); getRebateQtyBookFlow.setFilter(filter); EntitySet entitySet = SQLRunner.getEntitySet(getRebateQtyBookFlow); flowTable.appendEntitySet(entitySet); } return result; } private boolean getFlowTableAndValidate(BookCommand bookCommand) throws Exception { boolean result = true; String operate = bookCommand.getOperate(); //1. 根据【单据】+【明细账】获取记账工作表 NamedSQL getRebateQtyBookFlow = NamedSQL.getInstance("getRebateQtyBookFlowBasicFields"); getRebateQtyBookFlow.setParam("tableName", bookCommand.getDocumentTableName()); getRebateQtyBookFlow.setParam("detailTableName", bookCommand.getDocumentDetailTableName()); Filter filter = new Filter(); if ((!Util.isEmpty(operate)) && "import".equalsIgnoreCase(operate)) { getRebateQtyBookFlow.setParam("documentDetailParentId", "document_detail.id" ); getRebateQtyBookFlow.setParam("rebateId", "document_detail.id" ); filter.add("document_detail.io_batch_id",bookCommand.getIoBatchId()); } else if(bookCommand.getDetailTableName().equalsIgnoreCase(bookCommand.getDocumentDetailTableName()) ) { getRebateQtyBookFlow.setParam("documentDetailParentId", "document_detail.id" ); getRebateQtyBookFlow.setParam("rebateId", "document_detail.id" ); filter.add("document.id",dataReader.getString("id")); }else { getRebateQtyBookFlow.setParam("documentDetailParentId", "document_detail.parent_id" ); getRebateQtyBookFlow.setParam("rebateId", "document_detail.record_id" ); filter.add("document.id",bookCommand.getDocumentId()); } getRebateQtyBookFlow.setFilter(filter); getRebateQtyBookFlow.setParam("document_num", bookCommand.getDocumentQtySegment()); getRebateQtyBookFlow.setParam("batch_mark", bookCommand.getBatchMark()); getRebateQtyBookFlow.setParam("documentTypeCode" ,bookCommand.getConfigDocTypeSegment()); //2. 获取数据 EntitySet entitySet = SQLRunner.getEntitySet(getRebateQtyBookFlow); FlowTable flowTable = bookCommand.getFlowTable(); flowTable.setEntitySet(entitySet); return result; } public void doWriteBook(BookCommand bookCommand) throws Exception { //1. 记库存流水 writeStockFlow(bookCommand); if (bookCommand.getDocumentTableName().equalsIgnoreCase(bookCommand.getDocumentDetailTableName())) { return ; } //2. 记库存明细 writeStockDetail(bookCommand); } private void writeStockFlow(BookCommand bookCommand) throws Exception { QtyCommand qtyCommand = bookCommand.getQtyCommand(); if (qtyCommand.isDoNothing()) { return; } //1. 记录流水账 DataObject dataObject = DataObject.getInstance(bookCommand.getFlowTableName()); String batchMark = bookCommand.getBatchMark(); FlowTable flowTable = bookCommand.getFlowTable(); for (Entity flow : flowTable) { BigDecimal qty = flow.getBigDecimal("qty"); EntitySaver saver = dataObject.createEntitySaver(); saver.set("id", ID.newValue()); saver.set("rebate_id", flow.getValue("rebate_id")); saver.set("rebate_code", flow.getValue("rebate_code")); saver.set("rebate_name", flow.getValue("rebate_name")); saver.set("operate_name", flow.getValue("operate_name")); saver.set("year", flow.getValue("year")); saver.set("season", flow.getValue("season")); saver.set("doc_date", flow.getValue("doc_date")); saver.set("doc_code", flow.getValue("doc_code")); saver.set("org_id", flow.getValue("org_id")); saver.set("account_id", flow.getValue("account_id")); saver.set("account_code", flow.getValue("account_code")); saver.set("account_name", flow.getString("account_name")); saver.set("bu_id", flow.getValue("bu_id")); saver.set("bu_name", flow.getValue("bu_name")); saver.set("company_id", flow.getValue("company_id")); saver.set("company_name", flow.getValue("company_name")); saver.set("product_id", flow.getValue("product_id")); saver.set("product_code", flow.getValue("product_code")); saver.set("product_name", flow.getValue("product_name")); saver.set("sku_id", flow.getValue("sku_id")); saver.set("spec", flow.getValue("spec")); saver.set("emption_product_id", flow.getValue("emption_product_id")); saver.set("emption_product_code", flow.getValue("emption_product_code")); saver.set("emption_product_name", flow.getValue("emption_product_name")); saver.set("emption_sku_id", flow.getValue("emption_sku_id")); saver.set("emption_spec", flow.getValue("emption_spec")); saver.set("doc_date", flow.getValue("doc_date")); saver.set("expire_date", flow.getValue("expire_date")); boolean qtyChanged = false; RecordOperator recordOperate = RecordOperator.Insert; boolean negativeConver = bookCommand.isNegativeConvert(); if (qtyCommand.isSetAdd()) { BigDecimal qty_add = qty.multiply(qtyCommand.getAddOperator()); if (qty_add.compareTo(BigDecimal.ZERO) < 0 && negativeConver) { saver.set("num_used", BigDecimal.ZERO.subtract(qty_add)); } else { saver.set("num_return", qty_add); } recordOperate = RecordOperator.Update; qtyChanged = true; } if (qtyCommand.isSetDelete()) { BigDecimal qty_delete = qty.multiply(qtyCommand.getDeleteOperator()); if (qty_delete.compareTo(BigDecimal.ZERO) < 0 && negativeConver) { saver.set("num_return", BigDecimal.ZERO.subtract(qty_delete)); } else { saver.set("num_used", qty_delete); } recordOperate = RecordOperator.Update; qtyChanged = true; } FreezeCondition freezeCondition = bookCommand.getFreezeCondition(); if (qtyCommand.isSetFreeze()) { BigDecimal qty_freeze = qty.multiply(qtyCommand.getFreezeOperator()); //1. 例如:库存调整单,只有调减审批的时候才需要正数记冻结,只有调减审批不通过才能用负数记冻结 if (freezeCondition.isCompatible(qty_freeze)) { saver.set("num_freeze", qty_freeze); qtyChanged = true; } recordOperate = RecordOperator.Update; } if (qtyCommand.isSetUnfreeze()) { BigDecimal qty_unfreeze = qty.multiply(qtyCommand.getUnfreezeOperator()); //2. 例如:库存调整单,只有调减审批通过的时候才需要减少冻结 if (freezeCondition.isCompatible(qty_unfreeze)) { saver.set("num_unfreeze", qty_unfreeze); qtyChanged = true; } recordOperate = RecordOperator.Update; } saver.set("record_operator", recordOperate.name()); saver.set("batch_mark", batchMark); if(qtyChanged) { saver.insert(); } } } private void writeStockDetail(BookCommand bookCommand) throws Exception { BookResult result = new BookResult(); String batchMark = bookCommand.getBatchMark(); Date bookDate = bookCommand.getBookDate(); //1. 计入已使用 NamedSQL writeUpdateStockDetail = NamedSQL.getInstance("writeUpdateRebateQtyDetail"); writeUpdateStockDetail.setParam("batch_mark", batchMark); writeUpdateStockDetail.setParam("update_time", bookDate); int updateCount = SQLRunner.execSQL(writeUpdateStockDetail); result.setUpdateCount(updateCount); //2. 补充明细账字段(余额,可用金额) NamedSQL resetStockDetailOtherFields = NamedSQL.getInstance("resetRebateQtyDetailOtherFields"); resetStockDetailOtherFields.setParam("batch_mark", bookCommand.getBatchMark()); resetStockDetailOtherFields.execute(); //3. 检查余额,可用余额 NamedSQL getNegativeStockDetail = NamedSQL.getInstance("getNegativeRebateQtyDetail"); getNegativeStockDetail.setParam("batch_mark", batchMark); int negativeCount = SQLRunner.getInteger(getNegativeStockDetail); if (negativeCount > 0) { dataWriter.reportOneError("余额校验", "余额不足,无法抵扣"); throw new Exception("余额不足,无法抵扣"); } //4. 日志并校验 logger.debug("买赠明细>>计划记账{}条, 插入{} 条,修改{}条, 删除{}条;批次号:{}", result.getPlanCount(), result.getInsertCount(), result.getUpdateCount(), result.getDeleteCount(), batchMark); if (!result.isValid()) { // throw new Exception("库存明细记账时存在错误,操作已经终止并回滚"); } } public Object tranferDocumentDocType(Object doc_type) { if ("普通销售出库".equals(doc_type)) { return "普通销售入库"; } return doc_type; } }