order_service.go 106 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131
  1. package service
  2. import (
  3. "database/sql"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. mercator "git.xiaoniaokuaiyan.com/qiaozhi/xn-mercator"
  8. "github.com/smartwalle/alipay/v3"
  9. "gopkg.in/guregu/null.v3"
  10. "log"
  11. "math/rand"
  12. "strconv"
  13. "strings"
  14. "sync"
  15. "time"
  16. "xiaoniaokuaiyan.com/xiaoniao/pay/ali"
  17. "xiaoniaokuaiyan.com/xiaoniao/config"
  18. "xiaoniaokuaiyan.com/xiaoniao/constants"
  19. "xiaoniaokuaiyan.com/xiaoniao/dal"
  20. "xiaoniaokuaiyan.com/xiaoniao/entity"
  21. "xiaoniaokuaiyan.com/xiaoniao/pay/wx"
  22. "xiaoniaokuaiyan.com/xiaoniao/util"
  23. )
  24. type OrderService struct {
  25. dal.IOrder
  26. *WeixinService
  27. }
  28. /*
  29. type tubeInfo struct {
  30. Yellow uint `json:"yellow"`
  31. Green uint `json:"green"`
  32. Purple uint `json:"purple"`
  33. }
  34. */
  35. type OrderHookSymbol int
  36. const (
  37. BEFORE_ORDER_CREATE OrderHookSymbol = iota + 1
  38. AFTER_ORDER_CANCEL
  39. )
  40. const BUYER_OPENID_KEY string = "buyer_openid_key"
  41. const BUYER_TPL string = "支付成功,我们会尽快为被邀请人发送酒精基因检测包"
  42. const OPENID_TPL string = "您的朋友已经为您支付成功,我们会尽快为您邮寄酒精基因检测包"
  43. type OrderHookHandle func(oitem *entity.Order) error
  44. var orderHooks = map[OrderHookSymbol][]OrderHookHandle{}
  45. func RegistOrderHook(typ OrderHookSymbol, handle OrderHookHandle) {
  46. if _, ok := orderHooks[typ]; !ok {
  47. orderHooks[typ] = []OrderHookHandle{}
  48. }
  49. orderHooks[typ] = append(orderHooks[typ], handle)
  50. }
  51. func (srv *OrderService) AddOrder(orderItem *entity.Order, city_id int, city string) (interface{}, error) {
  52. if orderItem == nil || len(orderItem.ProductIds) == 0 {
  53. return nil, errors.New("1::wrong request")
  54. }
  55. var btime time.Time
  56. btime, err := time.Parse("2006-01", orderItem.Birthday)
  57. if err != nil {
  58. btime, err = time.Parse("2006-01-02", orderItem.Birthday)
  59. if err != nil {
  60. return nil, errors.New("9::wrong birthday")
  61. }
  62. }
  63. if orderItem.Age <= 0 {
  64. orderItem.Age = time.Now().Year() - btime.Year()
  65. }
  66. db := util.GetWriteSqlDB()
  67. var (
  68. productIds = []int{}
  69. productQuantityMap = map[int]int{}
  70. )
  71. for _, v := range orderItem.ProductIds {
  72. productIds = append(productIds, v.ProductId)
  73. //20210119 添加 产品1149 两人核酸,下单后拆单
  74. //splitProductId, err := config.IniConf.Section("server").Key("split_product").Int()
  75. //if err == nil && v.ProductId == splitProductId {
  76. // v.Quantity *= 2
  77. //}
  78. productQuantityMap[v.ProductId] = v.Quantity
  79. }
  80. /*
  81. var plist = []*entity.ProductDB{}
  82. //db.Select(&plist, "select * from t_product where id in ("+util.IntJoin(productIds, ",")+") order by is_no_booktime desc")
  83. s_source_zfb := ""
  84. if orderItem.IsZFB {
  85. s_source_zfb = " and t2.source='sp_zfb' "
  86. }
  87. sqlTemp := "select t1.*, sum(t4.quantity) as bought_num from (select * from t_product where id in(" + util.IntJoin(productIds, ",") + ")) t1 left join (select t3.quantity, t3.product_id from t_order t2 left join t_order_product t3 on t2.id = t3.order_id where custom_mobile = ? and t2.status not in (7,9,14) and t2.retype in ('100','110') " + s_source_zfb + " ) t4 on t1.id = t4.product_id GROUP BY t1.id order by t1.is_no_booktime desc"
  88. db.Select(&plist, sqlTemp, orderItem.CustomMobile)
  89. if len(plist) != len(productIds) {
  90. return nil, errors.New("6::wrong param productids")
  91. }
  92. // 20230629 增加支付宝特殊处理
  93. if orderItem.IsZFB {
  94. entity.ZFBWash(plist)
  95. }
  96. //检查库存以及个人限量
  97. for _, pitem := range plist {
  98. if pitem.StockSwitch == "ON" && pitem.Stock < productQuantityMap[pitem.Id] {
  99. return nil, errors.New("10::out of stock")
  100. }
  101. if pitem.PstockSwitch == "ON" && int(pitem.BoughtNum.Int64)+productQuantityMap[pitem.Id] > pitem.Pstock {
  102. return nil, errors.New(fmt.Sprintf("11::upper limit of product %d", pitem.Id))
  103. }
  104. //20210922 处理坐标
  105. if pitem.SaleMode == 100 && strings.Contains(orderItem.Coordinates, ",") {
  106. str := "select maps from v_product_city where city_id = ? and product_id = ?"
  107. var maps string
  108. err = db.Get(&maps, str, city_id, pitem.Id)
  109. is := mercator.IsPointInRingByStr(orderItem.Coordinates, maps)
  110. if !is {
  111. return nil, fmt.Errorf("12::订单坐标超过范围 %s", orderItem.Coordinates)
  112. }
  113. }
  114. }*/
  115. plist, err := Stocklimit(orderItem.CustomMobile, productIds, productQuantityMap, orderItem.IsZFB)
  116. if err != nil {
  117. return nil, err
  118. }
  119. for _, pitem := range plist {
  120. //20210922 处理坐标
  121. if pitem.SaleMode == 100 && strings.Contains(orderItem.Coordinates, ",") {
  122. str := "select maps from v_product_city where city_id = ? and product_id = ?"
  123. var maps string
  124. err = db.Get(&maps, str, city_id, pitem.Id)
  125. is := mercator.IsPointInRingByStr(orderItem.Coordinates, maps)
  126. if !is {
  127. return nil, fmt.Errorf("12::订单坐标超过范围 %s", orderItem.Coordinates)
  128. }
  129. }
  130. }
  131. //如果产品中含有不需要预约时间的,则省略产能检查
  132. //检查产能是否足够
  133. strSql := "select t1.gnum, t2.remain_num, t2.pdate, t1.id as gid, t2.id as infoid, t1.shortname from (select tpc.id, num as gnum, shortname from t_producer_config tpc,t_city where city_id = t_city.id and city_id = ? and tpc.id = ?) t1 left join t_producer_info t2 on t1.id = t2.global_id and t2.pdate = ? and t2.time_range = ?"
  134. var producerInfo = struct {
  135. GNum int `db:"gnum"`
  136. RemainNum sql.NullInt64 `db:"remain_num"`
  137. PDate sql.NullString `db:"pdate"`
  138. GId int `db:"gid"`
  139. InfoId sql.NullInt64 `db:"infoid"`
  140. Shortname string `db:"shortname"`
  141. }{}
  142. var pinfoSqlResult sql.Result
  143. err = db.Get(&producerInfo, strSql, city_id, orderItem.PTId, orderItem.VisitDate, orderItem.VisitTimeRange)
  144. if err != nil {
  145. return nil, errors.New("4::该城市暂未开通服务")
  146. }
  147. tx := db.MustBegin()
  148. if len(plist) > 0 && plist[0].IsNoBooktime != 1 {
  149. visitDate, err := time.Parse("2006-01-02", orderItem.VisitDate)
  150. if err != nil {
  151. return nil, errors.New("2::wrong visit date")
  152. }
  153. //当天下单最早只能约第二天上门,240220 houyf改为20点
  154. if visitDate.Before(time.Now()) || (time.Now().Hour() >= 20 && time.Now().Truncate(time.Hour*24).Add(time.Hour*48).After(visitDate)) {
  155. return nil, errors.New("3::invalid visit date")
  156. }
  157. if producerInfo.PDate.String == orderItem.VisitDate && producerInfo.RemainNum.Int64 <= 0 {
  158. return nil, errors.New("5::producer not enough")
  159. }
  160. if !producerInfo.PDate.Valid {
  161. pinfoSqlResult = tx.MustExec("insert into t_producer_info(global_id, pdate, time_range, num, remain_num) values(?, ?, ?, ?, ?)", producerInfo.GId, visitDate, orderItem.VisitTimeRange, producerInfo.GNum, producerInfo.GNum-1)
  162. lid, err := pinfoSqlResult.LastInsertId()
  163. if err != nil {
  164. tx.Tx.Rollback()
  165. return nil, err
  166. }
  167. orderItem.MaterialId = int(lid)
  168. } else {
  169. pinfoSqlResult = tx.MustExec("update t_producer_info set remain_num = ? where id = ? and remain_num = ?", producerInfo.RemainNum.Int64-1, producerInfo.InfoId, producerInfo.RemainNum.Int64)
  170. orderItem.MaterialId = int(producerInfo.InfoId.Int64)
  171. }
  172. if ra, _ := pinfoSqlResult.RowsAffected(); ra <= 0 {
  173. tx.Tx.Rollback()
  174. return nil, errors.New("7::failed to update producer info")
  175. }
  176. }
  177. //orderItem.VisitDate = visitDate
  178. if city == "" {
  179. if producerInfo.Shortname != "" {
  180. city = producerInfo.Shortname
  181. } else {
  182. city = "QG"
  183. }
  184. }
  185. orderId := GenerateOrderNo(city)
  186. orderItem.Id = orderId
  187. //region 20221012 护士加项 使用折扣金额
  188. result := map[string]interface{}{}
  189. isNurse := false
  190. json.Unmarshal([]byte(orderItem.ShareSource), &result)
  191. if nurse, ok := result["source"].(string); ok && nurse == "nurse" {
  192. if deliver_user_id, ok := result["id"].(float64); ok {
  193. orderItem.Payment, orderItem.RepeatItemFee, err = ComputeProductPriceByDeliverID(productIds, productQuantityMap, deliver_user_id)
  194. isNurse = true
  195. }
  196. }
  197. if !isNurse { //20221012如果没经过护士折扣,就正常计算价格
  198. orderItem.Payment, orderItem.RepeatItemFee, err = ComputeProductPrice(productIds, productQuantityMap, false)
  199. }
  200. // 20230629 增加支付宝特殊处理
  201. if orderItem.IsZFB {
  202. orderItem.Payment, orderItem.RepeatItemFee, err = ComputeProductPrice_ZFB(productIds, productQuantityMap)
  203. }
  204. //endregion
  205. //orderItem.Payment, orderItem.RepeatItemFee, err = ComputeProductPrice(productIds, productQuantityMap, false)
  206. //20211127 联仁根据门店id 修改定价
  207. if shopId, ok := util.StringToInt(orderItem.JdOrderId); ok && orderItem.Source == "lianren" {
  208. lianRenPrice(plist, shopId)
  209. orderItem.Payment = plist[0].Price
  210. }
  211. //取消减免重复项目费用
  212. orderItem.RepeatItemFee = 0
  213. if err != nil {
  214. tx.Tx.Rollback()
  215. return nil, err
  216. }
  217. if len(orderItem.ItemIds) > 0 {
  218. iprice, _, err := ComputeProductPrice(orderItem.ItemIds, productQuantityMap, true)
  219. if err != nil {
  220. tx.Tx.Rollback()
  221. return nil, err
  222. }
  223. orderItem.Payment += iprice
  224. tempResult := tx.MustExec("insert into t_product_detect_item(detect_item_ids) values(?)", util.IntJoin(orderItem.ItemIds, ","))
  225. if tpid, err := tempResult.LastInsertId(); err != nil {
  226. tx.Tx.Rollback()
  227. return nil, err
  228. } else {
  229. tx.MustExec("insert into t_order_product(order_id, product_id, is_personal) values(?,?,?)", orderId, tpid, 1)
  230. }
  231. }
  232. WORK_FEE_REQUIRED, _ := config.IniConf.Section("server").Key("work_fee_required_bound").Int()
  233. WORK_FEE, _ := config.IniConf.Section("server").Key("work_fee").Int()
  234. //判断是否需要上门费
  235. orderItem.OnlinePayment = orderItem.Payment
  236. for _, pitem := range plist {
  237. if pitem.SaleMode == 200 || pitem.IsWorkFee == 2 {
  238. orderItem.OnlinePayment -= pitem.Price
  239. }
  240. }
  241. if orderItem.Source != "web-jiaxiang" && (orderItem.OnlinePayment > 0 && orderItem.Payment < WORK_FEE_REQUIRED) {
  242. orderItem.WorkFee = WORK_FEE
  243. }
  244. //todo 20210331 判断是否活动来的订单,如果是某些特殊的产品id,按照数量扣减99块钱(2,132,568,645,958)
  245. //存到RepeatItemFee 里面,这样,在支付的时候,和前端都可以扣减相应的钱
  246. if len(orderItem.CustomManagerId) > 0 {
  247. cmId := &struct {
  248. Source string `json:"s"`
  249. IsCheck string `json:"t"`
  250. }{}
  251. err := json.Unmarshal([]byte(orderItem.CustomManagerId), &cmId)
  252. quantity := 0
  253. if err == nil && cmId.IsCheck == "200" {
  254. if count, ok := productQuantityMap[2]; ok {
  255. quantity += count
  256. }
  257. if count, ok := productQuantityMap[132]; ok {
  258. quantity += count
  259. }
  260. if count, ok := productQuantityMap[568]; ok {
  261. quantity += count
  262. }
  263. if count, ok := productQuantityMap[645]; ok {
  264. quantity += count
  265. }
  266. if count, ok := productQuantityMap[958]; ok {
  267. quantity += count
  268. }
  269. orderItem.RepeatItemFee += 99 * quantity * 100
  270. }
  271. }
  272. if orderItem.OnlinePayment <= 0 {
  273. orderItem.OnlinePayment = -1
  274. }
  275. orderItem.CreatedAt = time.Now().Format("2006-01-02 15:04:05")
  276. //判断并标记是否来自销售系统订单
  277. if srv.IsAgentOrder(orderItem.OpenId) {
  278. orderItem.IsAgent = 1
  279. }
  280. relationship := orderItem.Relationship
  281. orderItem.Relationship = ""
  282. strSql, mkv := util.GenerateInsertSqlFromStruct("t_order", orderItem)
  283. osqlResult, err := tx.NamedExec(strSql, mkv)
  284. if err != nil {
  285. tx.Tx.Rollback()
  286. return nil, err
  287. }
  288. if ra, _ := osqlResult.RowsAffected(); ra <= 0 {
  289. tx.Tx.Rollback()
  290. return nil, errors.New("8::failed to upadte order info")
  291. }
  292. var (
  293. tube = map[string]interface{}{}
  294. maxTube = map[string]interface{}{}
  295. )
  296. sqlStock := "update t_product set stock = stock -? where id = ?;"
  297. if orderItem.IsZFB {
  298. sqlStock = "update t_product set zfb_stock = zfb_stock -? where id = ?;"
  299. }
  300. for _, pitem := range plist {
  301. if pitem.Tube.Valid && pitem.Tube.String != "" {
  302. json.Unmarshal([]byte(pitem.Tube.String), &tube)
  303. for k, v := range tube {
  304. if iv, iok := v.(float64); iok {
  305. if v1, ok := maxTube[k]; ok {
  306. if uint(iv) > v1.(uint) {
  307. maxTube[k] = uint(iv)
  308. }
  309. } else {
  310. maxTube[k] = uint(iv)
  311. }
  312. } else {
  313. if _, ok := maxTube[k]; ok {
  314. maxTube[k] = fmt.Sprintf("%v[%v]", maxTube[k], v)
  315. } else {
  316. maxTube[k] = v
  317. }
  318. }
  319. }
  320. }
  321. tx.MustExec("insert into t_order_product(order_id, product_id, product_name, price, picture, quantity) values(?,?,?,?, ?, ?)", orderId, pitem.Id, pitem.Name, pitem.Price, pitem.Picture, productQuantityMap[pitem.Id])
  322. if pitem.StockSwitch == "ON" && pitem.Stock >= 0 {
  323. tx.MustExec(sqlStock, productQuantityMap[pitem.Id], pitem.Id)
  324. }
  325. }
  326. tx.Commit()
  327. go func() {
  328. strTube, _ := json.Marshal(maxTube)
  329. _, err = db.Exec("insert into t_order_extra(order_id, pressure_pipe, relationship, is_yunxue, is_dfguomin) values (?,?,?,?,?)", orderItem.Id, strTube, relationship, orderItem.IsYunxue, orderItem.IsDfguomin)
  330. if err != nil {
  331. fmt.Println(err)
  332. }
  333. if orderItem.IsNeedPay != "N" {
  334. client := util.GetRedis()
  335. client.Select(12)
  336. client.HSet("order_unpay", orderItem.Id, fmt.Sprintf("%s;%d", orderItem.CreatedAt, orderItem.MaterialId))
  337. }
  338. //update sale num of product
  339. db.Exec("update t_product set sale_num = sale_num + 1 where id in (" + util.IntJoin(productIds, ",") + ");")
  340. }()
  341. go func() {
  342. if util.SourceCheck(orderItem.Source) && orderItem.Source != "lianren" {
  343. client := util.GetRedis()
  344. client.Select(12)
  345. msg := map[string]interface{}{
  346. "user": "system",
  347. "orderid": orderItem.Id,
  348. "source": orderItem.Source,
  349. "status": constants.ORDERSTATUS_UNPAY,
  350. }
  351. buf, _ := json.Marshal(msg)
  352. client.Publish("order-status-change", string(buf))
  353. }
  354. }()
  355. return orderItem, nil
  356. }
  357. func (srv *OrderService) AddOrderInner(orderItem *entity.Order, city_id int, city string) (interface{}, error) {
  358. if orderItem == nil || len(orderItem.ProductIds) == 0 {
  359. return nil, errors.New("1::wrong request")
  360. }
  361. var btime time.Time
  362. btime, err := time.Parse("2006-01", orderItem.Birthday)
  363. if err != nil {
  364. btime, err = time.Parse("2006-01-02", orderItem.Birthday)
  365. if err != nil {
  366. return nil, errors.New("9::wrong birthday")
  367. }
  368. }
  369. if orderItem.Age <= 0 {
  370. orderItem.Age = time.Now().Year() - btime.Year()
  371. }
  372. db := util.GetWriteSqlDB()
  373. var (
  374. productIds = []int{}
  375. productQuantityMap = map[int]int{}
  376. )
  377. for _, v := range orderItem.ProductIds {
  378. productIds = append(productIds, v.ProductId)
  379. productQuantityMap[v.ProductId] = v.Quantity
  380. }
  381. var plist []entity.ProductDB = []entity.ProductDB{}
  382. db.Select(&plist, "select * from t_product where id in ("+util.IntJoin(productIds, ",")+") order by is_no_booktime desc")
  383. if len(plist) != len(productIds) {
  384. return nil, errors.New("6::wrong param productids")
  385. }
  386. tx := db.MustBegin()
  387. //orderItem.VisitDate = visitDate
  388. orderItem.Payment, orderItem.RepeatItemFee, err = ComputeProductPrice(productIds, productQuantityMap, false)
  389. //取消减免重复项目费用
  390. orderItem.RepeatItemFee = 0
  391. if err != nil {
  392. tx.Tx.Rollback()
  393. return nil, err
  394. }
  395. /*WORK_FEE_REQUIRED, _ := config.IniConf.Section("server").Key("work_fee_required_bound").Int()
  396. WORK_FEE, _ := config.IniConf.Section("server").Key("work_fee").Int()
  397. //判断是否需要上门费 */
  398. orderItem.OnlinePayment = orderItem.Payment
  399. for _, pitem := range plist {
  400. if pitem.SaleMode == 200 || pitem.IsWorkFee == 2 {
  401. orderItem.OnlinePayment -= pitem.Price
  402. }
  403. }
  404. discount, _ := config.IniConf.Section("server").Key("inner_add_discount").Int()
  405. orderItem.Payment = int(float64(orderItem.Payment) * float64(discount) / 100)
  406. /*if orderItem.OnlinePayment > 0 && orderItem.Payment < WORK_FEE_REQUIRED {
  407. orderItem.WorkFee = WORK_FEE
  408. }
  409. */
  410. if orderItem.OnlinePayment <= 0 {
  411. orderItem.OnlinePayment = -1
  412. }
  413. orderItem.CreatedAt = time.Now().Format("2006-01-02 15:04:05")
  414. relationship := orderItem.Relationship
  415. orderItem.Relationship = ""
  416. if city == "" {
  417. db.Get(&city, "select shortname from t_city where id = ?", city_id)
  418. }
  419. orderId := GenerateOrderNo(city)
  420. orderItem.Id = orderId
  421. if hooks, ok := orderHooks[BEFORE_ORDER_CREATE]; ok {
  422. for _, handle := range hooks {
  423. if err = handle(orderItem); err != nil {
  424. tx.Tx.Rollback()
  425. return nil, err
  426. }
  427. }
  428. }
  429. strSql, mkv := util.GenerateInsertSqlFromStruct("t_order", orderItem)
  430. osqlResult, err := tx.NamedExec(strSql, mkv)
  431. if err != nil {
  432. tx.Tx.Rollback()
  433. return nil, err
  434. }
  435. if ra, _ := osqlResult.RowsAffected(); ra <= 0 {
  436. tx.Tx.Rollback()
  437. return nil, errors.New("8::failed to upadte order info")
  438. }
  439. var (
  440. tube = map[string]uint{}
  441. maxTube = map[string]uint{}
  442. )
  443. for _, pitem := range plist {
  444. if pitem.Tube.Valid && pitem.Tube.String != "" {
  445. json.Unmarshal([]byte(pitem.Tube.String), &tube)
  446. for k, v := range tube {
  447. if v1, ok := maxTube[k]; ok {
  448. if v > v1 {
  449. maxTube[k] = v
  450. }
  451. } else {
  452. maxTube[k] = v
  453. }
  454. }
  455. }
  456. tx.MustExec("insert into t_order_product(order_id, product_id, product_name, price, picture, quantity) values(?,?,?,?, ?, ?)", orderId, pitem.Id, pitem.Name, pitem.Price, pitem.Picture, productQuantityMap[pitem.Id])
  457. }
  458. tx.Commit()
  459. go func() {
  460. strTube, _ := json.Marshal(maxTube)
  461. _, err = db.Exec("insert into t_order_extra(order_id, pressure_pipe, relationship, is_yunxue, is_dfguomin, bloodtest_id) values (?,?,?,?,?,?)", orderItem.Id, strTube, relationship, orderItem.IsYunxue, orderItem.IsDfguomin, orderItem.BloodTestId)
  462. if err != nil {
  463. fmt.Println(err)
  464. }
  465. client := util.GetRedis()
  466. client.Select(12)
  467. client.HSet("order_unpay", orderItem.Id, fmt.Sprintf("%s;%d", orderItem.CreatedAt, orderItem.MaterialId))
  468. //update sale num of product
  469. db.Exec("update t_product set sale_num = sale_num + 1 where id in (" + util.IntJoin(productIds, ",") + ");")
  470. }()
  471. //20210129 护士下单绑定护士信息
  472. if len(orderItem.NurseId) > 0 {
  473. nurseId, _ := strconv.Atoi(orderItem.NurseId)
  474. strSql = "insert into t_order_deliver_user(order_id,deliver_user_id,career,visit_date,visit_time_range,create_at,get_type) values(?,?,?,?,?,?,?);"
  475. sqlResult, _ := db.Exec(strSql, orderId, nurseId, "2", orderItem.VisitDate, orderItem.VisitTimeRange, time.Now().Format("2006-01-02 15:04:05"), "assign")
  476. if la, _ := sqlResult.RowsAffected(); la <= 0 {
  477. tx.Tx.Rollback()
  478. return false, nil
  479. }
  480. }
  481. return orderItem, nil
  482. }
  483. // 20210527 vip 健康好礼活动 兑换码下单
  484. func (srv *OrderService) AddOrderFCode(orderItem *entity.Order, city_id int, city, fcode string) (interface{}, error) {
  485. //直接待接单状态,不用支付
  486. //校验兑换码是否使用?
  487. //t_fcode 改成已使用
  488. //jd_order_id 保存 DHM:兑换码
  489. if len(fcode) == 0 {
  490. return nil, fmt.Errorf("12:fcode %s error ", fcode)
  491. }
  492. if orderItem == nil || len(orderItem.ProductIds) == 0 {
  493. return nil, errors.New("1::wrong request")
  494. }
  495. var btime time.Time
  496. btime, err := time.Parse("2006-01", orderItem.Birthday)
  497. if err != nil {
  498. btime, err = time.Parse("2006-01-02", orderItem.Birthday)
  499. if err != nil {
  500. return nil, errors.New("9::wrong birthday")
  501. }
  502. }
  503. if orderItem.Age <= 0 {
  504. orderItem.Age = time.Now().Year() - btime.Year()
  505. }
  506. db := util.GetWriteSqlDB()
  507. var (
  508. productIds = []int{}
  509. productQuantityMap = map[int]int{}
  510. )
  511. for _, v := range orderItem.ProductIds {
  512. productIds = append(productIds, v.ProductId)
  513. productQuantityMap[v.ProductId] = v.Quantity
  514. }
  515. /*var plist []entity.ProductDB = []entity.ProductDB{}
  516. //db.Select(&plist, "select * from t_product where id in ("+util.IntJoin(productIds, ",")+") order by is_no_booktime desc")
  517. sqlTemp := "select t1.*, sum(t4.quantity) as bought_num from (select * from t_product where id in(" + util.IntJoin(productIds, ",") + ")) t1 left join (select t3.quantity, t3.product_id from t_order t2 left join t_order_product t3 on t2.id = t3.order_id where custom_mobile = ? and t2.status not in (7,9,14) and t2.retype in ('100','110')) t4 on t1.id = t4.product_id GROUP BY t1.id order by t1.is_no_booktime desc"
  518. db.Select(&plist, sqlTemp, orderItem.CustomMobile)
  519. if len(plist) != len(productIds) {
  520. return nil, errors.New("6::wrong param productids")
  521. }
  522. //检查库存以及个人限量
  523. for _, pitem := range plist {
  524. if pitem.StockSwitch == "ON" && pitem.Stock < productQuantityMap[pitem.Id] {
  525. return nil, errors.New("10::out of stock")
  526. }
  527. if pitem.PstockSwitch == "ON" && int(pitem.BoughtNum.Int64)+productQuantityMap[pitem.Id] > pitem.Pstock {
  528. return nil, errors.New(fmt.Sprintf("11::upper limit of product %d", pitem.Id))
  529. }
  530. }*/
  531. plist, err := Stocklimit(orderItem.CustomMobile, productIds, productQuantityMap, false)
  532. if err != nil {
  533. return nil, err
  534. }
  535. //如果产品中含有不需要预约时间的,则省略产能检查
  536. //检查产能是否足够
  537. strSql := "select t1.gnum, t2.remain_num, t2.pdate, t1.id as gid, t2.id as infoid, t1.shortname from (select tpc.id, num as gnum, shortname from t_producer_config tpc,t_city where city_id = t_city.id and city_id = ? and tpc.id = ?) t1 left join t_producer_info t2 on t1.id = t2.global_id and t2.pdate = ? and t2.time_range = ?"
  538. var producerInfo = struct {
  539. GNum int `db:"gnum"`
  540. RemainNum sql.NullInt64 `db:"remain_num"`
  541. PDate sql.NullString `db:"pdate"`
  542. GId int `db:"gid"`
  543. InfoId sql.NullInt64 `db:"infoid"`
  544. Shortname string `db:"shortname"`
  545. }{}
  546. var pinfoSqlResult sql.Result
  547. err = db.Get(&producerInfo, strSql, city_id, orderItem.PTId, orderItem.VisitDate, orderItem.VisitTimeRange)
  548. if err != nil {
  549. return nil, errors.New("4::该城市暂未开通服务")
  550. }
  551. tx := db.MustBegin()
  552. if len(plist) > 0 && plist[0].IsNoBooktime != 1 {
  553. visitDate, err := time.Parse("2006-01-02", orderItem.VisitDate)
  554. if err != nil {
  555. return nil, errors.New("2::wrong visit date")
  556. }
  557. //当天下单最早只能约第二天上门,240220 houyf改为20点
  558. if visitDate.Before(time.Now()) || (time.Now().Hour() >= 20 && time.Now().Truncate(time.Hour*24).Add(time.Hour*48).After(visitDate)) {
  559. return nil, errors.New("3::invalid visit date")
  560. }
  561. if producerInfo.PDate.String == orderItem.VisitDate && producerInfo.RemainNum.Int64 <= 0 {
  562. return nil, errors.New("5::producer not enough")
  563. }
  564. if !producerInfo.PDate.Valid {
  565. pinfoSqlResult = tx.MustExec("insert into t_producer_info(global_id, pdate, time_range, num, remain_num) values(?, ?, ?, ?, ?)", producerInfo.GId, visitDate, orderItem.VisitTimeRange, producerInfo.GNum, producerInfo.GNum-1)
  566. lid, err := pinfoSqlResult.LastInsertId()
  567. if err != nil {
  568. tx.Tx.Rollback()
  569. return nil, err
  570. }
  571. orderItem.MaterialId = int(lid)
  572. } else {
  573. pinfoSqlResult = tx.MustExec("update t_producer_info set remain_num = ? where id = ? and remain_num = ?", producerInfo.RemainNum.Int64-1, producerInfo.InfoId, producerInfo.RemainNum.Int64)
  574. orderItem.MaterialId = int(producerInfo.InfoId.Int64)
  575. }
  576. if ra, _ := pinfoSqlResult.RowsAffected(); ra <= 0 {
  577. tx.Tx.Rollback()
  578. return nil, errors.New("7::failed to update producer info")
  579. }
  580. }
  581. //fcode 验证
  582. pinfoSqlResult = tx.MustExec("update t_fcode set already_use_num = already_use_num +1 where code_str = ? and use_num>= already_use_num+1 ", fcode)
  583. if ra, _ := pinfoSqlResult.RowsAffected(); ra <= 0 {
  584. tx.Tx.Rollback()
  585. return nil, errors.New("13::failed to update t_fcode ")
  586. }
  587. //orderItem.VisitDate = visitDate
  588. if city == "" {
  589. if producerInfo.Shortname != "" {
  590. city = producerInfo.Shortname
  591. } else {
  592. city = "QG"
  593. }
  594. }
  595. orderId := GenerateOrderNo(city)
  596. orderItem.Id = orderId
  597. orderItem.Payment, orderItem.RepeatItemFee, err = ComputeProductPrice(productIds, productQuantityMap, false)
  598. //取消减免重复项目费用
  599. orderItem.RepeatItemFee = 0
  600. if err != nil {
  601. tx.Tx.Rollback()
  602. return nil, err
  603. }
  604. if len(orderItem.ItemIds) > 0 {
  605. iprice, _, err := ComputeProductPrice(orderItem.ItemIds, productQuantityMap, true)
  606. if err != nil {
  607. tx.Tx.Rollback()
  608. return nil, err
  609. }
  610. orderItem.Payment += iprice
  611. tempResult := tx.MustExec("insert into t_product_detect_item(detect_item_ids) values(?)", util.IntJoin(orderItem.ItemIds, ","))
  612. if tpid, err := tempResult.LastInsertId(); err != nil {
  613. tx.Tx.Rollback()
  614. return nil, err
  615. } else {
  616. tx.MustExec("insert into t_order_product(order_id, product_id, is_personal) values(?,?,?)", orderId, tpid, 1)
  617. }
  618. }
  619. WORK_FEE_REQUIRED, _ := config.IniConf.Section("server").Key("work_fee_required_bound").Int()
  620. WORK_FEE, _ := config.IniConf.Section("server").Key("work_fee").Int()
  621. //判断是否需要上门费
  622. orderItem.OnlinePayment = orderItem.Payment
  623. for _, pitem := range plist {
  624. if pitem.SaleMode == 200 || pitem.IsWorkFee == 2 {
  625. orderItem.OnlinePayment -= pitem.Price
  626. }
  627. }
  628. if orderItem.Source != "web-jiaxiang" && (orderItem.OnlinePayment > 0 && orderItem.Payment < WORK_FEE_REQUIRED) {
  629. orderItem.WorkFee = WORK_FEE
  630. }
  631. if orderItem.OnlinePayment <= 0 {
  632. orderItem.OnlinePayment = -1
  633. }
  634. orderItem.CreatedAt = time.Now().Format("2006-01-02 15:04:05")
  635. //判断并标记是否来自销售系统订单
  636. if srv.IsAgentOrder(orderItem.OpenId) {
  637. orderItem.IsAgent = 1
  638. }
  639. relationship := orderItem.Relationship
  640. orderItem.Relationship = ""
  641. orderItem.JdOrderId = fmt.Sprintf("兑换码:%s", fcode)
  642. orderItem.Status = 10
  643. strSql, mkv := util.GenerateInsertSqlFromStruct("t_order", orderItem)
  644. osqlResult, err := tx.NamedExec(strSql, mkv)
  645. if err != nil {
  646. tx.Tx.Rollback()
  647. return nil, err
  648. }
  649. if ra, _ := osqlResult.RowsAffected(); ra <= 0 {
  650. tx.Tx.Rollback()
  651. return nil, errors.New("8::failed to upadte order info")
  652. }
  653. var (
  654. tube = map[string]interface{}{}
  655. maxTube = map[string]interface{}{}
  656. )
  657. var pnames string
  658. for _, pitem := range plist {
  659. if pitem.Tube.Valid && pitem.Tube.String != "" {
  660. json.Unmarshal([]byte(pitem.Tube.String), &tube)
  661. for k, v := range tube {
  662. if iv, iok := v.(float64); iok {
  663. if v1, ok := maxTube[k]; ok {
  664. if uint(iv) > v1.(uint) {
  665. maxTube[k] = uint(iv)
  666. }
  667. } else {
  668. maxTube[k] = uint(iv)
  669. }
  670. } else {
  671. if _, ok := maxTube[k]; ok {
  672. maxTube[k] = fmt.Sprintf("%v[%v]", maxTube[k], v)
  673. } else {
  674. maxTube[k] = v
  675. }
  676. }
  677. }
  678. }
  679. tx.MustExec("insert into t_order_product(order_id, product_id, product_name, price, picture, quantity) values(?,?,?,?, ?, ?)", orderId, pitem.Id, pitem.Name, pitem.Price, pitem.Picture, productQuantityMap[pitem.Id])
  680. if pitem.StockSwitch == "ON" && pitem.Stock >= 0 {
  681. tx.MustExec("update t_product set stock = stock -? where id = ?;", productQuantityMap[pitem.Id], pitem.Id)
  682. }
  683. pnames += pitem.Name + ","
  684. }
  685. tx.Commit()
  686. go func() {
  687. strTube, _ := json.Marshal(maxTube)
  688. _, err = db.Exec("insert into t_order_extra(order_id, pressure_pipe, relationship, is_yunxue, is_dfguomin) values (?,?,?,?,?)", orderItem.Id, strTube, relationship, orderItem.IsYunxue, orderItem.IsDfguomin)
  689. if err != nil {
  690. fmt.Println(err)
  691. }
  692. //update sale num of product
  693. db.Exec("update t_product set sale_num = sale_num + 1 where id in (" + util.IntJoin(productIds, ",") + ");")
  694. }()
  695. go func() {
  696. sms := &SMSService{dal.DefaultSMSCodeDal}
  697. smsType := int(constants.SMS_ORDER_PAID_INFORM)
  698. var params = map[string]string{}
  699. params["products"] = pnames[0 : len(pnames)-1]
  700. sms.SendSMS(orderItem.Mobile, smsType, params)
  701. }()
  702. return orderItem, nil
  703. }
  704. // 20240122 创建普通订单以后创建普通非支付订单可以调用次方法
  705. func AddOrderNormal(orderItem *entity.Order) (string, error) {
  706. db := util.GetWriteSqlDB()
  707. shortName := orderItem.Id
  708. us := UserService{}
  709. //注册用户
  710. user, err := us._registUser(orderItem.Mobile, false)
  711. if err != nil || user == nil {
  712. return "", errors.New(fmt.Sprintf("2::RegistUser user error :%s ,[%s]", orderItem.Mobile, err))
  713. }
  714. toUpFields := map[string]interface{}{
  715. "custom_mobile": orderItem.Mobile,
  716. "name": orderItem.Name,
  717. "custom_id": user.Id,
  718. "status": 10,
  719. "gender": orderItem.Gender,
  720. "birthday": orderItem.Birthday,
  721. "mobile": orderItem.Mobile,
  722. "source": orderItem.Source,
  723. "created_at": time.Now().Format("2006-01-02 15:04:05"),
  724. }
  725. tx := db.MustBegin()
  726. var strSql string
  727. //todo 插入 t_order_product
  728. var pinfo = struct {
  729. Name string `db:"name"`
  730. ProductId int `db:"product_id"`
  731. Price int `db:"price"`
  732. Picture string `db:"picture"`
  733. Tube null.String `db:"tube"`
  734. }{}
  735. strSql = "select id, name, price, picture, tube from t_product where id = ?"
  736. err = db.Get(&pinfo, strSql, orderItem.ProductIds[0].ProductId)
  737. if err != nil {
  738. tx.Tx.Rollback()
  739. return "", errors.New(fmt.Sprintf("6:: no record t_product :%d[%s]", orderItem.ProductIds[0].ProductId, err))
  740. }
  741. id := GenerateOrderNo(shortName)
  742. toUpFields["id"] = id
  743. toUpFields["payment"] = pinfo.Price
  744. //todo 插入 t_order
  745. strSql = util.GenerateInsertSql("t_order", toUpFields)
  746. _, err = tx.NamedExec(strSql, toUpFields)
  747. if err != nil {
  748. tx.Tx.Rollback()
  749. return "", errors.New(fmt.Sprintf("5:: Insert t_order error :[%s]", err))
  750. }
  751. strSql = "insert into t_order_product(order_id, product_id, product_name,price, picture, quantity) values(?,?,?,?,?,1);"
  752. _, err = tx.Exec(strSql, id, pinfo.ProductId, pinfo.Name, pinfo.Price, pinfo.Picture)
  753. if err != nil {
  754. tx.Tx.Rollback()
  755. return "", errors.New(fmt.Sprintf("7:: insert t_order_product error :[%s]", err))
  756. }
  757. //todo 插入t_order_extra 表
  758. strSql = "insert into t_order_extra(order_id, pressure_pipe) values(?,?);"
  759. _, err = tx.Exec(strSql, id, pinfo.Tube)
  760. if err != nil {
  761. tx.Tx.Rollback()
  762. return "", errors.New(fmt.Sprintf("8:: insert t_order_extra error :[%s]", err))
  763. }
  764. tx.Commit()
  765. return id, nil
  766. }
  767. // 20211220 酒精基因,推送公众号消息
  768. func (srv *OrderService) sendWXtpl(openid, tpl, url string) {
  769. msg := map[string]interface{}{
  770. "touser": openid,
  771. "template_id": "4E6pVJlubXT-uItbymrn-ghkvTCBQxBu2-Z0ljL0V3c",
  772. "url": url,
  773. "data": map[string]interface{}{
  774. "first": map[string]interface{}{
  775. "value": "",
  776. "color": "#173177",
  777. },
  778. "keyword1": map[string]interface{}{
  779. "value": "PK赢茅台 大奖等你来",
  780. "color": "#173177",
  781. },
  782. "keyword2": map[string]interface{}{
  783. "value": time.Now().Format("2006-01-02"),
  784. "color": "#173177",
  785. },
  786. "remark": map[string]interface{}{
  787. "value": tpl,
  788. "color": "#173177",
  789. },
  790. },
  791. }
  792. buf, _ := json.Marshal(msg)
  793. _, err := srv.WeixinService.SendTpl(string(buf), "")
  794. if err != nil {
  795. log.Println(err.Error())
  796. }
  797. }
  798. // 家政分享下单 相关操作 20200814 qz
  799. // openId:下单人,
  800. // toopenId:分享人,
  801. // custommobild 下单人电话
  802. func (srv *OrderService) InsertAgent(orderId, openId, toopenId, customMobile string) (interface{}, error) {
  803. //检索 分享人id 查不到就终止操作
  804. parentagent, err := getAgentByOpenId(toopenId)
  805. if err != nil {
  806. return nil, errors.New("no toopenid found")
  807. }
  808. fmt.Println(parentagent)
  809. db := util.GetWriteSqlDB()
  810. agent, _ := getAgentByOpenId(openId)
  811. if agent != nil {
  812. userparentid := ""
  813. agentType := 2
  814. if agent.UserParentId.String == "0" {
  815. //如果
  816. userparentid = agent.UserParentId.String
  817. if agent.AgentType.Int64 == 0 {
  818. agentType = 2
  819. } else if agent.AgentType.Int64 == 1 {
  820. agentType = 3
  821. } else {
  822. agentType = int(agent.AgentType.Int64)
  823. }
  824. //更新
  825. _, err = db.Exec("update t_agent set userparentid = ? ,type = ?where id = ?", userparentid, agentType, agent.Id)
  826. }
  827. } else {
  828. _, err = db.Exec("insert into t_agent(openid,userparentid,mobile,type) values(?,?,?,2)", openId, parentagent.Id, customMobile)
  829. }
  830. //日志存mongodb
  831. //defer func() {
  832. // // go func() {
  833. // // db := getMgoDB()
  834. // // defer db.Session.Close()
  835. // // message := "success"
  836. // // if err != nil {
  837. // // message = err.Error()
  838. // // }
  839. // // db.C("Order_add_InsertAgent_log").Insert(bson.M{
  840. // // "orderId": orderId,
  841. // // "toOpenId": toopenId,
  842. // // "mobile": customMobile,
  843. // // "message": message,
  844. // // "created_at": time.Now().Format("2006-01-02 15:04:05"),
  845. // // })
  846. // // }()
  847. // //}()
  848. return nil, err
  849. }
  850. func getAgentByOpenId(openid string) (*entity.AgentEntity, error) {
  851. strSql := "select id,type,openid,userparentid from t_agent a where openid = ? "
  852. db := util.GetSqlDB()
  853. var items entity.AgentEntity
  854. err := db.Get(&items, strSql, openid)
  855. if err != nil {
  856. return nil, errors.New("no record found")
  857. }
  858. return &items, nil
  859. }
  860. func (srv *OrderService) Pay(orderItem *entity.Order, extra map[string]string) (interface{}, error) {
  861. if orderItem == nil || orderItem.Id == "" {
  862. return nil, errors.New("wrong request")
  863. }
  864. ti, err := srv.IOrder.Detail(orderItem.Id)
  865. if err != nil {
  866. return nil, err
  867. }
  868. orderDb := ti.(*dal.OrderResult)
  869. //todo 检查用户是否已经生成支付请求
  870. if orderDb == nil {
  871. return nil, errors.New("1::can not find order " + orderItem.Id)
  872. }
  873. if orderDb.Status != int(constants.ORDERSTATUS_UNPAY) {
  874. return nil, errors.New("2::order already paid or canceled")
  875. }
  876. //判断是否使用优惠券并检查券的有效性
  877. if len(orderItem.Coupons) > 0 {
  878. coupon, err := dal.DefaultCouponDal.Get(orderItem.Coupons[0], "")
  879. if err != nil {
  880. return nil, errors.New("query coupon error")
  881. }
  882. if coupon == nil {
  883. return nil, errors.New("3::coupon not found")
  884. }
  885. if coupon.Mobile != orderDb.CustomMobile && coupon.Mobile != orderDb.Mobile {
  886. return nil, errors.New("4::wrong coupon")
  887. }
  888. if coupon.OrderId.Valid && coupon.OrderId.String == orderItem.Id {
  889. goto SkipCheck
  890. }
  891. if !coupon.IsValid(orderDb.Payment) {
  892. return nil, errors.New("5::invalid coupon")
  893. }
  894. SkipCheck:
  895. /*if coupon.TypeId == int(constants.COUPONTYPE_LIMIT) && coupon.UseMaxValue.Int64 > int64(orderDb.Payment) {
  896. return nil, errors.New("can not use this coupon")
  897. }*/
  898. var plist = []struct {
  899. ProductId string `json:"pid"`
  900. Name string `json:"name"`
  901. }{}
  902. if coupon.BindProducts.Valid && strings.Trim(coupon.BindProducts.String, " ") != "" {
  903. err = json.Unmarshal([]byte(coupon.BindProducts.String), &plist)
  904. if err != nil {
  905. return nil, errors.New("6::invalid product limit coupon")
  906. }
  907. }
  908. var computeValidProductPrice = func() (bool, int) {
  909. var (
  910. validTotalPrice int
  911. isValid bool
  912. )
  913. for _, opitem := range orderDb.Products {
  914. if len(plist) > 0 {
  915. for _, pitem := range plist {
  916. if opitem.DiscountSwitch == "OFF" {
  917. continue
  918. }
  919. if strconv.Itoa(opitem.ProductId) == pitem.ProductId {
  920. validTotalPrice += opitem.ProductPrice * opitem.Quantity
  921. isValid = true
  922. break
  923. //break OUTER_PRODUCT_LOOP
  924. }
  925. }
  926. } else {
  927. isValid = true
  928. if opitem.DiscountSwitch == "ON" {
  929. validTotalPrice += opitem.ProductPrice * opitem.Quantity
  930. }
  931. }
  932. }
  933. return isValid, validTotalPrice
  934. }
  935. //计算可以优惠的产品总价
  936. var maxProductPrice int
  937. var valid bool = false
  938. valid, maxProductPrice = computeValidProductPrice()
  939. //OUTER_PRODUCT_LOOP:
  940. if len(plist) > 0 {
  941. if !valid {
  942. return nil, errors.New("7::coupon and product dismatch")
  943. }
  944. //绑定产品的券去掉上门费
  945. orderDb.WorkFee.SetValid(0)
  946. }
  947. if coupon.Value > maxProductPrice {
  948. coupon.Value = maxProductPrice
  949. }
  950. //满减券
  951. if coupon.TypeId == int(constants.COUPONTYPE_LIMIT) {
  952. if coupon.UseMaxValue.Int64 > int64(maxProductPrice) {
  953. return nil, errors.New("5::invalid limit coupon")
  954. }
  955. }
  956. //免服务费券
  957. if coupon.TypeId == int(constants.COUPONTYPE_SERVICE) && orderDb.WorkFee.Int64 > 0 {
  958. coupon.Value = int(orderDb.WorkFee.Int64)
  959. }
  960. //折扣券
  961. if coupon.TypeId == int(constants.COUPONTYPE_DISCOUNT) {
  962. coupon.Value = maxProductPrice * (100 - coupon.Value) / 100
  963. }
  964. orderItem.FreeFee = coupon.Value
  965. orderItem.ActualPayment -= coupon.Value
  966. }
  967. //判断是否需要上门费
  968. //if orderDb.Payment < WORK_FEE_REQUIRED {
  969. orderItem.WorkFee = int(orderDb.WorkFee.Int64)
  970. orderItem.ActualPayment += orderItem.WorkFee
  971. //}
  972. orderItem.ActualPayment += orderDb.Payment - orderDb.RepeatItemFee
  973. //update order status
  974. //in order to update workfee to zero, let workfee euqals -1
  975. if orderItem.WorkFee == 0 {
  976. orderItem.WorkFee = -1
  977. }
  978. var payResult interface{}
  979. payType := constants.PaymentType(orderItem.PayType)
  980. if orderItem.ActualPayment <= 0 {
  981. //不需要使用第三方支付接口了
  982. payResult = map[string]interface{}{
  983. "needThirdPay": false,
  984. "payResult": "SUCCESS",
  985. }
  986. ouitem := entity.Order{
  987. Status: int(constants.ORDERSTATUS_UNRECEIVE),
  988. FreeFee: orderItem.FreeFee,
  989. PaymentTime: time.Now().Format("2006-01-02 15:04:05"),
  990. PayType: int(constants.PAYMENTTYPE_COUPON),
  991. PayNo: GenerateOrderPayNO("P"),
  992. Id: orderDb.Id,
  993. WorkFee: orderItem.WorkFee,
  994. }
  995. _, err := srv.IOrder.Update(&ouitem)
  996. if err != nil {
  997. return nil, err
  998. }
  999. go func() {
  1000. sms := &SMSService{dal.DefaultSMSCodeDal}
  1001. smsType := int(constants.SMS_ORDER_PAID_INFORM)
  1002. var pnames string
  1003. for _, opitem := range orderDb.Products {
  1004. pnames += opitem.ProductName + ","
  1005. }
  1006. if orderDb.Source == "jd-jicai" {
  1007. smsType = int(constants.SMS_JDBOOK)
  1008. }
  1009. sms.SendSMS(orderDb.Mobile, smsType, map[string]string{
  1010. "OrderId": orderDb.Id,
  1011. "products": pnames[0 : len(pnames)-1],
  1012. "time": orderDb.VisitDate.String + " " + orderDb.VisitTimeRange.String,
  1013. "address": orderDb.Address + "(" + orderDb.DetailAddress + ")",
  1014. })
  1015. _, err = srv.SendWxPaySuccessMsg(map[string]string{
  1016. "pay_no": ouitem.PayNo,
  1017. "openid": extra["openid"],
  1018. "money": "0元",
  1019. "wx_type": extra["wx_type"],
  1020. "sms_ctype": "",
  1021. })
  1022. if err != nil {
  1023. log.Println(err)
  1024. }
  1025. srv.firstGiveTicket(orderDb.CustomMobile)
  1026. //inform admin
  1027. client := util.GetRedis()
  1028. client.Select(12)
  1029. msg := map[string]interface{}{
  1030. "user": "system",
  1031. "orderid": orderItem.Id,
  1032. "source": orderDb.Source,
  1033. "status": constants.ORDERSTATUS_UNRECEIVE,
  1034. }
  1035. buf, _ := json.Marshal(msg)
  1036. client.Publish("order-status-change", string(buf))
  1037. delUnpayFromRedis(orderItem.Id)
  1038. }()
  1039. goto AFTERPAY
  1040. //return nil, nil
  1041. }
  1042. //根据支付类型调用相应支付方法
  1043. switch payType {
  1044. case constants.PAYMENTTYPE_WEIXIN:
  1045. payResult, err = srv.wxPay(orderItem, extra)
  1046. case constants.PAYMENTTYPE_ALIPAY:
  1047. payResult, err = srv.aliPay(orderItem, extra)
  1048. default:
  1049. return nil, errors.New("8::UnSupport pay type")
  1050. }
  1051. if err != nil {
  1052. return nil, err
  1053. }
  1054. //update coupon status if used
  1055. AFTERPAY:
  1056. if len(orderItem.Coupons) > 0 {
  1057. citem := entity.DiscountTicket{
  1058. Id: orderItem.Coupons[0],
  1059. Status: 1,
  1060. OrderId: orderItem.Id,
  1061. }
  1062. dal.DefaultCouponDal.Update(&citem)
  1063. }
  1064. //todo when pay success set coupon status to used
  1065. go func() {
  1066. if util.SourceCheck(orderDb.Source) {
  1067. client := util.GetRedis()
  1068. client.Select(12)
  1069. msg := map[string]interface{}{
  1070. "user": "system",
  1071. "orderid": orderDb.Id,
  1072. "source": orderDb.Source,
  1073. "status": constants.ORDERSTATUS_UNPAY,
  1074. }
  1075. buf, _ := json.Marshal(msg)
  1076. client.Publish("order-status-change", string(buf))
  1077. }
  1078. }()
  1079. return payResult, nil
  1080. }
  1081. // 从redis删除该订单未支付状态并发布消息通知订单状态变更
  1082. func delUnpayFromRedis(orderId string) {
  1083. client := util.GetRedis()
  1084. client.Select(12)
  1085. client.HDel("order_unpay", orderId)
  1086. }
  1087. func (srv *OrderService) IsAgentOrder(openid string) bool {
  1088. strSql := "select openid from t_agent a where openid = ? and a.type in(2,3) and a.userparentid>0 and a.isdelete='N'"
  1089. db := util.GetSqlDB()
  1090. var items = []string{}
  1091. db.Select(&items, strSql, openid)
  1092. if len(items) <= 0 {
  1093. return false
  1094. }
  1095. return true
  1096. }
  1097. //const NOORDERID string = "NOORDERID"
  1098. // 微信支付统一下单
  1099. func (srv *OrderService) wxPay(orderItem *entity.Order, extra map[string]string) (interface{}, error) {
  1100. //todo check whether have already done a wx union pay request
  1101. if extra == nil {
  1102. return nil, errors.New("miss param extra")
  1103. }
  1104. if _, ok := extra["ip"]; !ok {
  1105. return nil, errors.New("need request ip")
  1106. }
  1107. if _, ok := extra["trade_type"]; !ok {
  1108. return nil, errors.New("need param trade_type of weixin pay")
  1109. }
  1110. if _, ok := extra["device_info"]; !ok && extra["trade_type"] == "JSAPI" {
  1111. extra["device_info"] = "WEB"
  1112. }
  1113. if _, ok := extra["openid"]; !ok && extra["trade_type"] == "JSAPI" {
  1114. return nil, errors.New("miss param openid")
  1115. }
  1116. payNo := GenerateOrderPayNO("P")
  1117. wxJsSdk := wx.NewJsSdk()
  1118. var (
  1119. appid string = wx.DefaultConfig["appid"]
  1120. secret = wx.DefaultConfig["secret"]
  1121. )
  1122. if extra["wx_type"] == "mp" {
  1123. appid = config.IniConf.Section("weixin").Key("wx.mp.appid").Value()
  1124. secret = config.IniConf.Section("weixin").Key("wx.mp.secret").Value()
  1125. }
  1126. weixin := wx.NewWeixin(appid, secret)
  1127. nonceStr := wxJsSdk.GenerateNoncestr(16)
  1128. reqItem := map[string]string{
  1129. "appid": appid,
  1130. "mch_id": wx.DefaultConfig["mch_id"],
  1131. "nonce_str": nonceStr,
  1132. "body": "小鸟快验订单-" + payNo,
  1133. "notify_url": wx.DefaultConfig["paycb_notify_url"],
  1134. "out_trade_no": payNo,
  1135. "spbill_create_ip": extra["ip"],
  1136. "total_fee": fmt.Sprintf("%d", orderItem.ActualPayment),
  1137. "trade_type": extra["trade_type"],
  1138. "attach": orderItem.Id,
  1139. }
  1140. if extra["trade_type"] == "JSAPI" {
  1141. reqItem["openid"] = extra["openid"]
  1142. }
  1143. if extra["device_info"] != "" {
  1144. reqItem["device_info"] = extra["device_info"]
  1145. }
  1146. sign := wxJsSdk.ComputePaySignature(reqItem, wx.DefaultConfig["apikey"])
  1147. reqItem["sign"] = sign
  1148. fmt.Println(reqItem)
  1149. rel, err := weixin.PrepareOrder(reqItem)
  1150. if err != nil {
  1151. return nil, err
  1152. }
  1153. if rel.ReturnCode == "FAIL" {
  1154. return nil, errors.New(rel.ReturnMsg)
  1155. }
  1156. //update order payno
  1157. upOrder := &entity.Order{
  1158. PayNo: payNo,
  1159. Id: orderItem.Id,
  1160. WorkFee: orderItem.WorkFee,
  1161. FreeFee: orderItem.FreeFee,
  1162. }
  1163. _, err = srv.IOrder.Update(upOrder)
  1164. if err != nil {
  1165. return nil, err
  1166. }
  1167. resultItem := map[string]string{
  1168. "appId": appid,
  1169. "timeStamp": fmt.Sprintf("%d", time.Now().Unix()),
  1170. "nonceStr": wxJsSdk.GenerateNoncestr(16),
  1171. "package": "prepay_id=" + rel.PrepayId,
  1172. "signType": "MD5",
  1173. "mweb_url": rel.MWebUrl,
  1174. "code_url": rel.CodeUrl,
  1175. }
  1176. //小程序支付时保存prepare_id 到redis,用于后续支付成功发送模板消息
  1177. if extra["wx_type"] == "mp" {
  1178. rclient := util.GetRedis()
  1179. rclient.Select(12)
  1180. rclient.HSet("mp_prepare_id", orderItem.Id, rel.PrepayId)
  1181. }
  1182. resultItem["sign"] = wxJsSdk.ComputePaySignature(resultItem, config.IniConf.Section("weixin").Key("wx.apikey").Value())
  1183. return resultItem, nil
  1184. }
  1185. // 支付宝支付
  1186. func (srv *OrderService) aliPay(orderItem *entity.Order, extra map[string]string) (interface{}, error) {
  1187. aliClient := ali.GetAliClient()
  1188. if aliClient == nil {
  1189. return nil, fmt.Errorf("支付宝初始化错误")
  1190. }
  1191. pay := alipay.TradeCreate{}
  1192. payNo := GenerateOrderPayNO("P")
  1193. pay.NotifyURL = config.IniConf.Section("ali").Key("ali.paycb_notify_url").Value()
  1194. //支付标题
  1195. pay.Subject = "小鸟快验订单-" + payNo
  1196. //订单号,一个订单号只能支付一次
  1197. pay.OutTradeNo = payNo
  1198. //商品code
  1199. //pay.ProductCode = time.Now().String()
  1200. //金额
  1201. pay.TotalAmount = strconv.FormatFloat(float64(orderItem.ActualPayment)/100, 'f', -1, 64)
  1202. pay.BuyerId = extra["user_zfb_id"]
  1203. res, err := aliClient.TradeCreate(pay)
  1204. //失败
  1205. if err != nil {
  1206. return nil, err
  1207. }
  1208. if !res.Content.Code.IsSuccess() {
  1209. return nil, fmt.Errorf(res.Content.Msg)
  1210. }
  1211. upOrder := &entity.Order{
  1212. PayNo: payNo,
  1213. Id: orderItem.Id,
  1214. WorkFee: orderItem.WorkFee,
  1215. FreeFee: orderItem.FreeFee,
  1216. }
  1217. _, err = srv.IOrder.Update(upOrder)
  1218. resultItem := map[string]string{
  1219. "trade_no": res.Content.TradeNo,
  1220. }
  1221. return resultItem, nil
  1222. }
  1223. func (srv *OrderService) PayQuery(oid string, extra map[string]string) (interface{}, error) {
  1224. orderDb, err := srv.IOrder.Get(oid)
  1225. if err != nil {
  1226. return nil, err
  1227. }
  1228. //todo 检查用户是否已经生成支付请求
  1229. if orderDb == nil {
  1230. return nil, errors.New("1::can not find order " + oid)
  1231. }
  1232. if orderDb.ActualPayment.Int64 > 0 && orderDb.Status != int(constants.ORDERSTATUS_UNPAY) {
  1233. return map[string]string{
  1234. "status": "SUCCESS",
  1235. "order_id": oid,
  1236. "actual_payment": fmt.Sprintf("%d", orderDb.ActualPayment.Int64),
  1237. }, nil
  1238. }
  1239. switch extra["pay_type"] {
  1240. case fmt.Sprintf("%d", constants.PAYMENTTYPE_WEIXIN):
  1241. extra["out_trade_no"] = orderDb.PayNo.String
  1242. return srv.WxPayQuery(extra)
  1243. case fmt.Sprintf("%d", constants.PAYMENTTYPE_ALIPAY):
  1244. extra["out_trade_no"] = orderDb.PayNo.String
  1245. return srv.AliPayQuery(extra)
  1246. default:
  1247. return nil, errors.New("UNKNOWN PAY TYPE")
  1248. }
  1249. }
  1250. func (srv *OrderService) WxPayQuery(extra map[string]string) (map[string]string, error) {
  1251. wxJsSdk := wx.NewJsSdk()
  1252. var (
  1253. appid string = wx.DefaultConfig["appid"]
  1254. secret = wx.DefaultConfig["secret"]
  1255. )
  1256. if extra["wx_type"] == "mp" {
  1257. appid = config.IniConf.Section("weixin").Key("wx.mp.appid").Value()
  1258. secret = config.IniConf.Section("weixin").Key("wx.mp.secret").Value()
  1259. }
  1260. weixin := wx.NewWeixin(appid, secret)
  1261. nonceStr := wxJsSdk.GenerateNoncestr(16)
  1262. reqItem := map[string]string{
  1263. "appid": appid,
  1264. "mch_id": wx.DefaultConfig["mch_id"],
  1265. "nonce_str": nonceStr,
  1266. "out_trade_no": extra["out_trade_no"],
  1267. "sign_type": "MD5",
  1268. }
  1269. sign := wxJsSdk.ComputePaySignature(reqItem, wx.DefaultConfig["apikey"])
  1270. reqItem["sign"] = sign
  1271. rel, err := weixin.OrderQuery(reqItem)
  1272. if err != nil {
  1273. return nil, err
  1274. }
  1275. if rel["return_code"] == "FAIL" {
  1276. return nil, errors.New(rel["return_msg"])
  1277. }
  1278. if rel["return_code"] == "FAIL" {
  1279. return nil, errors.New(rel["err_code"] + ":" + rel["err_code_des"])
  1280. }
  1281. //kv, _ := util.StructToMap(rel)
  1282. kv := rel
  1283. osign := rel["sign"]
  1284. delete(kv, "sign")
  1285. csign := wxJsSdk.ComputePaySignature(kv, wx.DefaultConfig["apikey"])
  1286. if csign != osign {
  1287. log.Println("pay_query_err: wrong sign", csign, osign, kv)
  1288. return nil, errors.New("wrong sign")
  1289. }
  1290. log.Println("weixin pay query of order ", extra["out_trade_no"], ":", rel["trade_state"])
  1291. if rel["trade_state"] == "SUCCESS" {
  1292. //TODO update order status and pay infomation
  1293. srv.WxPayCB(rel)
  1294. }
  1295. return map[string]string{
  1296. "status": rel["trade_state"],
  1297. "actual_payment": rel["total_fee"],
  1298. }, nil
  1299. }
  1300. // 支付宝支付查询
  1301. func (srv *OrderService) AliPayQuery(extra map[string]string) (map[string]string, error) {
  1302. client := ali.GetAliClient()
  1303. req := alipay.TradeQuery{}
  1304. req.OutTradeNo = extra["out_trade_no"]
  1305. res, err := client.TradeQuery(req)
  1306. if err != nil {
  1307. return nil, errors.New("1::aliquery err" + err.Error())
  1308. }
  1309. if !res.IsSuccess() {
  1310. return nil, errors.New("2::aliquery err" + res.Content.SubMsg)
  1311. }
  1312. kv := map[string]string{
  1313. "gmt_payment": res.Content.SendPayDate,
  1314. "total_amount": res.Content.TotalAmount,
  1315. "out_trade_no": res.Content.OutTradeNo,
  1316. "trade_no": res.Content.TradeNo,
  1317. }
  1318. srv.AliPayCB(kv)
  1319. moneyFloat, _ := strconv.ParseFloat(res.Content.TotalAmount, 64)
  1320. moneyInt := int64(moneyFloat * 100)
  1321. actualPay := strconv.FormatInt(moneyInt, 10)
  1322. return map[string]string{
  1323. "status": "SUCCESS",
  1324. "actual_payment": actualPay,
  1325. }, nil
  1326. }
  1327. // 统一支付成功后推送微信消息
  1328. type pName struct {
  1329. PName string `db:"product_name"`
  1330. PId string `db:"product_id"`
  1331. OrderId string `db:"oid"`
  1332. PreOrderId string `db:"pre_order_id"`
  1333. }
  1334. // 推荐有奖活动-支付成功回调处理逻辑
  1335. func (srv *OrderService) recommentActCallback(params map[string]string) {
  1336. db := util.GetWriteSqlDB()
  1337. var actInfo = struct {
  1338. Mobile null.String `db:"mobile"`
  1339. Status null.Int `db:"age"`
  1340. Id int `db:"id"`
  1341. }{}
  1342. const source string = "SHARE_PRIZE"
  1343. strSql := "select id, mobile, age from t_activity_info where custom_name = ? and source = ? order by created_at desc limit 1;"
  1344. err := db.Get(&actInfo, strSql, params["openid"], source)
  1345. if err != nil {
  1346. if err == sql.ErrNoRows {
  1347. return
  1348. }
  1349. log.Println("recommentActCallback: ", err)
  1350. return
  1351. }
  1352. if actInfo.Id == 0 || actInfo.Status.Int64 == 1 {
  1353. return
  1354. }
  1355. //自己扫自己
  1356. if params["mobile"] == actInfo.Mobile.String {
  1357. return
  1358. }
  1359. strSql = "select id from t_activity_info where mobile = ? and custom_name = ? and source = ? and age = 1;"
  1360. var hasGetId int
  1361. err = db.Get(&hasGetId, strSql, actInfo.Mobile.String, source)
  1362. if hasGetId > 0 {
  1363. return
  1364. }
  1365. strSql = "select count(*) from t_activity_info where mobile = ? and source = ? and age = 1;"
  1366. var ac int
  1367. err = db.Get(&ac, strSql, actInfo.Mobile.String, source)
  1368. if err != nil {
  1369. log.Println("recommentActCallback1: ", err)
  1370. return
  1371. }
  1372. strSql = "update t_activity_info set age = 1 where id =?;"
  1373. db.Exec(strSql, actInfo.Id)
  1374. //发酒精代谢酶基因检测券
  1375. now := time.Now()
  1376. _, err = dal.DefaultCouponDal.Save(&entity.DiscountTicket{
  1377. Mobile: params["mobile"],
  1378. TypeId: int(constants.COUPONTYPE_NORMAL),
  1379. BindProducts: `[{"pid":"26", "name":"酒精代谢酶基因检测"}]`,
  1380. Value: 19900,
  1381. CreatedAt: now.Format("2006-01-02 15:04:05"),
  1382. Deadline: now.Add(time.Hour * 24 * 30 * 6).Format("2006-01-02 15:04:05"),
  1383. })
  1384. if err != nil {
  1385. fmt.Println("recommentActCallback: ", err)
  1386. return
  1387. }
  1388. var (
  1389. firstVal string = "感谢您参加分享有奖活动,现赠送您酒精基因检测一份"
  1390. remarkVal string = "我们已往您的账户内发放好相应的优惠券,点击下单"
  1391. linkUrl string = config.IniConf.Section("weixin").Key("wx.front_host").Value() + "/index/index/detail/id/26"
  1392. toUser string = params["openid"]
  1393. )
  1394. msg := map[string]interface{}{
  1395. "touser": &toUser,
  1396. "template_id": "gglvp7ygDMpqMgxW7scWCAW7xochSKD1LZtojEkNxcg",
  1397. "url": &linkUrl,
  1398. "data": map[string]interface{}{
  1399. "first": map[string]interface{}{
  1400. "value": &firstVal,
  1401. "color": "#173177",
  1402. },
  1403. "keyword1": map[string]interface{}{
  1404. "value": "推荐有奖活动",
  1405. "color": "#173177",
  1406. },
  1407. "keyword2": map[string]interface{}{
  1408. "value": "",
  1409. "color": "#173177",
  1410. },
  1411. "remark": map[string]interface{}{
  1412. "value": &remarkVal,
  1413. "color": "#173177",
  1414. },
  1415. },
  1416. }
  1417. buf, _ := json.Marshal(msg)
  1418. _, err = srv.WeixinService.SendTpl(string(buf), "")
  1419. if err != nil {
  1420. log.Println("recommentActCallback: ", err)
  1421. }
  1422. if ac > 4 {
  1423. return
  1424. }
  1425. //发100元优惠券
  1426. _, err = dal.DefaultCouponDal.Save(&entity.DiscountTicket{
  1427. Mobile: actInfo.Mobile.String,
  1428. TypeId: int(constants.COUPONTYPE_NORMAL),
  1429. CreatedAt: now.Format("2006-01-02 15:04:05"),
  1430. Deadline: now.Add(time.Hour * 24 * 30 * 6).Format("2006-01-02 15:04:05"),
  1431. Value: 10000,
  1432. })
  1433. if err != nil {
  1434. log.Println("recommentActCallback: ", err)
  1435. return
  1436. }
  1437. //发送微信通知
  1438. var uextra null.String
  1439. db.Get(&uextra, "select extra from t_custom where mobile = ? limit 1", actInfo.Mobile.String)
  1440. if !uextra.Valid || uextra.String == "" {
  1441. log.Println("fetch openid failed with mobile: ", actInfo.Mobile.String)
  1442. return
  1443. }
  1444. var extraMap = map[string]string{}
  1445. err = json.Unmarshal([]byte(uextra.String), &extraMap)
  1446. if err != nil {
  1447. log.Println("wrong extra json format from custom")
  1448. return
  1449. }
  1450. var wxNickname null.String
  1451. db.Get(&wxNickname, "select nickname from t_wechat_userinfo where openid = ?", params["openid"])
  1452. toUser = extraMap["openid"]
  1453. firstVal = fmt.Sprintf("您的好友%s通过您分享的海报下单啦!恭喜您获得100元优惠券,赶快到账户中查看吧!", wxNickname.String)
  1454. remarkVal = fmt.Sprintf("您还有%d次获得优惠券的机会哦,快快邀请其他好友吧~", 4-ac)
  1455. linkUrl = config.IniConf.Section("weixin").Key("wx.front_host").Value() + "/index/user/my"
  1456. buf, _ = json.Marshal(msg)
  1457. _, err = srv.WeixinService.SendTpl(string(buf), "")
  1458. if err != nil {
  1459. log.Println("recommentActCallback: ", err)
  1460. }
  1461. }
  1462. func (srv *OrderService) firstGiveTicket(mobile string) {
  1463. //如果是用户首次下单,发优惠券50,有效期两个星期
  1464. if isFirst, err := srv.IOrder.IsFirst(mobile); err != nil && isFirst {
  1465. //add coupon user account related to the order
  1466. couponItem := &entity.DiscountTicket{
  1467. TypeId: int(constants.COUPONTYPE_DISCOUNT),
  1468. Mobile: mobile,
  1469. Value: 88,
  1470. Deadline: time.Now().Add(time.Hour * 24 * 60).Format("2006-01-02 15:04:05"),
  1471. CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
  1472. }
  1473. _, err = dal.DefaultCouponDal.Save(couponItem)
  1474. if err != nil {
  1475. log.Println("firstGiveTicket: ", err)
  1476. }
  1477. } else {
  1478. if err != nil {
  1479. log.Println(err)
  1480. }
  1481. }
  1482. }
  1483. func (srv *OrderService) WxPayCB(payResult map[string]string) {
  1484. db := util.GetWriteSqlDB()
  1485. payTime, _ := time.Parse("20060102150405", payResult["time_end"])
  1486. actualPay := payResult["total_fee"]
  1487. strSql := `select t1.id, mobile, address, detail_address, custom_mobile, visit_date, visit_time_range, t2.product_id,t2.product_name, t3.is_jiyin, source from t_order t1 left join
  1488. t_order_product t2 on t1.id = t2.order_id left join t_product t3 on t2.product_id = t3.id where t1.pay_no = ?`
  1489. var orderItem = []struct {
  1490. Id string `db:"id"`
  1491. Mobile string `db:"mobile"`
  1492. CustomMobile string `db:"custom_mobile"`
  1493. VisitDate null.String `db:"visit_date"`
  1494. VisitTimeRange null.String `db:"visit_time_range"`
  1495. ProductName string `db:"product_name"`
  1496. ProductId int `db:"product_id"`
  1497. Source string `db:"source"`
  1498. Address string `db:"address"`
  1499. DetailAddress string `db:"detail_address"`
  1500. IsJiyin int `db:"is_jiyin"`
  1501. }{}
  1502. err := db.Select(&orderItem, strSql, payResult["out_trade_no"])
  1503. if len(orderItem) <= 0 {
  1504. log.Println("WX callback error: can not found order of out trade no ", payResult["out_trade_no"])
  1505. if err != nil {
  1506. log.Println(err)
  1507. }
  1508. return
  1509. }
  1510. srv.firstGiveTicket(orderItem[0].CustomMobile)
  1511. var status = 2
  1512. if orderItem[0].Source == "web-jiaxiang" {
  1513. status = 3
  1514. }
  1515. //if util.ProductStatusJumpTo10(orderItem[0].ProductId) {
  1516. // status = 10
  1517. //}
  1518. sqlResult, err := db.Exec("update t_order set status = ?, third_pay_no = ?, actual_payment = ?, payment_time = ?, pay_type = ? where pay_no = ? and status = 1", status, payResult["transaction_id"], actualPay, payTime.Format("2006-01-02 15:04:05"), constants.PAYMENTTYPE_WEIXIN, payResult["out_trade_no"])
  1519. if err != nil {
  1520. log.Println("UPDATE_PAY_STATUS:", err)
  1521. return
  1522. } else {
  1523. if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
  1524. log.Println("UPDATE_PAY_STATUS:", "update failed")
  1525. return
  1526. }
  1527. go func() {
  1528. var (
  1529. pnames string
  1530. )
  1531. if err == nil {
  1532. for _, oitem := range orderItem {
  1533. pnames += oitem.ProductName + ","
  1534. }
  1535. //20230413 问诊不发送短信
  1536. if util.ProductWenZhen(orderItem[0].ProductId) {
  1537. goto JUMPSMS
  1538. }
  1539. //fmt.Println(orderItem, isJiyin, hasMBH)
  1540. sms := &SMSService{dal.DefaultSMSCodeDal}
  1541. smsType := int(constants.SMS_ORDER_PAID_INFORM)
  1542. var params = map[string]string{}
  1543. params["OrderId"] = orderItem[0].Id
  1544. params["products"] = pnames[0 : len(pnames)-1]
  1545. params["time"] = orderItem[0].VisitDate.String + " " + orderItem[0].VisitTimeRange.String
  1546. params["address"] = orderItem[0].Address + "(" + orderItem[0].DetailAddress + ")"
  1547. if orderItem[0].Source == "jd-jicai" {
  1548. smsType = int(constants.SMS_JDBOOK)
  1549. }
  1550. sms.SendSMS(orderItem[0].Mobile, smsType, params)
  1551. }
  1552. JUMPSMS:
  1553. //inform admin
  1554. client := util.GetRedis()
  1555. client.Select(12)
  1556. msg := map[string]interface{}{
  1557. "user": "system",
  1558. "orderid": orderItem[0].Id,
  1559. "source": orderItem[0].Source,
  1560. "status": constants.ORDERSTATUS_UNRECEIVE,
  1561. }
  1562. buf, _ := json.Marshal(msg)
  1563. client.Publish("order-status-change", string(buf))
  1564. client.HDel("order_unpay", orderItem[0].Id)
  1565. //call recommentActCallback
  1566. srv.recommentActCallback(map[string]string{
  1567. "mobile": orderItem[0].Mobile,
  1568. "openid": payResult["openid"],
  1569. })
  1570. }()
  1571. var wxType = ""
  1572. if payResult["appid"] == config.IniConf.Section("weixin").Key("wx.mp.appid").Value() {
  1573. wxType = "mp"
  1574. }
  1575. smsCtype := ""
  1576. tfee, _ := strconv.ParseInt(payResult["total_fee"], 10, 64)
  1577. _, err = srv.SendWxPaySuccessMsg(map[string]string{
  1578. "pay_no": payResult["out_trade_no"],
  1579. "openid": payResult["openid"],
  1580. "money": fmt.Sprintf("%.2f元", float32(tfee)/100),
  1581. "wx_type": wxType,
  1582. "sms_ctype": smsCtype,
  1583. })
  1584. if err != nil {
  1585. log.Println(err)
  1586. }
  1587. //qz add 拆单的操作
  1588. //go srv.SplitOrder(orderItem[0].Id, orderItem[0].ProductId)
  1589. //20210816 加急核酸1274 发送钉钉
  1590. if orderItem[0].ProductId == 1274 {
  1591. srv.SendDingMsg(orderItem[0].Id)
  1592. }
  1593. //20211019 修改web-jiaxiang 护士佣金 前置条件/order/inner/pay ->20210129 护士下单绑定护士信息
  1594. go func() {
  1595. var count int
  1596. db.Get(&count, "select count(1) from t_order_deliver_user where order_id = ?", orderItem[0].Id)
  1597. if count > 0 && orderItem[0].Source == "web-jiaxiang" {
  1598. pay, err := strconv.Atoi(actualPay)
  1599. pay = pay / 10
  1600. sqlResult, err = db.Exec("update t_order_extra set paynurse = ? where order_id = ?", pay, orderItem[0].Id)
  1601. if err != nil {
  1602. log.Printf("error update t_order_extra paynurse id:%s payment:%s err:%v", orderItem[0].Id, actualPay, err)
  1603. return
  1604. }
  1605. log.Printf("success update t_order_extra paynurse id:%s payment:%s ", orderItem[0].Id, actualPay)
  1606. }
  1607. }()
  1608. }
  1609. }
  1610. // 支付宝callback
  1611. func (srv *OrderService) AliPayCB(payResult map[string]string) {
  1612. db := util.GetWriteSqlDB()
  1613. _, err := time.Parse("2006-01-02 15:04:05", payResult["gmt_payment"]) // noti.GmtPayment
  1614. if err != nil {
  1615. payResult["gmt_payment"] = time.Now().Format("2006-01-02 15:04:05")
  1616. }
  1617. moneyFloat, _ := strconv.ParseFloat(payResult["total_amount"], 64) //noti.TotalAmount
  1618. moneyInt := int64(moneyFloat * 100)
  1619. actualPay := strconv.FormatInt(moneyInt, 10)
  1620. strSql := `select t1.id, mobile, address, detail_address, custom_mobile, visit_date, visit_time_range, t2.product_id,t2.product_name, t3.is_jiyin, source from t_order t1 left join
  1621. t_order_product t2 on t1.id = t2.order_id left join t_product t3 on t2.product_id = t3.id where t1.pay_no = ?`
  1622. var orderItem = []struct {
  1623. Id string `db:"id"`
  1624. Mobile string `db:"mobile"`
  1625. CustomMobile string `db:"custom_mobile"`
  1626. VisitDate null.String `db:"visit_date"`
  1627. VisitTimeRange null.String `db:"visit_time_range"`
  1628. ProductName string `db:"product_name"`
  1629. ProductId int `db:"product_id"`
  1630. Source string `db:"source"`
  1631. Address string `db:"address"`
  1632. DetailAddress string `db:"detail_address"`
  1633. IsJiyin int `db:"is_jiyin"`
  1634. }{}
  1635. err = db.Select(&orderItem, strSql, payResult["out_trade_no"]) //noti.OutTradeNo
  1636. if len(orderItem) <= 0 {
  1637. log.Println("ZFB callback error: can not found order of out trade no ", payResult["out_trade_no"])
  1638. if err != nil {
  1639. log.Println(err)
  1640. }
  1641. return
  1642. }
  1643. srv.firstGiveTicket(orderItem[0].CustomMobile)
  1644. var status = 2
  1645. if orderItem[0].Source == "web-jiaxiang" {
  1646. status = 3
  1647. }
  1648. sqlResult, err := db.Exec("update t_order set status = ?, third_pay_no = ?, actual_payment = ?, payment_time = ?, pay_type = ? where pay_no = ? and status = 1", status, payResult["trade_no"], actualPay, payResult["gmt_payment"], constants.PAYMENTTYPE_ALIPAY, payResult["out_trade_no"])
  1649. if err != nil {
  1650. log.Println("UPDATE_PAY_STATUS:", err)
  1651. return
  1652. } else {
  1653. if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
  1654. log.Println("UPDATE_PAY_STATUS:", "update failed")
  1655. return
  1656. }
  1657. go func() {
  1658. var (
  1659. pnames string
  1660. )
  1661. if err == nil {
  1662. for _, oitem := range orderItem {
  1663. pnames += oitem.ProductName + ","
  1664. }
  1665. //fmt.Println(orderItem, isJiyin, hasMBH)
  1666. sms := &SMSService{dal.DefaultSMSCodeDal}
  1667. smsType := int(constants.SMS_ORDER_PAID_INFORM)
  1668. var params = map[string]string{}
  1669. params["OrderId"] = orderItem[0].Id
  1670. params["products"] = pnames[0 : len(pnames)-1]
  1671. params["time"] = orderItem[0].VisitDate.String + " " + orderItem[0].VisitTimeRange.String
  1672. params["address"] = orderItem[0].Address + "(" + orderItem[0].DetailAddress + ")"
  1673. if orderItem[0].Source == "jd-jicai" {
  1674. smsType = int(constants.SMS_JDBOOK)
  1675. }
  1676. sms.SendSMS(orderItem[0].Mobile, smsType, params)
  1677. }
  1678. //inform admin
  1679. client := util.GetRedis()
  1680. client.Select(12)
  1681. msg := map[string]interface{}{
  1682. "user": "system",
  1683. "orderid": orderItem[0].Id,
  1684. "source": orderItem[0].Source,
  1685. "status": constants.ORDERSTATUS_UNRECEIVE,
  1686. }
  1687. buf, _ := json.Marshal(msg)
  1688. client.Publish("order-status-change", string(buf))
  1689. client.HDel("order_unpay", orderItem[0].Id)
  1690. //call recommentActCallback
  1691. //srv.recommentActCallback(map[string]string{
  1692. // "mobile": orderItem[0].Mobile,
  1693. // "openid": payResult["openid"],
  1694. //})
  1695. }()
  1696. //qz add 拆单的操作
  1697. //go srv.SplitOrder(orderItem[0].Id, orderItem[0].ProductId)
  1698. _, err = srv.SendWxPaySuccessMsg(map[string]string{
  1699. "pay_no": payResult["out_trade_no"],
  1700. })
  1701. //20210816 加急核酸1274 发送钉钉
  1702. if orderItem[0].ProductId == 1274 {
  1703. srv.SendDingMsg(orderItem[0].Id)
  1704. }
  1705. }
  1706. }
  1707. func (srv *OrderService) SendWxPaySuccessMsg(params map[string]string) (interface{}, error) {
  1708. strSql := "select t1.id as oid, product_name,product_id from t_order t1 left join t_order_product t2 on t1.id = t2.order_id where t1.pay_no = ?"
  1709. var nameList = []pName{}
  1710. db := util.GetSqlDB()
  1711. err := db.Select(&nameList, strSql, params["pay_no"])
  1712. if err != nil {
  1713. return nil, err
  1714. }
  1715. if len(nameList) == 0 {
  1716. return nil, errors.New("order have no product")
  1717. }
  1718. go srv.IOrder.CheckAndSplitOrder(nameList[0].OrderId)
  1719. //20230413 问诊不发送微信通知
  1720. pid, _ := strconv.Atoi(nameList[0].PId)
  1721. if util.ProductWenZhen(pid) {
  1722. return nil, nil
  1723. }
  1724. strPName := ""
  1725. strPid := ""
  1726. yuanyiMap := map[string]struct{}{}
  1727. for i, item := range nameList {
  1728. if i+1 == len(nameList) {
  1729. strPName += item.PName
  1730. strPid += item.PId
  1731. } else {
  1732. strPName += item.PName + " "
  1733. strPid += item.PId + ","
  1734. }
  1735. yuanyiMap[item.PId] = struct{}{}
  1736. }
  1737. isExistShangMen := 1
  1738. //20220524 如果只有邮寄的,那么更换消息通知,存在上门的,就保持原来的推送
  1739. db.Get(&isExistShangMen, "select count(1) from t_product where id in ("+strPid+") and is_no_booktime =0")
  1740. var wxBodyContent = config.IniConf.Section("weixin").Key("msg.pay_success").Value()
  1741. if params["sms_ctype"] == "MBH" {
  1742. wxBodyContent = config.IniConf.Section("weixin").Key("msg.pay_success_mbh").Value()
  1743. }
  1744. if isExistShangMen == 0 {
  1745. wxBodyContent = config.IniConf.Section("weixin").Key("msg.pay_success_youji").Value()
  1746. }
  1747. //20220525 远毅 1338 ,推送新的报文
  1748. if len(yuanyiMap) == 1 {
  1749. for k := range yuanyiMap {
  1750. if util.ProductYuanYi(k) {
  1751. wxBodyContent = config.IniConf.Section("weixin").Key("msg.pay_success_yuanyi").Value()
  1752. }
  1753. }
  1754. }
  1755. msg := map[string]interface{}{
  1756. "touser": params["openid"],
  1757. "template_id": "og_C32ekCtZDIG86FodplOJ-Agj0pYYjTlQLJxt3j_0",
  1758. "url": config.IniConf.Section("weixin").Key("wx.front_host").Value() + "/activity/question", // + nameList[0].OrderId,
  1759. "data": map[string]interface{}{
  1760. "first": map[string]interface{}{
  1761. "value": wxBodyContent,
  1762. "color": "#173177",
  1763. },
  1764. "orderMoneySum": map[string]interface{}{
  1765. "value": params["money"],
  1766. "color": "#173177",
  1767. },
  1768. "orderProductName": map[string]interface{}{
  1769. "value": strPName,
  1770. "color": "#173177",
  1771. },
  1772. "Remark": map[string]interface{}{
  1773. "value": "为了能更加精准解读您的检测报告,请您点击详情填写“身体健康评估表”,我们将对您的个人信息进行严格保密。首次填写身体健康评估表并完成提交,小鸟将为您奉上金额不等优惠卷,随时供您使用。",
  1774. "color": "#173177",
  1775. },
  1776. },
  1777. }
  1778. if params["wx_type"] == "mp" {
  1779. rclient := util.GetRedis()
  1780. rclient.Select(12)
  1781. strCmd := rclient.HGet("mp_prepare_id", nameList[0].OrderId)
  1782. if terr := strCmd.Err(); terr != nil {
  1783. log.Println(terr)
  1784. return false, terr
  1785. }
  1786. msg = map[string]interface{}{
  1787. "touser": params["openid"],
  1788. "template_id": "_4Ps93u932mI8tnFhnde02aCKekEgVOLNPYc5L67Nuw",
  1789. "page": "",
  1790. "form_id": strCmd.Val(),
  1791. "data": map[string]interface{}{
  1792. "keyword1": map[string]interface{}{
  1793. "value": params["money"],
  1794. "color": "#173177",
  1795. },
  1796. "keyword2": map[string]interface{}{
  1797. "value": strPName,
  1798. "color": "#173177",
  1799. },
  1800. "keyword3": map[string]interface{}{
  1801. "value": "为了能更加精准解读您的检测报告,请您点击详情填写“身体健康评估表”,我们将对您的个人信息进行严格保密。首次填写身体健康评估表并完成提交,小鸟将为您奉上金额不等优惠卷,随时供您使用。",
  1802. "color": "#173177",
  1803. },
  1804. },
  1805. }
  1806. }
  1807. buf, _ := json.Marshal(msg)
  1808. return srv.WeixinService.SendTpl(string(buf), params["wx_type"])
  1809. /*_, err = srv.WeixinService.SendTpl(string(buf))
  1810. if err != nil {
  1811. log.Println(err)
  1812. }
  1813. msg = map[string]interface{}{
  1814. "touser": params["openid"],
  1815. "msgtype": "news",
  1816. "news": map[string]interface{}{
  1817. "articles": []map[string]interface{}{
  1818. map[string]interface{}{
  1819. "title": "身体健康调查表",
  1820. "description": "详细填写后,医生会为您撰写更加精准的报告",
  1821. "url": config.IniConf.Section("weixin").Key("wx.front_host").Value() + "/activity/question",
  1822. "picurl": config.IniConf.Section("weixin").Key("wx.front_host").Value() + "/images/wx_survey.jpg",
  1823. },
  1824. },
  1825. },
  1826. }
  1827. msg = map[string]interface{}{
  1828. "touser": params["openid"],
  1829. "msgtype": "text",
  1830. "text": map[string]interface{}{
  1831. "content": config.IniConf.Section("weixin").Key("msg.survey").Value(),
  1832. },
  1833. }
  1834. return srv.WeixinService.Send(msg)*/
  1835. }
  1836. // 退款
  1837. func (srv *OrderService) Refund(params map[string]string) (interface{}, error) {
  1838. if _, ok := params["orderId"]; !ok {
  1839. return nil, errors.New("miss param orderId")
  1840. }
  1841. orderItem, err := srv.IOrder.Get(params["orderId"])
  1842. if err != nil {
  1843. return nil, err
  1844. }
  1845. if orderItem.Status < int(constants.ORDERSTATUS_UNRECEIVE) || orderItem.Status == int(constants.ORDERSTATUS_COMPLETE) {
  1846. return nil, errors.New("the order can not refund")
  1847. }
  1848. payType := constants.PaymentType(orderItem.PayType.Int64)
  1849. var (
  1850. rid string
  1851. payNo string
  1852. thirdRefundId string
  1853. refundFee interface{}
  1854. cashRefundFee interface{}
  1855. rtype string
  1856. )
  1857. switch payType {
  1858. case constants.PAYMENTTYPE_WEIXIN:
  1859. rel, err := srv.wxRefund(orderItem, params)
  1860. if err != nil {
  1861. return nil, err
  1862. }
  1863. rid = rel["out_refund_no"]
  1864. payNo = rel["out_trade_no"]
  1865. thirdRefundId = rel["refund_id"]
  1866. refundFee = rel["refund_fee"]
  1867. cashRefundFee = rel["cash_refund_fee"]
  1868. rtype = "WX"
  1869. case constants.PAYMENTTYPE_ALIPAY:
  1870. rel, err := srv.aliRefund(orderItem, params)
  1871. if err != nil {
  1872. return nil, err
  1873. }
  1874. rid = rel["out_refund_no"]
  1875. payNo = rel["out_trade_no"]
  1876. thirdRefundId = rel["refund_id"]
  1877. refundFee = rel["refund_fee"]
  1878. cashRefundFee = rel["cash_refund_fee"]
  1879. rtype = "ZFB"
  1880. default:
  1881. return nil, errors.New("UnSupport pay type(非微信支付无法退款)")
  1882. }
  1883. strsql := "insert into t_refund(id, pay_no, third_refund_id, refund_fee, cash_refund_fee, type) values(?,?,?,?,?,?);"
  1884. db := util.GetWriteSqlDB()
  1885. tx := db.MustBegin()
  1886. sqlResult := tx.MustExec(strsql, rid, payNo, thirdRefundId, refundFee, cashRefundFee, rtype)
  1887. if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
  1888. log.Println("failed to update refund fee")
  1889. return nil, errors.New("failed to update refund fee")
  1890. }
  1891. strsql = "update t_order set refund = refund + ? where id = ?"
  1892. sqlResult = tx.MustExec(strsql, refundFee, orderItem.Id)
  1893. if ra, _ := sqlResult.RowsAffected(); ra <= 0 {
  1894. tx.Tx.Rollback()
  1895. log.Println("failed to update refund fee2")
  1896. return nil, errors.New("failed to update refund fee2")
  1897. }
  1898. tx.Tx.Commit()
  1899. return map[string]interface{}{
  1900. "refund_id": rid,
  1901. "pay_no": payNo,
  1902. "third_refund_id": thirdRefundId,
  1903. "type": rtype,
  1904. "refund_fee": refundFee,
  1905. "cash_refund_fee": cashRefundFee,
  1906. }, nil
  1907. }
  1908. // 微信退款
  1909. func (srv *OrderService) wxRefund(orderItem *entity.OrderDB, extra map[string]string) (map[string]string, error) {
  1910. wxJsSdk := wx.NewJsSdk()
  1911. weixin := wx.NewWeixin(wx.DefaultConfig["appid"], wx.DefaultConfig["secret"])
  1912. nonceStr := wxJsSdk.GenerateNoncestr(16)
  1913. var refundFee interface{} = orderItem.ActualPayment.Int64
  1914. if _, ok := extra["refund_fee"]; ok {
  1915. refundFee = extra["refund_fee"]
  1916. }
  1917. reqItem := map[string]string{
  1918. "appid": wx.DefaultConfig["appid"],
  1919. "mch_id": wx.DefaultConfig["mch_id"],
  1920. "nonce_str": nonceStr,
  1921. "out_trade_no": orderItem.PayNo.String,
  1922. "out_refund_no": GenerateOrderPayNO("R"),
  1923. "total_fee": fmt.Sprintf("%d", orderItem.ActualPayment.Int64),
  1924. "refund_fee": fmt.Sprintf("%v", refundFee),
  1925. "op_user_id": wx.DefaultConfig["mch_id"],
  1926. }
  1927. if _, ok := extra["device_info"]; ok {
  1928. reqItem["device_info"] = extra["device_info"]
  1929. }
  1930. sign := wxJsSdk.ComputePaySignature(reqItem, wx.DefaultConfig["apikey"])
  1931. reqItem["sign"] = sign
  1932. rel, err := weixin.Refund(reqItem, wx.DefaultConfig["cert_file"], wx.DefaultConfig["key_file"])
  1933. if err != nil {
  1934. return nil, err
  1935. }
  1936. if rel != nil && rel["return_code"] == "FAIL" {
  1937. return nil, errors.New(rel["return_msg"])
  1938. } else {
  1939. if rel["result_code"] == "FAIL" {
  1940. return nil, errors.New(rel["err_code_des"])
  1941. }
  1942. }
  1943. //todo save refund record
  1944. return rel, nil
  1945. }
  1946. // 支付宝退款
  1947. func (srv *OrderService) aliRefund(orderItem *entity.OrderDB, extra map[string]string) (map[string]string, error) {
  1948. //var refundFee interface{} = orderItem.ActualPayment.Int64
  1949. refundFee := strconv.FormatFloat(float64(orderItem.ActualPayment.Int64)/100, 'f', -1, 64)
  1950. if _, ok := extra["refund_fee"]; ok {
  1951. payment, err := strconv.ParseFloat(extra["refund_fee"], 64)
  1952. if err == nil {
  1953. refundFee = strconv.FormatFloat(payment/100, 'f', -1, 64)
  1954. }
  1955. }
  1956. client := ali.GetAliClient()
  1957. req := alipay.TradeRefund{}
  1958. req.OutTradeNo = orderItem.PayNo.String
  1959. req.RefundAmount = refundFee
  1960. req.OutRequestNo = GenerateOrderNo("R")
  1961. res, err := client.TradeRefund(req)
  1962. if err != nil {
  1963. return nil, errors.New("1::alirefund err" + err.Error())
  1964. }
  1965. if !res.IsSuccess() {
  1966. return nil, errors.New("2::alirefund err" + res.Content.SubMsg)
  1967. }
  1968. refund_fee, _ := strconv.ParseFloat(res.Content.SendBackFee, 64)
  1969. reqItem := map[string]string{
  1970. "out_trade_no": res.Content.OutTradeNo,
  1971. "refund_id": res.Content.TradeNo,
  1972. "out_refund_no": req.OutRequestNo,
  1973. "cash_refund_fee": fmt.Sprintf("%d", orderItem.ActualPayment.Int64),
  1974. "refund_fee": fmt.Sprintf("%v", refund_fee*100),
  1975. }
  1976. return reqItem, nil
  1977. }
  1978. // 微信支付回调
  1979. func (srv *OrderService) WxPayCallBack(payResult *wx.UnionPayResult) (interface{}, error) {
  1980. return nil, nil
  1981. }
  1982. // 支付失败
  1983. func (srv *OrderService) FailedOrder(oid string) (bool, error) {
  1984. //释放优惠券
  1985. db := util.GetWriteSqlDB()
  1986. oitem, err := srv.IOrder.Get(oid)
  1987. if err != nil {
  1988. return false, err
  1989. }
  1990. if oitem.Status != 1 {
  1991. return false, errors.New("该订单不能取消")
  1992. }
  1993. //20220124 联仁订单不解绑优惠券
  1994. if oitem.Source == "lianren" {
  1995. return true, nil
  1996. }
  1997. citem, _ := dal.DefaultCouponDal.Get(0, oitem.Id)
  1998. if citem == nil {
  1999. return true, nil
  2000. }
  2001. WORK_FEE_REQUIRED, _ := config.IniConf.Section("server").Key("work_fee_required_bound").Int()
  2002. WORK_FEE, _ := config.IniConf.Section("server").Key("work_fee").Int()
  2003. if citem.TypeId == int(constants.COUPONTYPE_SERVICE) || (citem.BindProducts.Valid && strings.Trim(citem.BindProducts.String, " ") != "" && oitem.OnlinePayment > 0 && oitem.Payment < WORK_FEE_REQUIRED) {
  2004. db.Exec("update t_order set work_fee = ? where id = ?", WORK_FEE, oid)
  2005. }
  2006. strSql := "update t_discount_ticket set order_id = null, status = 0 where order_id = ?;"
  2007. _, err = db.Exec(strSql, oid)
  2008. if err != nil {
  2009. return false, err
  2010. }
  2011. return true, nil
  2012. }
  2013. func (srv *OrderService) CancelOrder(oid string) (bool, error) {
  2014. orderDb, err := srv.IOrder.Get(oid)
  2015. if err != nil {
  2016. return false, err
  2017. }
  2018. //根据订单状态判断是否可以取消
  2019. status := constants.OrderStatus(orderDb.Status)
  2020. if (status == constants.ORDERSTATUS_UNPAY || status == constants.ORDERSTATUS_UNRECEIVE) && (orderDb.Source == "web" || orderDb.Source == "h5") {
  2021. //20210203如果来源是web 和h5 状态时 1:待支付,2:待接单 走取消流程(还有退款)
  2022. } else if status != constants.ORDERSTATUS_UNPAY && orderDb.Source != "jd-jicai" {
  2023. //其他来源,状态1 才可以取消 20210203 给前端开放取消功能,所以修改此条件
  2024. return false, errors.New("该订单不能取消")
  2025. }
  2026. if orderDb.Source == "jd-jicai" && orderDb.Status > 3 {
  2027. return false, errors.New("该订单不能取消")
  2028. }
  2029. //todo 释放订单占用的产能并更改订单状态
  2030. db := util.GetWriteSqlDB()
  2031. tx := db.MustBegin()
  2032. if orderDb.Source == "jd-jicai" {
  2033. result := tx.MustExec("update t_jd_productivity set remain_pnum = remain_pnum + 1 where addr_id = ? and pdate = ?;", orderDb.MaterialId, orderDb.VisitDate.String)
  2034. if ra, _ := result.RowsAffected(); ra <= 0 {
  2035. tx.Tx.Rollback()
  2036. return false, errors.New("更新产能失败")
  2037. }
  2038. } else {
  2039. if orderDb.MaterialId > 0 {
  2040. result := tx.MustExec("update t_producer_info set remain_num = remain_num + 1 where id = ? ", orderDb.MaterialId)
  2041. if ra, _ := result.RowsAffected(); ra <= 0 {
  2042. tx.Tx.Rollback()
  2043. return false, errors.New("更新产能失败")
  2044. }
  2045. }
  2046. }
  2047. result := tx.MustExec("update t_order set status = ?, m_id = 0 where id = ?", constants.ORDERSTATUS_CANCELED, orderDb.Id)
  2048. if ra, _ := result.RowsAffected(); ra <= 0 {
  2049. tx.Tx.Rollback()
  2050. return false, errors.New("更新订单状态失败")
  2051. }
  2052. //回滚库存
  2053. var ops = []entity.OrderProduct{}
  2054. db.Select(&ops, "select t1.*, t2.stock_switch from t_order_product t1 left join t_product t2 on t1.product_id = t2.id where order_id = ?", oid)
  2055. sql := "update t_product set stock = stock + ? where id = ?"
  2056. if orderDb.Source == "sp_zfb" {
  2057. sql = "update t_product set zfb_stock = zfb_stock + ? where id = ?"
  2058. }
  2059. for _, op := range ops {
  2060. if op.StockSwitch == "ON" {
  2061. result = tx.MustExec(sql, op.Quantity, op.ProductId)
  2062. if ra, _ := result.RowsAffected(); ra <= 0 {
  2063. tx.Tx.Rollback()
  2064. return false, errors.New("更新库存失败")
  2065. }
  2066. }
  2067. }
  2068. tx.Commit()
  2069. go delUnpayFromRedis(oid)
  2070. if orderDb.Source == "jd-jicai" && (orderDb.Status == 2 || orderDb.Status == 3) {
  2071. rps := map[string]string{
  2072. "orderId": orderDb.Id,
  2073. "refund_fee": fmt.Sprintf("%d", orderDb.ActualPayment.Int64),
  2074. }
  2075. log.Println("refund: ", orderDb.Id)
  2076. _, err = srv.Refund(rps)
  2077. if err != nil {
  2078. log.Println(err)
  2079. }
  2080. } else if (orderDb.Source == "web" || orderDb.Source == "h5" || orderDb.Source == "sp" || orderDb.Source == "sp_zfb") && orderDb.Status == 2 {
  2081. //20210203 如果来源是web h5 而且状态是2的,走退款流程
  2082. rps := map[string]string{
  2083. "orderId": orderDb.Id,
  2084. "refund_fee": fmt.Sprintf("%d", orderDb.ActualPayment.Int64),
  2085. }
  2086. log.Println("refund: ", orderDb.Id)
  2087. _, err = srv.Refund(rps)
  2088. if err != nil {
  2089. log.Println(err)
  2090. }
  2091. //优惠券复原
  2092. strSql := "update t_discount_ticket set order_id = null, status = 0 where order_id = ?;"
  2093. _, err = db.Exec(strSql, oid)
  2094. } else if orderDb.Source == "lianren" {
  2095. //20220124 联仁单独解绑优惠券
  2096. strSql := "update t_discount_ticket set order_id = null, status = 0 where order_id = ?;"
  2097. _, err = db.Exec(strSql, oid)
  2098. }
  2099. if util.SourceCheck(orderDb.Source) {
  2100. go pushOrderStatus(oid, orderDb.Source, orderDb.Status)
  2101. }
  2102. return true, nil
  2103. }
  2104. func (srv *OrderService) DelOrder(oid string) (bool, error) {
  2105. orderDb, err := srv.IOrder.Get(oid)
  2106. if err != nil {
  2107. return false, err
  2108. }
  2109. //根据订单状态判断是否可以删除
  2110. status := constants.OrderStatus(orderDb.Status)
  2111. if status > constants.ORDERSTATUS_UNPAY && status < constants.ORDERSTATUS_COMPLETE {
  2112. return false, errors.New("该订单不能删除")
  2113. }
  2114. //todo 释放订单占用的产能并更改订单状态
  2115. db := util.GetWriteSqlDB()
  2116. tx := db.MustBegin()
  2117. if status == constants.ORDERSTATUS_UNPAY && orderDb.MaterialId > 0 {
  2118. result := tx.MustExec("update t_producer_info set remain_num = remain_num + 1 where id = ? ", orderDb.MaterialId)
  2119. if ra, _ := result.RowsAffected(); ra <= 0 {
  2120. tx.Tx.Rollback()
  2121. return false, errors.New("更新产能失败")
  2122. }
  2123. }
  2124. //result := tx.MustExec("update t_order set status = ? where id = ?", constants.ORDERSTATUS_DELETED, orderDb.Id)
  2125. result := tx.MustExec("update t_order set is_delete = ? where id = ?", "Y", orderDb.Id)
  2126. if ra, _ := result.RowsAffected(); ra <= 0 {
  2127. tx.Tx.Rollback()
  2128. return false, errors.New("删除订单失败")
  2129. }
  2130. tx.Commit()
  2131. if status == constants.ORDERSTATUS_UNPAY {
  2132. go delUnpayFromRedis(oid)
  2133. }
  2134. if util.SourceCheck(orderDb.Source) {
  2135. go pushOrderStatus(oid, orderDb.Source, orderDb.Status)
  2136. }
  2137. return true, nil
  2138. }
  2139. func pushOrderStatus(orderId, source string, status int) {
  2140. if util.SourceCheck(source) {
  2141. client := util.GetRedis()
  2142. client.Select(12)
  2143. msg := map[string]interface{}{
  2144. "user": "system",
  2145. "orderid": orderId,
  2146. "source": source,
  2147. "status": status,
  2148. }
  2149. buf, _ := json.Marshal(msg)
  2150. client.Publish("order-status-change", string(buf))
  2151. }
  2152. }
  2153. // 获取订单列表
  2154. func (srv *OrderService) ListOrder(customId, pageIndex, pageSize, status int, mobile string, isZFB bool, isHis bool) (interface{}, error) {
  2155. return srv.IOrder.List(customId, pageIndex, pageSize, status, mobile, isZFB, isHis)
  2156. }
  2157. // 根据custom_file_id获取订单列表 20211210
  2158. func (srv *OrderService) ListFileOrder(customId, pageIndex, pageSize, status int, mobile string, isZFB, isHis bool) (interface{}, error) {
  2159. return srv.IOrder.ListCustomFile(customId, pageIndex, pageSize, status, mobile, isZFB, isHis)
  2160. }
  2161. // 获取订单详细信息
  2162. func (srv *OrderService) OrderDetail(oid string) (interface{}, error) {
  2163. if oid == "" {
  2164. return nil, errors.New("miss param order id")
  2165. }
  2166. return srv.IOrder.Detail(oid)
  2167. }
  2168. func (srv *OrderService) OrderReport(oid string, otype string) (interface{}, error) {
  2169. if oid == "" {
  2170. return nil, errors.New("miss param order id")
  2171. }
  2172. oid = strings.ToUpper(oid)
  2173. var orderTableName = "t_order"
  2174. if otype == "SPECIAL" {
  2175. orderTableName = "t_special_order"
  2176. }
  2177. strSql := "select t1.id,original_report, report_picture,complete_time, mobile,custom_mobile, t1.name,gender,birthday,age,t1.type, is_view_report, share_code, blood_codes, source, group_concat(t2.product_id) as product_ids,group_concat(t3.name) as product_names,group_concat(t3.is_jiyin) as is_jiyins from " + orderTableName + " t1 left join t_order_product t2 on t1.id = t2.order_id left join t_product t3 on t2.product_id = t3.id where t1.id = ?"
  2178. db := util.GetSqlDB()
  2179. var data = &struct {
  2180. Id string `db:"id"`
  2181. Mobile string `db:"mobile"`
  2182. CustomMobile string `db:"custom_mobile"`
  2183. ReportPicture string `db:"report_picture"`
  2184. IsViewReport string `db:"is_view_report"`
  2185. CustomName string `db:"name"`
  2186. Gender int `db:"gender"`
  2187. Age int `db:"age"`
  2188. Birthday string `db:"birthday"`
  2189. ProductIds string `db:"product_ids"`
  2190. ProductNames string `db:"product_names"`
  2191. BloodCodes null.String `db:"blood_codes"`
  2192. ShareCode null.String `db:"share_code"`
  2193. ReportData interface{} `db:"-"`
  2194. CompleteTime null.String `db:"complete_time"`
  2195. Type string `db:"type"`
  2196. IsJinyins string `db:"is_jiyins"`
  2197. OriginalReport null.String `db:"original_report"`
  2198. Source string `db:"source"`
  2199. }{}
  2200. err := db.Get(data, strSql, oid)
  2201. if err != nil {
  2202. return nil, err
  2203. }
  2204. if !data.ShareCode.Valid || strings.Trim(data.ShareCode.String, " ") == "" {
  2205. code := util.GenerateCodeStr(8)
  2206. strSql := fmt.Sprintf("update %s set share_code = ? where id = ?;", orderTableName)
  2207. _, err = db.Exec(strSql, code, oid)
  2208. if err != nil {
  2209. return nil, err
  2210. }
  2211. data.ShareCode.SetValid(code)
  2212. }
  2213. if strings.Trim(data.ReportPicture, " ") != "" {
  2214. return data, err
  2215. }
  2216. reportData, err := GetReportData(oid, otype)
  2217. if err != nil {
  2218. return nil, err
  2219. }
  2220. data.ReportData = reportData
  2221. return data, nil
  2222. }
  2223. type (
  2224. reportDetectItem struct {
  2225. DetectProductId string `json:"detect_product_id"`
  2226. Id string `json:"id"`
  2227. Name string `json:"name"`
  2228. UpRefValue string `json:"up_refvalue"`
  2229. RefValue string `json:"refvalue"`
  2230. Final string `json:"final"`
  2231. FinalStatus int8 `json:"final_status"`
  2232. Unit string `json:"unit"`
  2233. CheckTime string `json:"check_time"`
  2234. IsShowRefvalue int8 `json:"is_show_refvalue"`
  2235. Description string `json:"description"`
  2236. FinalTip string `json:"final_tip"`
  2237. Extra string `json:"extra"`
  2238. }
  2239. reportDetectProduct struct {
  2240. Id string `json:"id"`
  2241. ProductId string `json:"product_id"`
  2242. Name string `json:"name"`
  2243. SortNo string `json:"sort_no"`
  2244. Items []*reportDetectItem `json:"items"`
  2245. Comment string `json:"comment"`
  2246. AnomalyCount uint `json:"anomaly_count"`
  2247. Icon string `json:"icon"`
  2248. IconSmall string `json:"icon_small"`
  2249. }
  2250. reportProduct struct {
  2251. ProductId string `json:"product_id"`
  2252. ProductName string `json:"product_name"`
  2253. IsJiyin int `json:"is_jiyin"`
  2254. Items []*reportDetectProduct `json:"items"`
  2255. }
  2256. detectItemResult struct {
  2257. DetectItemId string `db:"detect_item_id"`
  2258. Final string `db:"final"`
  2259. FinalStatus int8 `db:"final_status"`
  2260. RefValue string `db:"refValue"`
  2261. Age string `db:"age"`
  2262. Gender string `db:"gender"`
  2263. Unit string `db:"unit"`
  2264. CheckTime null.String `db:"checkTime"`
  2265. Description null.String `db:"description"`
  2266. FinalTip null.String `db:"final_tip"`
  2267. Extra null.String `db:"extra"`
  2268. }
  2269. analysisItemResult struct {
  2270. Title null.String `db:"title"`
  2271. Analysis null.String `db:"analysis"`
  2272. OrderNum int `db:"order_num"`
  2273. }
  2274. tempCItem struct {
  2275. Comment null.String
  2276. Icon null.String
  2277. IconSmall null.String
  2278. }
  2279. )
  2280. func GetReportData(oid string, otype string) (interface{}, error) {
  2281. oid = strings.ToUpper(oid)
  2282. var (
  2283. strSql = "select product_schema from t_order_product_snapshot where order_id = ? limit 1"
  2284. productSchema string
  2285. db = util.GetSqlDB()
  2286. productList = []reportProduct{}
  2287. )
  2288. err := db.Get(&productSchema, strSql, oid)
  2289. if err != nil {
  2290. return nil, err
  2291. }
  2292. err = json.Unmarshal([]byte(productSchema), &productList)
  2293. if err != nil {
  2294. return nil, err
  2295. }
  2296. strSql = "select t1.*, t2.description from t_custom_detect_result t1 left join t_detect_item t2 on t1.detect_item_id = t2.id where order_no = ?"
  2297. ditemResultList := []detectItemResult{}
  2298. ditemIdxMap := map[string]int{}
  2299. err = db.Select(&ditemResultList, strSql, oid)
  2300. if err != nil {
  2301. return nil, err
  2302. }
  2303. for idx, ditem := range ditemResultList {
  2304. ditemIdxMap[ditem.DetectItemId] = idx
  2305. }
  2306. strSql = "select detect_product_id, result_comment, t2.icon, t2.icon_small from t_detect_product_comment t1 left join t_detect_product t2 on t1.detect_product_id = t2.id where order_no = ?"
  2307. rows, err := db.Queryx(strSql, oid)
  2308. if err != nil {
  2309. return nil, err
  2310. }
  2311. var (
  2312. dpid string
  2313. comment null.String
  2314. comments = map[string]tempCItem{}
  2315. icon null.String
  2316. iconSmall null.String
  2317. )
  2318. for rows.Next() {
  2319. rows.Scan(&dpid, &comment, &icon, &iconSmall)
  2320. comments[dpid] = tempCItem{
  2321. Comment: comment,
  2322. Icon: icon,
  2323. IconSmall: iconSmall,
  2324. }
  2325. }
  2326. rows.Close()
  2327. analysisInfo := struct {
  2328. Analysis null.String `db:"analysis" json:"analysis"`
  2329. CustomName string `db:"name" json:"custom_name"`
  2330. Mobile string `db:"mobile" json:"mobile"`
  2331. Age string `db:"-" json:"age"`
  2332. Gender string `db:"-" json:"gender"`
  2333. Summarize null.String `db:"summarize" json:"summarize"`
  2334. ReportItems string `db:"-" json:"report_items"`
  2335. AnalysisList interface{} `db:"-" json:"analysis_desc"`
  2336. }{}
  2337. var orderTableName = "t_order"
  2338. if otype == "SPECIAL" {
  2339. orderTableName = "t_special_order"
  2340. }
  2341. strSql = "select analysis, mobile, name, summarize from " + orderTableName + " t1 left join t_report_analysis t2 on t1.id = t2.order_id left join t_report_summarize t3 on t1.id = t3.order_id where t1.id = ?"
  2342. err = db.Get(&analysisInfo, strSql, oid)
  2343. if err != nil {
  2344. return nil, err
  2345. }
  2346. strSql = "select * from t_report_analysis_desc where order_id = ? order by order_num asc;"
  2347. var alist = []analysisItemResult{}
  2348. err = db.Select(&alist, strSql, oid)
  2349. if err != nil {
  2350. return nil, err
  2351. }
  2352. analysisInfo.AnalysisList = alist
  2353. var ritems string
  2354. db.Get(&ritems, "select item from t_report_item where order_id = ?", oid)
  2355. analysisInfo.ReportItems = ritems
  2356. for _, pitem := range productList {
  2357. for _, dpItem := range pitem.Items {
  2358. if _, ok := comments[dpItem.Id]; ok {
  2359. dpItem.Comment = comments[dpItem.Id].Comment.String
  2360. dpItem.Icon = comments[dpItem.Id].Icon.String
  2361. dpItem.IconSmall = comments[dpItem.Id].IconSmall.String
  2362. }
  2363. for _, ditem := range dpItem.Items {
  2364. if idx, ok := ditemIdxMap[ditem.Id]; ok {
  2365. ditem.RefValue = ditemResultList[idx].RefValue
  2366. ditem.FinalStatus = ditemResultList[idx].FinalStatus
  2367. ditem.Final = ditemResultList[idx].Final
  2368. ditem.Unit = ditemResultList[idx].Unit
  2369. ditem.CheckTime = ditemResultList[idx].CheckTime.String
  2370. ditem.Description = ditemResultList[idx].Description.String
  2371. ditem.FinalTip = ditemResultList[idx].FinalTip.String
  2372. if analysisInfo.Age == "" {
  2373. analysisInfo.Age = ditemResultList[idx].Age
  2374. }
  2375. if analysisInfo.Gender == "" {
  2376. analysisInfo.Gender = ditemResultList[idx].Gender
  2377. }
  2378. ditem.Extra = ditemResultList[idx].Extra.String
  2379. }
  2380. if ditem.FinalStatus == 1 || ditem.FinalStatus == 2 || ditem.FinalStatus == -1 || ditem.FinalStatus == 3 {
  2381. dpItem.AnomalyCount++
  2382. }
  2383. }
  2384. }
  2385. }
  2386. return map[string]interface{}{
  2387. "base_info": analysisInfo,
  2388. "product_list": productList,
  2389. }, nil
  2390. }
  2391. func (srv *OrderService) OrderUpdate(oitem *entity.Order, upType string) (interface{}, error) {
  2392. if oitem.Id == "" {
  2393. return nil, errors.New("miss param order id")
  2394. }
  2395. var upItem *entity.Order
  2396. switch upType {
  2397. case "1":
  2398. upItem = &entity.Order{
  2399. Id: oitem.Id,
  2400. IsViewReport: oitem.IsViewReport,
  2401. }
  2402. case "2":
  2403. strSql := "select blood_codes from t_order where blood_codes = ? and mobile <> ? limit 1;"
  2404. db := util.GetSqlDB()
  2405. var bcodes string
  2406. err := db.Get(&bcodes, strSql, oitem.BloodCodes, oitem.Mobile)
  2407. if err != nil && err != sql.ErrNoRows {
  2408. return nil, err
  2409. }
  2410. if err == nil {
  2411. return nil, errors.New("1:: blood code was already used")
  2412. }
  2413. var oids = strings.Split(oitem.Id, ",")
  2414. var strOids string
  2415. for _, oid := range oids {
  2416. strOids += "'" + oid + "',"
  2417. }
  2418. strOids = strOids[0 : len(strOids)-1]
  2419. db.Exec("update t_order set blood_codes = ? where id in("+strOids+");", oitem.BloodCodes)
  2420. return true, nil
  2421. case "4": //qz 20210105 修改
  2422. db := util.GetSqlDB()
  2423. if len(oitem.Remark) > 0 {
  2424. _, err := db.Exec("update t_order set remark = ? where id =? and custom_id = ? ", oitem.Remark, oitem.Id, oitem.CustomId)
  2425. if err != nil {
  2426. fmt.Println(err.Error())
  2427. return false, errors.New("4::update t_order remark error")
  2428. }
  2429. return true, nil
  2430. } else {
  2431. flag, err := UpdateOrderCase4(oitem)
  2432. if err != nil || !flag {
  2433. fmt.Println(err.Error())
  2434. return false, err
  2435. }
  2436. return true, nil
  2437. }
  2438. default:
  2439. }
  2440. if upItem == nil {
  2441. return nil, nil
  2442. }
  2443. return srv.IOrder.Update(upItem)
  2444. }
  2445. // 20210204 修改 orderUpdate case 4 的逻辑 只有remark 单独处理,其他的提取出来
  2446. func UpdateOrderCase4(oitem *entity.Order) (bool, error) {
  2447. db := util.GetSqlDB()
  2448. tx := db.MustBegin()
  2449. //获取原始订单,主要需要visit_date visit_time_range m_id
  2450. old, err := dal.DefaultOrderDal.Get(oitem.Id)
  2451. if err != nil {
  2452. return false, fmt.Errorf("7::查询订单失败%s", oitem.Id)
  2453. }
  2454. //todo 判断新旧日期,判断不同就需要查询产能,并且归还产能
  2455. if oitem.VisitTimeRange == old.VisitTimeRange.String && oitem.VisitDate == old.VisitDate.String {
  2456. //如果新旧日期相同, 就不修改产能
  2457. } else { //todo 更新产能
  2458. //todo 1 查询新产能
  2459. strSql := `SELECT
  2460. t1.num,
  2461. t2.remain_num,
  2462. t2.pdate,
  2463. t1.id AS gid,
  2464. t2.id AS infoid
  2465. FROM t_producer_config t1
  2466. LEFT JOIN t_producer_info t2 ON t1.id = t2.global_id
  2467. AND t1.id = ?
  2468. AND t2.pdate = ?
  2469. AND t2.time_range = ?`
  2470. var producerInfo = struct {
  2471. GNum int `db:"num"`
  2472. RemainNum sql.NullInt64 `db:"remain_num"`
  2473. PDate sql.NullString `db:"pdate"`
  2474. GId int `db:"gid"`
  2475. InfoId sql.NullInt64 `db:"infoid"`
  2476. }{}
  2477. var pinfoSqlResult sql.Result
  2478. err := db.Get(&producerInfo, strSql, oitem.PTId, oitem.VisitDate, oitem.VisitTimeRange)
  2479. if err != nil {
  2480. return false, errors.New("1::该城市暂未开通服务")
  2481. }
  2482. visitDate, err := time.Parse("2006-01-02", oitem.VisitDate)
  2483. if err != nil {
  2484. return false, errors.New("2::错误的上门日期")
  2485. }
  2486. //当天下单最早只能约第二天上门,240220 houyf改为20点
  2487. if visitDate.Before(time.Now()) || (time.Now().Hour() >= 20 && time.Now().Truncate(time.Hour*24).Add(time.Hour*48).After(visitDate)) {
  2488. return false, errors.New("3::失效的上门日期")
  2489. }
  2490. if producerInfo.PDate.String == oitem.VisitDate && producerInfo.RemainNum.Int64 <= 0 {
  2491. return false, errors.New("4::产能不足")
  2492. }
  2493. if !producerInfo.PDate.Valid {
  2494. pinfoSqlResult = tx.MustExec("insert into t_producer_info(global_id, pdate, time_range, num, remain_num) values(?, ?, ?, ?, ?)", producerInfo.GId, visitDate, oitem.VisitTimeRange, producerInfo.GNum, producerInfo.GNum-1)
  2495. lid, err := pinfoSqlResult.LastInsertId()
  2496. if err != nil {
  2497. tx.Tx.Rollback()
  2498. return false, err
  2499. }
  2500. oitem.MaterialId = int(lid)
  2501. } else {
  2502. pinfoSqlResult = tx.MustExec("update t_producer_info set remain_num = ? where id = ? and remain_num = ?", producerInfo.RemainNum.Int64-1, producerInfo.InfoId, producerInfo.RemainNum.Int64)
  2503. oitem.MaterialId = int(producerInfo.InfoId.Int64)
  2504. }
  2505. if ra, _ := pinfoSqlResult.RowsAffected(); ra <= 0 {
  2506. tx.Tx.Rollback()
  2507. return false, errors.New("5::更新产能失败")
  2508. }
  2509. //归还产能
  2510. if old.MaterialId > 0 && (old.Source == "web" || old.Source == "h5") {
  2511. result := tx.MustExec("update t_producer_info set remain_num = remain_num + 1 where id = ? ", old.MaterialId)
  2512. if ra, _ := result.RowsAffected(); ra <= 0 {
  2513. tx.Tx.Rollback()
  2514. return false, errors.New("6::更新产能失败")
  2515. }
  2516. }
  2517. }
  2518. sqlStr, kvm := util.GenerateUpdateSqlFromStruct("t_order", oitem, " where id='"+oitem.Id+"'")
  2519. _, err = tx.NamedExec(sqlStr, kvm)
  2520. if err != nil {
  2521. tx.Tx.Rollback()
  2522. return false, err
  2523. }
  2524. tx.Commit()
  2525. if util.SourceCheck(old.Source) {
  2526. client := util.GetRedis()
  2527. client.Select(12)
  2528. msg := map[string]interface{}{
  2529. "user": "system",
  2530. "orderid": old.Id,
  2531. "source": old.Source,
  2532. "status": old.Status,
  2533. }
  2534. buf, _ := json.Marshal(msg)
  2535. client.Publish("order-status-change", string(buf))
  2536. }
  2537. return true, nil
  2538. }
  2539. func (srv *OrderService) CommitSurvey(osItem *entity.OrderSurvey, userId int) (interface{}, error) {
  2540. oitem, err := srv.IOrder.Get(osItem.OrderId)
  2541. if oitem == nil {
  2542. return nil, errors.New("invalid order id")
  2543. }
  2544. if err != nil {
  2545. return nil, err
  2546. }
  2547. /*if oitem.CustomId != userId {
  2548. log.Println(oitem.CustomId, ":", userId)
  2549. return nil, errors.New("forbidden")
  2550. }*/
  2551. success, err := srv.IOrder.CommitSurvey(osItem)
  2552. if err != nil {
  2553. return false, err
  2554. }
  2555. if osItem.ServiceScore == "200" {
  2556. return success, nil
  2557. }
  2558. if success {
  2559. //add coupon user account related to the order
  2560. couponItem := &entity.DiscountTicket{
  2561. TypeId: int(constants.COUPONTYPE_NORMAL),
  2562. Mobile: oitem.Mobile,
  2563. Value: 1000,
  2564. Deadline: time.Now().Add(time.Hour * 24 * 365).Format("2006-01-02 15:04:05"),
  2565. OrderId: oitem.Id,
  2566. CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
  2567. }
  2568. _, err = dal.DefaultCouponDal.Save(couponItem)
  2569. if err != nil {
  2570. return false, err
  2571. }
  2572. return true, nil
  2573. }
  2574. return success, err
  2575. }
  2576. func (srv *OrderService) SaveCallbackInfo(info entity.OrderCallbackInfo) (interface{}, error) {
  2577. db := util.GetWriteSqlDB()
  2578. var c int
  2579. db.Get(&c, "select count(*) from t_order where id = ?", info.OrderId)
  2580. if c <= 0 {
  2581. return nil, errors.New("1::order not found")
  2582. }
  2583. c = 0
  2584. db.Get(&c, "select count(*) from t_order_abnormal where order_id = ?", info.OrderId)
  2585. if c > 0 {
  2586. return nil, errors.New("2::record already exists")
  2587. }
  2588. reviewDate, err := time.Parse("2006-01-02", info.VisitEndtime)
  2589. if err != nil {
  2590. return nil, errors.New("4::wrong visit end time")
  2591. }
  2592. info.ReviewDate = reviewDate.AddDate(0, 0, 60).Format("2006-01-02")
  2593. strSql, mkv := util.GenerateInsertSqlFromStruct("t_order_abnormal", &info)
  2594. _, err = db.NamedExec(strSql, mkv)
  2595. if err != nil {
  2596. return nil, errors.New("3::" + err.Error())
  2597. }
  2598. return true, nil
  2599. }
  2600. func (srv *OrderService) GetCallbackInfo(orderId string) (interface{}, error) {
  2601. var info = struct {
  2602. Mobile string `json:"mobile" db:"mobile"`
  2603. CustomMobile string `json:"custom_mobile" db:"custom_mobile"`
  2604. OrderId string `json:"order_id" db:"id"`
  2605. }{}
  2606. db := util.GetSqlDB()
  2607. err := db.Get(&info, "select mobile, custom_mobile, t2.id from t_order_abnormal t1 left join t_order t2 on t1.order_id = t2.id where t1.order_id = ? and is_own_date = 1 limit 1", orderId)
  2608. if err != nil {
  2609. if err == sql.ErrNoRows {
  2610. return nil, nil
  2611. }
  2612. return nil, err
  2613. }
  2614. return info, nil
  2615. }
  2616. // 根据血检条码获取订单信息
  2617. func (srv *OrderService) GetOrderInfoByCode(code string) (interface{}, error) {
  2618. return srv.IOrder.GetByCode(code)
  2619. }
  2620. func (srv *OrderService) GetOrderInfoByNurse(orderId string, deliverUserId int) (interface{}, error) {
  2621. db := util.GetSqlDB()
  2622. var oid string
  2623. db.Get(&oid, "select order_id from t_order_deliver_user where order_id = ? and deliver_user_id =?;", orderId, deliverUserId)
  2624. if oid == "" {
  2625. return nil, errors.New("forbidden")
  2626. }
  2627. return srv.OrderDetail(orderId)
  2628. }
  2629. func ComputeProductPrice(ids []int, quantityMap map[int]int, isPersonal bool) (int, int, error) {
  2630. if len(ids) == 0 {
  2631. return 0, 0, nil
  2632. }
  2633. inStr := ""
  2634. for _, pid := range ids {
  2635. inStr += fmt.Sprintf("%d,", pid)
  2636. }
  2637. inStr = inStr[0 : len(inStr)-1]
  2638. db := util.GetSqlDB()
  2639. var price int
  2640. var strSql string
  2641. var repeatFee int
  2642. if isPersonal {
  2643. strSql = "select sum(market_price) as price from t_detect_item where id in(" + inStr + ")"
  2644. } else {
  2645. strSql = `select t3.price, count(t3.id) as count from t_product_detect_product t1 left join t_detect_product_item t2 on
  2646. t1.detect_product_id = t2.detect_product_id left join t_detect_item t3 on t2.detect_item_id = t3.id where t1.product_id in (` + inStr + `) group by t3.id having (count > 1);`
  2647. rows, err := db.Queryx(strSql)
  2648. if err != nil {
  2649. return price, repeatFee, err
  2650. }
  2651. defer rows.Close()
  2652. var (
  2653. mp int
  2654. count int
  2655. )
  2656. for rows.Next() {
  2657. rows.Scan(&mp, &count)
  2658. repeatFee += mp * (count - 1)
  2659. }
  2660. rows.Close()
  2661. strSql = `select id, price from t_product where id in(` + inStr + ")"
  2662. var (
  2663. productId int
  2664. pprice int
  2665. )
  2666. rows, _ = db.Queryx(strSql)
  2667. for rows.Next() {
  2668. rows.Scan(&productId, &pprice)
  2669. price += pprice * quantityMap[productId]
  2670. }
  2671. }
  2672. return price, repeatFee, nil
  2673. }
  2674. // 20221009 通过护士id 获取 产品 折扣价格
  2675. func ComputeProductPriceByDeliverID(ids []int, quantityMap map[int]int, deliverid float64) (int, int, error) {
  2676. if len(ids) == 0 {
  2677. return 0, 0, nil
  2678. }
  2679. inStr := ""
  2680. for _, pid := range ids {
  2681. inStr += fmt.Sprintf("%d,", pid)
  2682. }
  2683. inStr = inStr[0 : len(inStr)-1]
  2684. db := util.GetSqlDB()
  2685. var price int
  2686. var strSql string
  2687. var repeatFee int
  2688. strSql = `select t3.price, count(t3.id) as count from t_product_detect_product t1 left join t_detect_product_item t2 on
  2689. t1.detect_product_id = t2.detect_product_id left join t_detect_item t3 on t2.detect_item_id = t3.id where t1.product_id in (` + inStr + `) group by t3.id having (count > 1);`
  2690. rows, err := db.Queryx(strSql)
  2691. if err != nil {
  2692. return price, repeatFee, err
  2693. }
  2694. defer rows.Close()
  2695. var (
  2696. mp int
  2697. count int
  2698. )
  2699. for rows.Next() {
  2700. rows.Scan(&mp, &count)
  2701. repeatFee += mp * (count - 1)
  2702. }
  2703. rows.Close()
  2704. strSql = `select p.id, p.price,case when d.discount_price is null then 0 else d.discount_price end as discount_price from t_product p LEFT JOIN t_product_question_deliver d on p.id = d.product_id and d.deliver_user_id = ? and d.is_delete = 0 where p.id in (` + inStr + ")"
  2705. var (
  2706. productId int
  2707. pprice int
  2708. discount int
  2709. )
  2710. rows, _ = db.Queryx(strSql, deliverid)
  2711. for rows.Next() {
  2712. rows.Scan(&productId, &pprice, &discount)
  2713. if discount > 0 {
  2714. price += discount * quantityMap[productId]
  2715. } else {
  2716. price += pprice * quantityMap[productId]
  2717. }
  2718. }
  2719. return price, repeatFee, nil
  2720. }
  2721. func ComputeProductPrice_ZFB(ids []int, quantityMap map[int]int) (int, int, error) {
  2722. if len(ids) == 0 {
  2723. return 0, 0, nil
  2724. }
  2725. inStr := ""
  2726. for _, pid := range ids {
  2727. inStr += fmt.Sprintf("%d,", pid)
  2728. }
  2729. inStr = inStr[0 : len(inStr)-1]
  2730. db := util.GetSqlDB()
  2731. var price int
  2732. var strSql string
  2733. var repeatFee int
  2734. strSql = `select t3.price, count(t3.id) as count from t_product_detect_product t1 left join t_detect_product_item t2 on
  2735. t1.detect_product_id = t2.detect_product_id left join t_detect_item t3 on t2.detect_item_id = t3.id where t1.product_id in (` + inStr + `) group by t3.id having (count > 1);`
  2736. rows, err := db.Queryx(strSql)
  2737. if err != nil {
  2738. return price, repeatFee, err
  2739. }
  2740. defer rows.Close()
  2741. var (
  2742. mp int
  2743. count int
  2744. )
  2745. for rows.Next() {
  2746. rows.Scan(&mp, &count)
  2747. repeatFee += mp * (count - 1)
  2748. }
  2749. rows.Close()
  2750. strSql = `select id, zfb_price from t_product where id in(` + inStr + ")"
  2751. var (
  2752. productId int
  2753. pprice int
  2754. )
  2755. rows, _ = db.Queryx(strSql)
  2756. for rows.Next() {
  2757. rows.Scan(&productId, &pprice)
  2758. price += pprice * quantityMap[productId]
  2759. }
  2760. return price, repeatFee, nil
  2761. }
  2762. var orderNoMutex = &sync.Mutex{}
  2763. func GenerateOrderNo(prefix string) string {
  2764. prefix = strings.ToUpper(prefix)
  2765. timeStr := time.Now().Format("060102150405")
  2766. orderNoMutex.Lock()
  2767. defer orderNoMutex.Unlock()
  2768. timestamp := time.Now().Unix()
  2769. rand.Seed(timestamp + int64(time.Now().Nanosecond()))
  2770. var rnum = rand.Intn(100000)
  2771. strNum := fmt.Sprintf("0000%d", rnum)
  2772. strNum = strNum[len(strNum)-5:]
  2773. return fmt.Sprintf("%s%s%s", prefix, timeStr, strNum)
  2774. }
  2775. func GenerateOrderPayNO(prefix string) string {
  2776. timeStr := time.Now().Format("20060102150405")
  2777. timestamp := time.Now().Unix() + int64(time.Now().Nanosecond())
  2778. rand.Seed(timestamp)
  2779. var rnum = rand.Intn(100000)
  2780. strNum := fmt.Sprintf("00000%d", rnum)
  2781. strNum = strNum[len(strNum)-5:]
  2782. return prefix + timeStr + strNum
  2783. }
  2784. // qz 20200828 特定产品在交钱完成之后,拆分
  2785. func (srv *OrderService) SplitOrder(orderId string, productId int) {
  2786. //20220620 取消
  2787. return
  2788. /*
  2789. db := util.GetWriteSqlDB()
  2790. //查询拆单关系
  2791. tpsInfoList := []struct {
  2792. ProductId int `db:"product_id" `
  2793. ChildId int `db:"child_id"`
  2794. IsMain int `db:"is_main"`
  2795. CreateAt string `db:"create_at"`
  2796. Remark null.String `db:"remark"`
  2797. Name null.String `db:"name"`
  2798. Price null.String `db:"price"`
  2799. }{}
  2800. sqlSearch := "select t1.*,t2.name as name,t2.price as price from t_product_split t1 left join t_product t2 on t1.child_id = t2.id where t1.product_id =? order by t1.is_main desc"
  2801. err := db.Select(&tpsInfoList, sqlSearch, productId)
  2802. if err != nil || len(tpsInfoList) <= 0 {
  2803. log.Println(fmt.Sprintf("订单%s,产品编号为%d 不需要拆单", orderId, productId))
  2804. return
  2805. }
  2806. //查询订单,
  2807. orderDb, err := srv.IOrder.Get(orderId)
  2808. fmt.Println(orderDb)
  2809. //查询订单 产品关联
  2810. plist := struct {
  2811. OrderId string `db:"order_id"`
  2812. ProductId string `db:"product_id"`
  2813. ProductName string `db:"product_name"`
  2814. Price int `db:"price"`
  2815. Picture string `db:"picture"`
  2816. Quantity int `db:"quantity"`
  2817. IsPersonal int `db:"is_personal"`
  2818. }{}
  2819. strSql := "select * from t_order_product where order_id = ? and product_id = ?"
  2820. err = db.Get(&plist, strSql, orderId, productId)
  2821. //查询订单 扩展
  2822. //elist :=struct {
  2823. // OrderID string `db:"order_id"`
  2824. // NeedEmtiness int `db:"need_emptiness"`
  2825. // ReportPeriod string `db:"report_period"`
  2826. // PressurePipe string `db:"pressure_pipe"`
  2827. // BloodAddress string `db:"blood_address"`
  2828. // Notice string `db:"notice"`
  2829. // UpdatedAt time.Time `db:"updated_at"`
  2830. // Remark1 string `db:"remark1"`
  2831. // CancelReason int `db:"cancel_reason"`
  2832. // IsNotice string `db:"is_notice"`
  2833. // RelationShip string `db:"relationship"`
  2834. // IsYunXue int `db:"is_yunxue"`
  2835. // IsDfgoumin int `db:"is_dfguomin"`
  2836. // BloodTestId string `db:"bloodtest_id"`
  2837. // ReportResult string `db:"reportresult"`
  2838. // PayNurse int `db:"paynurse"`
  2839. // IsAddpor string `db:"isaddpro"`
  2840. // Sample string `db:"sample"`
  2841. // JiCaiName string `db:"jicai_name"`
  2842. // Express string `db:"express"`
  2843. // ExpressNumber string `db:"expressnumber"`
  2844. // ExpressStatus string `db:"expressstatus"`
  2845. // ExpressInfo string `db:"expressinfo"`
  2846. // ExpressUser string `db:"express_user"`
  2847. // ExpressnumberUser string `db:"expressnumber_user"`
  2848. //}{}
  2849. //strSql = "select * from t_order_extra where order_id = ?"
  2850. //err = db.Select(&elist, strSql, orderId)
  2851. //拆分 order
  2852. tx := db.MustBegin()
  2853. for i := 0; i < len(tpsInfoList); i++ {
  2854. if tpsInfoList[i].IsMain == 1 {
  2855. //order 不用更新
  2856. //更新order_product
  2857. result := tx.MustExec("update t_order_product set product_id = ?,product_name = ?,price=? where order_id = ? and product_id = ?", tpsInfoList[i].ChildId, tpsInfoList[i].Name, tpsInfoList[i].Price, orderId, productId)
  2858. if ra, _ := result.RowsAffected(); ra <= 0 {
  2859. tx.Tx.Rollback()
  2860. log.Println(fmt.Sprintf("订单%s,产品编号为%d 拆单失败 更新 t_order_product ", orderId, productId))
  2861. return
  2862. }
  2863. //order_extra 不用更新
  2864. } else {
  2865. //生成订单号
  2866. orderNewId := GenerateOrderNoByOld(orderId, i)
  2867. fmt.Println(orderNewId)
  2868. //插入 t_order
  2869. orderDb.Id = orderNewId
  2870. orderDb.Payment = 0
  2871. orderDb.ServiceRemark = null.StringFrom(fmt.Sprintf("由%s拆单", orderId))
  2872. strSql, mkv := util.GenerateInsertSqlFromStruct("t_order", orderDb)
  2873. osqlResult, err := tx.NamedExec(strSql, mkv)
  2874. if err != nil {
  2875. tx.Tx.Rollback()
  2876. log.Println(fmt.Sprintf("订单%s,产品编号为%d 拆单失败 插入 t_order %s", orderId, productId, orderNewId))
  2877. return
  2878. }
  2879. if ra, _ := osqlResult.RowsAffected(); ra <= 0 {
  2880. tx.Tx.Rollback()
  2881. log.Println(fmt.Sprintf("订单%s,产品编号为%d 拆单失败 插入 t_order %s", orderId, productId, orderNewId))
  2882. return
  2883. }
  2884. //todo 查询product
  2885. //插入 t_order_product 注意 金额
  2886. var fields = map[string]interface{}{
  2887. "order_id": orderNewId,
  2888. "product_id": tpsInfoList[i].ChildId,
  2889. "product_name": tpsInfoList[i].Name,
  2890. "price": tpsInfoList[i].Price,
  2891. "picture": plist.Picture,
  2892. "quantity": plist.Quantity,
  2893. "is_personal": plist.IsPersonal,
  2894. }
  2895. strSql = util.GenerateInsertSql("t_order_product", fields)
  2896. _, err = tx.NamedExec(strSql, fields)
  2897. if err != nil {
  2898. tx.Tx.Rollback()
  2899. log.Println(fmt.Sprintf("订单%s,产品编号为%d 拆单失败,新建 t_order_product %s", orderId, productId, orderNewId))
  2900. return
  2901. }
  2902. //复制 t_order_extra
  2903. result := tx.MustExec(fmt.Sprintf("insert into t_order_extra(`order_id`, `need_emptiness`, `report_period`, `pressure_pipe`, `blood_address`, `notice`, `updated_at`, `remark1`, `cancel_reason`, `is_notice`, `relationship`, `is_yunxue`, `is_dfguomin`, `bloodtest_id`, `reportresult`, `paynurse`, `isaddpro`, `sample`, `jicai_name`, `express`, `expressnumber`, `expressstatus`, `expressinfo`, `express_user`, `expressnumber_user`) select '%s',`need_emptiness`, `report_period`, `pressure_pipe`, `blood_address`, `notice`, `updated_at`, `remark1`, `cancel_reason`, `is_notice`, `relationship`, `is_yunxue`, `is_dfguomin`, `bloodtest_id`, `reportresult`, `paynurse`, `isaddpro`, `sample`, `jicai_name`, `express`, `expressnumber`, `expressstatus`, `expressinfo`, `express_user`, `expressnumber_user` from t_order_extra where order_id =?", orderNewId), orderId)
  2904. if ra, _ := result.RowsAffected(); ra <= 0 {
  2905. tx.Tx.Rollback()
  2906. log.Println(fmt.Sprintf("订单%s,产品编号为%d 拆单失败,新建 t_order_extra %s", orderId, productId, orderNewId))
  2907. return
  2908. }
  2909. }
  2910. }
  2911. tx.Commit()
  2912. */
  2913. }
  2914. func (srv *OrderService) SendDingMsg(orderId string) {
  2915. util.SendOrderMsg(fmt.Sprintf("加急核酸来订单了,订单来源xn ,订单编号%s", orderId))
  2916. }
  2917. //20210119 添加 产品1149 两人核酸,下单后拆单 20220620 删除
  2918. // 20210607 金睡莲活动,支付成功后更新状态码
  2919. func (srv *OrderService) JinShuiLianServer(id string) {
  2920. //t_custom_wxscan_pay remark 保存了 t_activity_info 的 id ;t_activity_info address 保存 fcode 还需要mobile 发送短信
  2921. db := util.GetWriteSqlDB()
  2922. aInfo := struct {
  2923. Mobile null.String `db:"mobile"`
  2924. FCode string `db:"address"`
  2925. }{}
  2926. db.Get(&aInfo, "select mobile,address from t_activity_info where id = ?", id)
  2927. pinfoSqlResult := db.MustExec("update t_fcode set already_use_num = already_use_num +1 where code_str = ? and use_num>= already_use_num+1 ", aInfo.FCode)
  2928. if ra, _ := pinfoSqlResult.RowsAffected(); ra <= 0 {
  2929. fmt.Println("fcode update error")
  2930. }
  2931. sms := &SMSService{dal.DefaultSMSCodeDal}
  2932. if aInfo.Mobile.Valid {
  2933. sms.SendSMS(aInfo.Mobile.ValueOrZero(), 24, nil)
  2934. }
  2935. }
  2936. // 20211127 联仁根据门店id 修改定价
  2937. func lianRenPrice(list []*entity.ProductDB, shopId int) {
  2938. db := util.GetSqlDB()
  2939. var price int
  2940. db.Get(&price, "select price from t_shop_lianren where id = ? ", shopId)
  2941. if price > 0 {
  2942. for i := 0; i < len(list); i++ {
  2943. list[i].Price = price
  2944. }
  2945. }
  2946. }
  2947. // 20230830 拆分历史表
  2948. // 提取 addorder addorderFcode addorderFcodeYuanyi addGenorder 的库存检查
  2949. func Stocklimit(mobile string, productIds []int, productQuantityMap map[int]int, isZFB bool) ([]*entity.ProductDB, error) {
  2950. plist := []*entity.ProductDB{}
  2951. s_source_zfb := ""
  2952. if isZFB {
  2953. s_source_zfb = " and t2.source='sp_zfb' "
  2954. }
  2955. db := util.GetSqlDB()
  2956. sqlTemp := "select t1.*, sum(t4.quantity) as bought_num from (select * from t_product where id in(" + util.IntJoin(productIds, ",") + ")) t1 left join (select t3.quantity, t3.product_id from t_order t2 left join t_order_product t3 on t2.id = t3.order_id where custom_mobile = ? and t2.status not in (7,9,14) and t2.retype in ('100','110') " + s_source_zfb + " ) t4 on t1.id = t4.product_id GROUP BY t1.id order by t1.is_no_booktime desc"
  2957. db.Select(&plist, sqlTemp, mobile)
  2958. if len(plist) != len(productIds) {
  2959. return nil, errors.New("6::wrong param productids")
  2960. }
  2961. if isZFB {
  2962. entity.ZFBWash(plist)
  2963. }
  2964. for _, pitem := range plist {
  2965. if pitem.StockSwitch == "ON" && pitem.Stock < productQuantityMap[pitem.Id] {
  2966. return nil, errors.New("10::out of stock")
  2967. }
  2968. if pitem.PstockSwitch == "ON" && int(pitem.BoughtNum.Int64)+productQuantityMap[pitem.Id] > pitem.Pstock {
  2969. return nil, errors.New(fmt.Sprintf("11::upper limit of product %d", pitem.Id))
  2970. }
  2971. }
  2972. return plist, nil
  2973. }
  2974. // 20240221 查询有效订单表
  2975. func (*OrderService) OrderVaildCount(customId, status int, mobile string) (interface{}, error) {
  2976. strSql := "select count(distinct t2.id) from (select id, mobile from t_custom where id = ?) t1, t_order t2 "
  2977. strSql += " where (t1.id = t2.custom_id or t1.mobile = t2.mobile) and status not in (7,9,14) "
  2978. whereValue := []interface{}{
  2979. customId,
  2980. }
  2981. //if status > 0 {
  2982. // whereStr += " "
  2983. // whereValue = append(whereValue, status)
  2984. //} else if status == -1 {
  2985. // whereStr += " and status in(6,11) "
  2986. //} else {
  2987. // //whereStr += " and status <> 8 "
  2988. // whereStr += " and is_delete='N'"
  2989. //}
  2990. if mobile != "" {
  2991. strSql += " and t2.mobile = ? "
  2992. whereValue = append(whereValue, mobile)
  2993. }
  2994. strSql += " and t2.retype in ('100','110')"
  2995. db := util.GetSqlDB()
  2996. var count1, count2 int
  2997. err := db.Get(&count1, strSql, whereValue...)
  2998. if err != nil {
  2999. return 0, err
  3000. }
  3001. err = db.Get(&count2, util.ChangeOrderTableName(strSql), whereValue...)
  3002. if err != nil {
  3003. return 0, err
  3004. }
  3005. return count1 + count2, nil
  3006. }