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<BookCommandMeta> 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<BookCommand> 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<BookCommand> 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;
|
}
|
|
}
|