diff --git a/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseInvoiceReceive.java b/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseInvoiceReceive.java index 4299d30..31c9903 100644 --- a/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseInvoiceReceive.java +++ b/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseInvoiceReceive.java @@ -5,7 +5,7 @@ import com.jfinal.plugin.activerecord.IBean; import com.alibaba.fastjson.annotation.JSONField; /** - * Generated by COWR Fri Aug 14 11:13:17 CST 2020 + * Generated by COWR Mon Aug 17 10:47:18 CST 2020 * TableName: invoice_receive * Remarks: 发票管理 - 领用记录 * PrimaryKey: id @@ -64,6 +64,28 @@ public abstract class BaseInvoiceReceive> extend return getInt("num"); } + /** + * name: surplus + * type: INT(10) + * isNullable: NO + * isPrimaryKey: NO + * defaultValue: + * @param surplus 剩余数量 + */ + @JSONField(name="surplus") + public void setSurplus(Integer surplus) { + set("surplus", surplus); + } + + + /** + * @return surplus 剩余数量 + */ + @JSONField(name="surplus") + public Integer getSurplus() { + return getInt("surplus"); + } + /** * name: start_code * type: VARCHAR(20) diff --git a/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseOrderSale.java b/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseOrderSale.java index 2ac519b..c19b03e 100644 --- a/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseOrderSale.java +++ b/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseOrderSale.java @@ -5,7 +5,7 @@ import com.jfinal.plugin.activerecord.IBean; import com.alibaba.fastjson.annotation.JSONField; /** - * Generated by COWR Sun May 17 21:43:18 CST 2020 + * Generated by COWR Mon Aug 17 11:15:31 CST 2020 * TableName: order_sale * Remarks: 订单相关 - 销售单 * PrimaryKey: sn @@ -1091,7 +1091,7 @@ public abstract class BaseOrderSale> extends BaseMode /** * name: product_id * type: INT(10) - * isNullable: YES + * isNullable: NO * isPrimaryKey: NO * defaultValue: * @param productId 品类id @@ -1113,7 +1113,7 @@ public abstract class BaseOrderSale> extends BaseMode /** * name: product_name * type: VARCHAR(255) - * isNullable: YES + * isNullable: NO * isPrimaryKey: NO * defaultValue: * @param productName 品类名称 @@ -1154,5 +1154,27 @@ public abstract class BaseOrderSale> extends BaseMode return getInt("prepay_customer_id"); } + /** + * name: invoice_code + * type: VARCHAR(20) + * isNullable: YES + * isPrimaryKey: NO + * defaultValue: + * @param invoiceCode 发票号码 + */ + @JSONField(name="invoice_code") + public void setInvoiceCode(String invoiceCode) { + set("invoice_code", invoiceCode); + } + + + /** + * @return invoice_code 发票号码 + */ + @JSONField(name="invoice_code") + public String getInvoiceCode() { + return getStr("invoice_code"); + } + } diff --git a/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseOrderTemp.java b/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseOrderTemp.java index 5149ff8..590aa5c 100644 --- a/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseOrderTemp.java +++ b/ssjygl-xsx-common/src/main/java/com/cowr/model/base/BaseOrderTemp.java @@ -5,7 +5,7 @@ import com.jfinal.plugin.activerecord.IBean; import com.alibaba.fastjson.annotation.JSONField; /** - * Generated by COWR Wed Jul 01 11:46:36 CST 2020 + * Generated by COWR Mon Aug 17 11:15:31 CST 2020 * TableName: order_temp * Remarks: 订单相关 - 外销单 * PrimaryKey: sn @@ -1024,5 +1024,27 @@ public abstract class BaseOrderTemp> extends BaseMode return getStr("old_sn"); } + /** + * name: invoice_code + * type: VARCHAR(20) + * isNullable: YES + * isPrimaryKey: NO + * defaultValue: + * @param invoiceCode 发票号码 + */ + @JSONField(name="invoice_code") + public void setInvoiceCode(String invoiceCode) { + set("invoice_code", invoiceCode); + } + + + /** + * @return invoice_code 发票号码 + */ + @JSONField(name="invoice_code") + public String getInvoiceCode() { + return getStr("invoice_code"); + } + } diff --git a/ssjygl-xsx-common/src/main/java/com/cowr/ssjygl/invoice/receive/InvoiceReceiveValidator.java b/ssjygl-xsx-common/src/main/java/com/cowr/ssjygl/invoice/receive/InvoiceReceiveValidator.java index 3f37e0e..ae1d29d 100644 --- a/ssjygl-xsx-common/src/main/java/com/cowr/ssjygl/invoice/receive/InvoiceReceiveValidator.java +++ b/ssjygl-xsx-common/src/main/java/com/cowr/ssjygl/invoice/receive/InvoiceReceiveValidator.java @@ -21,11 +21,10 @@ public class InvoiceReceiveValidator extends CrudParamValidator { validateString("id", 1, 32, "id", "id 长度 1~32"); } - validateInteger("num", -2147483647, 2147483647, "num", "num 范围 -2147483647~2147483647"); + validateInteger("num", 1, 2147483647, "num", "num 范围 1~2147483647"); validateString("start_code", 1, 20, "start_code", "start_code 长度 1~20"); validateInteger("receive_user_id", 1, 2147483647, "receive_user_id", "receive_user_id 范围 1~2147483647"); validateInteger("supermarket_id", 1, 2147483647, "supermarket_id", "supermarket_id 范围 1~2147483647"); - // 使用 model 更新时,model 不能只有主键有值 // 这里用 getActionMethodName 写死,判断是 update 时,才做验证 diff --git a/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/invoice/log/InvoiceLogSyncService.java b/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/invoice/log/InvoiceLogSyncService.java index 168d9c8..1f064fa 100644 --- a/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/invoice/log/InvoiceLogSyncService.java +++ b/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/invoice/log/InvoiceLogSyncService.java @@ -1,9 +1,35 @@ package com.cowr.local.ssjygl.invoice.log; +import com.cowr.common.view.Result; import com.cowr.local.ssjygl.base.BaseSyncService; +import com.cowr.model.InvoiceReceive; import com.jfinal.log.Log; public class InvoiceLogSyncService extends BaseSyncService { - private static Log log = Log.getLog(InvoiceLogSyncService.class); - public static InvoiceLogSyncService me = new InvoiceLogSyncService(); + private static Log log = Log.getLog(InvoiceLogSyncService.class); + public static InvoiceLogSyncService me = new InvoiceLogSyncService(); + + /** + * 通过第三方税盘接口获取当前的 发票号码 + * + * @param supermarket_id + * @return + */ + public String taxationLastCode(int supermarket_id) { + // TODO: 通过税盘获取当前发票号码 + return null; + } + + public InvoiceReceive lastReceive(int supermarket_id) { + String sql = "select * from invoice_receive t\n" + + " where t.supermarket_id = ? \n" + + " and t.surplus > 0\n" + + " order by t.start_code asc\n" + + " limit 1"; + + InvoiceReceive receive = InvoiceReceive.dao.findFirst(sql, supermarket_id); + + + return receive; + } } diff --git a/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/OrderService.java b/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/OrderService.java index 5b7cbf4..616c6bd 100644 --- a/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/OrderService.java +++ b/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/OrderService.java @@ -10,15 +10,19 @@ import com.cowr.common.view.Result; import com.cowr.local.ssjygl.actioncmdlog.ActionCmdLogService; import com.cowr.local.ssjygl.devicectrl.common.Const; import com.cowr.local.ssjygl.devicectrl.printer.ExcelHelper; +import com.cowr.local.ssjygl.invoice.log.InvoiceLogSyncService; import com.cowr.local.ssjygl.main.Config; +import com.cowr.local.ssjygl.synctask.SyncTaskService; import com.cowr.local.ssjygl.transport.TransportDeviceService; import com.cowr.model.*; import com.cowr.ssjygl.CacheData; +import com.cowr.ssjygl.modifylog.ModifyLogService; import com.cowr.ssjygl.transprice.TransPriceService; import com.jfinal.kit.PathKit; import com.jfinal.kit.StrKit; import com.jfinal.log.Log; import com.jfinal.plugin.activerecord.Db; +import com.jfinal.plugin.activerecord.IAtom; import com.jfinal.plugin.activerecord.Record; import org.apache.poi.ss.usermodel.Workbook; @@ -26,6 +30,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.math.BigDecimal; +import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; @@ -40,6 +45,94 @@ public class OrderService { } }; + /** + * 支付完成,不打发票,只抬杆 + * + * @param ret + * @param transport + * @return + */ + public Result payComplete(boolean ret, Transport transport) { + Record out = new Record(); + out.set("pay", ret); // 支付结果 + + if (ret) { + try { + if (transport.getTruckLicense().equals(Config.deviceThread.getCtrlCurrentLicense(transport.getOutWhich()))) { + Config.deviceThread.cmdRodUp(Enums.RowEnum.BACK.getId(), transport.getOutWhich()); + out.set("rod", true); + } else { + // 银行通知支付完成,对应的车辆已经通过其他方式出场了 + log.debug("不是当前出场的车牌【%s】,不抬杆", transport.getTruckLicense()); + out.set("rod", false); + } + } catch (Exception e) { + out.set("rod", "抬闸指令发送失败"); + log.error(e.getMessage(), e); + } + + Config.socketio.pubRefreshInSup(TransportDeviceService.me.real()); + } + + return Result.success(out); + } + + /** + * 支付完成,打发票,并抬杆 + * + * @param ret + * @param printdata + * @param transport + * @param printerId + * @return + */ + public Result payCompleteAndPrint(boolean ret, Record printdata, Transport transport, String printerId) { + Record out = new Record(); + out.set("pay", ret); // 支付结果 + + if (!ret) { + out.set("print", false); + out.set("rod", false); + return Result.success(out); + } + + try { + printdata.set("first_weight", transport.getFirstWeight()); + printdata.set("second_weight", transport.getSecondWeight()); + + File file = getPrintFile(printdata); // TODO: 改成生成发票内容打印 + + Config.deviceThread.print(printerId, file); + out.set("print", true); + } catch (Exception e) { + out.set("print", "打印指令发送失败"); + log.error(e.getMessage(), e); + } + + try { + if (transport.getTruckLicense().equals(Config.deviceThread.getCtrlCurrentLicense(transport.getOutWhich()))) { + Config.deviceThread.cmdRodUp(Enums.RowEnum.BACK.getId(), transport.getOutWhich()); + out.set("rod", true); + } else { + // 银行通知支付完成,对应的车辆已经通过其他方式出场了 + log.debug("不是当前出场的车牌【%s】,不抬杆", transport.getTruckLicense()); + out.set("rod", false); + } + } catch (Exception e) { + out.set("rod", "抬闸指令发送失败"); + log.error(e.getMessage(), e); + } + + Config.socketio.pubRefreshInSup(TransportDeviceService.me.real()); + + return Result.success(out); + } + + // 默认不打印 + public Result orderPayComplete(boolean ret, Record printdata, Transport transport, String printerId) { + return orderPayComplete(ret, printdata, transport, printerId, 0); + } + /** * 订单结算完成,打印票据 * @@ -49,20 +142,22 @@ public class OrderService { * @param printerId * @return */ - public Result orderPayComplete(boolean ret, Record printdata, Transport transport, String printerId) { + public Result orderPayComplete(boolean ret, Record printdata, Transport transport, String printerId, int req_receipt) { Record out = new Record(); out.set("pay", ret); // 支付结果 if (ret) { - printdata.set("first_weight", transport.getFirstWeight()); - printdata.set("second_weight", transport.getSecondWeight()); + if (req_receipt == 1) { + try { + printdata.set("first_weight", transport.getFirstWeight()); + printdata.set("second_weight", transport.getSecondWeight()); - try { - Config.deviceThread.print(printerId, getPrintFile(printdata)); - out.set("print", true); - } catch (Exception e) { - out.set("print", "打印指令发送失败"); - log.error(e.getMessage(), e); + Config.deviceThread.print(printerId, getPrintFile(printdata)); + out.set("print", true); + } catch (Exception e) { + out.set("print", "打印指令发送失败"); + log.error(e.getMessage(), e); + } } try { @@ -348,6 +443,7 @@ public class OrderService { return out; } + public File getPrintFile(Record order) { long st = System.currentTimeMillis(); Map data = getPrintModel(order); @@ -456,6 +552,132 @@ public class OrderService { return Result.success("打印指令已发送"); } + /** + * 打印发票 + * + * @param sn + * @param printerId + * @param sysuser + * @return + */ + public Result printInvoice(String sn, String printerId, Sysuser sysuser) { + if (StrKit.isBlank(sn)) { + return Result.failed("sn 不能为 null"); + } + + int sntype = Integer.parseInt(sn.substring(10, 12)); + + if (sntype != OrderTypeEnum.SALE.getTypeid() && sntype != OrderTypeEnum.TEMP.getTypeid()) { + return Result.failed("订单类型错误,只有配送订单和外销订单才能开具发票"); + } + + BaseModel order = getOrderBySn(sn); + + if (order == null) { + return Result.failed("未找到订单信息"); + } + + if (order.getInt("state") != OrderStateEnum.RECEIVED.getStateid()) { + return Result.failed("订单未完成、或者已经取消"); + } + + if (sntype == OrderTypeEnum.SALE.getTypeid()) { + if (((OrderSale) order).getInvoiceCode() != null) { + return Result.failed("已经开具了发票。若需重新开票,请将旧的发票作废"); // TODO: 发票作废的流程 + } + } else if (sntype == OrderTypeEnum.TEMP.getTypeid()) { + if (((OrderTemp) order).getInvoiceCode() != null) { + return Result.failed("已经开具了发票。若需重新开票,请将旧的发票作废"); // TODO: 发票作废的流程 + } + } else { + return Result.failed("订单类型错误,只有配送订单和外销订单才能开具发票"); + } + + InvoiceReceive receive = InvoiceLogSyncService.me.lastReceive(order.getInt("supermarket_id")); + + if (receive == null) { + return Result.failed("没有有效的领用记录"); + } + + if (receive.getSurplus() == 0) { + return Result.failed("没有可用发票"); + } + + String taxation_invoice_code = InvoiceLogSyncService.me.taxationLastCode(order.getInt("supermarket_id")); + String next_invoice_code; + if (receive.getCurrentCode() == null) { + next_invoice_code = String.format("%0" + receive.getStartCode().length() + "d", Integer.parseInt(receive.getStartCode() + 1)); + } else { + next_invoice_code = String.format("%0" + receive.getStartCode().length() + "d", Integer.parseInt(receive.getCurrentCode() + 1)); + } + + if (!next_invoice_code.equals(taxation_invoice_code)) { + return Result.failed("本地记录和税务系统不一致"); + } + + order.set("invoice_code", next_invoice_code); + + boolean ret = Db.tx(new IAtom() { + @Override + public boolean run() { + Record logrecord = new Record(); + logrecord.set("sn", sn); + logrecord.set("invoice_code", next_invoice_code); + + SyncTask synctask = new SyncTask(); + + boolean ret = order.update(); + + if (!ret) { + log.error("跟新订单 %s 开票信息失败", next_invoice_code); + return false; + } + + receive.setSurplus(receive.getSurplus() - 1); + receive.setCurrentCode(next_invoice_code); + + ret = receive.update(); + + if (!ret) { + log.error("发票领用信息更新失败", next_invoice_code); + return false; + } + + synctask.addUpdateData(receive); + synctask.addUpdateData(order); + + return SyncTaskService.me.save(synctask) + && ModifyLogService.me.save(order.getTablename(), "sn", logrecord.toJson(), Enums.DataOpType.UPDATE.getId(), sysuser); + } + }); + + + Transport transport = Transport.dao.findById(order.get("transport_id")); + + if (transport == null) { + return Result.failed("运输记录不存在"); + } + + Record printdata = order.toRecord(); + printdata.set("first_weight", transport.getFirstWeight()); + printdata.set("second_weight", transport.getSecondWeight()); + + try { + Config.deviceThread.print(printerId, getPrintFile(printdata)); + } catch (Exception e) { + log.error(e.getMessage(), e); + return Result.failed("打印指令失败"); + } + + Record cmd = new Record(); + cmd.set("cmd", "print"); + cmd.set("sn", sn); + cmd.set("printer", printerId); + ActionCmdLogService.me.save(cmd.toJson(), sysuser); + + return Result.success("打印指令已发送"); + } + /** * 按 sn 查询订单相关信息 * diff --git a/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/ordertemp/OrderTempController.java b/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/ordertemp/OrderTempController.java index f778a63..b2ddcf3 100644 --- a/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/ordertemp/OrderTempController.java +++ b/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/ordertemp/OrderTempController.java @@ -56,8 +56,9 @@ public class OrderTempController extends BaseController { Integer pay_type = getInt("pay_type"); String memo = get("memo"); String printer = get("printer", Enums.PrinterIdEnum.printer1.name()); + int req_receipt = getInt("req_receipt", 0); // 是否需要发票,0 默认不需要,1需要 - renderJson(OrderTempSyncService.me.pay(uuid, transport_id, product_id, pay_type, memo, printer, tokenuser)); + renderJson(OrderTempSyncService.me.pay(uuid, transport_id, product_id, pay_type, memo, printer, tokenuser, req_receipt)); } @@ -75,7 +76,9 @@ public class OrderTempController extends BaseController { Integer ordercluster_id = getInt("ordercluster_id"); String memo = get("memo"); String printer = get("printer", Enums.PrinterIdEnum.printer1.name()); - renderJson(OrderTempSyncService.me.payordercluster(uuid, transport_id, ordercluster_id, memo, printer, tokenuser)); + int req_receipt = getInt("req_receipt", 0); // 是否需要发票,0 默认不需要,1需要 + + renderJson(OrderTempSyncService.me.payordercluster(uuid, transport_id, ordercluster_id, memo, printer, tokenuser, req_receipt)); } @Before(OrderTempPrepayValidator.class) @@ -93,7 +96,9 @@ public class OrderTempController extends BaseController { Integer product_id = getInt("product_id"); String memo = get("memo"); String printer = get("printer", Enums.PrinterIdEnum.printer1.name()); - renderJson(OrderTempSyncService.me.prepay(uuid, transport_id, ordercluster_id, product_id, memo, printer, tokenuser)); + int req_receipt = getInt("req_receipt", 0); // 是否需要发票,0 默认不需要,1需要 + + renderJson(OrderTempSyncService.me.prepay(uuid, transport_id, ordercluster_id, product_id, memo, printer, tokenuser, req_receipt)); } /** diff --git a/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/ordertemp/OrderTempSyncService.java b/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/ordertemp/OrderTempSyncService.java index b0adba9..7134316 100644 --- a/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/ordertemp/OrderTempSyncService.java +++ b/ssjygl-xsx-local/src/main/java/com/cowr/local/ssjygl/order/ordertemp/OrderTempSyncService.java @@ -5,6 +5,7 @@ import com.cowr.common.enums.OrderStateEnum; import com.cowr.common.enums.OrderTypeEnum; import com.cowr.common.utils.DateTimeUtil; import com.cowr.common.view.Result; +import com.cowr.local.ssjygl.invoice.log.InvoiceLogSyncService; import com.cowr.local.ssjygl.order.OrderService; import com.cowr.local.ssjygl.order.orderseq.OrderSeqService; import com.cowr.local.ssjygl.supermarket.product.SupermarketProductService; @@ -35,7 +36,8 @@ public class OrderTempSyncService { Integer pay_type, String memo, String printerId, - Sysuser sysuser + Sysuser sysuser, + int req_receipt ) { Transport transport = Transport.dao.findById(transport_id); @@ -59,10 +61,13 @@ public class OrderTempSyncService { return Result.failedstr("未查到有效的单价信息"); } - BigDecimal min = new BigDecimal(0.001); - Date now = new Date(); - SyncTask synctask = new SyncTask(); - OrderTemp order = new OrderTemp(); + BigDecimal min = new BigDecimal(0.001); + Date now = new Date(); + SyncTask synctask = new SyncTask(); + OrderTemp order = new OrderTemp(); + InvoiceReceive receive = null; + String next_invoice_code = null; + order.setUuid(uuid); if (order.checkDuplicate("uuid")) { @@ -81,6 +86,26 @@ public class OrderTempSyncService { BigDecimal net_weight = transport.getSecondWeight().subtract(transport.getFirstWeight()); // 销售的用第二次减第一次 + if (req_receipt == 1) { // 需要同时开具发票 + receive = InvoiceLogSyncService.me.lastReceive(transport.getSupermarketId()); + + if (receive == null) { + return Result.failed("没有有效的领用记录"); + } + + if (receive.getSurplus() == 0) { + return Result.failed("没有可用发票"); + } + + if (receive.getCurrentCode() == null) { + next_invoice_code = String.format("%0" + receive.getStartCode().length() + "d", Integer.parseInt(receive.getStartCode() + 1)); + } else { + next_invoice_code = String.format("%0" + receive.getStartCode().length() + "d", Integer.parseInt(receive.getCurrentCode() + 1)); + } + + order.setInvoiceCode(next_invoice_code); + } + order.setTransportId(transport.getId()); order.setSupermarketId(transport.getSupermarketId()); order.setTruckLicense(transport.getTruckLicense()); @@ -104,15 +129,18 @@ public class OrderTempSyncService { // 更新 transport 出入场信息 // 线下支付才同步将出入场记录设置为完成 - if(order.getPayType() == 1) { + if (order.getPayType() == 1) { transport.setArriveTime(now); order.setState(OrderStateEnum.RECEIVED.getStateid()); // 直接完成,没有前面的过程 - }else{ + } else { order.setState(OrderStateEnum.LEAVE.getStateid()); // 等等付款 } + transport.setState(order.getState()); // 使用 order 的 state transport.setType(OrderTypeEnum.TEMP.getTypeid()); + InvoiceReceive finalReceive = receive; + String finalNext_invoice_code = next_invoice_code; boolean ret = Db.tx(new IAtom() { @Override public boolean run() { @@ -139,6 +167,29 @@ public class OrderTempSyncService { return false; } + if (req_receipt == 1) { // 需要同时开具发票 + // 这里的 finalReceive 在前面肯定验证过了 + finalReceive.setSurplus(finalReceive.getSurplus() - 1); + finalReceive.setCurrentCode(finalNext_invoice_code); + + ret = finalReceive.update(); + + if (!ret) { + log.error("发票领用信息更新失败", finalNext_invoice_code); + return false; + } + + // 各种信息都保存成功后,再提交税务系统,获取当前发票信息 // TODO:税盘接口是不是还要提交金额等开票相关的信息 + String taxation_invoice_code = InvoiceLogSyncService.me.taxationLastCode(order.getInt("supermarket_id")); + + if (!finalNext_invoice_code.equals(taxation_invoice_code)) { + log.error("本地记录和税务系统不一致"); + return false; + } + + synctask.addUpdateData(finalReceive); + } + synctask.addUpdateData(transport); synctask.addSaveData(order); synctask.addUpdateData(stock); @@ -151,9 +202,9 @@ public class OrderTempSyncService { } }); - if(order.getPayType() == 1){ + if (order.getPayType() == 1) { return OrderService.me.orderPayComplete(ret, order.toRecord(), transport, printerId); - }else{ + } else { return ret ? Result.success(order) : Result.failed("结算失败"); } } @@ -164,7 +215,8 @@ public class OrderTempSyncService { Integer ordercluster_id, String memo, String printerId, - Sysuser sysuser + Sysuser sysuser, + int req_receipt ) { Transport transport = Transport.dao.findById(transport_id); @@ -196,10 +248,13 @@ public class OrderTempSyncService { return Result.failedstr("未查到有效的单价信息"); } - BigDecimal min = new BigDecimal(0.001); - Date now = new Date(); - SyncTask synctask = new SyncTask(); - OrderTemp order = new OrderTemp(); + BigDecimal min = new BigDecimal(0.001); + Date now = new Date(); + SyncTask synctask = new SyncTask(); + OrderTemp order = new OrderTemp(); + InvoiceReceive receive = null; + String next_invoice_code = null; + order.setUuid(uuid); if (order.checkDuplicate("uuid")) { @@ -218,6 +273,26 @@ public class OrderTempSyncService { BigDecimal net_weight = transport.getSecondWeight().subtract(transport.getFirstWeight()); // 销售的用第二次减第一次 + if (req_receipt == 1) { // 需要同时开具发票 + receive = InvoiceLogSyncService.me.lastReceive(transport.getSupermarketId()); + + if (receive == null) { + return Result.failed("没有有效的领用记录"); + } + + if (receive.getSurplus() == 0) { + return Result.failed("没有可用发票"); + } + + if (receive.getCurrentCode() == null) { + next_invoice_code = String.format("%0" + receive.getStartCode().length() + "d", Integer.parseInt(receive.getStartCode() + 1)); + } else { + next_invoice_code = String.format("%0" + receive.getStartCode().length() + "d", Integer.parseInt(receive.getCurrentCode() + 1)); + } + + order.setInvoiceCode(next_invoice_code); + } + order.setTransportId(transport.getId()); order.setSupermarketId(transport.getSupermarketId()); order.setTruckLicense(transport.getTruckLicense()); @@ -276,6 +351,9 @@ public class OrderTempSyncService { transport.setArriveTime(now); transport.setType(OrderTypeEnum.TEMP.getTypeid()); + InvoiceReceive finalReceive = receive; + String finalNext_invoice_code = next_invoice_code; + boolean ret = Db.tx(new IAtom() { @Override public boolean run() { @@ -303,6 +381,29 @@ public class OrderTempSyncService { return false; } + if (req_receipt == 1) { // 需要同时开具发票 + // 这里的 finalReceive 在前面肯定验证过了 + finalReceive.setSurplus(finalReceive.getSurplus() - 1); + finalReceive.setCurrentCode(finalNext_invoice_code); + + ret = finalReceive.update(); + + if (!ret) { + log.error("发票领用信息更新失败", finalNext_invoice_code); + return false; + } + + // 各种信息都保存成功后,再提交税务系统,获取当前发票信息 // TODO:税盘接口是不是还要提交金额等开票相关的信息 + String taxation_invoice_code = InvoiceLogSyncService.me.taxationLastCode(order.getInt("supermarket_id")); + + if (!finalNext_invoice_code.equals(taxation_invoice_code)) { + log.error("本地记录和税务系统不一致"); + return false; + } + + synctask.addUpdateData(finalReceive); + } + // 在这里更新sn字段之后存入 synctask.addSaveData(order); synctask.addUpdateData(transport); @@ -319,7 +420,6 @@ public class OrderTempSyncService { return OrderService.me.orderPayComplete(ret, order.toRecord(), transport, printerId); } - public Result prepay( String uuid, String transport_id, @@ -327,7 +427,8 @@ public class OrderTempSyncService { Integer product_id, String memo, String printerId, - Sysuser sysuser + Sysuser sysuser, + int req_receipt ) { OrderTemp order = new OrderTemp(); order.setUuid(uuid); @@ -440,8 +541,30 @@ public class OrderTempSyncService { return Result.failed("客户余额不足"); } - Date now = new Date(); - SyncTask synctask = new SyncTask(); + Date now = new Date(); + SyncTask synctask = new SyncTask(); + InvoiceReceive receive = null; + String next_invoice_code = null; + + if (req_receipt == 1) { // 需要同时开具发票 + receive = InvoiceLogSyncService.me.lastReceive(transport.getSupermarketId()); + + if (receive == null) { + return Result.failed("没有有效的领用记录"); + } + + if (receive.getSurplus() == 0) { + return Result.failed("没有可用发票"); + } + + if (receive.getCurrentCode() == null) { + next_invoice_code = String.format("%0" + receive.getStartCode().length() + "d", Integer.parseInt(receive.getStartCode() + 1)); + } else { + next_invoice_code = String.format("%0" + receive.getStartCode().length() + "d", Integer.parseInt(receive.getCurrentCode() + 1)); + } + + order.setInvoiceCode(next_invoice_code); + } order.setTransportId(transport.getId()); order.setSupermarketId(transport.getSupermarketId()); @@ -483,6 +606,8 @@ public class OrderTempSyncService { transport.setArriveTime(now); transport.setType(OrderTypeEnum.TEMP.getTypeid()); + InvoiceReceive finalReceive = receive; + String finalNext_invoice_code = next_invoice_code; boolean ret = Db.tx(new IAtom() { @Override public boolean run() { @@ -596,6 +721,29 @@ public class OrderTempSyncService { return false; } + if (req_receipt == 1) { // 需要同时开具发票 + // 这里的 finalReceive 在前面肯定验证过了 + finalReceive.setSurplus(finalReceive.getSurplus() - 1); + finalReceive.setCurrentCode(finalNext_invoice_code); + + ret = finalReceive.update(); + + if (!ret) { + log.error("发票领用信息更新失败", finalNext_invoice_code); + return false; + } + + // 各种信息都保存成功后,再提交税务系统,获取当前发票信息 // TODO:税盘接口是不是还要提交金额等开票相关的信息 + String taxation_invoice_code = InvoiceLogSyncService.me.taxationLastCode(order.getInt("supermarket_id")); + + if (!finalNext_invoice_code.equals(taxation_invoice_code)) { + log.error("本地记录和税务系统不一致"); + return false; + } + + synctask.addUpdateData(finalReceive); + } + // 在这里更新sn字段之后存入 synctask.addSaveData(order); synctask.addUpdateData(transport); diff --git a/ssjygl-xsx-local/src/main/resources/dev/db.properties b/ssjygl-xsx-local/src/main/resources/dev/db.properties index 492a575..2f161a5 100644 --- a/ssjygl-xsx-local/src/main/resources/dev/db.properties +++ b/ssjygl-xsx-local/src/main/resources/dev/db.properties @@ -9,7 +9,7 @@ user=root password=Local_1 # redis -redis.basekey =ssjcgl_xsx_dev +redis.basekey=ssjcgl_xsx_dev redis.ip=r-wz9168ab2f2f7ec4pd.redis.rds.aliyuncs.com redis.port=6379 redis.pwd=CoWR1111 diff --git a/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/invoice/receive/InvoiceReceiveSyncService.java b/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/invoice/receive/InvoiceReceiveSyncService.java index d8645f5..164c945 100644 --- a/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/invoice/receive/InvoiceReceiveSyncService.java +++ b/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/invoice/receive/InvoiceReceiveSyncService.java @@ -1,12 +1,18 @@ package com.cowr.service.ssjygl.invoice.receive; +import com.cowr.common.enums.Enums; import com.cowr.common.view.Result; import com.cowr.model.InvoiceReceive; import com.cowr.model.Supermarket; +import com.cowr.model.SyncTask; import com.cowr.model.Sysuser; import com.cowr.service.ssjygl.base.BaseSyncService; +import com.cowr.service.ssjygl.synctask.SyncTaskService; +import com.cowr.ssjygl.modifylog.ModifyLogService; import com.jfinal.kit.StrKit; import com.jfinal.log.Log; +import com.jfinal.plugin.activerecord.Db; +import com.jfinal.plugin.activerecord.IAtom; public class InvoiceReceiveSyncService extends BaseSyncService { private static Log log = Log.getLog(InvoiceReceiveSyncService.class); @@ -27,7 +33,34 @@ public class InvoiceReceiveSyncService extends BaseSyncService { return Result.failed("未找到对应超市信息"); } + // TODO: 这里需要验证输入的起始发票号码和领用份数,避免多个批次的领用和多个超市的领用出现发票代码重复的情况 + receive.setId(StrKit.getRandomUUID()); - return super.save(receive, user); + receive.setSurplus(receive.getNum()); + + try { + boolean ret = Db.tx(new IAtom() { + @Override + public boolean run() { + try { + return receive.save() + && SyncTaskService.me.save(new SyncTask().addSaveData(receive), receive.getSupermarketId()) // 下发到指定的超市 + && ModifyLogService.me.save(receive, null, Enums.DataOpType.SAVE.getId(), user); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + }); + + return ret ? Result.object(receive) : Result.failed(false, "新增失败"); + } catch (Exception e) { + log.error(e.getMessage(), e); + if (e.getMessage().contains("PRIMARY")) { + return Result.failed(false, "主键冲突"); + } else { + return Result.failed(false, e.getMessage()); + } + } } } diff --git a/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/synctask/SyncTaskService.java b/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/synctask/SyncTaskService.java index 5943448..d9113e7 100644 --- a/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/synctask/SyncTaskService.java +++ b/ssjygl-xsx-service/src/main/java/com/cowr/service/ssjygl/synctask/SyncTaskService.java @@ -38,7 +38,7 @@ public class SyncTaskService { * @return */ public boolean save(SyncTask model) { - if(!isEnable()){ + if (!isEnable()) { return true; } @@ -71,25 +71,25 @@ public class SyncTaskService { boolean ret = Db.tx(new IAtom() { @Override public boolean run() throws SQLException { - try{ + try { int[] ret = Db.batchSave(list, list.size()); - for(int i : ret){ - if( i != 1){ + for (int i : ret) { + if (i != 1) { return false; } } return true; - }catch (Exception e){ + } catch (Exception e) { log.error(e.getMessage(), e); return false; } } }); - if(ret){ - for(SyncTask obj : list){ + if (ret) { + for (SyncTask obj : list) { send(obj); } } @@ -98,6 +98,33 @@ public class SyncTaskService { } } + /** + * 同步到指定的超市 + * + * @param model + * @param supermarket_id + * @return + */ + public boolean save(SyncTask model, int supermarket_id) { + if (!isEnable()) { + return true; + } + + model.setJson(); // 使用逐步加入的数据设置数据 + model.setSupermarketId(supermarket_id); + model.setId(StrKit.getRandomUUID()); + model.setCreateTime(new Date()); + + boolean ret = model.save(); + + if (ret) { + send(model); + } + + return ret; // 有插入的,还是需要返回插入状态 + + } + /** * 向所有客户端广播 *

@@ -106,7 +133,7 @@ public class SyncTaskService { * @param model */ public void send(SyncTask model) { - if(!isEnable()){ + if (!isEnable()) { return; } @@ -131,7 +158,7 @@ public class SyncTaskService { } public void task() { - if(!isEnable()){ + if (!isEnable()) { return; } @@ -160,7 +187,7 @@ public class SyncTaskService { * @return */ public boolean recv(JSONObject data, int current_supermarket_id) { - if(!isEnable()){ + if (!isEnable()) { return true; } @@ -237,9 +264,9 @@ public class SyncTaskService { if (delete_data != null && !delete_data.isEmpty()) { for (String tablename : delete_data.keySet()) { - JSONObject data = delete_data.getJSONObject(tablename); - String pks = data.getString("pks"); - JSONArray arr = data.getJSONArray("data"); + JSONObject data = delete_data.getJSONObject(tablename); + String pks = data.getString("pks"); + JSONArray arr = data.getJSONArray("data"); if (AuthLicense.dao.getTablename().equals(tablename)) { deleteauthlics.addAll(arr);