BasicBill.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. package beans.stockbill.bills;
  2. import beans.datacontrllog.DataContrlLog;
  3. import common.Controller;
  4. import common.UserInfo;
  5. import common.YosException;
  6. import common.data.*;
  7. import common.data.db.DBConnect;
  8. import org.apache.commons.lang.StringUtils;
  9. import java.math.BigDecimal;
  10. import java.text.SimpleDateFormat;
  11. import java.util.ArrayList;
  12. import java.util.Date;
  13. public abstract class BasicBill {
  14. Controller controller;
  15. DBConnect dbConnect;
  16. UserInfo userInfo;
  17. long st_stockbillid;
  18. boolean issale;//是否销售出库
  19. String billType;//单据类型
  20. String billTypeMX;//单据类型
  21. String billno;
  22. String siteid;
  23. String status;
  24. int rb;
  25. String period;
  26. Row billRow;
  27. Rows itemRows;
  28. Rows codeRows;
  29. public static BasicBill getBill(Controller controller, long st_stockbillid) throws YosException {
  30. Rows billRows = controller.dbConnect.runSqlQuery("select type from st_stockbill where st_stockbillid ='" + st_stockbillid + "'");
  31. if (billRows.isEmpty()) {
  32. throw new YosException("该出入库单不存在");
  33. }
  34. String type = billRows.get(0).getString("type");
  35. switch (type) {
  36. case "销售出库":
  37. return new XSCK(controller, st_stockbillid);
  38. case "返修出库":
  39. return new ck(controller, st_stockbillid);
  40. case "生产领料出库":
  41. return new ck(controller, st_stockbillid);
  42. case "委外领料出库":
  43. return new ck(controller, st_stockbillid);
  44. case "其他出库":
  45. return new QTCK(controller, st_stockbillid);
  46. case "外购入库":
  47. return new rk(controller, st_stockbillid);
  48. case "生产入库":
  49. return new rk(controller, st_stockbillid);
  50. case "委外入库":
  51. return new rk(controller, st_stockbillid);
  52. case "返修入库":
  53. return new FXRK(controller, st_stockbillid);
  54. case "其他入库":
  55. return new QTRK(controller, st_stockbillid);
  56. default: {
  57. throw new YosException("不支持的出入库单类型");
  58. }
  59. }
  60. }
  61. /**
  62. * 构造函数
  63. *
  64. * @param controller
  65. * @param st_stockbillid 出入库单ID
  66. * @throws YosException
  67. */
  68. public BasicBill(Controller controller, long st_stockbillid) throws YosException {
  69. this.controller = controller;
  70. this.dbConnect = this.controller.dbConnect;
  71. this.userInfo = controller.userInfo;
  72. this.st_stockbillid = st_stockbillid;
  73. queryBills();
  74. }
  75. /**
  76. * 单据审核校验
  77. *
  78. * @param ischeck
  79. * @throws YosException
  80. */
  81. public void checkValidate(boolean ischeck) throws YosException {
  82. /*
  83. 通用校验
  84. */
  85. if (ischeck) {
  86. if (StringUtils.isBlank(period)) {
  87. period = getPeriod(true, billRow.getDate("billdate"));
  88. dbConnect.runSqlUpdate("update st_stockbill set period='" + period + "' where st_stockbillid=" + st_stockbillid);
  89. }
  90. if (!status.equals("新建")) {
  91. throw new YosException("单号为:【" + billno + "】的出入库单为非新建状态,无法审核");
  92. }
  93. RowsMap rowsMap = dbConnect.runSqlQuery("select CONCAT(year, '-',LPAD(month, 2, '0')) period,isclose from st_period where CONCAT(year, '-',LPAD(month, 2, '0'))='" + period + "'").toRowsMap("period");
  94. if (rowsMap.containsKey(period)) {
  95. if (rowsMap.get(period).toRowsMap("isclose").containsKey("1")) {
  96. throw new YosException("原单据会计期间已关闭,不可审核");
  97. }
  98. } else {
  99. throw new YosException("原单据会计期间未生成,不可审核");
  100. }
  101. if (itemRows.isEmpty()) {
  102. throw new YosException("表体为空");
  103. }
  104. if (itemRows.min("qty").doubleValue() < 0) {
  105. throw new YosException("表体数量不能小于0");
  106. }
  107. if (rb == 0) {
  108. if (!billRow.getString("sourceobject").equals("tpartreimbursement")) {
  109. Rows olditemRows = dbConnect.runSqlQuery("select * from st_stockbill_items where siteid='" + siteid + "' and st_stockbillid=" + billRow.getLong("sourceid"));
  110. RowsMap olditemRowsMap = olditemRows.toRowsMap("st_stockbill_itemsid");
  111. for (Row row : itemRows) {
  112. if (StringUtils.isNotBlank(row.getString("sourceobject")) && row.getString("sourceobject").equals("st_stockbill_items")) {
  113. if (olditemRowsMap.containsKey(row.getString("sourceid"))) {
  114. Row row1 = olditemRowsMap.get(row.getString("sourceid")).get(0);
  115. if (row.getBigDecimal("qty").compareTo((row1.getBigDecimal("qty").subtract(row1.getBigDecimal("hongqty")))) > 0) {
  116. throw new YosException("行号为:" + row.getString("rowno") + "的商品红冲数量超过原单可红冲数量" + row1.getBigDecimal("qty").subtract(row1.getBigDecimal("hongqty")));
  117. }
  118. } else {
  119. throw new YosException("行号为:" + row.getString("rowno") + "的物料不在原单中,不可进行红冲");
  120. }
  121. }
  122. }
  123. }
  124. }
  125. } else {
  126. if (StringUtils.isBlank(period)) {
  127. period = getPeriod(true, billRow.getDate("billdate"));
  128. dbConnect.runSqlUpdate("update st_stockbill set period='" + period + "' where st_stockbillid=" + st_stockbillid);
  129. }
  130. if (!status.equals("审核")) {
  131. throw new YosException("单号为:【" + billno + "】的出入库单为非审核状态,无法反审核");
  132. }
  133. RowsMap rowsMap = dbConnect.runSqlQuery("select CONCAT(year, '-',LPAD(month, 2, '0')) period,isclose from st_period where CONCAT(year, '-',LPAD(month, 2, '0'))='" + period + "'").toRowsMap("period");
  134. if (rowsMap.containsKey(period)) {
  135. if (rowsMap.get(period).toRowsMap("isclose").containsKey("1")) {
  136. throw new YosException("原单据会计期间已关闭,不可反审核");
  137. }
  138. } else {
  139. throw new YosException("单据日期所属会计期间未生成,不可反审核");
  140. }
  141. }
  142. }
  143. public ArrayList<String> getCheckSql(boolean ischeck) throws YosException {
  144. ArrayList<String> sqlList = new ArrayList<>();
  145. sqlList.addAll(updateInvbal(ischeck));//更新库存
  146. sqlList.addAll(updateMCode(ischeck));//更新序列号
  147. sqlList.addAll(updateHongqty(ischeck));//更新红冲数量
  148. sqlList.addAll(updateStatus(ischeck));//更新状态
  149. if (ischeck) {
  150. sqlList.add(DataContrlLog.createLog(controller, "st_stockbill", st_stockbillid, "审核", billRow.getString("type") + "单审核成功").getSQL());
  151. } else {
  152. sqlList.add(DataContrlLog.createLog(controller, "st_stockbill", st_stockbillid, "反审核", billRow.getString("type") + "单反审核成功").getSQL());
  153. }
  154. return sqlList;
  155. }
  156. public ArrayList<String> getCheckSql_custamount(boolean ischeck) throws YosException {
  157. ArrayList<String> sqlList = new ArrayList<>();
  158. return sqlList;
  159. }
  160. /**
  161. * 更新库存
  162. *
  163. * @param ischeck
  164. * @return
  165. * @throws YosException
  166. */
  167. private ArrayList<String> updateInvbal(boolean ischeck) throws YosException {
  168. ArrayList<String> sqlList = new ArrayList<>();
  169. RowsMap invbalsRowsMap = SQLFactory.createQuerySQL(dbConnect, "st_invbal").setWhere("siteid", siteid).setWhere("itemid", itemRows.toArrayList("itemid")).query().toRowsMap("itemid");
  170. RowsMap invbalsSaleRowsMap = SQLFactory.createQuerySQL(dbConnect, "st_invbal_sale").setWhere("siteid", siteid).setWhere("itemid", itemRows.toArrayList("itemid")).query().toRowsMap("itemid");
  171. for (Row row : itemRows) {
  172. long itemid = row.getLong("itemid");
  173. long stockid = row.getLong("stockid");
  174. BigDecimal qty = isInStock(ischeck) ? row.getBigDecimal("qty") : row.getBigDecimal("qty").negate();
  175. if (!invbalsRowsMap.containsKey(String.valueOf(itemid)) || !invbalsRowsMap.get(String.valueOf(itemid)).toRowsMap("stockid").containsKey(String.valueOf(stockid))) {
  176. InsertSQL invbalInsert = SQLFactory.createInsertSQL(controller, "st_invbal");
  177. invbalInsert.setValue("siteid", siteid);
  178. invbalInsert.setValue("stockid", stockid);
  179. invbalInsert.setValue("itemid", itemid);
  180. invbalInsert.setValue("qty", qty.doubleValue());
  181. sqlList.add(invbalInsert.getSQL());
  182. } else {
  183. UpdateSQL invbalUpdate = SQLFactory.createUpdateSQL(controller, "st_invbal");
  184. invbalUpdate.addValue("qty", qty);
  185. invbalUpdate.setWhere("itemid", itemid);
  186. invbalUpdate.setWhere("stockid", stockid);
  187. invbalUpdate.setWhere("siteid", siteid);
  188. sqlList.add(invbalUpdate.getSQL());
  189. }
  190. //是否为销售仓库
  191. if (SQLFactory.getRow(controller, "st_stock", stockid).getBoolean("issalestock")) {
  192. if (!invbalsSaleRowsMap.containsKey(String.valueOf(itemid))) {
  193. InsertSQL invbalInsert = SQLFactory.createInsertSQL(controller, "st_invbal_sale");
  194. invbalInsert.setValue("siteid", siteid);
  195. invbalInsert.setValue("itemid", itemid);
  196. if (!issale) {
  197. invbalInsert.setValue("cansaleqty", qty.doubleValue());//可销售数量
  198. invbalInsert.setValue("candispatchqty", qty.doubleValue());//可发货数量
  199. } else {
  200. invbalInsert.setValue("cansaleqty", 0);//可销售数量
  201. invbalInsert.setValue("candispatchqty", 0);//可发货数量
  202. }
  203. invbalInsert.setValue("qty", qty.doubleValue());//库存数量
  204. sqlList.add(invbalInsert.getSQL());
  205. } else {
  206. UpdateSQL invbalUpdate = SQLFactory.createUpdateSQL(controller, "st_invbal_sale");
  207. if (!issale) {
  208. invbalUpdate.addValue("cansaleqty", qty.doubleValue());//可销售数量
  209. invbalUpdate.addValue("candispatchqty", qty.doubleValue());//可发货数量
  210. }
  211. invbalUpdate.addValue("qty", qty);//库存数量
  212. invbalUpdate.setWhere("itemid", itemid);
  213. invbalUpdate.setWhere("siteid", siteid);
  214. sqlList.add(invbalUpdate.getSQL());
  215. }
  216. }
  217. }
  218. return sqlList;
  219. }
  220. /**
  221. * 更新已红冲数量
  222. *
  223. * @param ischeck
  224. * @return
  225. * @throws YosException
  226. */
  227. private ArrayList<String> updateHongqty(boolean ischeck) throws YosException {
  228. ArrayList<String> sqlList = new ArrayList<>();
  229. if (rb == 0) {
  230. for (Row row : itemRows) {
  231. if (row.getString("sourceobject").equals("st_stockbill_items")) {
  232. long sourceid = row.getLong("sourceid");
  233. BigDecimal qty = ischeck ? row.getBigDecimal("qty") : row.getBigDecimal("qty").negate();
  234. sqlList.add("update st_stockbill_items set hongqty=ifnull(hongqty,0)+" + qty + " where st_stockbill_itemsid=" + sourceid);
  235. }
  236. }
  237. }
  238. return sqlList;
  239. }
  240. /**
  241. * 更新状态
  242. *
  243. * @param ischeck
  244. * @return
  245. * @throws YosException
  246. */
  247. private ArrayList<String> updateStatus(boolean ischeck) throws YosException {
  248. ArrayList<String> sqlList = new ArrayList<>();
  249. if (ischeck) {
  250. sqlList.add("update st_stockbill set status='审核',checkby='" + controller.username + "',checkdate=CURRENT_TIMESTAMP where st_stockbillid = " + st_stockbillid + " and siteid='" + siteid + "'");
  251. } else {
  252. sqlList.add("update st_stockbill set status='新建',checkby='',checkdate=null where st_stockbillid = " + st_stockbillid + " and siteid='" + siteid + "'");
  253. }
  254. return sqlList;
  255. }
  256. /**
  257. * 更新序列号
  258. *
  259. * @param ischeck
  260. * @return
  261. * @throws YosException
  262. */
  263. public ArrayList<String> updateMCode(boolean ischeck) throws YosException {
  264. ArrayList<String> sqlList = new ArrayList<>();
  265. for (Row row : codeRows) {
  266. long itemid = row.getLong("itemid");
  267. long stockid = row.getLong("stockid");
  268. String sku = row.getString("sku");
  269. UpdateSQL saItemsku = SQLFactory.createUpdateSQL(controller, "sa_itemsku");
  270. if (isInStock(ischeck)) {
  271. saItemsku.setValue("stockid", stockid);
  272. saItemsku.setValue("status", "在库");
  273. if (issale) {
  274. saItemsku.setValue("sys_enterpriseid", null);
  275. }
  276. } else {
  277. saItemsku.setValue("stockid", 0);
  278. if (issale) {
  279. saItemsku.setValue("status", "售出");
  280. saItemsku.setValue("sys_enterpriseid", billRow.getLong("sys_enterpriseid"));
  281. }
  282. }
  283. saItemsku.setWhere("itemid", itemid);
  284. saItemsku.setWhere("sku", sku);
  285. sqlList.add(saItemsku.getSQL());
  286. }
  287. return sqlList;
  288. }
  289. /**
  290. * 单据查询
  291. *
  292. * @throws YosException
  293. */
  294. private void queryBills() throws YosException {
  295. Rows billRows = dbConnect.runSqlQuery("select * from st_stockbill where st_stockbillid ='" + st_stockbillid + "'");
  296. if (billRows.isNotEmpty()) {
  297. billRow = billRows.get(0);
  298. } else {
  299. throw new YosException("该出入库单不存在");
  300. }
  301. this.billno = billRow.getString("billno");
  302. this.issale = billRow.getString("type").equals("销售出库");
  303. this.billType = billRow.getString("type");
  304. this.billTypeMX = billRow.getString("typemx");
  305. this.rb = billRow.getInteger("rb");
  306. this.siteid = billRow.getString("siteid");
  307. this.status = billRow.getString("status");
  308. this.period = billRow.getString("period");
  309. itemRows = dbConnect.runSqlQuery("select t1.*,ifnull(t1.sa_orderitemsid,0) sa_orderitemsidnum,t2.isnegative,t2.ismodule from st_stockbill_items t1 left join plm_item t2 on t1.itemid=t2.itemid where t1.st_stockbillid ='" + st_stockbillid + "'");
  310. codeRows = dbConnect.runSqlQuery("select t1.* from st_stockbill_items_sku t1 where t1.st_stockbillid ='" + st_stockbillid + "'");
  311. }
  312. public String getPeriod(boolean isjudge, Date date) throws YosException {
  313. String preioddate = new SimpleDateFormat("yyyy-MM-dd").format(date);
  314. Rows rows = dbConnect.runSqlQuery("select CONCAT_WS('-', year, LPAD(month, 2, '0')) period from st_period where begdate<='" + preioddate + "' and enddate>='" + preioddate + "'");
  315. if (rows.size() != 1) {
  316. if (isjudge) {
  317. throw new YosException("单据日期所属会计期间未生成");
  318. } else {
  319. return "null";
  320. }
  321. } else {
  322. return rows.get(0).getString("period");
  323. }
  324. }
  325. public abstract boolean isInStock(boolean fischeck);
  326. }