先创建服务端的APP
1.官网下载Winrun4j。 http://winrun4j.sourceforge.net/
2.打开winrun4j文件夹。
打开bin目录;
3.把服务端那个APP所需要的东西都复制到一块
我们看下posapp.ini里边配置:
到这一步,就差不多了,可以跑跑这个EXE,看看能不能跑起来,如果跑不起来,去看日志哪里有错误,修改哪里
接下来再创建服务端APP注册为windows服务的小玩意
1.我们看下service.ini的配置,和APP的配置是不一样的。
2.那么重点来了,这一步才是注册为服务至关重要的一步,
文件夹里是这几个bat命令:
3.如果想把该程序注册为服务,那么以管理员身份运行这里的命令,而不是去双击运行service.exe,那样是不对的
我们下面看下这几个文件的内容,从上到下的四个:
RegisterService32.bat--
StartService32.bat--
StopService32.bat--
UnregisterService32.bat--
然后以管理员身份,去执行RegisterService32.bat这个bat,该程序就被注册为Windows服务了,去控制面板看下服务是否启动,欧克啦
下面为代码,
注意注册为服务的,需要在项目中继承 【winrun4j的AbstractService这个类】
我们可以看下这三个类的代码:
APPServer类
package hyi.pos.appserver.server
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.j256.ormlite.dao.Dao
import com.j256.ormlite.dao.DaoManager
import com.j256.ormlite.dao.GenericRawResults
import com.j256.ormlite.jdbc.JdbcDatabaseConnection
import com.j256.ormlite.stmt.DeleteBuilder
import com.j256.ormlite.stmt.UpdateBuilder
import com.j256.ormlite.support.ConnectionSource
import com.j256.ormlite.support.DatabaseConnection
import com.j256.ormlite.table.TableUtils
import groovy.sql.Sql
import groovy.util.logging.Log4j
import hyi.pos.appclient.client.AppClient
import hyi.pos.appserver.server.ext.NoticeProcess
import hyi.pos.appserver.util.MposMasterCopy
import hyi.pos.db.DBUtil
import hyi.pos.entity.mpos.ApplyPlan
import hyi.pos.entity.mpos.MemberBase
import hyi.pos.entity.mpos.MemberCard
import hyi.pos.entity.mpos.Model注册
import hyi.pos.entity.mpos.MposCardDtl
import hyi.pos.entity.mpos.MposCashier
import hyi.pos.entity.mpos.MposDiffSalesOrder
import hyi.pos.entity.mpos.MposDiningArea
import hyi.pos.entity.mpos.MposDiningTable
import hyi.pos.entity.mpos.MposItemSet
import hyi.pos.entity.mpos.MposJshopTranflow
import hyi.pos.entity.mpos.MposJshopTranpay
import hyi.pos.entity.mpos.MposJshopTransaction
import hyi.pos.entity.mpos.MposLineItem
import hyi.pos.entity.mpos.MposO2oPayDtl
import hyi.pos.entity.mpos.MposSalesOrder
import hyi.pos.entity.mpos.MposServerCommand
import hyi.pos.entity.mpos.MposShift
import hyi.pos.entity.mpos.MposShiftReport
import hyi.pos.entity.mpos.MposTakeOutTranflow
import hyi.pos.entity.mpos.MposTakeOutTransaction
import hyi.pos.entity.mpos.MposTicketDtl
import hyi.pos.entity.mpos.MposTransactionTender
import hyi.pos.entity.mpos.MposTrantaste
import hyi.pos.entity.mpos.PointExItem
import hyi.pos.entity.mpos.Ticket
import hyi.pos.entity.mpos.Voucher
import hyi.pos.pay.PayUtil
import hyi.pos.pay.einvoice.EInvoiceUtil
import hyi.pos.pay.member.MemberDao
import hyi.pos.pay.member.MemberUtil
import hyi.pos.print.PrintServer
import hyi.pos.entity.mpos.MposTransaction
import org.apache.log4j.PropertyConfigurator
import java.lang.reflect.Type
import java.sql.ResultSet
import java.sql.Types
import java.text.SimpleDateFormat
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
/**
* App Server for mobile POS app.
*
* Start up command:
* java -jar app_server.jar
*
* To Peeping Tom: Don't mess up my code :)
*
* @author Bruce You
* @since 2012/12/12
*/
@Log4j
class AppServer{
static final def VERSION= '1.5.6'
static int APP_SERVER_PORT= 3160
static final def COLUMN_VALUE_SEPARATOR= '¦' // Pipe, Broken vertical bar
static PushServer pushServer
static ServerSocket server
static String transDirInConf
static String dbType
static String TABLE_PREFIX
static String serverType
/** Directory where device will upload its files that are going to get processed. */
static String uploadDir
static def dbConf
static Lock lock= new ReentrantLock()
static masterVersion= ""
/**
* Dining table state transition rules in STL (State Transition Language).
* Example:
*
* stl = '0空桌 -> 1点餐中 <-> 2已点餐 <-> 3结账中 -> 4已结账 & 清桌中 -> 0空桌'
*
*
* The stlMap will be:
*
* [0:1, 1:2, 2:13, 3:24, 4:0]
*
* The key is the source state, the value is the states to which could be transferred.
*/
static stlMap= [:]
/**
* Create server socket and listen on port 3160.
*/
static void serverLoop() {
dbConf= new ConfigSlurper().parse(new File('conf/db.properties').toURI().toURL())
server= new ServerSocket(APP_SERVER_PORT)
log.info"App server starts up (Ver ${VERSION} port=${APP_SERVER_PORT})..."
println"App server starts up (Ver ${VERSION} port=${APP_SERVER_PORT})..."
getUploadDir2()
for (; ;) {
server.accept{ Socket socket ->
try {
socket.setSoTimeout(dbConf.readTimeOut ?:67000)
protocolLoop(socket)
} catch (Throwable e) {
log.warn'serverLoop> Server failed', e
}
}
}
}
static Gson createGson() {
new GsonBuilder().setDateFormat('yyyy-MM-dd HH:mm:ss.SSS').create()
}
//static String readUtf8Line(InputStream inputStream) {
// new BufferedReader(new InputStreamReader(inputStream, "UTF-8")).readLine()
//}
static String readLine(InputStream inputStream) throws IOException{
//StringBuilder line = new StringBuilder(40);
def byteBuffer= new ByteArrayOutputStream()
boolean foundTerminator= false;
while (true) {
int nextByte= inputStream.read();
switch (nextByte) {
case -1:
//if (line.length() == 0 && !foundTerminator) {
if (byteBuffer.size() == 0 && !foundTerminator) {
return null;
}
//return line.toString();
return byteBuffer.toString('UTF-8')
case /*(byte) '\r'*/ 0x0d:
if (foundTerminator) {
((PushbackInputStream) inputStream).unread(nextByte);
//return line.toString();
return byteBuffer.toString('UTF-8')
}
foundTerminator= true;
/* Have to be able to peek ahead one byte */
if (!(inputStream.getClass() == PushbackInputStream.class)) {
inputStream= new PushbackInputStream(inputStream);
}
break;
case /*(byte) '\n' */ 0x0a:
//return line.toString();
return byteBuffer.toString('UTF-8')
default:
if (foundTerminator) {
((PushbackInputStream) inputStream).unread(nextByte);
//return line.toString();
return byteBuffer.toString('UTF-8')
}
//line.append((char) nextByte);
byteBuffer.write(nextByte)
}
}
}
/**
* Server-side protocol handler dispatcher.
*/
static void protocolLoop(Socket socket) {
log.info"Device connect: ${socket.remoteSocketAddress}"
socket.withStreams{ InputStream input, OutputStream output ->
def command
//def deviceId = ''
def storeIdAndDeviceId= ''
while ((command= readLine(input)) != null) {
try {
storeIdAndDeviceId= processCommand(socket, input, output, command)
} catch (Exception e) {
log.error("AppServer", e)
} finally {
// in case of unwritten data exists
output.flush()
}
}
log.info"[${storeIdAndDeviceId}]Device disconnect: ${socket.remoteSocketAddress}"
}
}
static String processCommand(socket, input, output, command) {
PrintWriter out= new PrintWriter(socket.getOutputStream());
//BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
log.info"Server received: $command"
System.out.println"Server received: $command"
if (command.startsWith('ok'))
return ''
/*// Command format: {command} {store_id}_{device_id} [arguments...]
if (command.startsWith('ruok')) {
//心跳
output << 'ok\n'
return ''
}*/
if (command.startsWith('generateMaster')) {//主档制作
def args= command.split(/\s/)
def s= ''
if (args.size() > 1) {
s= args[1]
}
log.info"Response: ok"
MposMasterCopy.main(s== '' ?null : s)
if (MposMasterCopy.ok) {
log.info"MposMasterCopy: ok"
output<< 'ok\n'
} else {
log.info"MposMasterCopy: ng"
output<< 'ng\n'
}
return '' // finish this session immediately
}
def args= command.split(/\s/)
/*if (args.length < 2)
return ''*/
def storeIdAndDeviceId= args[1]
def storeIdAndDeviceIdArray= storeIdAndDeviceId.split(/_/)
if (storeIdAndDeviceIdArray.length< 2) {
log.error("Cannot process command: \"${command}\", store_id or device_id is missed.")
return ''
}
def storeId= storeIdAndDeviceIdArray[0]
//deviceId在pos server上是机号,在后台server上是客户编号
def deviceId= storeIdAndDeviceIdArray[1]
//会员和支付时是pos直连后台server,需要客户编号
def custId= storeIdAndDeviceIdArray.length> 2 ? storeIdAndDeviceIdArray[2] :''
switch (command) {
case ~/DownLoad\s.*/:
def tableName= args[2];
if (tableName.equals('end')) {
out.println('end');
out.flush();
break;
} else {
File file= dumpTable storeId, deviceId, tableName
FileInputStream fis= new FileInputStream(file);
File files= new File("D:\\JAVA\\TabletPos\\mobilepos\\appclient\\tmp")
FileOutputStream fos= new FileOutputStream(new File(files));
byte[] buffer= new byte[4096];
int c= 0;
while ((c= fis.read(buffer)) != -1) {
for (int i= 0; i< c; i++)
fos.write(buffer[i]);
System.out.println(c);
}
fos.close();
fis.close();
out.println(files.absolutePath);
out.flush();
break;
}
case ~/getTable\s.*/:
def tableName= args[2]
if (args.size() > 2) {
def columnName= args[3]
def keyName= args.size() > 4 ? args[4] :""
doGetTable storeId, deviceId, columnName, tableName, keyName, output, input
} else
doGetTable storeId, deviceId, tableName, output, input
break
case ~/getFile\s.*/:
//TODO: 根據店号决定如何找到这个文件
if (args.size() < 3) {
doGetFile2 storeId, deviceId, output, input
} else {
def getFile= args[2] as File
doGetFile storeId, deviceId, getFile, output, input
}
break
case ~/putFile\s.*/:
//TODO: 根據店号决定这个文件的路径
def putFile= args[2] as File
doPutFile storeId, deviceId, putFile, output, input
break
case ~/putObject\s.*/:
def objectClassName= args[2]
def objectClass=
objectClassName.endsWith('.MposDiningTable') ? MposDiningTable :
objectClassName.endsWith('.MposSalesOrder') ? MposSalesOrder :
objectClassName.endsWith('.MposItemSet') ? MposItemSet :
objectClassName.endsWith('.MposTransaction') ? MposTransaction :
objectClassName.endsWith('.MposShift') ? MposShift :
objectClassName.endsWith('.MposShiftReport') ? MposShiftReport :
objectClassName.endsWith('.MposServerCommand') ? MposServerCommand :
//objectClassName.endsWith('.Pos_shift') ? Pos_shift :
//objectClassName.endsWith('.Pos_tranflow') ? Pos_tranflow :
//objectClassName.endsWith('.Pos_tranhead') ? Pos_tranhead :
//objectClassName.endsWith('.Pos_tranpay') ? Pos_tranpay :
//objectClassName.endsWith('.Tc_Shift') ? Tc_Shift :
(objectClassNameas Class)
def numOfObjects= args[3].toInteger()
doPutObject storeId, deviceId, objectClass, numOfObjects, output, input
break
case ~/putFile2\s.*/:
putFile2 storeId, deviceId, output, input
break
//case ~/deleteObject\s.*/:
// def objectClassName = args[2]
// def objectClass =
// objectClassName.endsWith('.MposDiningTable') ? MposDiningTable :
// objectClassName.endsWith('.MposSalesOrder') ? MposSalesOrder :
// (objectClassName as Class)
// def numOfObjects = args[3].toInteger()
// doDeleteObject storeId, deviceId, objectClass, numOfObjects, output, input
// break
case ~/putObject2\s.*/:
doPutObject2 storeId, deviceId, args[2], args[3], args[4], output, input
break
case ~/uploadLog\s.*/:
doUpLog storeId,deviceId,output,input
break
case ~/getObject\s.*/:
def objectClassName= args[2]
def objectClass=
objectClassName.endsWith('.MposDiningArea') ? MposDiningArea :
objectClassName.endsWith('.MposSalesOrder') ? MposSalesOrder :
objectClassName.endsWith('.MposTransaction') ? MposTransaction :
objectClassName.endsWith('.MposShiftReport') ? MposShiftReport :
(objectClassNameas Class)
def argument=
objectClass== MposSalesOrder ? args[3] :// 如果要查詢点单数据,client端会带上桌子id
objectClass== MposTransaction ? args[3] :// 如果要查詢历史交易,client端会带上桌子代号
objectClass== MposShiftReport ? args[3] :// 如果要查詢交班报表,client端会带上日期
null
doGetObject storeId, deviceId, objectClass, argument, output, input
break
case ~/getPosVersion\s.*/:
doGetPosVersion storeId, deviceId, output, input
break
case ~/getApkVersion\s.*/:
doGetApkVersion storeId, deviceId, output, input
break
case ~/ruok\s.*/:
String masterVersion= ""
try {
String masterJosnData= ([serverType== 'HQ' ?"db/${custId}/${storeId}/master.json" :"db/master.json"] as File).text
masterVersion= masterJosnData.split("\n")[2].split("\":\"")[1].substring(0,19)//本地master版本
} catch (Exception e) {}
output<< "ok_${masterVersion}\n"
def date= null
if (args.length> 4) {
date= "${args[4]} ${args[5]}"
}
upPosVersion custId, storeId, deviceId, args[2], args[3], date, output, input
break
case ~/getMasterVersion\s.*/:
doGetMasterVersion storeId, deviceId, output, input
break
case ~/checkSellOff\s.*/:
def pluno= args[2]
checkSellOff storeId, deviceId, pluno, output, input
break
case ~/getTransaction\s.*/:
def flowno= args[2]
getTransaction storeId, deviceId, flowno, output, input
break
case ~/getTransactionInfos\s.*/:
def diningTableCode= args[2]
getTransactionInfos storeId, deviceId, diningTableCode, output, input
break
case ~/getTransactionsAndShifts\s.*/:
def startDate= args[2]
def endDate= args[3]
getTransactionsAndShifts custId, storeId, deviceId, startDate, endDate, output, input
break
case ~/getDiffSalesOrders\s.*/:
def period= args[2]
getDiffSalesOrders deviceId, period, output, input
break
case ~/getMposItemSets\s.*/:
def period= args[2]
getMposItemSets storeId, deviceId, period, output, input
break
case ~/getPlatformOrders\s.*/:
String uploadFlag= args[2]
getPlatformOrders storeId, uploadFlag, output, input
break
case ~/platformOrderUpdate\s.*/:
String flowno= args[2]
String flag= args[3]
platformOrderUpdate storeId, flowno, flag, output, input
break
case ~/kitchenPlayUpdate\s.*/:
def id= args[2]
kitchenPlayUpdate id, output, input
break
case ~/putCombineTable\s.*/:
putCombineTable storeId, deviceId, output, input
break
case ~/putSplitTable\s.*/:
putSplitTable storeId, deviceId, output, input
break
case ~/getSalesOrders\s.*/:
def diningTableIds= args[2]
getSalesOrders storeId, deviceId, diningTableIds, output, input
break
case ~/o2oPay\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
def data= args[2]
getO2oPay custId, storeId, deviceId, data, output, input
break
case ~/getMember\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
def data= args[2]
getMember custId, storeId, deviceId, data, output, input
break
case ~/getMemberCard\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
def data= args[2]
getMemberCard custId, storeId, deviceId, data, output, input
break
case ~/weiXinOpenMemberCard\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
weiXinOpenMemberCard custId, storeId, args[2], args[3], args[4], args[5], args[6], output, input
break
case ~/bindEntityCard\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}//custId, storeno, memberno, idCode, telNo, OutputStream output, InputStream input
bindEntityCard custId, storeId, args[2], args[3], args[4], output, input
break
case ~/registVerify\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
registVerify custId, storeId, deviceId, args[2], args[3], args.length> 4 ? args[4] :'', output, input
break
case ~/openMemberCard\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
openMemberCard custId, storeId, deviceId, args[2], args[3], args[4], args[5], output, input
break
case ~/changeMemberCard\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
changeMemberCard custId, storeId, deviceId, args[2], args[3], args[4], args[5], output, input
break
case ~/updateVipPwd\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
updateVipPwd custId, storeId, deviceId, args[2], args[3], args[4], args[5], output, input
break
case ~/updateMenberPoins\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
updateMenberPoins custId, storeId, deviceId, args[2], args[3], args[4], args[5], output, input
break
case ~/getApplyPlan\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
getApplyPlan custId, storeId, deviceId, output, input
break
case ~/getPointExItem\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
getPointExItem custId, storeId, deviceId, args[2], output, input
break
case ~/apply\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
apply custId, storeId, deviceId, args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], output, input
break
case ~/applyReturn\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
applyReturn custId, storeId, deviceId, args[2], args[3], args[4], args[5], args[6], output, input
break
case ~/getVoucher\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
getVoucher custId, storeId, deviceId, args[2], output, input
break
case ~/getReturnAmount\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
getReturnAmount custId, storeId, deviceId, args[2], args[3], output, input
break
case ~/pay\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
pay custId, storeId, deviceId, args[2], args[3], args[4], output, input
break
case ~/pay2\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
pay2 custId, storeId, deviceId, args[2], args[3], args[4], output, input
break
case ~/integral\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
integral(custId, storeId, deviceId, output, input)
break
case ~/integralToMoney\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
integralToMoney(custId, storeId, deviceId, args[2], args[3], output, input)
break
case ~/getTicket\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
getTicket custId, storeId, deviceId, args[2], output, input
break
case ~/loseCard\s.*/:
if (!custId) {
log.error("Cannot process command: \"${command}\", custId is missed.")
break
}
loseCard custId, storeId, deviceId, args[2], args[3], args[4], output, input
case ~/getAccDate\s.*/:
String accDate= getAccDate(storeId)
log.info("${storeId} accDate = ${accDate}")
output<< "${accDate}\n"
break
case ~/updateAccDate\s.*/:
updateAccdate(args[2], args[3], args[4], args[5], storeId, custId)
break
case ~/notice\s.*/:
(new NoticeProcess()).process(input, output, storeId, deviceId, args)
break
case ~/getEInvoice\s.*/:
getEInvoice(custId, storeId, deviceId, args.length> 2 ? args[2] :'', output, input)
break
case ~/checkObject\s.*/:
def objectClassName= args[2]
def objectClass=
objectClassName.endsWith('.MposDiningTable') ? MposDiningTable :
(objectClassNameas Class)
doCheckObject storeId, deviceId, objectClass, output, input
break
case ~/updateMemberMemo4\s.*/:
updateMemberMemo4 custId, storeId, deviceId, args[2], args[3], output, input
break
default:
output<< "Response: ${command}\n"
}
return storeIdAndDeviceId
}
static void doUpLog(storeId,deviceId,OutputStream output,InputStream input) {
DataInputStream dataInputStream= new DataInputStream(input);
File file= new File("log\\" + storeId+ "-" + deviceId);
/* if (!file.exists()){
file.mkdir();
}*/
FileOutputStream fileOutputStream1= new FileOutputStream(file);
byte[] bytes= new byte[51200];
int length= 0;
while ((length= dataInputStream.read(bytes)) != -1) {
fileOutputStream1.write(bytes,0,length);
fileOutputStream1.flush();
}
fileOutputStream1.close();
dataInputStream.close();
}
static void doCheckObject(storeId, deviceId, objectClass, OutputStream output, InputStream input) {
log.info"[${storeId}_${deviceId}]Going to get ${objectClass.toString()}objects"
String objectsInJSON= readLine(input)
log.info"[${storeId}_${deviceId}]Receive: ${objectsInJSON}"
def gson= createGson()
if (objectClass== MposDiningTable) { // 桌子状态更新上传
Type collectionType= new TypeToken>(){}.getType()
List diningTables= gson.fromJson(objectsInJSON, collectionType)
def connSrc= getDbConnection(false)
def dao= DaoManager.createDao(connSrc, MposDiningTable)
def errResponse= checkDiningTableState(dao, diningTables)
if (errResponse) {
output<< errResponse+ "\n"
log.info"[${storeId}_${deviceId}]Send: $errResponse"
return
}
}
output<< 'ok\n'
log.info"[${storeId}_${deviceId}]Send: ok"
}
//下单时检查桌子是否是空桌
static String checkDiningTableState(Dao dao, List diningTables) {
for (diningTablein diningTables) {
def origDiningTable= dao.queryForId(diningTable.fId)
def sourceState= origDiningTable.state
def targetState= diningTable.state
if (sourceState!= targetState) {
// reject the transition
def response= "ng Reject the dinging table state from $sourceState to $targetState"
return response
}
}
return null
}
//更新营业日期
static void updateAccdate(accdate, shiftNumber, begFlowNo, endFlowNo, storeId, custId) {
log.info("updateAccdate ${accdate} ${shiftNumber} ${begFlowNo} ${endFlowNo} ${storeId}")
def transDb= getDbConnection(false)
def tdao= DaoManager.createDao(transDb, MposTicketDtl)
tdao.callBatchTasks{
UpdateBuilder tupdateBuilder= tdao.updateBuilder()
tupdateBuilder.updateColumnValue('Accdate', accdate).where().eq('custId', custId).and().eq('WarehouseID', storeId).and().between('Flowno', begFlowNo, endFlowNo)
tupdateBuilder.update()
def odao= DaoManager.createDao(transDb, MposO2oPayDtl)
UpdateBuilder oupdateBuilder= odao.updateBuilder()
oupdateBuilder.updateColumnValue('Accdate', accdate).where().eq('custId', custId).and().eq('Warehouseid', storeId).and().between('Flowno', begFlowNo, endFlowNo)
oupdateBuilder.update()
def cdao= DaoManager.createDao(transDb, MposCardDtl)
UpdateBuilder cupdateBuilder= cdao.updateBuilder()
cupdateBuilder.updateColumnValue('Accdate', accdate).where().eq('custId', custId).and().eq('Warehouseid', storeId).and().between('Flowno', begFlowNo, endFlowNo)
cupdateBuilder.update()
def ldao= DaoManager.createDao(transDb, MposLineItem)
UpdateBuilder iupdateBuilder= ldao.updateBuilder()
iupdateBuilder.updateColumnValue('AccDate', accdate).where().eq('custId', custId).and().eq('WarehouseID', storeId).and().between('flowno', begFlowNo, endFlowNo)
iupdateBuilder.update()
def ttdao= DaoManager.createDao(transDb, MposTransactionTender)
UpdateBuilder ttupdateBuilder= ttdao.updateBuilder()
ttupdateBuilder.updateColumnValue('Accdate', accdate).where().eq('custId', custId).and().eq('WarehouseID', storeId).and().between('flowno', begFlowNo, endFlowNo)
ttupdateBuilder.update()
def tsdao= DaoManager.createDao(transDb, MposTransaction)
UpdateBuilder tstupdateBuilder= tsdao.updateBuilder()
tstupdateBuilder.updateColumnValue('Accdate', accdate).where().eq('custId', custId).and().eq('Warehouseid', storeId).and().between('Flowno', begFlowNo, endFlowNo)
tstupdateBuilder.update()
def dao= DaoManager.createDao(transDb, MposShiftReport)
UpdateBuilder updateBuilder= dao.updateBuilder()
updateBuilder.updateColumnValue('Accdate', accdate).where().eq('custId', custId).and().eq('warehouseId', storeId).and().eq('flowno', shiftNumber)
updateBuilder.update()
def sao= DaoManager.createDao(transDb, MposShift)
UpdateBuilder supdateBuilder= sao.updateBuilder()
supdateBuilder.updateColumnValue('fAccDate',new SimpleDateFormat('yyyy-MM-dd').parse(accdate)).where().eq('custId', custId).and().eq('warehouseId', storeId).and().eq('fShift', shiftNumber)
supdateBuilder.update()
}
}
/**
* 挂失/解挂
* 接收
* idCode 卡识别号
* type 状态(1:挂失,2:解挂)
* 返回
* ok 挂失/解挂成功
* ng 挂失/解挂失败
*/
static void loseCard(custId, storeId, deviceId, idCode, type, cashierNumber, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]Going to get loseCard of ${idCode} ${type}"
def connSrc= getDbConnection()
String result= MemberUtil.loseCard(custId, idCode, type, cashierNumber, connSrc)
output<< "${result}"
}
/**
* 通过礼劵编号查询
* 接收
* code 礼劵编号
*
* 返回
* Ticket对象, Ticket对象包含TicketBatch
*/
static void getTicket(custId, storeId, deviceId, code, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]Going to get getTicket of ${code}"
def connSrc= getDbConnection()
Ticket ticket= MemberDao.queryTicketByCode(custId, code, connSrc)
def gson= createGson()
def json= gson.toJson(ticket)
output<< json
output<< '\n'
output.flush()
log.info"[${custId}_${storeId}_${deviceId}]Send ${Ticket.simpleName}: ${json}"
def response= readLine(input)
if (response)
log.info"[${custId}_${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${custId}_${storeId}_${deviceId}]Client disconnected."
}
/**
* 礼券消费扣款
* 接收
* code 礼券编号
* amount 扣款金额,礼券允许多次使用时填要扣的金额,如果是一次性则填0
* cashierNumber 操作员
* transactions 交易数据
*
* 返回
* ok_XX 扣款成功,XX表示扣款金额,允许溢收
* ng 扣款失败,数据插入失败
* noUse 扣款失败,不满足扣款条件
* Ticket 礼券不存在
* status_8 礼券已注销
*
*/
static void pay2(custId, storeId, deviceId, code, amount, cashierNumber, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}] pay2 ${code}"
String objectsInJSON= readLine(input)
log.info"[${custId}_${storeId}_${deviceId}]Receive: ${objectsInJSON}"
Type collectionType= new TypeToken>() {}.getType()
def gson= createGson()
List transactions= gson.fromJson(objectsInJSON, collectionType)
if (transactions) {
def connSrc= getDbConnection()
String result= MemberUtil.pay2(custId, storeId, code, amountas BigDecimal, transactions.get(0), cashierNumber, connSrc)
output<< "${result}"
} else {
output<< 'ng\n'
}
}
/**
* 会员储值卡消费扣款
* 接收
* idCode 卡识别卡号
* amount 扣款金额,退金额填负数
* cashierNumber 操作员
* transactions 交易数据
*
* 返回
* ok 扣款成功
* ng 扣款失败,数据插入失败
* Member 扣款失败,找不到会员卡/会员钱包/钱包使用规则
* noUse 扣款失败,不满足扣款条件
* noBalance 余额不足
*/
static void pay(custId, storeId, deviceId, idCode, amount, cashierNumber, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}] pay ${idCode} ${amount} "
String objectsInJSON= readLine(input)
log.info"[${custId}_${storeId}_${deviceId}]Receive: ${objectsInJSON}"
Type collectionType= new TypeToken>() {}.getType()
def gson= createGson()
List transactions= gson.fromJson(objectsInJSON, collectionType)
if (transactions) {
def connSrc= getDbConnection()
String result= MemberUtil.pay(custId, storeId, idCode, amountas BigDecimal, transactions.get(0), cashierNumber, connSrc)
output<< "${result}"
} else {
output<< 'ng\n'
}
}
/**
* 计算积分
*
* 返回
* 本次积分或0(0积分或计算积分失败)
*/
static void integral(custId, storeId, deviceId, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}] integral "
String objectsInJSON= readLine(input)
log.info"[${custId}_${storeId}_${deviceId}]Receive: ${objectsInJSON}"
Type collectionType= new TypeToken>() {}.getType()
def gson= createGson()
List transactions= gson.fromJson(objectsInJSON, collectionType)
if (transactions) {
def connSrc= getDbConnection()
String result= MemberUtil.integral(custId, storeId, transactions.get(0), connSrc)
output<< "${result}"
} else {
output<< '0\n'
}
}
/**
* 积分抵扣
* 接收
* vipNo 会员号或手机号
* inputMoney 输入的抵扣金额
* transactions 交易数据
*
* 返回
* ok 支付成功
* ng 支付失败ø
* noIntegral 积分不足
*/
static void integralToMoney(custId, storeId, deviceId, vipNo, inputMoney, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}] integralToMoney "
String objectsInJSON= readLine(input)
log.info"[${custId}_${storeId}_${deviceId}]Receive: ${objectsInJSON}"
Type collectionType= new TypeToken>() {}.getType()
def gson= createGson()
List transactions= gson.fromJson(objectsInJSON, collectionType)
if (transactions) {
def connSrc= getDbConnection()
String result= MemberUtil.integralToMoney(custId, storeId, vipNo, inputMoney, transactions.get(0), connSrc)
output<< "${result}"
} else {
output<< 'ng\n'
}
}
/**
* 获取会员可退金额
* 接收
* idCode 卡识别卡号
* eWalletType 钱包类型
*
* 返回
* ok_XX 获取可退金额成功,XX表示可退金额
* ng 获取可退金额失败,数据插入失败
*
*/
static void getReturnAmount(custId, storeId, deviceId, idCode, eWalletType, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}] getReturnAmount ${idCode} ${eWalletType}"
def connSrc= getDbConnection()
String result= MemberUtil.getReturnAmount(custId, idCode, eWalletType, connSrc)
output<< "${result}"
}
/**
* 通过交易号查询会员充值凭证
* 接收
* flowNo 交易号
*
* 返回
* Voucher对象, Voucher对象中包含List
*/
static void getVoucher(custId, storeId, deviceId, flowNo, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]Going to get getVoucher of ${flowNo}"
def connSrc= getDbConnection()
Voucher voucher= MemberDao.queryVoucherByFlowNo(custId, storeId, flowNo, connSrc)
def gson= createGson()
def json= gson.toJson(voucher)
output<< json
output<< '\n'
output.flush()
log.info"[${custId}_${storeId}_${deviceId}]Send ${Voucher.simpleName}: ${json}"
def response= readLine(input)
if (response)
log.info"[${custId}_${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${custId}_${storeId}_${deviceId}]Client disconnected."
}
/**
* 会员充值/充值退款
* 接收
* idCode 卡识别卡号
* eWalletType 钱包类型
* planNo 充值方案编号,如果是手输金额或退款,则填0即可
* payment 支付代号:支付金额金额,多种支付方式用英文逗号隔开,例如【A:100,B:100】 退款时金额加负号
* amount 充值总金额/充值总次数 退款时金额加负号
* unitPrice 计次钱包充值时,带上单价,其它情况填0即可
* flowNo pos交易序号
*
* 返回
* ok_XX 充值成功,XX表示充值凭证编号
* ng 充值失败,数据插入失败
* Member 充值失败,找不到会员卡/会员钱包/钱包使用规则
* charge 充值失败,钱包不允许充值
* cardStatus_XX 充值失败,会员卡或会员钱包不可用, XX表示卡或钱包状态
*/
static void apply(custId, storeId, deviceId, idCode, eWalletType, planNo, payment, amount, unitPrice, cashierNumber, flowNo, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}] apply ${idCode} ${eWalletType} ${planNo} ${amount} ${unitPrice} ${flowNo}"
def connSrc= getDbConnection()
String result= MemberUtil.apply(custId, storeId, deviceId, idCode, eWalletType, planNo, payment, amount, unitPrice, cashierNumber, flowNo, connSrc)
output<< "${result}\n"
}
/**
* 会员充值退货
* 接收
* payment 支付代号:支付金额金额,多种支付方式用英文逗号隔开,例如【A:100,B:100】 退款时金额加负号
* amount 充值总金额/充值总次数 退款时金额加负号
* flowno 充值退货的交易号
* rtnFlowno 原充值交易号
* 返回
* ok_XX 充值退货成功,XX表示充值凭证编号
* ng 充值退货失败,数据插入失败
* Member 充值退货失败,找不到会员卡/会员钱包/钱包使用规则
* Balance 充值退货失败,钱包余额不够
*/
static void applyReturn(custId, storeId, deviceId, payment, amount, cashierNumber, flowno, rtnFlowno, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}] applyReturn ${payment} ${amount} ${flowno} ${rtnFlowno}"
def connSrc= getDbConnection()
String result= MemberUtil.applyReturn(custId, storeId, deviceId, payment, amount, cashierNumber,flowno, rtnFlowno, connSrc)
output<< "${result}\n"
}
/**
* 获取会员充值方案
*
* 返回
* List
*/
static void getApplyPlan(custId, storeId, deviceId, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}] getApplyPlan"
def connSrc= getDbConnection()
List applyPlanList= MemberDao.queryApplyPlan(custId, storeId, connSrc)
def gson= createGson()
def json= gson.toJson(applyPlanList)
output<< json
output<< '\n'
output.flush()
log.info"[${custId}_${storeId}_${deviceId}]Send ${MemberCard.simpleName}: ${json}"
def response= readLine(input)
if (response)
log.info"[${custId}_${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${custId}_${storeId}_${deviceId}]Client disconnected."
}
/**
* 获取积分兑换方案
*
* 返回
* List
*/
static void getPointExItem(custId, storeId, deviceId, point, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId} ${point}] getApplyPlan"
def connSrc= getDbConnection()
List pointExItem= MemberDao.queryPointExItem(Integer.valueOf(point), connSrc)
def gson= createGson()
def json= gson.toJson(pointExItem)
output<< json
output<< '\n'
output.flush()
log.info"[${custId}_${storeId}_${deviceId}]Send ${MemberCard.simpleName}: ${json}"
def response= readLine(input)
if (response)
log.info"[${custId}_${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${custId}_${storeId}_${deviceId}]Client disconnected."
}
/**
* 会员换卡
* 接收
* oldIdCode 旧卡识别卡号
* idCode 新卡识别卡号
*
* 返回
* ok 换卡成功
* password 换卡失败,密码错误
* ng 换卡失败,数据插入失败
* OldMemberCard 换卡失败,旧卡不存在
* cardStatus_XX 换卡失败,新会员卡已经存在, XX表示卡状态
*/
static void changeMemberCard(custId, storeId, deviceId, oldIdCode, idCode, password, cashierNumber, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]changeMemberCard ${oldIdCode} ${idCode} ${cashierNumber}"
def connSrc= getDbConnection()
//换卡
int result= MemberUtil.changeMemberCard(custId, storeId, oldIdCode, idCode, password, cashierNumber, connSrc)
if (result== 0) {
log.info"[${custId}_${storeId}_${deviceId}] changeMemberCard ok."
output<< 'ok\n'
} else if (result== -1) {
log.info"[${custId}_${storeId}_${deviceId}] changeMemberCard ng."
output<< 'ng\n'
} else if (result== -2) {
log.info"[${custId}_${storeId}_${deviceId}] changeMemberCard password error."
output<< 'password\n'
} else if (result== 1) {
log.info"[${custId}_${storeId}_${deviceId}] changeMemberCard old MemberCard null."
output<< 'OldMemberCard\n'
} else {
int cardStatus= result- 2
log.info"[${custId}_${storeId}_${deviceId}] changeMemberCard new memberCard.cardStatus = ${cardStatus}."
output<< "cardStatus_${result}\n"
}
}
/**
* 修改会员密码
* 接收
* oldIdCode 旧卡识别卡号
* newPwd 新密码
*
* 返回
* ok 修改成功
* password 修改失败,密码错误
* ng 修改失败,数据插入失败
* OldMemberCard 修改失败,卡号不存在
*/
static void updateVipPwd(custId, storeId, deviceId, oldIdCode, newPwd, password, cashierNumber, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]updateVipPwd ${oldIdCode} ${newPwd} ${cashierNumber}"
def connSrc= getDbConnection()
//修改会员密码
int result= MemberUtil.updateVipPwd(custId, storeId, oldIdCode, newPwd, password, cashierNumber, connSrc)
if (result== 0) {
log.info"[${custId}_${storeId}_${deviceId}] updateVipPwd ok."
output<< 'ok\n'
} else if (result== -1) {
log.info"[${custId}_${storeId}_${deviceId}] updateVipPwd ng."
output<< 'ng\n'
} else if (result== -2) {
log.info"[${custId}_${storeId}_${deviceId}] updateVipPwd password error."
output<< 'password\n'
} else {
log.info"[${custId}_${storeId}_${deviceId}] updateVipPwd old updateVipPwd null."
output<< 'OldMemberCard\n'
}
}
/**
* 修改会员积分
* 接收
* oldIdCode 卡识别卡号
*
* 返回
* ok 修改成功
* ng 修改失败,数据插入失败
*/
static void updateMenberPoins(custId, storeId, deviceId, point, vipNo, cashierNumber, flowNo, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]updateVipPwd ${point} ${vipNo} ${cashierNumber}"
def connSrc= getDbConnection()
//修改会员积分
int result= MemberUtil.updateMenberPoins(custId, storeId, point, vipNo, cashierNumber, flowNo, connSrc)
if (result== 0) {
log.info"[${custId}_${storeId}_${deviceId}] updateVipPwd ok."
output<< 'ok\n'
} else {
log.info"[${custId}_${storeId}_${deviceId}] updateVipPwd old updateVipPwd null."
output<< 'ng\n'
}
}
/**
* 修改会员支付凭证
* 接收
* memberno 会员事情
* memo4 支付凭证
*
* 返回
* ok 修改成功
* ng 修改失败,数据插入失败
*
*/
static void updateMemberMemo4(custId, storeId, deviceId, memberno, memo4, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]updateMemberMemo4 ${memberno} ${memo4} "
def connSrc= getDbConnection()
MemberBase memberBase= MemberDao.queryMemberByMemberNo(custId, memberno, connSrc)
if (memberBase) {
log.info"[${custId}_${storeId}_${deviceId}]updateMemberMemo4 memberBase"
memberBase.memo4= memo4
if (MemberDao.updateMemberIntegral(memberBase, connSrc)) {
output<< 'ok\n'
return
}
}
output<< 'ng\n'
return
}
/**
* 微信会员开卡
* 接收
* memberno 会员ID(微信识别码)
* idCode 微信会员卡编号
* chipNumber 微信会员卡code
* telNo 联系电话
* memName 姓名
* sex 性别
* birthdate 生日
*
* 返回
* ok 开卡成功
* ng 开卡失败,数据插入失败
* EWallet 开卡失败,后台未设置钱包规则
* cardStatus_XX 开卡失败,会员卡已经存在, XX表示卡状态
*
*/
static void weiXinOpenMemberCard(custId, storeno, memberno, idCode, chipNumber, telNo, memName, sex, birthdate, OutputStream output, InputStream input) {
log.info"[${custId}_${storeno}_${memberno}]weiXinOpenMemberCard ${idCode} ${telNo} ${memName} ${sex} ${birthdate}"
def connSrc= getDbConnection()
//开卡
def isDoubleMember= dbConf.isDoubleMember ?:'1'
int result= MemberUtil.weiXinOpenMemberCard custId, storeno, memberno, idCode, chipNumber, telNo, memName, sex, birthdate, isDoubleMember, connSrc
if (result== 0) {
log.info"[${custId}_${storeno}_${memberno}] weiXinOpenMemberCard ok."
output<< 'ok\n'
} else if (result== 1) {
log.info"[${custId}_${storeno}_${memberno}] weiXinOpenMemberCard EWallet null."
output<< 'EWallet\n'
} else if (result== -2) {
log.info"[${custId}_${storeno}_${memberno}] weiXinOpenMemberCard member exist."
output<< 'exist\n'
} else if (result== -1) {
log.info"[${custId}_${storeno}_${memberno}] weiXinOpenMemberCard ng."
output<< 'ng\n'
} else {
int cardStatus= result- 2
log.info"[${custId}_${storeno}_${memberno}] weiXinOpenMemberCard memberCard.cardStatus = ${cardStatus}."
output<< "cardStatus_${result}\n"
}
}
/**
* 绑定实体卡
* 接收
* idCode 微信会员卡号
* memberno 会员号
* custId 客户号
* storeno 店号
*
* 返回
* ok 绑定成功
* ng 绑定失败
* noMemberCard 没有找到会员卡
* noMember 没有找到会员
* cardStatus_XX 会员卡状态不正常, XX表示卡状态
* memberStatus_XX 会员状态不正常, XX表示会员状态
*
*/
static void bindEntityCard(custId, storeno, memberno, idCode, OutputStream output, InputStream input) {
log.info"[${custId}_${storeno}_${memberno}]bindEntityCard ${idCode}"
def connSrc= getDbConnection()
//绑定
String result= MemberUtil.bindEntityCard custId, storeno, memberno, idCode, connSrc
output<< "${result}\n"
}
/**
* 注册验证
* 接收
* code 。。(注册)码
* custId 客户号
* storeno 店号
* deviceId 机号
*
* 返回
* ok 验证成功
* ng 验证失败
*
*/
static void registVerify(custId, storeId, deviceId, code, type, layoutCode, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]registVerify ${code} ${type}"
def connSrc= getDbConnection()
//注册申请
if (type== '0') {
try {
def tDao= DaoManager.createDao(connSrc, Model注册)
List lists= tDao.queryBuilder().where().eq('custId', custId).and().eq('Warehouseid', storeId).and().eq('FSYSNO', deviceId).query()
if (lists&& lists.size() > 0) {
Model注册 model注册= lists.get(0)
if (model注册) {
if (model注册.FSYSID== code) {
output<< "ok\n"
return
} else {
output<< "ng\n"
return
}
}
}
lists= tDao.queryBuilder().where().eq('FSYSID', code).query()
if (lists&& lists.size() > 0) {
Model注册 model注册= lists.get(0)
if (model注册) {
if (model注册.custId== custId&& model注册.Warehouseid== storeId&& model注册.FSYSNO== deviceId) {
output<< "ok\n"
return
} else {
output<< "ng\n"
return
}
}
}
List list= tDao.queryForAll()
int maxId= 0
for (Model注册 model注册 : list) {
if (model注册.FSYSNUM> maxId) {
maxId= model注册.FSYSNUM
}
}
maxId++
Model注册 model注册= new Model注册()
model注册.FSYSNUM= maxId
model注册.FSYSNO= deviceId
model注册.FSYSID= code
model注册.FSYSTYPE= 1
model注册.FSYSFLAG= 0
model注册.FMEMO= layoutCode
model注册.FPOSTYPE= layoutCode== 'ls_layout' ?1 :(layoutCode== 'coffe_table_layout' ?2 :(layoutCode== 'food_table_layout' ?3 :0))
model注册.FOPERATOR= ''
model注册.FUPDDATE= new Date()
model注册.custId= custId
model注册.Warehouseid= storeId
tDao.create(model注册)
output<< "ok\n"
} catch (Exception e){
log.error('registVerify failed' , e)
output<< "ng\n"
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
}
} else {
//注册验证
String result= MemberUtil.registVerify custId, storeId, deviceId, code,type, connSrc
output<< "${result}\n"
}
}
/**
* 会员开卡
* 接收
* idCode 识别卡号
* telNo 联系电话
* cashierNumber 操作员
* deposit 押金
*
* 返回
* ok 开卡成功
* ng 开卡失败,数据插入失败
* EWallet 开卡失败,后台未设置钱包规则
* cardStatus_XX 开卡失败,会员卡已经存在, XX表示卡状态
*
*/
static void openMemberCard(custId, storeId, deviceId, idCode, telNo, deposit, cashierNumber, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]createMemberCard ${idCode} ${telNo} ${cashierNumber}"
def connSrc= getDbConnection()
//开卡
def isDoubleMember= dbConf.isDoubleMember ?:'1'
int result= MemberUtil.openMemberCard custId, storeId, idCode, telNo, deposit, isDoubleMember, cashierNumber, connSrc
if (result== 0) {
log.info"[${custId}_${storeId}_${deviceId}] createMemberCard ok."
output<< 'ok\n'
} else if (result== 1) {
log.info"[${custId}_${storeId}_${deviceId}] createMemberCard EWallet null."
output<< 'EWallet\n'
} else if (result== -2) {
log.info"[${custId}_${storeId}_${deviceId}] createMemberCard member exist."
output<< 'exist\n'
} else if (result== -1) {
log.info"[${custId}_${storeId}_${deviceId}] createMemberCard ng."
output<< 'ng\n'
} else {
int cardStatus= result- 2
log.info"[${custId}_${storeId}_${deviceId}] createMemberCard memberCard.cardStatus = ${cardStatus}."
output<< "cardStatus_${result}\n"
}
}
/**
* 根据卡号查询会员卡资料
* 接收
* idCode 卡片识别号
*
* 返回
* MemberCard对象, MemberCard中包含List
*/
static void getMemberCard(custId, storeId, deviceId, idCode, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]Going to get MemberCard of ${idCode}"
def connSrc= getDbConnection()
MemberCard memberCard= MemberDao.queryMemberCardByIdCode2(custId, idCode, connSrc)
def gson= createGson()
def json= gson.toJson(memberCard)
output<< json
output<< '\n'
output.flush()
log.info"[${custId}_${storeId}_${deviceId}]Send ${MemberCard.simpleName}: ${json}"
def response= readLine(input)
if (response)
log.info"[${custId}_${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${custId}_${storeId}_${deviceId}]Client disconnected."
}
/**
* 根据会员号或手机号查询会员资料
* 接收
* data 会员号/手机号 三者一一对应
*
* 返回
* MemberBase对象,MemberBase中包含List
*
*/
static void getMember(custId, storeId, deviceId, data, OutputStream output, InputStream input) {
log.info"[${custId}_${storeId}_${deviceId}]Going to get MemberBase of ${data}"
def connSrc= getDbConnection()
MemberBase memberBase= MemberDao.queryMember(storeId, custId, data, connSrc)
def gson= createGson()
def json= gson.toJson(memberBase)
output<< json
output<< '\n'
output.flush()
log.info"[${custId}_${storeId}_${deviceId}]Send ${MemberBase.simpleName}: ${json}"
def response= readLine(input)
if (response)
log.info"[${custId}_${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${custId}_${storeId}_${deviceId}]Client disconnected."
}
static boolean doGetFile2(storeId, deviceId, OutputStream output, InputStream input) {
def files= ("download/${deviceId}/${storeId}" as File)
if (!files.exists()) {
files.mkdirs()
}
def fs= files.listFiles()
output<< "${fs.size()}\n"
for (File getFile : fs) {
log.info"[${storeId}_${deviceId}]Send file size: ${getFile.length()}"
output<< "${getFile.length()}\n"
log.info"[${storeId}_${deviceId}]Send file name: ${getFile.getName()}"
output<< "${getFile.getName()}\n"
log.info"[${storeId}_${deviceId}]Send file content: $getFile"
def getFileInputStream= null
try {
getFileInputStream= new BufferedInputStream(new FileInputStream(getFile))
copy storeId, deviceId, getFileInputStream, output
} catch (Exception e) {
throw e
} finally {
getFileInputStream?.close()
}
}
def response= readLine(input)
if (response) {
for (File getFile : fs) {
log.info"[${storeId}_${deviceId}]delete file: ${getFile.getName()}"
getFile.delete()
}
log.info"[${storeId}_${deviceId}]Client response: ${response}"
} else
log.info"[${storeId}_${deviceId}]Client disconnected."
return true
}
/**
* Dump a database table.
*
* File format:
* column_name_1/column_type_1,column_name_2/column_type_2,column_name_3/column_type_3,...\n
* column_value_1,column_value_2,column_value_3,...\n
* column_value_1,column_value_2,column_value_3,...\n
* ...
*
* Field type:
* S: String, I: Integer, D: Date, F: Decimal
*/
static File dumpTable(storeId, deviceId, String tableName) {
Sql serverDb= getGroovySql()
try {
// Create temp file
def tempFileDir= new File('tmp')
tempFileDir.mkdir()
def tempFile= File.createTempFile(tableName,'.sql', tempFileDir)
tempFile.withWriter('UTF-8') { writer ->
// Table schema query
def columnCount= 0
def selectSql= dbType== 'MySQL' ?
"select * from ${tableName} limit 1".toString() :
"select top 1 * from ${TABLE_PREFIX}${tableName}".toString()
def hasStoreIdColumn= false
serverDb.query(selectSql) { ResultSet rs ->
columnCount= rs.metaData.columnCount
for (iin 1..columnCount) {
def columnName= rs.metaData.getColumnName(i)
if (columnName== 'store_id')
hasStoreIdColumn= true
writer<< columnName
writer<< '/'
switch (rs.metaData.getColumnType(i)) {
case Types.CHAR:
case Types.VARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
writer<< 'S'
break
case Types.INTEGER:
case Types.BIGINT:
case Types.SMALLINT:
writer<< 'I'
break
case Types.DATE:
case Types.TIMESTAMP:
writer<< 'D'
break
case Types.DECIMAL:
case Types.FLOAT:
case Types.DOUBLE:
writer<< 'F'
break
default:
writer<< 'S'
}
if (i< columnCount)
writer<< ','
}
writer<< '\n'
}
// Table content query
def selectAll= "select * from ${TABLE_PREFIX}${tableName}"
if (hasStoreIdColumn)
selectAll+= " where store_id=${storeId}"
serverDb.eachRow(selectAll.toString()) { row ->
for (iin 0..
writer<< row[i]
if (i< columnCount- 1) {
writer<< COLUMN_VALUE_SEPARATOR
}
}
writer<< '\n'
}
log.info"[${storeId}_${deviceId}]Table dump: $tempFilewas created"
}
return tempFile
} catch (Exception e) {
log.error("[${storeId}_${deviceId}]doGetTable() failed", e)
return null
} finally {
serverDb?.close()
}
}
static void doGetTable(storeId, deviceId, String columnName, String tablename, String keyName,
OutputStream output, InputStream input) {
log.info"[${storeId}_${deviceId}]Going to get ${tablename} ${keyName}"
def connSrc= getDbConnection()
def tDao= DaoManager.createDao(connSrc, MposCashier)
String sql= "select ${columnName} from ${tablename}"
if (keyName!= '')
sql+= " where ${keyName} = '${storeId}'"
GenericRawResults rawResults= tDao.queryRaw(sql)
List results= new ArrayList();
results.add(rawResults.getColumnNames())
results.addAll(rawResults.getResults())
def gson= createGson()
def json= gson.toJson(results)
output<< json
output<< '\n'
output.flush()
log.info"[${storeId}_${deviceId}]Send ${tablename}: ${results.size()}"
}
/**
* Server-side getTable protocol handler.
*
* Server Client
* -------------------- --------------------
* "getTable {store_id}_{device_id}{table_name}\n"
* <----------------------
* "{file_size}\n" or -1 if rejected
* ---------------------->
* "{file content}"
* ---------------------->
* "ok\n" or "ng\n"
* <----------------------
*
*/
static boolean doGetTable(storeId, deviceId, String tableName, OutputStream output, InputStream input) {
File tableFile
try {
tableFile= dumpTable(storeId, deviceId, tableName)
doGetFile(storeId, deviceId, tableFile, output, input)
} finally {
tableFile?.delete()
if (tableFile)
log.info"[${storeId}_${deviceId}]Table dump: $tableFilewas deleted."
}
}
/**
* Server-side getFile protocol handler.
*
* Server Client
* -------------------- --------------------
* "getFile {store_id}_{device_id}{file_name}\n"
* <----------------------
* "{file_size}\n" or -1 if rejected
* ---------------------->
* "{file content}"
* ---------------------->
* "ok\n" or "ng\n"
* <----------------------
*
*/
static boolean doGetFile(storeId, deviceId, File getFile, OutputStream output, InputStream input) {
if (getFile.exists()) {
log.info"[${storeId}_${deviceId}]Send file size: ${getFile.length()}"
output<< "${getFile.length()}\n"
log.info"[${storeId}_${deviceId}]Send file content: $getFile"
def getFileInputStream= null
try {
getFileInputStream= new BufferedInputStream(new FileInputStream(getFile))
copy storeId, deviceId, getFileInputStream, output
} catch (Exception e) {
// rethrow the exception to interrupt the whole process
log.error(e)
throw e
} finally {
getFileInputStream?.close()
}
} else {
output<< '0\n'
}
def response= readLine(input)
if (response) {
if (getFile.getName().endsWith('update.zip')) {
getFile.delete()
}
log.info"[${storeId}_${deviceId}]Client response: ${response}"
} else
log.info"[${storeId}_${deviceId}]Client disconnected."
return true
}
/**
* Server-side putFile protocol handler.
*
* Server Client
* -------------------- --------------------
* "putFile {store_id}_{device_id}{file_name}\n"
* <----------------------
* "{file_size}\n"
* <----------------------
* "{file content}"
* <----------------------
* "ok\n" or "ng\n"
* ---------------------->
*
*
* Upload the file and save it as "trans/{file}_{store id}_{device id}_{week}.db".
*/
static void doPutFile(storeId, deviceId, File putFile, OutputStream output, InputStream input) {
def putFileOutputStream= null
try {
def fileSize= readLine(input).toInteger()
File transDir= new File(transDirInConf)
transDir.mkdir()
def weekName= String.format('%1$ta', Calendar.getInstance())
File fileUpload= new File(transDir,"${putFile.name}_${storeId}_${deviceId}_${weekName}.db")
log.info"[${storeId}_${deviceId}]Receiving file: ${putFile.name} to ${fileUpload}, size: ${fileSize}"
putFileOutputStream= new BufferedOutputStream(new FileOutputStream(fileUpload))
copy storeId, deviceId, input, putFileOutputStream, fileSize
output<< 'ok\n'
log.info"[${storeId}_${deviceId}]Send ok."
} catch (Exception e) {
log.warn"[${storeId}_${deviceId}]doPutFile failed", e
output<< 'ng\n'
} finally {
putFileOutputStream?.close()
}
}
/**
* Server-side doPutMasterVersion protocol handler.
*
* Server Client
* -------------------- --------------------
* "doPutMasterVersion {store_id}_{device_id}\n"
* <----------------------
* "{json_file_size}\n" or -1 if upload directory is not empty
* ---------------------->
* "{file content}"
* ---------------------->
* "ok\n" or "ng\n"
* <----------------------
*
*/
static void putFile2(storeId, deviceId, OutputStream output, InputStream input) {
int filesize= Integer.valueOf(readLine(input))
final ByteArrayOutputStream jsonBytes= new ByteArrayOutputStream()
copy2(input, jsonBytes, filesize)
final String objectsInJSON= jsonBytes.toString('UTF-8')
jsonBytes.close()
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd-HH")
Date date= new Date()
String date2= sdf.format(date)
if (!(['posLog'] as File).exists()) {
(['posLog'] as File).mkdirs()
}
File[] files= (['posLog'] as File).listFiles()
for (File file : files) {
if(file.getName().startsWith(storeId.toString()+"_"+deviceId.toString())){
file.delete()
}
}
def versionFile= ['posLog',"${storeId}_${deviceId}_${date2}.log"] as File
versionFile.text= objectsInJSON
output<< 'ok\n'
}
/**
* Copy fully {fileSize} bytes from input stream to output stream.
*/
static void copy2(InputStream input, OutputStream output,int filesize)
throws IOException{
int totalLen= 0
int length= 0
try {
byte[] buffer= new byte[1024]
while (totalLen< filesize&& (length= input.read(buffer)) > 0) {
output.write buffer,0, length
totalLen+= length
}
output.flush()
} catch (IOException e) {
log.info"Failed on copy: read=" + totalLen
throw e
}
}
static void doPutObject2(storeId, deviceId, tableName, objectClass, length, OutputStream output, InputStream input) {
log.info"[${storeId}_${deviceId}]Going to get ${objectClass.toString()}objects2"
String objectsInJSON= readLine(input)
def jdbcConn= (getDbConnection(false).getReadWriteConnection() as JdbcDatabaseConnection).getInternalConnection()
jdbcConn.autoCommit= false;//设置不自动提交
Sql sql= new Sql(jdbcConn)
List l= createGson().fromJson(objectsInJSON, List.class)//Json转成String[]
String name= l.get(0)
for (int i= 1; i< l.size(); i++) {
String value= ""
String[] s= l.get(i)
for (String s2 : s) {
if (i== 0) {
name+= ",${s2}"
} else {
if (s2== null)
value+= ",${s2}"
else
value+= ",'${s2}'"
}
}
String sqlStr= "insert into ${tableName} (${name}) values (${value.substring(1)})"
try {
sql.execute(sqlStr,new ArrayList())//插入
} catch (Exception e) {
//java.sql.SQLException: 违反了 PRIMARY KEY 约束 'PK_POS_TRANHEAD'。不能在对象 'dbo.POS_TRANHEAD' 中插入重复键。
if (e.message.contains("PRIMARY KEY")) {//重复插入跳过
log.info(e.getMessage())
} else {
log.info(sqlStr)
log.error("insert into faild", e)
output<< 'ng\n'
jdbcConn.close()
log.info"[${storeId}_${deviceId}]Send: ng"
return
}
}
}
log.info("${tableName} insert success count ${length- 1}")
jdbcConn.commit()//最后一起提交
jdbcConn.close()
output<< 'ok\n'
log.info"[${storeId}_${deviceId}]Send: ok"
}
/**
* Server-side putObject protocol handler.
*
* Protocols:
* Server Client
* -------------------- --------------------
* "putObject {store_id}_{device_id}{class_name}{#_of_objects}\n"
* <----------------------
*{JSON stream of the n objects}\n
* <----------------------
* "ok\n" or "ng\n"
* ---------------------->
*
*/
static void doPutObject(storeId, deviceId, objectClass, numOfObjects, OutputStream output, InputStream input) {
log.info"[${storeId}_${deviceId}]Going to get ${numOfObjects} ${objectClass.toString()}objects"
String objectsInJSON= readLine(input)
log.info"[${storeId}_${deviceId}]Receive: ${objectsInJSON}"
def gson= createGson()
// output << 'stream_ok\n'
if (objectClass== MposSalesOrder) { // 点餐数据上传
try {
boolean succeeded= processUploadedMposSalesOrders(gson, objectsInJSON, storeId, deviceId)
if (!succeeded) {
output<< 'ng\n'
log.info"[${storeId}_${deviceId}]Send: ng"
return
}
} catch (Exception e) {
output<< 'ng\n'
log.error('processUploadedMposSalesOrders', e)
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
return
}
} else if (objectClass== MposItemSet) { // 沽清数据上传
try {
def errorResponse= processUploadedMposItemSet(gson, objectsInJSON, storeId, deviceId)
if (errorResponse) {
output<< errorResponse+ "\n"
log.info"[${storeId}_${deviceId}]Send: $errorResponse"
return
}
} catch (Exception e) {
output<< 'ng\n'
log.error('processUploadedMposItemSet', e)
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
return
}
} else if (objectClass== MposDiningTable) { // 桌子状态更新上传
try {
def errorResponse= processUploadedMposDiningTable(gson, objectsInJSON, storeId, deviceId)
if (errorResponse) {
output<< errorResponse+ "\n"
log.info"[${storeId}_${deviceId}]Send: $errorResponse"
return
}
} catch (Exception e) {
output<< 'ng\n'
log.error('processUploadedMposDiningTable', e)
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
return
}
} else if (objectClass== MposTransaction) { // 交易数据上传
try {
processUploadedMposTransaction objectsInJSON
} catch (Exception e) {
output<< 'ng\n'
log.error('processUploadedMposTransaction', e)
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
return
}
} else if (objectClass== MposServerCommand) { // Server command
def result= processServerCommand objectsInJSON
output<< result+ "\n"
log.info"[${storeId}_${deviceId}]Send: ${result}"
return
} else if (objectClass== MposShift) {
try {
proocessUploadedShift objectsInJSON
} catch (Exception e) {
output<< 'ng\n'
log.error('proocessUploadedShift', e)
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
return
}
} else if (objectClass== MposShiftReport) {
try {
proocessUploadedPosShift objectsInJSON
} catch (Exception e) {
output<< 'ng\n'
log.error('proocessUploadedPosShift', e)
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
return
}
} /*else if (objectClass == Pos_tranflow) {
proocessUploadedPosTranflow objectsInJSON
} else if (objectClass == Pos_tranhead) {
proocessUploadedPosTranhead objectsInJSON
}*/ else {
// Save to uploadDir: {object class name}_{device id}_{upload timestamp}.json
def yyyymmddHHMMSS= String.format('%1$tY%1$tm%1$td%1$tH%1$tM%1$tS%1$tL',new Date())
def saveFile= [uploadDir,"${objectClass.name}_${deviceId}_${yyyymmddHHMMSS}.json"] as File
saveFile.text= objectsInJSON
log.info"[${storeId}_${deviceId}]Create: $saveFile"
}
output<< 'ok\n'
log.info"[${storeId}_${deviceId}]Send: ok"
}
static void proocessUploadedShift(String objectsInJSON) {
Type collectionType= new TypeToken>() {}.getType()
def gson= createGson()
List modelShifts= gson.fromJson(objectsInJSON, collectionType)
def connSrc= getDbConnection(false)
def sDao= DaoManager.createDao(connSrc, MposShift)
modelShifts.each{ shift ->
sDao.callBatchTasks{
shift.with{
fAccDate= new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(fAccDate))
if (serverType== 'SC')
fUploadFlag= 'N' // Mark it uploaded
else
fUploadFlag= 'Y' // Mark it uploaded
}
def deleteBuilder= sDao.deleteBuilder()
deleteBuilder.where().eq('Warehouseid', shift.warehouseid).and().eq('fPosNo', shift.fPosNo).and().eq('fShift', shift.fShift).and().eq('custId', shift.custId)
def rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from Tc_Shift with fPosNo='${shift.fPosNo}' Warehouseid = '${shift.warehouseid}'"
sDao.create shift
if (serverType!= 'SC')
if (shift.fAccDate== getInitialDate() && shift.fState!= 1) {//如果营业日期是1970-01-01,则更新该班别的营业日期
updateAccdate(getAccDate(shift.warehouseid), shift.fShift, shift.begFlowno ?:"", shift.endFlowno, shift.warehouseid, shift.custId)
}
}
}
}
static void proocessUploadedPosShift(String objectsInJSON) {
Type collectionType= new TypeToken>() {}.getType()
def gson= createGson()
List modelShifts= gson.fromJson(objectsInJSON, collectionType)
if (modelShifts.size() == 0)
return
def connSrc= getDbConnection(false)
def sDao= DaoManager.createDao(connSrc, MposShiftReport)
sDao.callBatchTasks{
def deleteBuilder= sDao.deleteBuilder()
modelShifts.each{ shift ->
deleteBuilder.where().eq('warehouseId', shift.warehouseId).and().eq('flowno', shift.flowno).and()
.eq('custId', shift.custId).and().eq('payWay', shift.payWay)
def rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from pos_shift with id='${modelShifts.flowno}'"
shift.with{
//id = 0
if (serverType== 'SC')
uploadFlag= 'N' // Mark it uploaded
else
uploadFlag= 'Y' // Mark it uploaded
}
sDao.create shift
}
}
}
static String processUploadedMposItemSet(Gson gson, String objectsInJSON, storeId, deviceId) {
Type collectionType= new TypeToken>() {}.getType()
List modelItemSet= gson.fromJson(objectsInJSON, collectionType)
if (modelItemSet.size() == 0)
return
def connSrc= getDbConnection()
def sDao= DaoManager.createDao(connSrc, MposItemSet)
sDao.callBatchTasks{
def deleteBuilder= sDao.deleteBuilder()
deleteBuilder.where().eq('Warehouseid', storeId).and().eq('PosNO', deviceId)
if(modelItemSet.get(0).tranType== 2){
def rows= deleteBuilder.delete()
if(rows){
log.info"Delete existing $rows rows from tbl_itemset with Warehouseid='$storeId' and PosNo='$deviceId'"
}
}else{
def rows= deleteBuilder.delete()
if(rows){
log.info"Delete existing $rows rows from tbl_itemset with Warehouseid='$storeId' and PosNo='$deviceId'"
}
modelItemSet.each{ set ->
sDao.create set
log.info"tbl_itemset inserted (id=${set.id},tranType=${set.tranType},pluno=${set.pluno},foodName=${set.foodName}...)"
// pushServer.pushString objectsInJSON
}
}
}
}
static synchronized String processUploadedMposDiningTable(Gson gson, String objectsInJSON, storeId, deviceId) {
Type collectionType= new TypeToken>() {}.getType()
List diningTables= gson.fromJson(objectsInJSON, collectionType)
def connSrc= getDbConnection(false)
def dao= DaoManager.createDao(connSrc, MposDiningTable)
def errResponse= stateTransitionCheck(dao, diningTables)
if (errResponse) {
return errResponse
} else {
for (diningTablein diningTables) {
dao.update diningTable
log.info"[${storeId}_${deviceId}]Updated: $diningTable"
// Push objectsInJSON
pushServer.pushString objectsInJSON
}
// 换桌需要调用后端存储过程
def changingDiningTable= diningTables.size() == 2
if (changingDiningTable) {
def targetDiningTable= diningTables[1]
proccessChangingDiningTable targetDiningTable, diningTables[0], connSrc
}
return null
}
}
static void proccessChangingDiningTable(MposDiningTable targetDiningTable, MposDiningTable diningTable, ConnectionSource connSrc) {
def sdao= DaoManager.createDao(connSrc, MposDiffSalesOrder)
List diffSalesOrderList= sdao.queryForEq("flowno", targetDiningTable.tranFlowno)
diffSalesOrderList*.roomNo= targetDiningTable.roomNo
diffSalesOrderList*.deskNo= targetDiningTable.deskNo
diffSalesOrderList*.deskName= targetDiningTable.deskName
int allQty= 0
diffSalesOrderList.each{
it.roomNo= targetDiningTable.roomNo
it.deskNo= targetDiningTable.deskNo
it.deskName= targetDiningTable.deskName
it.message= "换桌 原${diningTable.deskName} "
allQty+= it.saleQty
sdao.update(it)
}
//打印控菜单
if (dbConf.kitchen.printAll== 'Y') {
try {
lock.lock()
diffSalesOrderList*.allQty= allQty
if (diffSalesOrderList.size() > 0) {
PrintServer printServer= new PrintServer()
printServer.printSaleOrder(diffSalesOrderList)
}
} catch (Exception e) {
log.error(e)
} finally {
lock.unlock()
}
}
}
static synchronized boolean processUploadedMposSalesOrders(Gson gson, String objectsInJSON, storeId, deviceId) {
Type collectionType= new TypeToken>() {}.getType()
List salesOrders= gson.fromJson(objectsInJSON, collectionType)
if (salesOrders) {
log.info"Deserialized salesOrders: $salesOrders"
// def connSrc = getDbConnection()
def transConnSrc= getDbConnection(false)
def tDao= DaoManager.createDao(transConnSrc, MposDiningTable)
def sDao= DaoManager.createDao(transConnSrc, MposSalesOrder)
def diffDao= DaoManager.createDao(transConnSrc, MposDiffSalesOrder)
def diningTableId= salesOrders[0].diningTableId
def orderNumber= salesOrders[0].orderNumber
Map> diffSalesOrdersMap= [:]
Map> diffSalesOrderCancelsMap= [:]
boolean cancel= false
try {
if (diningTableId) {
def diningTable= tDao.queryForId(diningTableId)
if (diningTable?.orderNumber!= null && diningTable?.orderNumber!= '' && diningTable?.orderNumber!= orderNumber) {
log.info"processUploadedMposSalesOrders tableId = ${diningTableId} tableOrderNumber = ${diningTable?.orderNumber} orderNumber = $orderNumber"
return false
}
diningTable.orderNumber= orderNumber//设置交易单号
log.info"processUploadedMposSalesOrders tableId = ${diningTable} orderNumber = ${orderNumber}"
tDao.update(diningTable)
}
tDao.callBatchTasks{
// -> 手机下单时在发送sales orders之后,也负责发送dining table状态至后端(因为需要能更新后端桌子的
// 来客数、服务员、和备注等信息)。不过目前在结帐后的交易数据上传后,仍由后端修改重置桌子为idle,
// 并push桌子信息。
//def diningTable = tDao.queryForId(diningTableId)
//// 更新桌子对应的点单号
//diningTable.orderNumber = orderNumber
//if (diningTable.state == 'N')
// diningTable.createDate = new Date() // 开桌时间
//// 桌子状态为被占用
//diningTable.state = 'Y'
//tDao.update(diningTable)
//List diffSalesOrderOrigs = mpos查询某张桌子的点单差异表数据(connSrc, storeId, deviceId, diningTableId)
List diffSalesOrderList= []
int allQty= 0
for (salesOrderin salesOrders) {
if (salesOrder.sellWay!= 'A' && salesOrder.sellWay!= 'B' && salesOrder.sellWay!= 'S')
continue
if (salesOrder.id== 0) {
sDao.create salesOrder
log.info"Create: $salesOrder"
} else {
sDao.update salesOrder
log.info"Update: $salesOrder"
}
if (!salesOrder.printName|| salesOrder.printFlag== 'N') {
log.info"${salesOrder.pluName} ${salesOrder.pluno} ${salesOrder.printName}not print"
continue
}
// 处理点单厨打表
log.info"salesOrder.id=" + salesOrder.id+ ",saleQty=" +
salesOrder.saleQty+ ",lastSaleQty=" + salesOrder.lastSaleQty
allQty+= salesOrder.saleQty
MposDiffSalesOrder diffSalesOrder= MposDiffSalesOrder.getAndCreateDiffSalesOrder(salesOrder)
if (diffSalesOrder) {
// 处理下diffSalesOrder.id, 以便成功update----目前厨打表只做insert
/*if (diffSalesOrderOrigs) {
for (diffSalesOrderOrig in diffSalesOrderOrigs) {
diffSalesOrderOrig = diffSalesOrderOrig as MposDiffSalesOrder
if (diffSalesOrderOrig.itemseq == salesOrder.lastItemseq
&& diffSalesOrderOrig.flowno == salesOrder.flowno
&& diffSalesOrderOrig.pluno == salesOrder.pluno) {
diffSalesOrder.id = diffSalesOrderOrig.id
}
}*/
// 创建diffSalesOrder
diffDao.create diffSalesOrder
// if (diffSalesOrder.deskNo == null)
// continue
log.info"Create: $diffSalesOrder"
salesOrder.lastSaleQty= salesOrder.saleQty
diffSalesOrderList.add(diffSalesOrder)
}
// -> 桌子状态改为由手机端发送
//// Push table status back
//pushServer.pushString gson.toJson([diningTable])
}
//打印控菜单
if (dbConf.kitchen.printAll== 'Y') {
try {
lock.lock()
diffSalesOrderList*.allQty= allQty
if (diffSalesOrderList.size() > 0) {
PrintServer printServer= new PrintServer()
printServer.printSaleOrder(diffSalesOrderList)
}
} catch (Exception e) {
log.error(e)
} finally {
lock.unlock()
}
}
// 手机点单: 调用存储过程:exec Proc_POS_APP 2,1,点单单号,''
// callStoredProcedure(1, salesOrders[0].flowno)
// -> 桌子状态改为由手机端发送
//// Push table status back
//pushServer.pushString gson.toJson([diningTable])
}
} catch (Exception e) {
log.error'processUploadedMposSalesOrders() failed', e
return false
}
}
return true
}
static String stateTransitionCheck(Dao dao, List diningTables) {
if (stlMap) {
for (diningTablein diningTables) {
def origDiningTable= dao.queryForId(diningTable.fId)
def sourceState= (origDiningTable.state== '0' ?'N' : origDiningTable.state)
def targetState= (diningTable.state== '0' ?'N' : diningTable.state)
def expectedOldState= (diningTable.previousState== '0' ?'N' : diningTable.previousState)
log.info"DiningTable.id=${diningTable.fId}: sourceState=$sourceState, expectedOldState=$expectedOldState, targetState=$targetState"
if (sourceState!= expectedOldState|| // 状态被别人抢先更新(optimistic lock)
(sourceState!= targetState&& !stlMap[sourceState].contains(targetState))) {
// reject the transition
def response= "ng Reject the transition from $sourceState to $targetState"
return response
}
}
}
return null
}
static String processServerCommand(String objectsInJSON) {
Type collectionType= new TypeToken>() {}.getType()
def gson= createGson()
List serverCommands= gson.fromJson(objectsInJSON, collectionType)
for (serverCommandin serverCommands) {
switch (serverCommand.command) {
case 'refund':// 整笔退单
def orderNumber= serverCommand.argument
callStoredProcedure5, orderNumber
def connSrc= getDbConnection(false)
def hDao= DaoManager.createDao(connSrc, MposTransaction)
MposTransaction transaction= hDao.queryForEq("RtnFlowNo", orderNumber).get(0)
PrintServer.printTrans(transaction.flowno,'0', dbConf.PrintName,'','',1,false)
break
case 'reprint':// 小票重印
def orderNumber= serverCommand.argument
callStoredProcedure4, orderNumber
PrintServer.printTrans(orderNumber,'1', dbConf.PrintName,'','',1,false)
break
case 'date'://date, 比对系统日期
def clientDate= serverCommand.argument
def serverDate= new SimpleDateFormat("yyyy-MM-dd HH").format(new Date())
if (clientDate== serverDate)
return 'ok'
else
return 'ng'
break;
}
}
return 'ok'
}
static void processUploadedMposTransaction(String objectsInJSON) {
Type collectionType= new TypeToken>() {}.getType()
def gson= createGson()
List transactions= gson.fromJson(objectsInJSON, collectionType)
log.info"Deserialized: $transactions"
def connSrc= getDbConnection()
def transConnSrc= getDbConnection(false)
def hDao= DaoManager.createDao(transConnSrc, MposTransaction)
def dDao= DaoManager.createDao(transConnSrc, MposLineItem)
def pDao= DaoManager.createDao(transConnSrc, MposTransactionTender)
def oDao= DaoManager.createDao(transConnSrc, MposO2oPayDtl)
def cDao= DaoManager.createDao(transConnSrc, MposCardDtl)
def tdDao= DaoManager.createDao(transConnSrc, MposTicketDtl)
def todDao= DaoManager.createDao(transConnSrc, MposTakeOutTransaction)
def tofdDao= DaoManager.createDao(transConnSrc, MposTakeOutTranflow)
def tDao= DaoManager.createDao(transConnSrc, MposDiningTable)
def tsDao= DaoManager.createDao(transConnSrc, MposTrantaste)
transactions.each{ transaction ->
// 一笔交易的以下四张表的写入在一个事务中
hDao.callBatchTasks{
def print= false
if (transaction.flowno) {
// Try to delete existing data that with the same order number
def storeId= transaction.warehouseid
def orderNumber= transaction.flowno
def custId= transaction.custId
def deleteBuilder= pDao.deleteBuilder()
deleteBuilder.where().eq('warehouseId', storeId).and().eq('flowno', orderNumber).and().eq('custId', custId)
def rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from pos_tranpay with warehouseId='$storeId' and flowno='$orderNumber'"
deleteBuilder= tsDao.deleteBuilder()
deleteBuilder.where().eq('warehouseId', storeId).and().eq('flowno', orderNumber).and().eq('custId', custId)
rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from pos_trantaste with warehouseId='$storeId' and flowno='$orderNumber'"
deleteBuilder= dDao.deleteBuilder()
deleteBuilder.where().eq('warehouseId', storeId).and().eq('flowno', orderNumber).and().eq('custId', custId)
rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from pos_tranflow with warehouseId='$storeId' and flowno='$orderNumber'"
deleteBuilder= oDao.deleteBuilder()
deleteBuilder.where().eq('Warehouseid', storeId).and().eq('Flowno', orderNumber).and().eq('custId', custId)
rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from pos_carddtl with warehouseId='$storeId' and flowno='$orderNumber'"
deleteBuilder= cDao.deleteBuilder()
deleteBuilder.where().eq('Warehouseid', storeId).and().eq('Flowno', orderNumber).and().eq('custId', custId)
rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from pos_carddtl with warehouseId='$storeId' and flowno='$orderNumber'"
deleteBuilder= hDao.deleteBuilder()
deleteBuilder.where().eq('warehouseId', storeId).and().eq('flowno', orderNumber).and().eq('custId', custId)
rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from pos_o2opaydtl with warehouseId='$storeId' and flowno='$orderNumber'"
deleteBuilder= tdDao.deleteBuilder()
deleteBuilder.where().eq('Warehouseid', storeId).and().eq('Flowno', orderNumber).and().eq('custId', custId)
rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from pos_TicketDtl with warehouseId='$storeId' and Flowno='$orderNumber'"
deleteBuilder= todDao.deleteBuilder()
deleteBuilder.where().eq('Warehouseid', storeId).and().eq('posFlowno', orderNumber).and().eq('custId', custId)
rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from takeOut_postranhead with warehouseId='$storeId' and posFlowno='$orderNumber'"
if (transaction.deskNo) {
// deleteBuilder = tDao.deleteBuilder()
// deleteBuilder.where().eq('warehouseId', storeId).and().eq('tranFlowno', orderNumber).and().eq('custId', custId)
// rows = deleteBuilder.delete()
// if (rows > 0)
// log.info "Delete existing $rows rows from pos_TicketDtl with warehouseId='$storeId' and flowno='$orderNumber'"
} else {
print= true
}
}
transaction.with{
//id = 0 // Don't use the ID on client-side
if (serverType== 'SC')
uploadFlag= 'N' // Mark it uploaded
else {
uploadFlag= 'Y' // Mark it uploaded
//更新桌边点餐状态
if (transaction.jshopFlowno) {
def jDao= DaoManager.createDao(transConnSrc, MposJshopTransaction)
UpdateBuilder updateBuilder= jDao.updateBuilder()
updateBuilder.updateColumnValue('uploadFlag' ,'Y')
.where().eq('flowNo', transaction.jshopFlowno).and().eq('warehouseid', transaction.warehouseid)
updateBuilder.update()
}
}
// if (sellway == 'O' || sellway == 'F') // 开班/交班交易,手机端并没有给交易单号,所以这里补填上
// flowno = getNextOrderNumberOfDevice(connSrc, warehouseid, posNo)
}
hDao.create transaction
transaction.with{
log.info"pos_tranhead inserted (id=$id,posNo=$posNo,flowno=$flowno,SellWay=$sellway,saleAmt=$saleAmt)"
}
transaction.details.each{ lineItem ->
//lineItem.id = 0
if (serverType== 'SC')
lineItem.uploadflag= 'N' // Mark it uploaded
else
lineItem.uploadflag= 'Y' // Mark it uploaded
dDao.create lineItem
log.info"pos_tranflow inserted (id=${lineItem.id})"
}
transaction.payments.each{ tender ->
//tender.id = 0
if (serverType== 'SC')
tender.uploadFlag= 'N'
else
tender.uploadFlag= 'Y'
pDao.create tender
log.info"pos_tranpay inserted (id=${tender.id})"
}
transaction.trantastes.each{ trantaste ->
trantaste.id= 0
tsDao.create trantaste
log.info"pos_trantaste inserted (id=${trantaste.id})"
}
transaction.o2oPayDtls.each{ o2oPayDtl ->
o2oPayDtl.id= 0
if (serverType== 'SC')
o2oPayDtl.uploadFlag= 'N'
else
o2oPayDtl.uploadFlag= 'Y'
oDao.create o2oPayDtl
log.info"pos_o2opaydtl inserted (id=${o2oPayDtl.id})"
}
transaction.cardDtls.each{ cardDtl ->
cardDtl.id= 0
if (serverType== 'SC')
cardDtl.uploadFlag= 'N'
else
cardDtl.uploadFlag= 'Y'
cDao.create cardDtl
log.info"pos_carddtl inserted (id=${cardDtl.id})"
}
transaction.ticketDtls.each{ ticketDtls ->
if (serverType== 'SC')
ticketDtls.uploadFlag= 'N'
else
ticketDtls.uploadFlag= 'Y'
tdDao.create ticketDtls
log.info"pos_TicketDtl inserted (id=${ticketDtls.ticketNo})"
}
transaction.takeOutTrans.each{ takeOuttran ->
if (serverType== 'SC')
takeOuttran.uploadFlag= 'N'
else
takeOuttran.uploadFlag= 'Y'
todDao.create takeOuttran
log.info"takeOut_postranhead inserted (id=${takeOuttran.posFlowno})"
def deleteBuilder= tofdDao.deleteBuilder()
deleteBuilder.where().eq('fmId', takeOuttran.fmId)
int rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from takeOut_postranflow with fmId='$takeOuttran.fmId'"
takeOuttran.tranflows.each{tranflow ->
tofdDao.create(tranflow)
log.info"takeOut_postranflow inserted (id=${tranflow.fmId})"
}
}
if (transaction.deskNo&& serverType== 'SC') {
def diningTable= tDao.queryBuilder().where().eq('deskNo', transaction.deskNo).queryForFirst()
if (diningTable) {
if (transaction.sellway!= 'B') { //退货不改变桌子状态
diningTable.transferToIdleState()
}
tDao.update diningTable
log.info"pos_deskInfo of transaction.deskNo=${transaction.deskNo}is back to idle."
// Push table status back
pushServer.pushString gson.toJson([diningTable])
}
}
if (serverType== 'SC')
callStoredProcedureForTransaction transaction
if (print)
if (transaction.sellway== 'A' || transaction.sellway== 'B') {
//TODO
// PrintServer.printTrans(transaction.flowno, '0')
}
}
}
}
// 手机 交易类型 to 存储过程参数 map
static spParamMap= [
A:3,// 手机结账 调用存储过程:exec Proc_POS_APP 2,3,交易单号,''
C:2,// 交易取消 调用存储过程:exec Proc_POS_APP 2,2,点单单号,''
B:5,// 整笔退餐 调用存储过程:exec Proc_POS_APP 2,5,交易单号,'
O:3,// 开班
F:3,// 交班
]
// pc 交易类型 to 存储过程参数 map
static sp2ParamMap= [
A:6,// 手机结账 调用存储过程:exec Proc_POS_APP 2,3,交易单号,''
C:2,// 交易取消 调用存储过程:exec Proc_POS_APP 2,2,点单单号,''
B:5,// 整笔退餐 调用存储过程:exec Proc_POS_APP 2,5,交易单号,'
O:3,// 开班
F:3,// 交班
]
/**
* 调用存储过程 for Transaction.
*/
static void callStoredProcedureForTransaction(MposTransaction tran) {
def param2= sp2ParamMap[tran.sellway]
if (param2)
callStoredProcedure(param2, tran.flowno)
// if (tran.sellway == 'F') {
// def connSrc = getDbConnection(false)
// def dao = DaoManager.createDao(connSrc, MposShift)
// def List shiftList = dao.queryBuilder().where()
// .eq('fState', '2').and().eq('warehouseId', tran.warehouseid).and().eq("fPosNo", tran.posNo)
// .query()
// if (shiftList.size() > 0) {
// def shiftNo = shiftList.get(shiftList.size() - 1)?.fShift
// if (shiftNo) {
// PrintServer.printShift(shiftNo, tran.posNo, dbConf.PrintName)
// }
// }
// }
}
/**
* 调用存储过程Proc_POS_APP。
*
* @param param2 操作动作:
*
*
1: 手机点单 *
2: 交易取消 *
3: 手机结账 *
4: 小票重印 *
5: 整笔退单 *
* @param flowno 交易单号
*/
static void callStoredProcedure(int param2, String flowno) {
def db= getDbConnection()
if (dbType.contains("sqlite") || dbType== 'MySQL')
return
def dbConn
try {
log.info"Call Proc_POS_APP(1, $param2, $flowno, '')"
dbConn= db.getReadWriteConnection()
def jdbcConn= (dbConnas JdbcDatabaseConnection).internalConnection
def sql= new Sql(jdbcConn)
sql.call'{call dbo.Proc_POS_APP(?, ?, ?, ?)}',[1, param2, flowno,'']
} catch (Exception e) {
e.printStackTrace()
log.error"Call dbo.Proc_POS_APP(2, $param2, $flowno, '') failed", e
} finally {
if (dbConn) db.releaseConnection dbConn
}
}
/*
static void doDeleteObject(storeId, deviceId, objectClass, numOfObjects, OutputStream output, InputStream input) {
log.info "[${storeId}_${deviceId}]Going to get ${numOfObjects} ${objectClass.toString()} objects"
String objectsInJSON = readLine(input)
log.info "[${storeId}_${deviceId}]Receive: ${objectsInJSON}"
if (objectClass == MposSalesOrder) { // 点餐数据交易取消
Type collectionType = new TypeToken>() {}.getType()
def gson = createGson()
List salesOrders = gson.fromJson(objectsInJSON, collectionType)
if (salesOrders) {
log.info "Deserialized salesOrders: $salesOrders"
def connSrc = getDbConnection()
def tDao = DaoManager.createDao(connSrc, MposDiningTable)
def sDao = DaoManager.createDao(connSrc, MposSalesOrder)
def diningTableId = salesOrders[0].diningTableId
def orderNumber = salesOrders[0].orderNumber
tDao.callBatchTasks {
def diningTable = tDao.queryForId(diningTableId)
try {
List objects = mpos查询某张桌子的点单数据2(connSrc, storeId, deviceId, diningTableId)
for (salesOrder in objects) {
sDao.delete salesOrder
log.info "delete: $salesOrder"
}
System.out.println('salesOrders1.size=' + salesOrders.size())
objects ? System.out.println('objects.size=' + objects.size()) : System.out.println('objects is null')
} catch (Exception e) {
System.out.println('salesOrders2.size=' + salesOrders.size())
for (salesOrder in salesOrders) {
sDao.delete salesOrder
log.info "delete: $salesOrder"
}
}
// 清除桌子对应的点单号
diningTable.orderNumber = ''
// 桌子状态为被未占用
diningTable.state = 'N'
tDao.update(diningTable)
// Push table status back
pushServer.pushString gson.toJson([diningTable])
}
}
}
output << 'ok\n'
log.info "[${storeId}_${deviceId}]Send: ok"
}
*/
/**
* Server-side getObject protocol handler.
*
* Protocols:
* Server Client
* -------------------- --------------------
* "getObject {store_id}_{device_id}{class_name}\n"
* <----------------------
*{JSON stream of objects}\n
* ---------------------->
* "ok\n" or "ng\n"
* <----------------------
*
*/
static void doGetObject(storeId, deviceId, Class objectClass, String argument,
OutputStream output, InputStream input) {
log.info"[${storeId}_${deviceId}]Going to get ${objectClass.toString()}objects"
//output.withWriter('UTF-8') { writer ->
def connSrc= getDbConnection()
def transConnSrc= getDbConnection(false)
List objects
switch (objectClass) {
case MposSalesOrder:// 查询某张桌子的点单数据
def diningTableId= argument.toInteger() // 参数会传入桌子的id
objects= mpos查询某张桌子的点单数据(transConnSrc, storeId, deviceId, diningTableId)
break
case MposTransaction:// 如果要查詢历史交易,参数会传入桌子代号
objects= queryTodayTransactionForDiningTable(transConnSrc, storeId, argument)
break
case MposShiftReport:// 如果要查詢交班报表,client端会带上日期
objects= queryShiftReportOfCertainDate(transConnSrc, storeId, argument)
break
case MposDiningArea://获取桌子信息
objects= queryDiningArea(connSrc, transConnSrc)
break
default:
def dao= DaoManager.createDao(connSrc, objectClass)
objects= dao.queryForAll()
}
// queryOtherAssociatedData connSrc, objects, objectClass
def gson= createGson()
def json= gson.toJson(objects)
output<< json
output<< '\n'
output.flush()
log.info"[${storeId}_${deviceId}]Send ${objectClass.simpleName}: ${json}"
def response= readLine(input)
if (response)
log.info"[${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${storeId}_${deviceId}]Client disconnected."
}
/** 获取桌子信息 并且将mater库的桌子信息转到trans库里**/
static List queryDiningArea(connSrc, transConnSrc) {
def dao= DaoManager.createDao(connSrc, MposDiningArea)
def dao2= DaoManager.createDao(transConnSrc, MposDiningArea)
def tdao= DaoManager.createDao(connSrc, MposDiningTable)
def tdao2= DaoManager.createDao(transConnSrc, MposDiningTable)
if (masterVersion!= AppClient.masterVersion) {//当主档有更新时需要把master库的区域表和桌子表转到trans库对应的表中
def areaList= dao.queryForAll()
//2018-01-05 @pingping 将区域全删除再插入
dao2.deleteBuilder().delete()
for (MposDiningArea areain areaList) {
// List areaList2 = dao2.queryBuilder().where().eq("roomNo", area.roomNo).query()
// if (!areaList2) {
dao2.create(area)//桌子区域放到trans库
// } else {
// if (areaList2.get(0).roomName != area.roomName) {
// areaList2.get(0).roomName = area.roomName
// dao2.update(areaList2.get(0))
// }
// }
}
def tableList= tdao.queryForAll()
//2018-01-05 @pingping 先删除未开桌的桌子,再插入
DeleteBuilder deleteBuilder= tdao2.deleteBuilder()
deleteBuilder.where().ne("State","Y")
deleteBuilder.delete()
for (MposDiningTable table : tableList) {
List list2= tdao2.queryBuilder().where().eq('fId', table.fId).query()
if (list2) {
if (list2.get(0).deskName!= table.deskName) {
list2.get(0).deskName= table.deskName
tdao2.update(list2.get(0))
}
if (list2.get(0).roomNo!= table.roomNo) {
list2.get(0).roomNo= table.roomNo
tdao2.update(list2.get(0))
}
if (list2.get(0).tranFlowno!= '' && list2.get(0).state!= 'Y') {
list2.get(0).tranFlowno= table.tranFlowno
tdao2.update(list2.get(0))
}
} else {
tdao2.create(table)//桌子信息放到trans库
}
}
masterVersion= AppClient.masterVersion
}
def objects= dao2.queryForAll()//取trans库的桌子区域
for (MposDiningArea areain objects) {
def list= tdao2.queryForEq('roomNo', area.roomNo)//取trans库的桌子信息
if (list.size() == 0)
masterVersion= ""
area.diningTables= list
}
return objects
}
/** 判断交易是否已经被退货。 */
static boolean isTransactonRefund(connSrc, storeId, deviceId, flowno) {
def tDao= DaoManager.createDao(connSrc, MposTransaction)
GenericRawResults rawResults= tDao.queryRaw(
"select 1 from pos_tranhead where WarehouseID='${storeId}' and rtnflowno = '${flowno}'")
List results= rawResults.getResults()
if (results) {
String[] resultArray= results.get(0)
if (resultArray) {
return true
}
}
return false
}
/** 求某个手机本日的下个交易单号。从pos_tranflowhd和pos_tranhead中取最大者+1。 */
static String getNextOrderNumberOfDevice(connSrc, storeId, deviceId) {
def sDao= DaoManager.createDao(connSrc, MposSalesOrder)
def yyyymmdd= String.format('%1$tY%1$tm%1$td',new Date())
deviceId= String.format('%02d', deviceId.toInteger()) // two-digit device ID
GenericRawResults rawResults= sDao.queryRaw(
"select MAX(flowno) from pos_tranflowhd where WarehouseID='${storeId}' and flowno like '${deviceId}${yyyymmdd}%'")
List results= rawResults.getResults()
int maxSequence= 0
if (results) {
String[] resultArray= results.get(0)
if (resultArray) {
String maxOrderNumber= resultArray[0]
maxSequence= (maxOrderNumber?.substring(10) ?:'0').toInteger()
}
}
maxSequence++
rawResults= sDao.queryRaw(
"select MAX(flowno) from pos_tranhead where WarehouseID='${storeId}' and flowno like '${deviceId}${yyyymmdd}%'")
results= rawResults.getResults()
if (results) {
String[] resultArray= results.get(0)
if (resultArray) {
String maxOrderNumber= resultArray[0]
maxSequence= Math.max((maxOrderNumber?.substring(10) ?:'0').toInteger() + 1, maxSequence)
}
}
def newSequence= String.format('%04d', maxSequence) // four-digit order number
return "${deviceId}${yyyymmdd}${newSequence}"
}
/** 查询本日某张桌子的交易。 */
static List queryTodayTransactionForDiningTable(connSrc, storeId, diningTableCode) {
def today= new SimpleDateFormat("yyyy-MM-dd").format(new Date())
def dao= DaoManager.createDao(connSrc, MposTransaction)
dao.queryBuilder().where()
.eq('accdate', today).and().eq('deskNo', diningTableCode)
.query()
}
static List queryShiftReportOfCertainDate(connSrc, storeId, date) {
def dao= DaoManager.createDao(connSrc, MposShiftReport)
dao.queryBuilder()
.orderBy('flowno',false)
.where().eq('warehouseId', storeId).and().eq('accdate', date)
.query()
}
static List mpos查询某张桌子的点单数据(transConnSrc, storeId, deviceId, diningTableId) {
def tDao= DaoManager.createDao(transConnSrc, MposDiningTable)
def diningTable= tDao.queryForId(diningTableId)
def orderNo= diningTable.tranFlowno// 当前对应的点单号
def sDao= DaoManager.createDao(transConnSrc, MposSalesOrder)
List salesOrders
if (orderNo) {
salesOrders= sDao.queryBuilder()
.orderBy('id',true)
.where().eq('flowno', orderNo)
.query()
}
if (!salesOrders) { // 如果找不到这张桌子的任何点餐数据,就生成一笔空记录,里面只包含了新的点单号
def nextOrderNumber= getNextOrderNumberOfDevice(getDbConnection(false), storeId, deviceId)
salesOrders= [new MposSalesOrder(flowno: nextOrderNumber, diningTableId: diningTableId)]
} else {
// Fill some non-database fields
salesOrders.each{ MposSalesOrder salesOrder ->
salesOrder.diningTableId= diningTableId
salesOrder.lastSaleQty= salesOrder.saleQty.setScale(3,4)
salesOrder.lastItemseq= salesOrder.itemseq.setScale(0)
}
}
return salesOrders
}
// static List mpos查询某张桌子的点单数据2(connSrc, storeId, deviceId, diningTableId) {
// def tDao = DaoManager.createDao(connSrc, MposDiningTable)
// def diningTable = tDao.queryForId(diningTableId)
// def orderNo = diningTable.tranFlowno // 当前对应的点单号
// def sDao = DaoManager.createDao(connSrc, MposSalesOrder)
// List salesOrders
// if (orderNo) {
// salesOrders = sDao.queryBuilder()
// .orderBy('itemseq', true)
// .where().eq('flowno', orderNo)
// .query()
// }
// if (!salesOrders) { // 如果找不到这张桌子的任何点餐数据,返回null
// return salesOrders
// } else {
// // Fill some non-database fields
// salesOrders.each { MposSalesOrder salesOrder ->
// salesOrder.diningTableId = diningTableId
// salesOrder.lastSaleQty = salesOrder.saleQty.setScale(0)
// salesOrder.lastItemseq = salesOrder.itemseq.setScale(0)
// }
// }
// return salesOrders
// }
// static List mpos查询某张桌子的点单差异表数据(connSrc, storeId, deviceId, diningTableId) {
// def tDao = DaoManager.createDao(connSrc, MposDiningTable)
// def diningTable = tDao.queryForId(diningTableId)
// def orderNo = diningTable.tranFlowno // 当前对应的点单号
// def diffDao = DaoManager.createDao(connSrc, MposDiffSalesOrder)
// List diffSalesOrders
// if (orderNo) {
// try {
// diffSalesOrders = diffDao.queryBuilder()
// .orderBy('itemseq', true)
// .where().eq('flowno', orderNo)
// .query()
// } catch (Exception e) {
// log.error e.message, e
// }
// }
// return diffSalesOrders // 如果找不到这张桌子的任何点餐数据,返回null
// // Fill some non-database fields
// // diffSalesOrders.each { MposDiffSalesOrder diffSalesOrder ->
// // diffSalesOrder.diningTableId = diningTableId
// // }
// }
static void queryOtherAssociatedData(ConnectionSource connSrc, List objects, Class objectClass) {
if (objectClass== MposDiningArea) {
def dao= DaoManager.createDao(connSrc, MposDiningTable)
for (MposDiningArea areain objects) {
area.diningTables= dao.queryForEq('roomNo', area.roomNo)
if (!area.diningTables)
continue
// Fix table state if it is inconsistent with its order number
// for (MposDiningTable table in area.diningTables) {
// if (table.orderNumber && table.state != 'Y') {
// table.state = 'Y'
// dao.update table
// } else if (!table.orderNumber && table.state != 'N') {
// table.state = 'N'
// dao.update table
// }
// }
}
}
}
static void doGetApkVersion(storeId, deviceId, OutputStream output, InputStream input) {
// Find latest apk's release note JSON file
def fs= ('apk' as File).listFiles()?.sort()?.collect{ it.name}
def jsonFile= fs ? fs[-1] :null
log.info"[${storeId}_${deviceId}]The last file in apk/: ${jsonFile}"
if (jsonFile?.endsWith('.json'))
doGetFile storeId, deviceId,['apk', jsonFile] as File, output, input
else {
log.info"[${deviceId}]Cannot find any latest apk version info."
output<< '0\n'
def response= readLine(input)
if (response)
log.info"[${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${storeId}_${deviceId}]Client disconnected."
}
}
/**
* Server-side getPosVersion protocol handler.
*
* Server Client
* -------------------- --------------------
* "getPosVersion {store_id}_{device_id}\n"
* <----------------------
* "{json_file_size}\n"
* ---------------------->
* "{file content}"
* ---------------------->
* "ok\n" or "ng\n"
* <----------------------
*
*/
static void doGetPosVersion(storeId, deviceId, OutputStream output, InputStream input) {
// Find latest pos's release note JSON file
def fs= (('update/' + deviceId) as File).listFiles(new FilenameFilter() {
@Override
boolean accept(File dir, String name) {
log.info'===== ' + name
return name.lastIndexOf('.json') > 0
}
})?.sort()?.collect{ it.name}
def jsonFile= fs ? fs[-1] :null
log.info"[${storeId}_${deviceId}]The last file in pos/: ${jsonFile}"
if (jsonFile?.endsWith('.json'))
doGetFile storeId, deviceId,['update/' + deviceId, jsonFile] as File, output, input
else {
log.info"[${deviceId}]Cannot find any latest pos version info."
output<< '0\n'
def response= readLine(input)
if (response)
log.info"[${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${storeId}_${deviceId}]Client disconnected."
}
}
static void upPosVersion(String custId, String storeId, String deviceId, String version, String type, String date, OutputStream output, InputStream input) {
if (serverType== 'HQ') {
try {
def jdbcConn= (getDbConnection(false).getReadWriteConnection() as JdbcDatabaseConnection).getInternalConnection()
Sql sql= new Sql(jdbcConn)
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String todayStr= sdf.format(new Date());
String sqlStr= "select id from pos_masterversion where custId='${custId}' and warehouseId='${storeId}' " +
"and posNo='${deviceId}' and type='${type}'"
log.info(sqlStr)
def connSrc= getDbConnection()
def sDao= DaoManager.createDao(connSrc, MposItemSet)
GenericRawResults rawResults= sDao.queryRaw(sqlStr)
if (rawResults.size() > 0) {
sqlStr= "update pos_masterversion set version='${version}', updateTime='${todayStr}', memo = '${date ?:''}' " +
"where custId='${custId}' and warehouseId='${storeId}' and posNo='${deviceId}' and type='${type}'"
} else {
sqlStr= "insert into pos_masterversion values('${custId}','${storeId}','${deviceId}','${version}','${type}','${todayStr}','${date ?:''}')"
}
log.info(sqlStr)
sql.execute(sqlStr)
} catch (Exception e) {
log.warn"[${storeId}_${deviceId}]upPosVersion failed", e
log.info(e.getMessage())
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
}
}
}
/**
* Server-side getMasterVersion protocol handler.
*
* Server Client
* -------------------- --------------------
* "getMasterVersion {store_id}_{device_id}\n"
* <----------------------
* "{json_file_size}\n" or -1 if upload directory is not empty
* ---------------------->
* "{file content}"
* ---------------------->
* "ok\n" or "ng\n"
* <----------------------
*
*/
static void doGetMasterVersion(storeId, deviceId, OutputStream output, InputStream input) {
// Find latest master's release note JSON file
def dirStr= 'db'
if (serverType== 'HQ')
dirStr= "db/${deviceId}/${storeId}"
def fs= (dirStras File).listFiles()?.sort()?.collect{ it.name}
def jsonFile= fs ? fs[-1] :null
if (jsonFile?.endsWith('.json'))
doGetFile storeId, deviceId,[dirStr, jsonFile] as File, output, input
else {
log.info"[${storeId}_${deviceId}]Cannot find any latest master version info."
output<< '0\n'
def response= readLine(input)
if (response)
log.info"[${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${storeId}_${deviceId}]Client disconnected."
}
}
/**
* Server-side putFile protocol handler.
*
* Server Client
* -------------------- --------------------
* "checkSellOff {store_id}_{device_id}{pluno}\n"
* <----------------------
* "ok\n" or "nofound\n" or "ng\n"
* ---------------------->
*
*
*/
static void checkSellOff(storeId, deviceId, String pluno, OutputStream output, InputStream input) {
try {
def connSrc= getDbConnection()
def sDao= DaoManager.createDao(connSrc, MposItemSet)
GenericRawResults rawResults= sDao.queryRaw(
"select tranType from tbl_itemset where tranType=1 and pluno = '${pluno}'")
List results= rawResults.getResults()
if (results) {
output<< 'off\n'
log.info"[${storeId}_${deviceId}]Send ok."
} else {
output<< 'ok\n'
log.info"[${storeId}_${deviceId}]Send nofound."
}
} catch (Exception e) {
log.warn"[${storeId}_${deviceId}]checkSellOff failed", e
output<< 'ng\n'
}
def response= readLine(input)
if (response)
log.info"[${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${storeId}_${deviceId}]Client disconnected."
}
/**
* Server-side getTransaction protocol handler.
*
* Server Client
* -------------------- --------------------
* "getTransaction {store_id}_{device_id}{flowno}\n"
* <----------------------
* transaction / null
* ---------------------->
*
*
*/
static void getTransaction(storeId, deviceId, String flowno, OutputStream output, InputStream input) {
try {
def connSrc= getDbConnection(false)
if (isTransactonRefund(connSrc, storeId,'', flowno)) {
output<< 'ng refund\n'
return
}
def hDao= DaoManager.createDao(connSrc, MposTransaction)
def dDao= DaoManager.createDao(connSrc, MposLineItem)
def pDao= DaoManager.createDao(connSrc, MposTransactionTender)
def tDao= DaoManager.createDao(connSrc, MposTicketDtl)
def oDao= DaoManager.createDao(connSrc, MposO2oPayDtl)
def cDao= DaoManager.createDao(connSrc, MposCardDtl)
List transactions= hDao.queryBuilder()
.where().eq('warehouseId', storeId).and().eq('flowno', flowno)
.query()
MposTransaction transaction
if (transactions) {
transaction= transactions[0]
if (transaction.sellway!= 'A') {
output<< 'ng sale\n'
return
}
transaction.details= dDao.queryBuilder().where().eq('warehouseId', storeId).and().eq('flowno', flowno)
.query()
transaction.payments= pDao.queryBuilder().where().eq('warehouseId', storeId).and().eq('flowno', flowno)
.query()
transaction.o2oPayDtls= oDao.queryBuilder().where().eq('Warehouseid', storeId).and().eq('Flowno', flowno)
.query()
transaction.cardDtls= cDao.queryBuilder().where().eq('Warehouseid', storeId).and().eq('Flowno', flowno)
.query()
transaction.ticketDtls= tDao.queryBuilder().where().eq('WarehouseID', storeId).and().eq('Flowno', flowno)
.query()
}
def objects= transaction ?[transaction] :[]
def gson= createGson()
def json= gson.toJson(objects)
output<< json
output<< '\n'
output.flush()
log.info"[${storeId}_${deviceId}]Send ${MposTransaction.simpleName}: ${json}"
def response= readLine(input)
if (response)
log.info"[${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${storeId}_${deviceId}]Client disconnected."
} catch (Exception e) {
log.warn"[${storeId}_${deviceId} ${flowno}]getTransaction failed", e
output<< 'ng\n'
}
}
/**
* Server-side getTransactionInfos protocol handler.
*
* Server Client
* -------------------- --------------------
* "getTransactionInfos {store_id}_{device_id}{accday}\n"
* <----------------------
* transactions / null
* ---------------------->
*
*
*/
static void getTransactionInfos(storeId, deviceId, String diningTableCode, OutputStream output, InputStream input) {
try {
def connSrc= getDbConnection(false)
def today= new SimpleDateFormat("yyyy-MM-dd").format(new Date())
def dao= DaoManager.createDao(connSrc, MposTransaction)
List transactions= dao.queryBuilder().where()
.eq('accdate', today).and().eq('deskNo', diningTableCode)
.and().in('sellway','A','B')
.query()
Map map= [:]
transactions.each{
map[it.flowno] = it
}
GenericRawResults rawResults= dao.queryRaw(
"""select RtnFlowNo from pos_tranhead where RtnFlowNo in
(select flowno from pos_tranhead where Accdate='${today}' and Sellway = 'A')""")
List results= rawResults.getResults()
if (results) {
results.each{ String[] rtnFlowNo ->
MposTransaction t= map[rtnFlowNo[0]]
if (t)
t.rtnFlowNo= 'Y'
}
}
def gson= createGson()
def json= gson.toJson(transactions)
output<< json
output<< '\n'
output.flush()
log.info"[${storeId}_${deviceId}]Send ${MposTransaction.simpleName}: ${json}"
def response= readLine(input)
if (response)
log.info"[${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${storeId}_${deviceId}]Client disconnected."
} catch (Exception e) {
log.warn"[${storeId}_${deviceId} ${diningTableCode}]getTransactionInfos failed", e
output<< 'ng\n'
}
}
/**
* Server-side getTransactionsAndShifts protocol handler.
*
* Server Client
* -------------------- --------------------
* "getTransactionsAndShifts ${storeId}_${posNo}_${custId} ${startDate} ${endDate}\n"
* <----------------------
* transactions / null
* ---------------------->
* shifts / null
* ---------------------->
* shiftReports / null
* ---------------------->
*
*
*/
static void getTransactionsAndShifts(custId, storeId, deviceId, startDate, endDate, OutputStream output, InputStream input) {
try {
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date sDate= sdf.parse(startDate+' 00:00:00');
Date eDate= sdf.parse(endDate+' 23:59:59');
startDate= sdf.format(sDate)
endDate= sdf.format(eDate)
def connSrc= getDbConnection(false)
def dao= DaoManager.createDao(connSrc, MposTransaction)
def dDao= DaoManager.createDao(connSrc, MposLineItem)
def pDao= DaoManager.createDao(connSrc, MposTransactionTender)
def tDao= DaoManager.createDao(connSrc, MposTicketDtl)
def oDao= DaoManager.createDao(connSrc, MposO2oPayDtl)
def cDao= DaoManager.createDao(connSrc, MposCardDtl)
def sDao= DaoManager.createDao(connSrc, MposShift)
def srDao= DaoManager.createDao(connSrc, MposShiftReport)
List transactions= dao.queryBuilder().where().eq('custId', custId).and()
.eq('warehouseId', storeId).and().eq('PosNo', deviceId).and().between('OperDate', sDate, eDate)
// .le('Accdate', endDate).and().ge('Accdate', startDate)
.query()
for (MposTransaction transaction : transactions) {
transaction.details= dDao.queryBuilder().where().eq('warehouseId', storeId).and().eq('flowno', transaction.flowno)
.query()
transaction.payments= pDao.queryBuilder().where().eq('warehouseId', storeId).and().eq('flowno', transaction.flowno)
.query()
transaction.o2oPayDtls= oDao.queryBuilder().where().eq('Warehouseid', storeId).and().eq('Flowno', transaction.flowno)
.query()
transaction.cardDtls= cDao.queryBuilder().where().eq('Warehouseid', storeId).and().eq('Flowno', transaction.flowno)
.query()
transaction.ticketDtls= tDao.queryBuilder().where().eq('WarehouseID', storeId).and().eq('Flowno', transaction.flowno)
.query()
}
List shifts= sDao.queryBuilder().where().eq('custId', custId).and()
.eq('warehouseId', storeId).and().eq('fPosNo', deviceId).and().between('fBegDate', sDate, eDate)
// .le('fAccdate', eDate).and().ge('fAccdate', sDate)
.query()
List shiftReports= srDao.queryBuilder().where().eq('custId', custId).and()
.eq('warehouseId', storeId).and().eq('PosNo', deviceId).and().between('operDate', sDate, eDate)
// .le('accdate', endDate).and().ge('accdate', startDate)
.query()
def gson= createGson()
def json= gson.toJson(transactions)
output<< json
output<< '\n'
output.flush()
log.info"[${storeId}_${deviceId}]Send : ${json}"
json= gson.toJson(shifts)
output<< json
output<< '\n'
output.flush()
log.info"[${storeId}_${deviceId}]Send : ${json}"
json= gson.toJson(shiftReports)
output<< json
output<< '\n'
output.flush()
log.info"[${storeId}_${deviceId}]Send : ${json}"
def response= readLine(input)
if (response)
log.info"[${storeId}_${deviceId}]Client response: ${response}"
else
log.info"[${storeId}_${deviceId}]Client disconnected."
} catch (Exception e) {
log.warn"[${storeId}_${deviceId}]getTransactionInfos failed", e
output<< 'ng\n'
}
}
//获取未打印的厨打
static void getDiffSalesOrders(String posNo, String period, OutputStream output, InputStream input) {
try {
Date now= new Date();
Calendar calendar= Calendar.getInstance();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
String yesterdayStr= sdf.format(now);
Date yesterday= sdf.parse(yesterdayStr)
calendar.setTime(now);
calendar.add(Calendar.SECOND,-Integer.parseInt(period));
Date before= calendar.getTime();
sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String beforeStr= sdf.format(before);
before= sdf.parse(beforeStr)
def connSrc= getDbConnection(false)
def dao= DaoManager.createDao(connSrc, MposDiffSalesOrder)
List diffSalesOrders= dao.queryBuilder().where().eq('PrintFlag','N').and()
.eq('PosNo', posNo).and().between('operDate', yesterday, before)
// .le('Accdate', endDate).and().ge('Accdate', startDate)
.query()
def gson= createGson()
def json= gson.toJson(diffSalesOrders)
output<< json
output<< '\n'
output.flush()
log.info"Send : ${json}"
def response= readLine(input)
if (response)
log.info"Client response: ${response}"
else
log.info"Client disconnected."
} catch (Exception e) {
log.warn"getDiffSalesOrders failed", e
output<< 'ng\n'
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
}
}
//获取沽清商品
static void getMposItemSets(String storeId, String posNo, String period, OutputStream output, InputStream input) {
try {
def connSrc= getDbConnection(false)
def dao= DaoManager.createDao(connSrc, MposItemSet)
List mposItemSet= dao.queryBuilder().where().eq('Warehouseid', storeId).and()
.ne('PosNO', posNo).query()
// .le('Accdate', endDate).and().ge('Accdate', startDate)
def gson= createGson()
def json= gson.toJson(mposItemSet)
output<< json
output<< '\n'
output.flush()
log.info"Send : ${json}"
def response= readLine(input)
if (response)
log.info"Client response: ${response}"
else
log.info"Client disconnected."
} catch (Exception e) {
log.warn"getMposItemSets failed", e
output<< 'ng\n'
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
}
}
//获取未打印的厨打
static void getPlatformOrders(String storeId, String uploadFlag, OutputStream output, InputStream input) {
try {
def connSrc= getDbConnection(false)
def dao= DaoManager.createDao(connSrc, MposJshopTransaction)
def fDao= DaoManager.createDao(connSrc, MposJshopTranflow)
def pDao= DaoManager.createDao(connSrc, MposJshopTranpay)
List diffSalesOrders= []
List diffSalesOrders2= new ArrayList()
Date date1= new Date()
date1.setHours(0);
date1.setMinutes(0);
date1.setSeconds(0);
Calendar calendar= new GregorianCalendar();
calendar.setTime(date1);
calendar.add(calendar.DATE,1);//把日期往后增加一天.整数往后推,负数往前移动
Date date2= calendar.getTime();
if (uploadFlag== 'N') {
diffSalesOrders= dao.queryBuilder().orderBy('operDate',true)
.where().eq('uploadFlag','N').and().eq('warehouseid', storeId)
.and().in('sellway','A','B').and().ge("operDate", date1)
.and().le("operDate", date2).query()
diffSalesOrders.each{
diffSalesOrders2<< it
}
for (MposJshopTransaction jshopTran : diffSalesOrders) {
if (jshopTran.rtnFlowNo&& jshopTran.rtnFlowNo!= "") {
for (MposJshopTransaction jshop : diffSalesOrders) {
if (jshopTran.rtnFlowNo== jshop.flowno) {
diffSalesOrders2.remove(jshopTran)
diffSalesOrders2.remove(jshop)
break
}
}
}
}
} else if (uploadFlag== 'Y') {
diffSalesOrders2= dao.queryBuilder().orderBy('operDate',false).where().eq('uploadFlag','Y').and()
.eq('warehouseid', storeId).and().in('sellway','A','B').query()
}
for (MposJshopTransaction jTran : diffSalesOrders2) {
jTran.tranflows= fDao.queryBuilder().orderBy("itemseq",true).where().eq('warehouseid', storeId).and().eq('flowno',jTran.flowno).query()
}
for (MposJshopTransaction jTran : diffSalesOrders2) {
jTran.tranpays= pDao.queryBuilder().where().eq('warehouseid', storeId).and().eq('flowno',jTran.flowno).query()
}
def gson= createGson()
def json= gson.toJson(diffSalesOrders2)
output<< json
output<< '\n'
output.flush()
log.info"Send : ${json}"
} catch (Exception e) {
log.warn"getPlatformOrders failed", e
output<< 'ng\n'
}
}
//获取未打印的厨打
static void platformOrderUpdate(String storeId, String flowno, String flag, OutputStream output, InputStream input) {
try {
def connSrc= getDbConnection(false)
def dao= DaoManager.createDao(connSrc, MposJshopTransaction)
dao.callBatchTasks{
List diffSalesOrders= dao.queryBuilder().where().eq('flowno', flowno).and()
.eq('warehouseid', storeId).query()
MposJshopTransaction diff= diffSalesOrders ? diffSalesOrders[0] :null
if (diff) {
if (flag== 'S') {
if (diff.uploadFlag== 'N') {
diff.uploadFlag= 'S'
dao.update(diff)
output<< 'ok\n'
} else {
output<< 'ng\n'
}
} else if (flag== 'Y') {
diff.uploadFlag= 'Y'
dao.update(diff)
String sql= "update jshop_orderform set order_status = 30 where pos_sale_flowno = '${flowno}' and store_no = '${storeId}';"
dao.queryRaw(sql)
sql= "insert into jshop_order_log(addtime,deletestatus,log_info,of_id) select getdate(),0,'已出单',id " +
"from jshop_orderform where pos_sale_flowno = '${flowno}' and store_no = '${storeId}';"
dao.queryRaw(sql)
output<< 'ok\n'
}
}
output.flush()
log.info"Send :"
}
} catch (Exception e) {
log.warn"platformOrderUpdate failed", e
output<< 'error\n'
}
}
//修改未打印的厨打为已打印
static void kitchenPlayUpdate(id, output, input) {
try {
def connSrc= getDbConnection(false)
def dao= DaoManager.createDao(connSrc, MposDiffSalesOrder)
UpdateBuilder supdateBuilder= dao.updateBuilder()
supdateBuilder.updateColumnValue('PrintFlag','Y').where().eq('id', id)
int rows= supdateBuilder.update()
output<< 'ok\n'
} catch (Exception e) {
log.warn"kitchenPlayUpdate failed", e
output<< 'ng\n'
}
}
/**
* 获取电子发票 一定要填写MposTransaction.eInvoice和MposTransaction.eInvoiceFlowNo
* 接收参数data 数据以【|】分隔 退货才能用到
* 第一段 原发票代码
* 第二段 原发票号码
*
* 返回
* ng 失败
* eInvoiceSet 电子发票未设定
* 其它 电子发票开票成功 数据以【|】分隔 说明如下:
* 第一段 发票流水号 记录到tranhead.EInvoiceFlowNo字段
* 第二段 发票代码 记录到tranhead.EInvoiceFPDM字段
* 第三段 发票号码 记录到tranhead.EInvoiceFPHM字段
* 第四段 发票下载URL 记录到tranhead.EInvoicePDFURL字段,并将URL生成二维码打印到小票上
*
*/
static void getEInvoice(String custId, String storeId, String deviceId, String data, OutputStream output, InputStream input) {
log.info("[${custId}_${storeId}_${deviceId}] data ${data}")
String objectsInJSON= readLine(input)
log.info"[${custId}_${storeId}_${deviceId}]Receive: ${objectsInJSON}"
Type collectionType= new TypeToken>() {}.getType()
def gson= createGson()
List transactions= gson.fromJson(objectsInJSON, collectionType)
if (transactions) {
def connSrc= getDbConnection()
String result= EInvoiceUtil.getDFXJ1001(transactions.get(0), data, custId, connSrc)
output<< "${result}\n"
} else {
output<< 'ng\n'
}
}
/**
* 接收参数data 数据以【|】分隔
* 第一段为类型 13:微支付 28:支付宝
* 第二段为类型 1:消费 2:查询 3:撤销 4:退货
* 第三段为订单号 唯一编号,消费/查询/撤销/退货都要用到单号
* 第四段为金额 消费/退货时用到,金额都为正数
* 第五段为消费付款码/退货原订单号 消费时传付款码,退货时传原订单号
* 第六段为消费商品说明/退货原接口交易流水号 消费时传一个两个商品名称就可以了,退货时传接口返回的交易流水号
* 第七段为退货原接口非码交易流水号 退货时传接口返回的非码交易流水号 ,只有非码接口才有
* 第八段为收银员编号 消费/退货(非码)时用到
*
* 返回参数result 数据以【|】分隔
* 第一段为状态 0:成功 1:失败 2:等待付款(建议每53秒查询一次)
* 第二段为提示信息 成功/失败的文字说明
* 第三段为接口返回的订单号 消费/退货成功时才返回
* 第四段为接口返回的顾客账号 消费成功时才返回
* 第五段为接口返回的支付渠道(非码) 消费成功时才返回
* 第六段为接口返回的非码支付流水号(非码) 消费成功时才返回
*
*/
static void getO2oPay(String custId, String storeId, String deviceId, String data, OutputStream output, InputStream input) {
if (o2oPayMap.containsKey(data)) {
String result= o2oPayMap.get(data)
log.info("[${storeId}_${deviceId}_${custId}] retry ${result}")
output<< "${result}\n"
return
}
String result= PayUtil.getO2oPay(custId, storeId, deviceId, data, getDbConnection());
log.info("[${storeId}_${deviceId}_${custId}] ${result}")
o2oPayMap.put(data, result)
output<< "${result}\n"
}
static Map o2oPayMap= [:]
static void getSalesOrders(storeId, deviceId, String diningTableIds, OutputStream output, InputStream input) {
try {
// def connSrc = getDbConnection()
def transConnSrc= getDbConnection(false)
def tDao= DaoManager.createDao(transConnSrc, MposDiningTable)
String[] ids= diningTableIds.split('_')
def diningTable= tDao.queryForId(ids[0])
def orderNo= diningTable.tranFlowno// 当前对应的点单号
def sDao= DaoManager.createDao(transConnSrc, MposSalesOrder)
List salesOrders
if (orderNo) {
salesOrders= sDao.queryBuilder()
.orderBy('id',true)
.where().eq('flowno', orderNo).and().ne("saleQty",new BigDecimal(0))
.query()
}
if (!salesOrders) {
salesOrders= []
}
def gson= createGson()
def json= gson.toJson(salesOrders)
output<< json
output<< '\n'
output.flush()
def response= readLine(input)
if (response) {
log.info"[${storeId}_${deviceId}]Client response: ${response}"
} else {
log.info"[${storeId}_${deviceId}]Client disconnected."
return
}
diningTable= tDao.queryForId(ids[1])
orderNo= diningTable.tranFlowno// 当前对应的点单号
sDao= DaoManager.createDao(transConnSrc, MposSalesOrder)
salesOrders= []
if (orderNo) {
salesOrders= sDao.queryBuilder()
.orderBy('id',true)
.where().eq('flowno', orderNo).and().ne("saleQty",new BigDecimal(0))
.query()
}
if (!salesOrders) {
salesOrders= []
}
json= gson.toJson(salesOrders)
output<< json
output<< '\n'
output.flush()
response= readLine(input)
if (response) {
log.info"[${storeId}_${deviceId}]Client response: ${response}"
} else {
log.info"[${storeId}_${deviceId}]Client disconnected."
return
}
} catch (Exception e) {
log.warn"[${storeId}_${deviceId} ${diningTableIds}]getTransactionInfos failed", e
output<< 'ng\n'
}
}
static void putCombineTable(storeId, deviceId, OutputStream output, InputStream input) {
try {
String objectsInJSON= readLine(input)
log.info"[${storeId}_${deviceId}]Receive: ${objectsInJSON}"
def gson= createGson()
Type collectionType= new TypeToken>() {}.getType()
List diningTables= gson.fromJson(objectsInJSON, collectionType)
String sourceTableCode= diningTables[0].deskNo
String targetTableCode= diningTables[1].deskNo
// def connSrc = getDbConnection()
def transConnSrc= getDbConnection(false)
def dao= DaoManager.createDao(transConnSrc, MposDiningTable)
def tdao= DaoManager.createDao(transConnSrc, MposSalesOrder)
String sql= "select deskNo, tranFlowno from pos_deskInfo where deskNo = '${sourceTableCode}' or deskNo = '${targetTableCode}'"
GenericRawResults rawResults= dao.queryRaw(sql)
List results= rawResults.getResults()
int targetTranFlowCount= 0
String sourceFlowno= ''
String targetFlowno= ''
if (results) {
results.each{ String[] resultArray ->
String deskNo= resultArray[0]
if (deskNo== sourceTableCode) {
sourceFlowno= resultArray[1]
} else {
targetFlowno= resultArray[1]
sql= "select COUNT(flowno) from pos_Tranflowhd where flowno = '${resultArray[1]}'"
GenericRawResults rawResults1= tdao.queryRaw(sql)
List results1= rawResults1.getResults()
if (results)
targetTranFlowCount= results1[0][0] as Integer
}
}
}
sql= "update pos_tranflowhd set flowno = '${targetFlowno}', itemseq = itemseq + ${targetTranFlowCount} where WarehouseID='${storeId}' and flowno = '${sourceFlowno}'"
tdao.updateRaw(sql)
diningTables.each{
dao.update it
}
def sdao= DaoManager.createDao(transConnSrc, MposDiffSalesOrder)
List diffSalesOrderList= sdao.queryForEq("flowno", diningTables[1].tranFlowno)
diffSalesOrderList*.roomNo= diningTables[1].roomNo
diffSalesOrderList*.deskNo= diningTables[1].deskNo
diffSalesOrderList*.deskName= diningTables[1].deskName
int allQty= 0
diffSalesOrderList.each{
it.roomNo= diningTables[1].roomNo
it.deskNo= diningTables[1].deskNo
it.deskName= diningTables[1].deskName
it.message= "并桌 原${diningTables[0].deskName} "
allQty+= it.saleQty
sdao.update(it)
}
//打印控菜单
if (dbConf.kitchen.printAll== 'Y') {
try {
lock.lock()
diffSalesOrderList*.allQty= allQty
if (diffSalesOrderList.size() > 0) {
PrintServer printServer= new PrintServer()
printServer.printSaleOrder(diffSalesOrderList)
}
} catch (Exception e) {
log.error(e)
} finally {
lock.unlock()
}
}
output<< 'ok\n'
} catch (Exception e) {
log.warn"[${storeId}_${deviceId} combine table failed", e
output<< 'ng\n'
}
}
static void putSplitTable(storeId, deviceId, OutputStream output, InputStream input) {
try {
String objectsInJSON= readLine(input)
log.info"[${storeId}_${deviceId}]Receive: ${objectsInJSON}"
def gson= createGson()
Type collectionType= new TypeToken>() {}.getType()
List diningTables= gson.fromJson(objectsInJSON, collectionType)
// def connSrc = getDbConnection()
def transConnSrc= getDbConnection(false)
def tDao= DaoManager.createDao(transConnSrc, MposDiningTable)
def dDao= DaoManager.createDao(transConnSrc, MposSalesOrder)
diningTables.each{ diningTable ->
tDao.callBatchTasks{
String tranFlowno= diningTable.tranFlowno
if (tranFlowno) {
def deleteBuilder= dDao.deleteBuilder()
deleteBuilder.where().eq('warehouseId', storeId).and().eq('flowno', tranFlowno)
int rows= deleteBuilder.delete()
if (rows> 0)
log.info"Delete existing $rows rows from pos_tranflowhd with warehouseId='$storeId' and flowno='$diningTable.tranFlowno'"
}
if (diningTable.salesOrders.size() > 0) {
if (!tranFlowno) {
tranFlowno= getNextOrderNumberOfDevice(transConnSrc, storeId, deviceId)
diningTable.tranFlowno= tranFlowno
}
diningTable.salesOrders.each{ salesOrder ->
salesOrder.id= 0
salesOrder.flowno= tranFlowno
dDao.create salesOrder
}
} else {
diningTable.tranFlowno= ''
}
tDao.update diningTable
}
}
output<< 'ok\n'
} catch (Exception e) {
log.warn"[${storeId}_${deviceId} split table failed", e
output<< 'ng\n'
}
}
static void copy(storeId, deviceId, InputStream inputStream, OutputStream outputStream) {
byte[] buffer= new byte[1024]
int length
while ((length= inputStream.read(buffer)) > 0) {
outputStream.write(buffer,0, length)
}
log.info"[${storeId}_${deviceId}]Write... end"
outputStream.flush()
}
static void copy(storeId, deviceId, InputStream inputStream, OutputStream outputStream, size) {
byte[] buffer= new byte[1024]
int length
int lengthRead= 0
while ((length= inputStream.read(buffer)) > 0) {
outputStream.write(buffer,0, length)
lengthRead+= length
if (lengthRead>= size)
break;
}
log.info"[${storeId}_${deviceId}]Write... end"
outputStream.flush()
}
/**
* Read directory info from Groovy script: conf/db.properties.
*/
static void getUploadDir2() {
dbConf= new ConfigSlurper().parse(new File('conf/db.properties').toURI().toURL())
uploadDir= dbConf.db.uploadDir ? dbConf.db.uploadDir :'inbox'
log.info"uploadDir = ${uploadDir}"
transDirInConf= dbConf.db.transDir ? dbConf.db.transDir :'trans'
log.info"transDir = ${transDirInConf}"
}
/** Read database connection info from Groovy script:conf/db.properties, and create ORMLite connection source. */
static ConnectionSource getDbConnection(boolean isMaster= true) {
log.info("AppServer getDbConnection() isMaster = ${isMaster}")
ConnectionSource db
if (isMaster) {
db= DBUtil.getMasterDbConnection()
} else {
db= DBUtil.getTransDbConnection()
}
dbType= DBUtil.dbType
return db
}
/** Read database connection info from Groovy script: conf/db.properties, and create Groovy Sql object. */
static Sql getGroovySql() {
dbConf= new ConfigSlurper().parse(new File('conf/db.properties').toURI().toURL())
dbType= (dbConf.db.url.contains('mysql')) ?'MySQL' :
(dbConf.db.url.contains('sqlserver')) ?'SQLServer' :'Sybase'
TABLE_PREFIX= (dbType== 'Sybase' ?'tab.' :'')
Sql.newInstance(dbConf.db.url, dbConf.db.user, dbConf.db.password, dbConf.db.driverClass)
}
/** Load dining table state transition rules in STL (State Transition Language). */
static void loadSTLMap() {
stlMap.clear()
dbConf= new ConfigSlurper().parse(new File('conf/db.properties').toURI().toURL())
if (dbConf.stl) {
def stl= dbConf.stl ?:'0空桌 -> 1点餐中 <-> 2已点餐 <-> 3结账中 -> 4已结账 & 清桌中 -> 0空桌'
def tokens= stl.split(/(?<=(<->))|(?=(<->))/).collect{
(it== '<->') ? it : it.split(/(?<=(->))|(?=(->))/)
}.flatten()*.replaceAll(/^\s*/,'')*.trim()
tokens.eachWithIndex{ token, idx ->
if (token== '->' || token== '<->') {
def left= tokens[idx- 1][0]
def right= tokens[idx+ 1][0]
stlMap[left] = (stlMap[left] ?:'') + right
if (token== '<->')
stlMap[right] = (stlMap[right] ?:'') + left
}
}
}
//println stlMap
}
//获取当前门店营业日期
static String getAccDate(String storeId) {
ConnectionSource db= getDbConnection(false)
Dao dao= DaoManager.createDao(db, MposTransaction)
GenericRawResults rawResults1= dao.queryRaw("select faccdate from calendar where fOrgNo = ${storeId}")
List results1= rawResults1.getResults()
Date accdate= null
if (results1) {
String str= results1[0][0]
if (str.length() > 10) {
return str.substring(0,10)
}
accdate= new Date()
}
if (!accdate) {
accdate= new Date()
}
SimpleDateFormat format= new SimpleDateFormat("yyyy-MM-dd")
return format.format(accdate)
}
/** Start method of Apache Commons Procrun. */
static void start(String[] args) {
main(null)
}
/** Stop method of Apache Commons Procrun. */
static void stop(String[] args) {
System.exit0
}
static void init() {
try {
ConnectionSource db= getDbConnection(false)
log.info("init getDbConnection .")
// ['Tc_Shift', 'MposShift', '交班表'],
TableUtils.createTableIfNotExists(db, MposShift.class)
//['pos_tranflowhd', 'MposSalesOrder', '点单表'],
TableUtils.createTableIfNotExists(db, MposSalesOrder.class)
//厨打
TableUtils.createTableIfNotExists(db, MposDiffSalesOrder.class)
//['pos_tranhead', 'MposTransaction', '交易主表'],
TableUtils.createTableIfNotExists(db, MposTransaction.class)
//['pos_tranflow', 'MposLineItem', '交易明细'],
TableUtils.createTableIfNotExists(db, MposLineItem.class)
//['pos_tranpay', 'MposTransactionTender', '交易支付'],
TableUtils.createTableIfNotExists(db, MposTransactionTender.class)
//第三方支付明细
TableUtils.createTableIfNotExists(db, MposO2oPayDtl.class)
//礼券明细
TableUtils.createTableIfNotExists(db, MposTicketDtl.class)
//外卖平台交易
TableUtils.createTableIfNotExists(db, MposTakeOutTransaction.class)
//外卖平台交易明细
TableUtils.createTableIfNotExists(db, MposTakeOutTranflow.class)
//银行支付明细
TableUtils.createTableIfNotExists(db, MposCardDtl.class)
TableUtils.createTableIfNotExists(db, MposDiningArea.class)
TableUtils.createTableIfNotExists(db, MposDiningTable.class)
TableUtils.createTableIfNotExists(db, MposShiftReport.class)
TableUtils.createTableIfNotExists(db, MposTrantaste.class)
log.info("Tables was created.")
deleteHistoryData(dbConf.TransReserved ?:2)
databaseCheck(db)
} catch (Exception e) {
log.error('AppServer', e)
}
}
static void deleteHistoryData(int month) {
ConnectionSource db= getDbConnection(false)
SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd")
Calendar dueDate= Calendar.getInstance()
dueDate.setTime(new Date())
dueDate.add(Calendar.MONTH,-month)
String dateStr= formatter.format(dueDate.getTime())
//删除礼券支付明细
log.info("Remove pos_TicketDtl before " + dateStr)
def tkDao= DaoManager.createDao(db, MposTicketDtl)
DeleteBuilder db5= tkDao.deleteBuilder()
db5.where().lt("Accdate", dateStr).and().ne('Accdate','1970-01-01')
db5.delete()
//删除第三方式支付明细
log.info("Remove pos_o2opaydtl before " + dateStr)
def oDao= DaoManager.createDao(db, MposO2oPayDtl)
DeleteBuilder db4= oDao.deleteBuilder()
db4.where().lt("Accdate", dateStr).and().ne('Accdate','1970-01-01')
db4.delete()
//删除银联支付明细
log.info("Remove pos_carddtl before " + dateStr)
def cDao= DaoManager.createDao(db, MposCardDtl)
DeleteBuilder db10= cDao.deleteBuilder()
db10.where().lt("Accdate", dateStr).and().ne('Accdate','1970-01-01')
db10.delete()
//删除明细
log.info("Remove pos_tranflow before " + dateStr)
def dDao= DaoManager.createDao(db, MposLineItem)
DeleteBuilder db2= dDao.deleteBuilder()
db2.where().lt("AccDate", dateStr).and().ne('Accdate','1970-01-01')
db2.delete()
//删除点餐明细
log.info("Remove pos_tranflowhd before " + dateStr)
def soDao= DaoManager.createDao(db, MposSalesOrder)
DeleteBuilder db8= soDao.deleteBuilder()
db8.where().lt("operDate", dueDate.getTime())
db8.delete()
//删除厨打明细
log.info("Remove pos_tranflowhd before " + dateStr)
def dsDao= DaoManager.createDao(db, MposDiffSalesOrder)
DeleteBuilder db9= dsDao.deleteBuilder()
db9.where().lt("operDate", dueDate.getTime())
db9.delete()
//删除支付明细
log.info("Remove pos_tranpay before " + dateStr)
def tDao= DaoManager.createDao(db, MposTransactionTender)
DeleteBuilder db3= tDao.deleteBuilder()
db3.where().lt("Accdate", dateStr).and().ne('Accdate','1970-01-01')
db3.delete()
//删除头表
log.info("Remove pos_tranhead before " + dateStr)
def hDao= DaoManager.createDao(db, MposTransaction)
DeleteBuilder db1= hDao.deleteBuilder()
db1.where().lt("AccDate", dateStr).and().ne('Accdate','1970-01-01')
db1.delete()
//删除交班支付明细表
log.info("Remove Tc_Shift before " + dateStr)
def psDao= DaoManager.createDao(db, MposShiftReport)
DeleteBuilder db7= psDao.deleteBuilder()
db7.where().lt("Accdate", dateStr).and().ne('Accdate','1970-01-01')
db7.delete()
//删除交班头表
log.info("Remove Tc_Shift before " + dateStr)
def sDao= DaoManager.createDao(db, MposShift)
DeleteBuilder db6= sDao.deleteBuilder()
db6.where().lt("fAccDate", dueDate.getTime()).and().ne('fAccdate', getInitialDate())
db6.delete()
}
static void version1_4_9(DatabaseConnection conn) {
try {
conn.executeStatement('''\
select elecDiscountAmt from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add elecDiscountAmt decimal(12, 2); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select elecIptNum from pos_TicketDtl''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_TicketDtl add elecIptNum VARCHAR(20); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select ticketType from pos_TicketDtl''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_TicketDtl add ticketType VARCHAR(20); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select type from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add type VARCHAR(100); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select AgeLevel from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add AgeLevel int; ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select returnPartAmount from pos_carddtl''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_carddtl add returnPartAmount decimal(12, 2); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select taste_nos from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add taste_nos VARCHAR(100); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select memo from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add memo VARCHAR(100); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select taste_nos from pos_TranflowhdPr''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_TranflowhdPr add taste_nos VARCHAR(100); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select comment from pos_TranflowhdPr''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_TranflowhdPr add comment VARCHAR(100); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select taste_nos from pos_tranflowhd''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranflowhd add taste_nos VARCHAR(100); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select comment from pos_tranflowhd''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranflowhd add comment VARCHAR(100); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select pcouponAmount from pos_o2opaydtl''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_o2opaydtl add pcouponAmount decimal(12, 2); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select discountAcc from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add discountAcc VARCHAR(20); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select discountType from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add discountType VARCHAR(10); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select discountNum from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add discountNum VARCHAR(20); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select delivery_type from takeOut_postranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table takeOut_postranhead add delivery_type int; ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select delivery_party from takeOut_postranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table takeOut_postranhead add delivery_party VARCHAR(50); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select package_amount from takeOut_postranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table takeOut_postranhead add package_amount int; ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select GrosalAMT from takeOut_postranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table takeOut_postranhead add GrosalAMT decimal(12, 2); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select foodType from takeOut_postranflow''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table takeOut_postranflow add foodType VARCHAR(10); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select discAmt from takeOut_postranflow''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table takeOut_postranflow add discAmt decimal(12, 2); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select tranState from pos_o2opaydtl''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_o2opaydtl add tranState varchar(5); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select origamt from pos_carddtl''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_carddtl add origamt decimal(12, 2); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select mcouponamount from pos_carddtl''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_carddtl add mcouponamount decimal(12, 2); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select pcouponAmount from pos_carddtl''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_carddtl add pcouponAmount decimal(12, 2); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select point from pos_carddtl''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_carddtl add point decimal(12, 2); ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
}
static void version1_4_2(DatabaseConnection conn) {
try {
conn.executeStatement('''\
select isEInvoice from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add isEInvoice VARCHAR(10) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select custNumber from pos_tranflowhd''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranflow add custNumber int default 1 ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select custNumber from pos_TranflowhdPr''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_TranflowhdPr add custNumber int default 1 ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select custNumber from pos_Tranflowhd''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_Tranflowhd add custNumber int default 1 ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
}
static void version1_4_1(DatabaseConnection conn) {
try {
conn.executeStatement('''\
select EInvoiceContent from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add EInvoiceContent varchar(200) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select tariffNo from pos_tranflow''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranflow add tariffNo varchar(50) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select tariffName from pos_tranflow''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranflow add tariffName varchar(100) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select fClassStNo from pos_tranflow''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranflow add fClassStNo varchar(50) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select EInvoiceFlowNo from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add EInvoiceFlowNo varchar(20) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select EInvoiceFPDM from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add EInvoiceFPDM varchar(20) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select EInvoiceFPHM from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add EInvoiceFPHM varchar(20) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select EInvoicePDFURL from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add EInvoicePDFURL varchar(200) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
}
static void version1_4_0(DatabaseConnection conn) {
try {
conn.executeStatement('''\
select platformType from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add platformType varchar(20) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select jshopFlowno from pos_tranhead''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranhead add jshopFlowno varchar(50) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select TaxId from pos_tranflow''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table pos_tranflow add TaxId decimal(12, 2) ''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select pointChange from tc_shift''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table Tc_Shift add pointChange int''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select point from tc_shift''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table Tc_Shift add point int''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select RefillAmt from tc_shift''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table tc_shift add RefillAmt decimal(12, 2)''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select ServiceAmt from tc_shift''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table tc_shift add ServiceAmt decimal(12, 2)''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select RefundAmt from tc_shift''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table tc_shift add RefundAmt RefundAmt(12, 2)''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select OverAmt from tc_shift''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table tc_shift add OverAmt RefundAmt(12, 2)''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select inAmt from tc_shift''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table tc_shift add inAmt RefundAmt(12, 2)''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
try {
conn.executeStatement('''\
select outAmt from tc_shift''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
} catch (Exception e) {
conn.executeStatement('''\
alter table tc_shift add outAmt outAmt(12, 2)''', DatabaseConnection.DEFAULT_RESULT_FLAGS)
}
}
static databaseCheck(ConnectionSource sqlserverConn) {
DatabaseConnection conn
try {
conn= sqlserverConn.getReadWriteConnection()
version1_4_0(conn)
version1_4_1(conn)
version1_4_2(conn)
version1_4_9(conn)
} catch (Exception e) {
log.error('Failed ', e)
} finally {
if (conn)
sqlserverConn.releaseConnection conn
}
}
static Date getInitialDate() {
Date initDate= new Date(0);
int timeOffset= 0;
TimeZone timeZone= Calendar.getInstance().getTimeZone();
timeOffset= timeOffset- timeZone.getRawOffset();
initDate.setTime(timeOffset);
return initDate;
}
/**
* Entry point of App Server.
*/
static main(_) {
// Help to find log4j.properties
PropertyConfigurator.configure'conf/log4j.properties'
log.info("AppServer is starting")
// Remove log files one month ago
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate({
def now= new Date()
def dueDay= String.format('%1$tY-%1$tm-%1$td', now- 30)
('log' as File).eachFile{ logFile ->
def extension= logFile.name.split(/\./)[-1]
if (extension==~ /2\d\d\d-\d\d-\d\d/ && extension< dueDay)
logFile.delete()
}
},0,1, TimeUnit.HOURS)
//半夜四点重启系统
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate({
def now= new Date()
log.info("system exit")
int hour= 4
try {
if (dbConf.rebootHour!= 4) {
hour= Integer.valueOf(dbConf.rebootHour).intValue()
}
} catch (Exception e){}
if (now.hours== hour) {
log.info("system exit ${now.hours}")
System.exit(0)
}
},30,40, TimeUnit.MINUTES)
try {
Thread.sleep(5000)
} catch (Exception e){}
loadSTLMap()
//判断是否启动厨打
if (dbConf.kitchen.print!= 'N') {
// PrintServer.lock = lock
PrintServer.main(null)
}
APP_SERVER_PORT= dbConf.serverPort ? Integer.valueOf(dbConf.serverPort) : APP_SERVER_PORT
serverType= dbConf.serverType
try {
log.info("PushServer start")
pushServer= new PushServer()
} catch (Exception e) {
log.error("AppServer PushServer error", e)
}
try {
if (serverType== 'SC') {
log.info("AppServer init()")
init()
if (dbConf.runType== '1')
new Thread(new Runnable() {
@Override
void run() {
AppClient.main(['true', VERSION] as String[])
}
}).start()
} else if (serverType== 'HQ') {
//自动生成主档
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate({
def now= new Date()
log.info("master copy ")
int hour= 5
try {
if (dbConf.masterCopyHour!= 5) {
hour= (Integer.valueOf(dbConf.masterCopyHour).intValue())
}
} catch (Exception e){}
if (now.hours== hour) {
log.info("master copy ${now.hours}")
MposMasterCopy.main("001_")
}
},0,40, TimeUnit.MINUTES)
//HQ的通讯server启动时将非码client启动
if (dbConf.runFmClient!= 'N') {
try {
log.info("./FMClient/fmstart.bat")
Runtime.runtime.exec("./FMClient/fmstart.bat")
} catch (Exception e) {}
}
}
} catch (Exception e) {
log.error("AppServer process serverType", e)
}
// Start server loop
for (; ;) {
try {
serverLoop()
} catch (BindException e) {
log.warn'main> Server close', e
System.exit(0)
return
} catch (Exception e) {
log.warn'main> Server failed', e
if (e.getMessage().contains('maximum connections reached')) {
System.exit(1)
}
} finally {
try {
server?.close()
server= null
sleep2000
} catch (Exception ignore) {
}
}
}
}
}
APPServer32类
package hyi.pos.appserver.server;
import org.boris.winrun4j.AbstractService;
import org.boris.winrun4j.EventLog;
import org.boris.winrun4j.ServiceException;
import java.io.File;
/**
* App server starter. It'll run as a Windows service.
*
* This class will be packaged as AppServerStarter.jar, and put it to SC's c:\AppServer directory.
*
* @author Bruce You
* @since 2013 Mar.
*/
public class AppServerStarter32 extends AbstractService {
private static final String TAG = "AppServerStarter";
//private static final String HOME_DIR = ".";
//创建一个进程
private Process appServerProcess;
@Override
public int serviceMain(String[] args) throws ServiceException {
for (;;) {
try {
// Respawn AppServer.exe --
ProcessBuilder pb = new ProcessBuilder(args.length > 0 ? args[0] : "AppServer32.exe");
//pb.directory(new File(HOME_DIR));
appServerProcess = pb.start();
EventLog.report(TAG, EventLog.INFORMATION, "Start " + (args.length > 0 ? args[0] : "AppServer32.exe"));
appServerProcess.waitFor();
appServerProcess = null;
} catch (Exception e) {
EventLog.report(TAG, EventLog.WARNING, e.getMessage());
}
}
}
@Override
public int serviceRequest(int control) throws ServiceException {
super.serviceRequest(control);
switch (control) {
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
if (appServerProcess != null)
appServerProcess.destroy();
System.exit(0);
}
return 0;
}
}
AppServer64类:
package hyi.pos.appserver.server;
import org.boris.winrun4j.AbstractService;
import org.boris.winrun4j.EventLog;
import org.boris.winrun4j.ServiceException;
import java.io.File;
/**
* App server starter. It'll run as a Windows service.
*
* This class will be packaged as AppServerStarter.jar, and put it to SC's c:\AppServer directory.
*
* @author Bruce You
* @since 2013 Mar.
*/
public class AppServerStarter64 extends AbstractService {
private static final String TAG = "AppServerStarter";
// private static final String HOME_DIR = ".";
private Process appServerProcess;
@Override
public int serviceMain(String[] args) throws ServiceException {
for (;;) {
try {
// Respawn AppServer.exe --
//进程建立
ProcessBuilder pb = new ProcessBuilder(args.length > 0 ? args[0] : "AppServer64.exe");
// pb.directory(new File(HOME_DIR));
appServerProcess = pb.start();
EventLog.report(TAG, EventLog.INFORMATION, "Start " + (args.length > 0 ? args[0] : "AppServer64.exe"));
appServerProcess.waitFor();
appServerProcess = null;
} catch (Exception e) {
EventLog.report(TAG, EventLog.WARNING, e.getMessage());
}
}
}
@Override
public int serviceRequest(int control) throws ServiceException {
super.serviceRequest(control);
switch (control) {
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
if (appServerProcess != null)
appServerProcess.destroy();
System.exit(0);
}
return 0;
}
}
官网解释: