invoiceManager.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package service
  2. import (
  3. "ElectronicInvoice/util"
  4. "context"
  5. "fmt"
  6. "github.com/gogf/gf/v2/errors/gerror"
  7. "github.com/gogf/gf/v2/frame/g"
  8. "github.com/gogf/gf/v2/os/gcron"
  9. "time"
  10. )
  11. var (
  12. JyInvoiceManager *InvoiceManager
  13. )
  14. type InvoiceManager struct {
  15. Auth *TripartiteAuth
  16. jobRunning bool //开票是否运行中
  17. StopRunning bool //财务占用账号,需要暂停任务
  18. Login bool //登录状态
  19. RunPool chan bool //任务(每次只能进行一个开票任务)
  20. phoneCode chan string //短信验证码池
  21. ScanLogin chan bool //扫码登录
  22. }
  23. func init() {
  24. JyInvoiceManager = createInvoiceManager()
  25. //开票任务
  26. job, err := gcron.Add(context.Background(), g.Cfg().MustGet(context.Background(), "invoiceJob.cron").String(), JyInvoiceManager.RunJob, "invoiceJob")
  27. if err != nil {
  28. panic(err)
  29. }
  30. job.Start()
  31. //超时开票提醒
  32. jobNotice, errNotice := gcron.Add(context.Background(), g.Cfg().MustGet(context.Background(), "invoiceJob.notice.unFinish.cron").String(), JyInvoiceManager.NoticeJob, "invoiceNoticeJob")
  33. if errNotice != nil {
  34. panic(errNotice)
  35. }
  36. jobNotice.Start()
  37. //初始化三方接口
  38. JyInvoiceManager.Auth.CallBackInit()
  39. //go func() {
  40. // time.Sleep(time.Second * 5)
  41. // JyInvoiceManager.RunRedBatchOnce(context.Background())
  42. //}()
  43. //go JyInvoiceManager.RunOneJob(context.Background())//流程
  44. //go JyInvoiceManager.Demo(context.Background()) //开票
  45. //go JyInvoiceManager.Auth.Login() //登录
  46. //go JyInvoiceManager.RedDemo(context.Background())//红冲
  47. //err = JyInvoiceManager.Auth.AddTaxCode([]Billitem{{
  48. // Name: "技术服务费",
  49. // Ssflbm: "3040205000000000000",
  50. // Thirdid: "6f2e6a7a-18a7-4f21-b52e-a47437f817cc",
  51. //}})
  52. //if err != nil {
  53. // panic(err)
  54. //}
  55. //list, err := JyInvoiceManager.Auth.GetSuccessTaxCodeList()
  56. //g.Dump(list, err)
  57. }
  58. func createInvoiceManager() *InvoiceManager {
  59. return &InvoiceManager{
  60. Auth: createTripartite(),
  61. Login: true, //默认已经登录
  62. RunPool: make(chan bool, 1), //开票只能单线程跑
  63. phoneCode: make(chan string, 1), //手机验证码
  64. ScanLogin: make(chan bool, 1), //扫码登录通知
  65. }
  66. }
  67. func (im *InvoiceManager) MobileVerificationCode(code string) error {
  68. if code == "" {
  69. return gerror.New("验证码为空")
  70. }
  71. select {
  72. case <-time.After(time.Minute):
  73. return gerror.New("验证码接收超时")
  74. case im.phoneCode <- code:
  75. return nil
  76. }
  77. }
  78. func (im *InvoiceManager) MobileVerificationClear() error {
  79. select {
  80. case <-time.After(time.Minute):
  81. return gerror.New("清除验证码超时")
  82. case <-im.phoneCode:
  83. return nil
  84. }
  85. }
  86. // RunJob 开票定时任务
  87. func (im *InvoiceManager) RunJob(ctx context.Context) {
  88. if im.jobRunning || im.StopRunning {
  89. g.Log().Infof(ctx, "RunJob-程序本次任务中断 jobRunning:%v StopRunning:%v", im.jobRunning, im.StopRunning)
  90. return
  91. }
  92. im.jobRunning = true
  93. defer func() {
  94. im.jobRunning = false
  95. g.Log().Infof(ctx, "RunJob-开票任务完成")
  96. }()
  97. if g.Cfg().MustGet(ctx, "invoiceJob.stop", false).Bool() {
  98. g.Log().Infof(ctx, "RunJob-开票程序任务已暂停,开启请删除 config.json > invoiceJob.stop")
  99. return
  100. }
  101. if !im.Login {
  102. if err := im.Auth.Login(); err != nil {
  103. g.Log().Errorf(ctx, "模拟登录异常 %v", err)
  104. return
  105. } else {
  106. g.Log().Infof(ctx, "登录成功")
  107. }
  108. }
  109. //TODO 普通蓝票任务(线上开票、管理后台一个订单开多张票)
  110. total, okNum, end, err := im.simpleMakeInvoice(ctx)
  111. if err != nil {
  112. g.Log().Errorf(ctx, "RunJob-simpleMakeInvoice任务异常 %v", err)
  113. if end {
  114. return
  115. }
  116. }
  117. g.Log().Infof(ctx, "RunJob-simpleMakeInvoice任务完成 共%d个 完成%d个", total, okNum)
  118. // TODO 多订单合并开票(管理后台-多订单合并开票)
  119. total, okNum, end, err = im.multipleOrdersMakeInvoice(ctx)
  120. if err != nil {
  121. g.Log().Errorf(ctx, "RunJob-multipleOrdersMakeInvoice任务异常 %v", err)
  122. if end {
  123. return
  124. }
  125. }
  126. g.Log().Infof(ctx, "RunJob-multipleOrdersMakeInvoice任务完成 共%d个 完成%d个", total, okNum)
  127. // TODO 红冲(线上开票、管理后台一个订单开多张票)
  128. total, okNum, end, err = im.makeRedInvoice(ctx)
  129. if err != nil {
  130. g.Log().Errorf(ctx, "RunJob-makeRedInvoice任务异常 %v", err)
  131. if end {
  132. return
  133. }
  134. }
  135. g.Log().Infof(ctx, "RunJob-makeRedInvoice任务完成 共%d个 完成%d个", total, okNum)
  136. // TODO 红冲(线上开票、管理后台一个订单开多张票)
  137. total, okNum, end, err = im.multipleOrdersMakeRedInvoice(ctx)
  138. if err != nil {
  139. g.Log().Errorf(ctx, "RunJob-multipleOrdersMakeRedInvoice任务异常 %v", err)
  140. if end {
  141. return
  142. }
  143. }
  144. g.Log().Infof(ctx, "RunJob-multipleOrdersMakeRedInvoice任务完成 共%d个 完成%d个", total, okNum)
  145. //保证所有回调已执行完成
  146. select {
  147. case im.RunPool <- true:
  148. <-im.RunPool
  149. case <-time.After(time.Minute * 5):
  150. g.Log().Infof(ctx, "RunJob-等待回调完成超时")
  151. }
  152. g.Log().Infof(ctx, "开票任务结束")
  153. }
  154. // NoticeJob 为开票成功提示
  155. func (im *InvoiceManager) NoticeJob(ctx context.Context) {
  156. var (
  157. unMakeRed = 0
  158. unMakeBlue = 0
  159. limitHours = g.Cfg().MustGet(ctx, "invoiceJob.notice.unFinish.hours", 24).Int64()
  160. )
  161. if im.StopRunning {
  162. return
  163. }
  164. createTimeLimit := time.Now().Unix() - limitHours*60*60
  165. // 蓝票未完成发票数量查询
  166. unMakeBlue, _ = g.DB().GetCount(ctx, `SELECT count(*) FROM(
  167. SELECT a.id as onlyId FROM invoice a WHERE a.invoice_variety like '%电子%' AND ((a.invoice_status=0 AND a.invoice_changed=0) or (a.invoice_status=2 AND a.invoice_changed=1 )) AND (a.invoice_order_code is NULL OR a.invoice_order_code not like '%,%') AND a.create_time > UNIX_TIMESTAMP('2024-04-23 00:00:00') AND a.create_time<?
  168. UNION
  169. SELECT a.only_Identifying as onlyId FROM invoice a WHERE a.invoice_variety like '%电子%' AND ((a.invoice_status=0 AND a.invoice_changed=0) or (a.invoice_status=2 AND a.invoice_changed=1)) AND a.invoice_order_code like '%,%' AND a.create_time > UNIX_TIMESTAMP('2024-04-23 00:00:00') AND a.create_time<? GROUP BY invoice_order_code
  170. ) as data`, createTimeLimit, createTimeLimit)
  171. // 红票未完成发票数量查询
  172. unMakeRed, _ = g.DB().GetCount(ctx, `SELECT count(*) FROM(
  173. SELECT a.invoice_number as onlyId FROM invoice a WHERE a.invoice_variety like '%电子%' AND a.invoice_status=0 AND a.invoice_changed=1 AND (a.invoice_order_code is NULL OR a.invoice_order_code not like '%,%') AND a.create_time > UNIX_TIMESTAMP('2024-04-23 00:00:00') AND a.create_time<?
  174. UNION
  175. SELECT a.invoice_number as onlyId FROM invoice a WHERE a.invoice_variety like '%电子%' AND a.invoice_status=0 AND a.invoice_changed=1 AND a.invoice_order_code like '%,%' AND a.create_time > UNIX_TIMESTAMP('2024-04-23 00:00:00') AND a.create_time<? GROUP BY invoice_order_code
  176. ) as data`, createTimeLimit, createTimeLimit)
  177. if unMakeRed > 0 || unMakeBlue > 0 {
  178. noticeMsg := fmt.Sprintf("开票超%d小时提醒\n", limitHours)
  179. if unMakeBlue > 0 {
  180. noticeMsg += fmt.Sprintf("蓝票:%d例\n", unMakeBlue)
  181. }
  182. if unMakeRed > 0 {
  183. noticeMsg += fmt.Sprintf("红票:%d例\n", unMakeRed)
  184. }
  185. if err := util.SendSimpleMsg2ChatBot(noticeMsg, g.Cfg().MustGet(ctx, "invoiceJob.notice.unFinish.notice").Strings()...); err != nil {
  186. g.Log().Errorf(ctx, "发送未开票消息异常 %v", err)
  187. }
  188. }
  189. }