ctr_contract.go 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782
  1. package service
  2. import (
  3. "context"
  4. worksrv "dashoo.cn/micro/app/service/work"
  5. "database/sql"
  6. "encoding/base64"
  7. "encoding/json"
  8. "fmt"
  9. "github.com/gogf/gf/util/gconv"
  10. "io"
  11. "net/http"
  12. "strconv"
  13. "strings"
  14. "sync"
  15. "time"
  16. basedao "dashoo.cn/micro/app/dao/base"
  17. dao "dashoo.cn/micro/app/dao/contract"
  18. custdao "dashoo.cn/micro/app/dao/cust"
  19. projdao "dashoo.cn/micro/app/dao/proj"
  20. workflowdao "dashoo.cn/micro/app/dao/workflow"
  21. model "dashoo.cn/micro/app/model/contract"
  22. proj "dashoo.cn/micro/app/model/proj"
  23. workflowModel "dashoo.cn/micro/app/model/workflow"
  24. "dashoo.cn/micro/app/service"
  25. baseService "dashoo.cn/micro/app/service/base"
  26. projsrv "dashoo.cn/micro/app/service/proj"
  27. "dashoo.cn/opms_libary/micro_srv"
  28. "dashoo.cn/opms_libary/multipart"
  29. "dashoo.cn/opms_libary/myerrors"
  30. "dashoo.cn/opms_libary/plugin/dingtalk"
  31. "dashoo.cn/opms_libary/plugin/dingtalk/message"
  32. "dashoo.cn/opms_libary/request"
  33. "github.com/gogf/gf/database/gdb"
  34. "github.com/gogf/gf/frame/g"
  35. "github.com/gogf/gf/os/gcron"
  36. "github.com/gogf/gf/os/glog"
  37. "github.com/gogf/gf/os/gtime"
  38. "github.com/gogf/gf/util/gvalid"
  39. )
  40. type CtrContractService struct {
  41. Dao *dao.CtrContractDao
  42. ProjBusinessDao *projdao.ProjBusinessDao
  43. CustomerDao *custdao.CustCustomerDao
  44. CtrProductDao *dao.CtrContractProductDao
  45. ProductDao *basedao.BaseProductDao
  46. DynamicsDao *dao.CtrContractDynamicsDao
  47. WorkflowDao *workflowdao.PlatWorkflowDao
  48. AppendDao *dao.CtrContractAppendDao
  49. GoalDao *dao.CtrContractGoalDao
  50. ShareDao *dao.CtrContractShareDao
  51. TargetDao *dao.CtrContractSaleTargetDao
  52. Tenant string
  53. userInfo request.UserInfo
  54. DataScope g.Map `json:"dataScope"`
  55. }
  56. var mtx sync.Mutex
  57. func NewCtrContractService(ctx context.Context) (*CtrContractService, error) {
  58. tenant, err := micro_srv.GetTenant(ctx)
  59. if err != nil {
  60. err = myerrors.TipsError(fmt.Sprintf("获取租户码异常:%s", err.Error()))
  61. return nil, err //fmt.Errorf("获取租户码异常:%s", err.Error())
  62. }
  63. // 获取用户信息
  64. userInfo, err := micro_srv.GetUserInfo(ctx)
  65. if err != nil {
  66. return nil, fmt.Errorf("获取用户信息异常:%s", err.Error())
  67. }
  68. return &CtrContractService{
  69. Dao: dao.NewCtrContractDao(tenant),
  70. ProjBusinessDao: projdao.NewProjBusinessDao(tenant),
  71. CustomerDao: custdao.NewCustCustomerDao(tenant),
  72. CtrProductDao: dao.NewCtrContractProductDao(tenant),
  73. ProductDao: basedao.NewBaseProductDao(tenant),
  74. DynamicsDao: dao.NewCtrContractDynamicsDao(tenant),
  75. WorkflowDao: workflowdao.NewPlatWorkflowDao(tenant),
  76. AppendDao: dao.NewCtrContractAppendDao(tenant),
  77. GoalDao: dao.NewCtrContractGoalDao(tenant),
  78. ShareDao: dao.NewCtrContractShareDao(tenant),
  79. TargetDao: dao.NewCtrContractSaleTargetDao(tenant),
  80. Tenant: tenant,
  81. userInfo: userInfo,
  82. DataScope: userInfo.DataScope,
  83. }, nil
  84. }
  85. func (s CtrContractService) Get(ctx context.Context, id int) (*model.CtrContractGetRsp, error) {
  86. ent, err := s.Dao.Where("Id = ?", id).One()
  87. if err != nil {
  88. return nil, err
  89. }
  90. if ent == nil {
  91. return nil, myerrors.TipsError("合同不存在")
  92. }
  93. product, err := s.CtrProductDao.Where("contract_id = ?", id).All()
  94. if err != nil {
  95. return nil, err
  96. }
  97. if product == nil {
  98. product = []*model.CtrContractProduct{}
  99. }
  100. return &model.CtrContractGetRsp{
  101. CtrContract: *ent,
  102. Product: product,
  103. }, nil
  104. }
  105. func (s CtrContractService) DynamicsList(ctx context.Context, req *model.CtrContractDynamicsListReq) (int, interface{}, error) {
  106. dao := &s.DynamicsDao.CtrContractDynamicsDao
  107. if req.SearchText != "" {
  108. likestr := fmt.Sprintf("%%%s%%", req.SearchText)
  109. dao = dao.Where("(opn_people LIKE ? || opn_content LIKE ?)", likestr, likestr)
  110. }
  111. if req.ContractId != 0 {
  112. dao = dao.Where("contract_id = ?", req.ContractId)
  113. }
  114. if req.OpnPeopleId != 0 {
  115. dao = dao.Where("opn_people_id = ?", req.OpnPeopleId)
  116. }
  117. if req.OpnPeople != "" {
  118. likestr := fmt.Sprintf("%%%s%%", req.OpnPeople)
  119. dao = dao.Where("opn_people like ?", likestr)
  120. }
  121. if req.OpnType != "" {
  122. dao = dao.Where("opn_type = ?", req.OpnType)
  123. }
  124. // if req.OpnContent != "" {
  125. // likestr := fmt.Sprintf("%%%s%%", req.OpnContent)
  126. // dao = dao.Where("opn_content like ?", likestr)
  127. // }
  128. if req.BeginTime != "" {
  129. dao = dao.Where("created_time > ?", req.BeginTime)
  130. }
  131. if req.EndTime != "" {
  132. dao = dao.Where("created_time < ?", req.EndTime)
  133. }
  134. total, err := dao.Count()
  135. if err != nil {
  136. return 0, nil, err
  137. }
  138. if req.PageNum != 0 {
  139. dao = dao.Page(req.GetPage())
  140. }
  141. orderby := "created_time desc"
  142. if req.OrderBy != "" {
  143. orderby = req.OrderBy
  144. }
  145. dao = dao.Order(orderby)
  146. ents := []*model.CtrContractDynamics{}
  147. err = dao.Structs(&ents)
  148. if err != nil && err != sql.ErrNoRows {
  149. return 0, nil, err
  150. }
  151. ret := map[string][]*model.CtrContractDynamics{}
  152. for _, ent := range ents {
  153. date := ent.OpnDate.Format("Y-m-d")
  154. ret[date] = append(ret[date], ent)
  155. }
  156. return total, ret, err
  157. }
  158. func (s CtrContractService) List(ctx context.Context, req *model.CtrContractListReq) (int, []*model.CtrContractListRsp, error) {
  159. ctx = context.WithValue(ctx, "contextService", s)
  160. dao := s.Dao.DataScope(ctx, "incharge_id").As("a")
  161. if req.SearchText != "" {
  162. likestr := fmt.Sprintf("%%%s%%", req.SearchText)
  163. dao = dao.Where("(a.contract_code LIKE ? || a.contract_name LIKE ? || a.cust_name LIKE ? || a.nbo_name LIKE ?)", likestr, likestr, likestr, likestr)
  164. }
  165. if req.ContractCode != "" {
  166. likestr := fmt.Sprintf("%%%s%%", req.ContractCode)
  167. dao = dao.Where("a.contract_code like ?", likestr)
  168. }
  169. if req.ContractName != "" {
  170. likestr := fmt.Sprintf("%%%s%%", req.ContractName)
  171. dao = dao.Where("a.contract_name like ?", likestr)
  172. }
  173. if req.CustId != 0 {
  174. dao = dao.Where("a.cust_id = ?", req.CustId)
  175. }
  176. if req.CustName != "" {
  177. likestr := fmt.Sprintf("%%%s%%", req.CustName)
  178. dao = dao.Where("a.cust_name like ?", likestr)
  179. }
  180. if req.NboId != 0 {
  181. dao = dao.Where("a.nbo_id = ?", req.NboId)
  182. }
  183. if req.NboName != "" {
  184. likestr := fmt.Sprintf("%%%s%%", req.NboName)
  185. dao = dao.Where("a.nbo_name like ?", likestr)
  186. }
  187. if req.ApproStatus != "" {
  188. dao = dao.Where("a.appro_status = ?", req.ApproStatus)
  189. }
  190. if req.ContractType != "" {
  191. dao = dao.Where("a.contract_type = ?", req.ContractType)
  192. }
  193. // if req.ContractStartTime != nil {
  194. // dao = dao.Where("a.contract_start_time > ?", req.ContractStartTime)
  195. // }
  196. // if req.ContractEndTime != nil {
  197. // dao = dao.Where("a.contract_end_time < ?", req.ContractEndTime)
  198. // }
  199. if req.InchargeId != 0 {
  200. dao = dao.Where("a.incharge_id = ?", req.InchargeId)
  201. }
  202. if req.InchargeName != "" {
  203. likestr := fmt.Sprintf("%%%s%%", req.InchargeName)
  204. dao = dao.Where("a.incharge_name like ?", likestr)
  205. }
  206. if req.SignatoryId != 0 {
  207. dao = dao.Where("a.signatory_id = ?", req.SignatoryId)
  208. }
  209. if req.SignatoryName != "" {
  210. likestr := fmt.Sprintf("%%%s%%", req.SignatoryName)
  211. dao = dao.Where("a.signatory_name like ?", likestr)
  212. }
  213. if req.DistributorId != 0 {
  214. dao = dao.Where("a.distributor_id = ?", req.DistributorId)
  215. }
  216. if req.DistributorName != "" {
  217. likestr := fmt.Sprintf("%%%s%%", req.DistributorName)
  218. dao = dao.Where("a.distributor_name like ?", likestr)
  219. }
  220. if req.BeginTime != "" {
  221. dao = dao.Where("a.created_time > ?", req.BeginTime)
  222. }
  223. if req.EndTime != "" {
  224. dao = dao.Where("a.created_time < ?", req.EndTime)
  225. }
  226. if req.ContractEndTimeStart != "" {
  227. dao = dao.Where("a.contract_end_time >= ?", req.ContractEndTimeStart)
  228. }
  229. if req.ContractEndTimeEnd != "" {
  230. dao = dao.Where("a.contract_end_time <= ?", req.ContractEndTimeEnd)
  231. }
  232. if req.ContractSignTimeStart != "" {
  233. dao = dao.Where("a.contract_sign_time >= ?", req.ContractSignTimeStart)
  234. }
  235. if req.ContractSignTimeEnd != "" {
  236. dao = dao.Where("a.contract_sign_time <= ?", req.ContractSignTimeEnd)
  237. }
  238. if req.CustProvinceId != 0 {
  239. dao = dao.Where("a.cust_province_id = ?", req.CustProvinceId)
  240. }
  241. if req.CustCityId != 0 {
  242. dao = dao.Where("a.cust_city_id = ?", req.CustCityId)
  243. }
  244. if req.ProductLine != "" {
  245. dao = dao.Where("a.product_line = ?", req.ProductLine)
  246. }
  247. if req.SoftwareMaintenanceBeginTimeStart != nil {
  248. dao = dao.Where("DATE(a.software_maintenance_begin_time) >= DATE(?)", req.SoftwareMaintenanceBeginTimeStart)
  249. }
  250. if req.SoftwareMaintenanceBeginTimeEnd != nil {
  251. dao = dao.Where("DATE(a.software_maintenance_begin_time) <= DATE(?)", req.SoftwareMaintenanceBeginTimeEnd)
  252. }
  253. if req.SoftwareMaintenanceEndTimeStart != nil {
  254. dao = dao.Where("DATE(a.software_maintenance_end_time) >= DATE(?)", req.SoftwareMaintenanceEndTimeStart)
  255. }
  256. if req.SoftwareMaintenanceEndTimeEnd != nil {
  257. dao = dao.Where("DATE(a.software_maintenance_end_time) <= DATE(?)", req.SoftwareMaintenanceEndTimeEnd)
  258. }
  259. if req.HardwareMaintenanceBeginTimeStart != nil {
  260. dao = dao.Where("DATE(a.hardware_maintenance_begin_time) >= DATE(?)", req.HardwareMaintenanceBeginTimeStart)
  261. }
  262. if req.HardwareMaintenanceBeginTimeEnd != nil {
  263. dao = dao.Where("DATE(a.hardware_maintenance_begin_time) <= DATE(?)", req.HardwareMaintenanceBeginTimeEnd)
  264. }
  265. if req.HardwareMaintenanceEndTimeStart != nil {
  266. dao = dao.Where("DATE(a.hardware_maintenance_end_time) >= DATE(?)", req.HardwareMaintenanceEndTimeStart)
  267. }
  268. if req.HardwareMaintenanceEndTimeEnd != nil {
  269. dao = dao.Where("DATE(a.hardware_maintenance_end_time) <= DATE(?)", req.HardwareMaintenanceEndTimeEnd)
  270. }
  271. if req.IsNotMaintenanceContract == "10" {
  272. dao = dao.Where("a.contract_id = 0 or a.contract_id is NULL")
  273. }
  274. total, err := dao.Count()
  275. if err != nil {
  276. return 0, nil, err
  277. }
  278. if req.PageNum != 0 {
  279. dao = dao.Page(req.GetPage())
  280. }
  281. orderby := "a.contract_sign_time desc"
  282. if req.OrderBy != "" {
  283. orderby = req.OrderBy
  284. }
  285. dao = dao.Order(orderby)
  286. ents := []*model.CtrContractListRsp{}
  287. err = dao.Structs(&ents)
  288. if err != nil && err != sql.ErrNoRows {
  289. return 0, nil, err
  290. }
  291. return total, ents, err
  292. }
  293. func (s CtrContractService) RenewList(ctx context.Context, req *model.CtrRenewContractListReq) ([]*model.CtrContractListRsp, error) {
  294. ctx = context.WithValue(ctx, "contextService", s)
  295. dao := s.Dao.DataScope(ctx, "incharge_id").As("a").Where("contract_id=?", req.ContractId)
  296. if req.SearchText != "" {
  297. likestr := fmt.Sprintf("%%%s%%", req.SearchText)
  298. dao = dao.Where("(a.contract_code LIKE ? || a.contract_name LIKE ? || a.cust_name LIKE ? || a.nbo_name LIKE ?)", likestr, likestr, likestr, likestr)
  299. }
  300. orderby := "a.contract_sign_time desc"
  301. dao = dao.Order(orderby)
  302. ents := []*model.CtrContractListRsp{}
  303. err := dao.Structs(&ents)
  304. if err != nil && err != sql.ErrNoRows {
  305. return nil, err
  306. }
  307. return ents, err
  308. }
  309. func (s CtrContractService) BindProduct(tx *gdb.TX, id int, code string, product []model.CtrAddProduct) error {
  310. var amount float64
  311. for _, p := range product {
  312. amount += (p.TranPrice * float64(p.ProdNum))
  313. }
  314. _, err := tx.Delete("ctr_contract_product", "contract_id = ?", id)
  315. if err != nil {
  316. return err
  317. }
  318. tocreate := []model.CtrContractProduct{}
  319. for _, p := range product {
  320. product, err := s.ProductDao.Where("id = ?", p.ProdId).One()
  321. if err != nil {
  322. return err
  323. }
  324. if product == nil {
  325. return myerrors.TipsError(fmt.Sprintf("产品: %d 不存在", p.ProdId))
  326. }
  327. tocreate = append(tocreate, model.CtrContractProduct{
  328. ContractId: id,
  329. ContractCode: code,
  330. ProdId: p.ProdId,
  331. ProdCode: product.ProdCode,
  332. ProdName: product.ProdName,
  333. ProdClass: product.ProdClass,
  334. ProdNum: p.ProdNum,
  335. MaintTerm: p.MaintTerm,
  336. SugSalesPrice: p.SugSalesPrice,
  337. TranPrice: p.TranPrice,
  338. ContractPrive: amount,
  339. Remark: p.Remark,
  340. CreatedBy: int(s.userInfo.Id),
  341. CreatedName: s.userInfo.NickName,
  342. CreatedTime: gtime.Now(),
  343. UpdatedBy: int(s.userInfo.Id),
  344. UpdatedName: s.userInfo.NickName,
  345. UpdatedTime: gtime.Now(),
  346. })
  347. }
  348. if len(tocreate) != 0 {
  349. _, err = tx.Insert("ctr_contract_product", tocreate)
  350. if err != nil {
  351. return err
  352. }
  353. }
  354. return nil
  355. }
  356. func (s CtrContractService) AddDynamicsByCurrentUser(tx *gdb.TX, contractId int, opnType string, content map[string]interface{}) error {
  357. contentByte, err := json.Marshal(content)
  358. if err != nil {
  359. return err
  360. }
  361. _, err = tx.InsertAndGetId("ctr_contract_dynamics", model.CtrContractDynamics{
  362. ContractId: contractId,
  363. OpnPeopleId: s.userInfo.Id,
  364. OpnPeople: s.userInfo.NickName,
  365. OpnDate: gtime.Now(),
  366. OpnType: opnType,
  367. OpnContent: string(contentByte),
  368. Remark: "",
  369. CreatedBy: s.userInfo.Id,
  370. CreatedName: s.userInfo.NickName,
  371. CreatedTime: gtime.Now(),
  372. UpdatedBy: s.userInfo.Id,
  373. UpdatedName: s.userInfo.NickName,
  374. UpdatedTime: gtime.Now(),
  375. })
  376. return err
  377. }
  378. func (s CtrContractService) Add(ctx context.Context, req *model.CtrContractAddReq) (int, error) {
  379. validErr := gvalid.CheckStruct(ctx, req, nil)
  380. if validErr != nil {
  381. return 0, myerrors.TipsError(validErr.Current().Error())
  382. }
  383. if len(req.Product) == 0 {
  384. return 0, myerrors.TipsError("产品不能为空")
  385. }
  386. for _, p := range req.Product {
  387. if p.ProdNum < 1 {
  388. return 0, myerrors.TipsError("产品数量必须大于 0")
  389. }
  390. }
  391. // c, err := s.Dao.Where("contract_name = ?", req.ContractName).One()
  392. // if err != nil {
  393. // return 0, err
  394. // }
  395. // if c != nil {
  396. // return 0, myerrors.TipsError(fmt.Sprintf("合同名称:%s 已存在", req.ContractName))
  397. // }
  398. nbo, err := s.ProjBusinessDao.Where("id = ?", req.NboId).One()
  399. if err != nil {
  400. return 0, err
  401. }
  402. if nbo == nil {
  403. return 0, myerrors.TipsError("项目不存在")
  404. }
  405. // c, err = s.Dao.Where("nbo_id = ?", req.NboId).One()
  406. // if err != nil {
  407. // return 0, err
  408. // }
  409. // if c != nil {
  410. // return 0, myerrors.TipsError("所选项目已添加合同")
  411. // }
  412. var sequence int
  413. if req.ContractType == "XS" { // 销售合同
  414. sequence, err = service.SequenceYearRest(s.Dao.DB, "contract_code_xs")
  415. if err != nil {
  416. return 0, err
  417. }
  418. } else if req.ContractType == "JS" { // 技术合同
  419. sequence, err = service.SequenceYearRest(s.Dao.DB, "contract_code_js")
  420. if err != nil {
  421. return 0, err
  422. }
  423. } else {
  424. return 0, myerrors.TipsError("不支持的合同类型")
  425. }
  426. if req.ContractCode == "" {
  427. req.ContractCode = fmt.Sprintf("DH%s%s-%03d", req.ContractType, time.Now().Format("0601"), sequence)
  428. }
  429. c, err := s.Dao.Where("contract_code = ?", req.ContractCode).One()
  430. if err != nil {
  431. return 0, err
  432. }
  433. if c != nil {
  434. return 0, myerrors.TipsError(fmt.Sprintf("合同编号:%s 已存在", req.ContractCode))
  435. }
  436. var contractAmount float64
  437. for _, p := range req.Product {
  438. contractAmount += (p.TranPrice * float64(p.ProdNum))
  439. }
  440. ctr := model.CtrContract{
  441. ContractCode: req.ContractCode,
  442. ContractName: req.ContractName,
  443. CustId: nbo.CustId,
  444. CustName: nbo.CustName,
  445. NboId: nbo.Id,
  446. NboName: nbo.NboName,
  447. IsBig: nbo.IsBig,
  448. ProductLine: nbo.ProductLine,
  449. CustProvinceId: nbo.CustProvinceId,
  450. CustProvince: nbo.CustProvince,
  451. CustCityId: nbo.CustCityId,
  452. CustCity: nbo.CustCity,
  453. ApproStatus: "10",
  454. ContractType: req.ContractType,
  455. ContractAmount: contractAmount,
  456. InvoiceAmount: 0,
  457. CollectedAmount: 0,
  458. ContractStartTime: req.ContractStartTime,
  459. ContractEndTime: req.ContractEndTime,
  460. ContractSignTime: req.ContractSignTime,
  461. InchargeId: req.InchargeId,
  462. InchargeName: req.InchargeName,
  463. SignatoryId: req.SignatoryId,
  464. SignatoryName: req.SignatoryName,
  465. SignatoryType: req.SignatoryType,
  466. SignatoryUnit: req.SignatoryUnit,
  467. EarnestMoney: req.EarnestMoney,
  468. CustSignatoryId: req.CustSignatoryId,
  469. CustSignatoryName: req.CustSignatoryName,
  470. DistributorId: req.DistributorId,
  471. DistributorName: req.DistributorName,
  472. Remark: req.Remark,
  473. ServiceFeeAgreement: req.ServiceFeeAgreement,
  474. SoftwareMaintenanceLimit: req.SoftwareMaintenanceLimit,
  475. HardwareMaintenanceLimit: req.HardwareMaintenanceLimit,
  476. MaintenanceClause: req.MaintenanceClause,
  477. CreatedBy: s.userInfo.Id,
  478. CreatedName: s.userInfo.NickName,
  479. CreatedTime: gtime.Now(),
  480. UpdatedBy: s.userInfo.Id,
  481. UpdatedName: s.userInfo.NickName,
  482. UpdatedTime: gtime.Now(),
  483. }
  484. var id int
  485. txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  486. ctrid, err := tx.InsertAndGetId("ctr_contract", ctr)
  487. if err != nil {
  488. return err
  489. }
  490. err = s.BindProduct(tx, int(ctrid), ctr.ContractCode, req.Product)
  491. if err != nil {
  492. return err
  493. }
  494. err = s.AddDynamicsByCurrentUser(tx, int(ctrid), "创建合同", map[string]interface{}{})
  495. if err != nil {
  496. return err
  497. }
  498. _, err = tx.Update("proj_business", map[string]interface{}{
  499. "nbo_type": projsrv.StatusDeal,
  500. }, "id = ?", nbo.Id)
  501. if err != nil {
  502. return err
  503. }
  504. id = int(ctrid)
  505. return nil
  506. })
  507. return id, txerr
  508. }
  509. func (s CtrContractService) ReNew(ctx context.Context, req *model.CtrContractReNewReq) (int, error) {
  510. validErr := gvalid.CheckStruct(ctx, req, nil)
  511. if validErr != nil {
  512. return 0, myerrors.TipsError(validErr.Current().Error())
  513. }
  514. if len(req.Product) == 0 {
  515. return 0, myerrors.TipsError("产品不能为空")
  516. }
  517. for _, p := range req.Product {
  518. if p.ProdNum < 1 {
  519. return 0, myerrors.TipsError("产品数量必须大于 0")
  520. }
  521. }
  522. nbo, err := s.ProjBusinessDao.Where("id = ?", req.NboId).One()
  523. if err != nil {
  524. return 0, err
  525. }
  526. if nbo == nil {
  527. return 0, myerrors.TipsError("项目不存在")
  528. }
  529. oldContract, err := s.Dao.Where("id = ?", req.ContractId).One()
  530. if err != nil {
  531. return 0, err
  532. }
  533. if oldContract == nil {
  534. return 0, myerrors.TipsError("合同不存在")
  535. }
  536. var sequence int
  537. if req.ContractType == "XS" { // 销售合同
  538. sequence, err = service.SequenceYearRest(s.Dao.DB, "contract_code_xs")
  539. if err != nil {
  540. return 0, err
  541. }
  542. } else if req.ContractType == "JS" { // 技术合同
  543. sequence, err = service.SequenceYearRest(s.Dao.DB, "contract_code_js")
  544. if err != nil {
  545. return 0, err
  546. }
  547. } else {
  548. return 0, myerrors.TipsError("不支持的合同类型")
  549. }
  550. if req.ContractCode == "" {
  551. req.ContractCode = fmt.Sprintf("DH%s%s-%03d", req.ContractType, time.Now().Format("0601"), sequence)
  552. }
  553. c, err := s.Dao.Where("contract_code = ?", req.ContractCode).One()
  554. if err != nil {
  555. return 0, err
  556. }
  557. if c != nil {
  558. return 0, myerrors.TipsError(fmt.Sprintf("合同编号:%s 已存在", req.ContractCode))
  559. }
  560. var contractAmount float64
  561. for _, p := range req.Product {
  562. contractAmount += (p.TranPrice * float64(p.ProdNum))
  563. }
  564. softSub := req.SoftwareMaintenanceEndTime.Sub(req.SoftwareMaintenanceBeginTime).Hours() / 24 / 365
  565. req.SoftwareMaintenanceLimit = int(softSub)
  566. hardSub := req.HardwareMaintenanceEndTime.Sub(req.HardwareMaintenanceBeginTime).Hours() / 24 / 365
  567. req.HardwareMaintenanceLimit = int(hardSub)
  568. ctr := model.CtrContract{
  569. ContractCode: req.ContractCode,
  570. ContractName: req.ContractName,
  571. CustId: nbo.CustId,
  572. CustName: nbo.CustName,
  573. ContractId: req.ContractId,
  574. NboId: nbo.Id,
  575. NboName: nbo.NboName,
  576. IsBig: nbo.IsBig,
  577. ProductLine: nbo.ProductLine,
  578. CustProvinceId: nbo.CustProvinceId,
  579. CustProvince: nbo.CustProvince,
  580. CustCityId: nbo.CustCityId,
  581. CustCity: nbo.CustCity,
  582. ApproStatus: "10",
  583. ContractType: req.ContractType,
  584. ContractAmount: contractAmount,
  585. InvoiceAmount: 0,
  586. CollectedAmount: 0,
  587. ContractStartTime: req.ContractStartTime,
  588. ContractEndTime: req.ContractEndTime,
  589. ContractSignTime: req.ContractSignTime,
  590. InchargeId: req.InchargeId,
  591. InchargeName: req.InchargeName,
  592. SignatoryId: req.SignatoryId,
  593. SignatoryName: req.SignatoryName,
  594. SignatoryType: req.SignatoryType,
  595. SignatoryUnit: req.SignatoryUnit,
  596. EarnestMoney: req.EarnestMoney,
  597. CustSignatoryId: req.CustSignatoryId,
  598. CustSignatoryName: req.CustSignatoryName,
  599. DistributorId: req.DistributorId,
  600. DistributorName: req.DistributorName,
  601. Remark: req.Remark,
  602. ServiceFeeAgreement: req.ServiceFeeAgreement,
  603. SoftwareMaintenanceBeginTime: req.SoftwareMaintenanceBeginTime,
  604. SoftwareMaintenanceEndTime: req.SoftwareMaintenanceEndTime,
  605. HardwareMaintenanceBeginTime: req.HardwareMaintenanceBeginTime,
  606. HardwareMaintenanceEndTime: req.HardwareMaintenanceEndTime,
  607. SoftwareMaintenanceLimit: req.SoftwareMaintenanceLimit,
  608. HardwareMaintenanceLimit: req.HardwareMaintenanceLimit,
  609. MaintenanceClause: req.MaintenanceClause,
  610. CreatedBy: s.userInfo.Id,
  611. CreatedName: s.userInfo.NickName,
  612. CreatedTime: gtime.Now(),
  613. UpdatedBy: s.userInfo.Id,
  614. UpdatedName: s.userInfo.NickName,
  615. UpdatedTime: gtime.Now(),
  616. }
  617. var id int
  618. txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  619. ctrid, err := tx.InsertAndGetId("ctr_contract", ctr)
  620. if err != nil {
  621. return err
  622. }
  623. err = s.BindProduct(tx, int(ctrid), ctr.ContractCode, req.Product)
  624. if err != nil {
  625. return err
  626. }
  627. //ContractApplyApproval
  628. err = s.AddDynamicsByCurrentUser(tx, int(ctrid), "创建合同", map[string]interface{}{})
  629. if err != nil {
  630. return err
  631. }
  632. _, err = tx.Update("proj_business", map[string]interface{}{
  633. "nbo_type": projsrv.StatusDeal,
  634. }, "id = ?", nbo.Id)
  635. if err != nil {
  636. return err
  637. }
  638. err = s.AddDynamicsByCurrentUser(tx, int(req.ContractId), "创建续签合同", map[string]interface{}{
  639. "contractName": req.ContractName,
  640. })
  641. if err != nil {
  642. return err
  643. }
  644. id = int(ctrid)
  645. return nil
  646. })
  647. return id, txerr
  648. }
  649. func (s CtrContractService) UpdateReNew(ctx context.Context, req *model.CtrContractUpdateReNewReq) error {
  650. validErr := gvalid.CheckStruct(ctx, req, nil)
  651. if validErr != nil {
  652. return myerrors.TipsError(validErr.Current().Error())
  653. }
  654. ent, err := s.Dao.Where("id = ?", req.Id).One()
  655. if err != nil {
  656. return err
  657. }
  658. if ent == nil {
  659. return myerrors.TipsError(fmt.Sprintf("合同不存在: %d", req.Id))
  660. }
  661. //if req.ContractName != "" {
  662. // exist, err := s.Dao.Where("contract_name = ?", req.ContractName).One()
  663. // if err != nil {
  664. // return err
  665. // }
  666. // if exist != nil && exist.Id != req.Id {
  667. // return myerrors.TipsError(fmt.Sprintf("合同名称:%s 已存在", req.ContractName))
  668. // }
  669. //}
  670. var nbo *proj.ProjBusiness
  671. if req.NboId != 0 {
  672. nbo, err = s.ProjBusinessDao.Where("id = ?", req.NboId).One()
  673. if err != nil {
  674. return err
  675. }
  676. if nbo == nil {
  677. return myerrors.TipsError("项目不存在")
  678. }
  679. }
  680. toupdate := map[string]interface{}{}
  681. if req.ContractName != "" {
  682. toupdate["contract_name"] = req.ContractName
  683. }
  684. if req.NboId != 0 {
  685. toupdate["cust_id"] = nbo.CustId
  686. toupdate["cust_name"] = nbo.CustName
  687. toupdate["nbo_id"] = nbo.Id
  688. toupdate["nbo_name"] = nbo.NboName
  689. toupdate["is_big"] = nbo.IsBig
  690. toupdate["product_line"] = nbo.ProductLine
  691. toupdate["cust_province_id"] = nbo.CustProvinceId
  692. toupdate["cust_province"] = nbo.CustProvince
  693. toupdate["cust_city_id"] = nbo.CustCityId
  694. toupdate["cust_city"] = nbo.CustCity
  695. }
  696. if req.ContractType != "" {
  697. toupdate["contract_type"] = req.ContractType
  698. }
  699. if req.ContractStartTime != nil {
  700. toupdate["contract_start_time"] = req.ContractStartTime
  701. }
  702. if req.ContractEndTime != nil {
  703. toupdate["contract_end_time"] = req.ContractEndTime
  704. }
  705. if req.ContractSignTime != nil {
  706. toupdate["contract_sign_time"] = req.ContractSignTime
  707. }
  708. if req.SignatoryId != 0 {
  709. toupdate["signatory_id"] = req.SignatoryId
  710. }
  711. if req.SignatoryName != "" {
  712. toupdate["signatory_name"] = req.SignatoryName
  713. }
  714. if req.SignatoryType != "" {
  715. toupdate["signatory_type"] = req.SignatoryType
  716. }
  717. if req.SignatoryUnit != "" {
  718. toupdate["signatory_unit"] = req.SignatoryUnit
  719. }
  720. if req.EarnestMoney != 0 {
  721. toupdate["earnest_money"] = req.EarnestMoney
  722. }
  723. if req.CustSignatoryId != 0 {
  724. toupdate["cust_signatory_id"] = req.CustSignatoryId
  725. }
  726. if req.CustSignatoryName != "" {
  727. toupdate["cust_signatory_name"] = req.CustSignatoryName
  728. }
  729. if req.DistributorId != 0 {
  730. toupdate["distributor_id"] = req.DistributorId
  731. }
  732. if req.DistributorName != "" {
  733. toupdate["distributor_name"] = req.DistributorName
  734. }
  735. if req.SoftwareMaintenanceBeginTime != nil {
  736. toupdate["software_maintenance_begin_time"] = req.SoftwareMaintenanceBeginTime
  737. }
  738. if req.SoftwareMaintenanceEndTime != nil {
  739. toupdate["software_maintenance_end_time"] = req.SoftwareMaintenanceEndTime
  740. }
  741. if req.HardwareMaintenanceBeginTime != nil {
  742. toupdate["hardware_maintenance_begin_time"] = req.HardwareMaintenanceBeginTime
  743. }
  744. if req.HardwareMaintenanceEndTime != nil {
  745. toupdate["hardware_maintenance_end_time"] = req.HardwareMaintenanceEndTime
  746. }
  747. softSub := req.SoftwareMaintenanceEndTime.Sub(req.SoftwareMaintenanceBeginTime).Hours() / 24 / 365
  748. req.SoftwareMaintenanceLimit = int(softSub)
  749. hardSub := req.HardwareMaintenanceEndTime.Sub(req.HardwareMaintenanceBeginTime).Hours() / 24 / 365
  750. req.HardwareMaintenanceLimit = int(hardSub)
  751. if req.SoftwareMaintenanceLimit != 0 {
  752. toupdate["software_maintenance_limit"] = req.SoftwareMaintenanceLimit
  753. }
  754. if req.HardwareMaintenanceLimit != 0 {
  755. toupdate["hardware_maintenance_limit"] = req.HardwareMaintenanceLimit
  756. }
  757. if req.Remark != "" {
  758. toupdate["remark"] = req.Remark
  759. }
  760. if req.Product != nil {
  761. var contractAmount float64
  762. for _, p := range req.Product {
  763. contractAmount += (p.TranPrice * float64(p.ProdNum))
  764. }
  765. toupdate["contract_amount"] = contractAmount
  766. }
  767. if len(toupdate) != 0 {
  768. toupdate["updated_by"] = int(s.userInfo.Id)
  769. toupdate["updated_name"] = s.userInfo.NickName
  770. toupdate["updated_time"] = gtime.Now()
  771. txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  772. _, err = tx.Update("ctr_contract", toupdate, "id = ?", req.Id)
  773. if err != nil {
  774. return err
  775. }
  776. if req.Product != nil {
  777. err = s.BindProduct(tx, req.Id, ent.ContractCode, req.Product)
  778. if err != nil {
  779. return err
  780. }
  781. }
  782. return nil
  783. })
  784. if txerr != nil {
  785. return txerr
  786. }
  787. }
  788. return nil
  789. }
  790. var ContractApplyProcessCode = "PROC-7057E20A-2066-4644-9B35-9331E4DA912C" // 创建合同
  791. func (s CtrContractService) Commit(ctx context.Context, req *model.CtrContractCommitReq) error {
  792. validErr := gvalid.CheckStruct(ctx, req, nil)
  793. if validErr != nil {
  794. return myerrors.TipsError(validErr.Current().Error())
  795. }
  796. if !(req.ContractModel == "大数模板" || req.ContractModel == "客户模板") {
  797. return myerrors.TipsError("合同模板不合法")
  798. }
  799. if !(req.Terms == "接纳全部条款" || req.Terms == "不接纳全部条款") {
  800. return myerrors.TipsError("条款情况不合法")
  801. }
  802. if req.PayTerms == "" {
  803. return myerrors.TipsError("付款条件不能为空")
  804. }
  805. if len(req.File) == 0 {
  806. return myerrors.TipsError("附件不能为空")
  807. }
  808. ent, err := s.Dao.Where("id = ?", req.Id).One()
  809. if err != nil {
  810. return err
  811. }
  812. if ent == nil {
  813. return myerrors.TipsError(fmt.Sprintf("合同不存在: %d", req.Id))
  814. }
  815. err = s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  816. // 审批通过
  817. _, err = s.Dao.TX(tx).Where("id = ?", ent.Id).Data(map[string]interface{}{
  818. "appro_status": 30,
  819. }).Update()
  820. if err != nil {
  821. return err
  822. }
  823. // 交付状态(0发起 10项目立项 15进行中 20 完成 30审批拒绝40关闭)
  824. _, err = worksrv.DeliverOrderAdd(tx, ent.Id, request.UserInfo{}, nil, "10")
  825. if err != nil {
  826. return err
  827. }
  828. if ent.ContractId != 0 {
  829. oldContract, err := s.Dao.TX(tx).Where("id = ?", ent.ContractId).One()
  830. if err != nil {
  831. return err
  832. }
  833. softSub := ent.SoftwareMaintenanceEndTime.Sub(oldContract.SoftwareMaintenanceBeginTime).Hours() / 24 / 365
  834. SoftwareMaintenanceLimit := int(softSub)
  835. hardSub := ent.HardwareMaintenanceEndTime.Sub(oldContract.HardwareMaintenanceBeginTime).Hours() / 24 / 365
  836. HardwareMaintenanceLimit := int(hardSub)
  837. opnContent := map[string]interface{}{
  838. "contractId": ent.ContractId,
  839. "contractName": ent.ContractName,
  840. "contractCode": ent.ContractCode,
  841. "oldSoftwareMaintenanceBeginTime": oldContract.SoftwareMaintenanceBeginTime,
  842. "oldSoftwareMaintenanceEndTime": oldContract.SoftwareMaintenanceEndTime,
  843. "oldHardwareMaintenanceBeginTime": oldContract.HardwareMaintenanceBeginTime,
  844. "oldHardwareMaintenanceEndTime": oldContract.HardwareMaintenanceEndTime,
  845. "newSoftwareMaintenanceBeginTime": ent.SoftwareMaintenanceBeginTime,
  846. "newSoftwareMaintenanceEndTime": ent.SoftwareMaintenanceEndTime,
  847. "newHardwareMaintenanceBeginTime": ent.HardwareMaintenanceBeginTime,
  848. "newHardwareMaintenanceEndTime": ent.HardwareMaintenanceEndTime,
  849. }
  850. dynamics := model.CtrContractDynamics{
  851. ContractId: ent.ContractId,
  852. OpnPeople: "系统自动创建",
  853. OpnDate: gtime.Now(),
  854. OpnType: "续签合同审批通过",
  855. OpnContent: gconv.String(opnContent),
  856. }
  857. _, err = s.Dao.DB.Model("ctr_contract_dynamics").TX(tx).Data(dynamics).InsertAndGetId()
  858. if err != nil {
  859. return err
  860. }
  861. _, err = s.Dao.TX(tx).Where("id = ?", ent.ContractId).Data(map[string]interface{}{
  862. "software_maintenance_end_time": ent.SoftwareMaintenanceEndTime,
  863. "hardware_maintenance_end_time": ent.HardwareMaintenanceEndTime,
  864. "software_maintenance_limit": SoftwareMaintenanceLimit,
  865. "hardware_maintenance_limit": HardwareMaintenanceLimit,
  866. }).Update()
  867. if err != nil {
  868. return err
  869. }
  870. }
  871. return nil
  872. })
  873. return err
  874. }
  875. // var spaceId = "21042518430"
  876. var spaceId = "21077726250"
  877. func (s CtrContractService) CommitWithFile(ctx context.Context, formData *multipart.Form) error {
  878. if s.userInfo.DingtalkUid == "" {
  879. return fmt.Errorf("该用户钉钉 uid 为空")
  880. }
  881. if len(formData.File) == 0 {
  882. return myerrors.TipsError("文件不能为空")
  883. }
  884. if _, ok := formData.File["file"]; !ok {
  885. return myerrors.TipsError("文件不能为空")
  886. }
  887. if formData.File["file"].FileName == "" {
  888. return fmt.Errorf("文件名称不能为空")
  889. }
  890. if formData.File["file"].File == nil {
  891. return fmt.Errorf("文件不能为空")
  892. }
  893. if formData.File["file"].File.Name() == "" {
  894. return fmt.Errorf("文件路径不能为空")
  895. }
  896. contractId, err := strconv.Atoi(formData.Value["contractId"])
  897. if err != nil {
  898. return fmt.Errorf("合同 Id 不合法 %s", formData.Value["contractId"])
  899. }
  900. //fmt.Println(args.File.Name(), args.FileName, args.FileSize, args.Meta)
  901. //fmt.Println(spaceId, s.userInfo.DingtalkId, args.FileName, args.File.Name())
  902. // resp, err := s.UploadFile("21042518430", "8xljy04PZiS9iPxp5PhDnUzQiEiE", "引物导入模板-000000.xlsx", "/Users/chengjian/Downloads/引物导入模板.xlsx")
  903. resp, err := dingtalk.Client.GetStorage().UploadFile(spaceId, s.userInfo.DingtalkId, formData.File["file"].FileName, formData.File["file"].File.Name())
  904. if err != nil {
  905. return fmt.Errorf("钉钉上传文件异常 %s", err.Error())
  906. }
  907. err = s.Commit(ctx, &model.CtrContractCommitReq{
  908. Id: contractId,
  909. ContractModel: formData.Value["contractModel"],
  910. Terms: formData.Value["terms"],
  911. PayTerms: formData.Value["payTerms"],
  912. File: []model.DingFileInfo{
  913. {
  914. SpaceId: resp.Dentry.SpaceId,
  915. FileId: resp.Dentry.Id,
  916. FileName: resp.Dentry.Name,
  917. FileSize: resp.Dentry.Size,
  918. FileType: resp.Dentry.Extension,
  919. },
  920. },
  921. })
  922. if err != nil {
  923. return err
  924. }
  925. // workflow, err := s.WorkflowDao.Where("id = ?", workflowId).One()
  926. // if err != nil {
  927. // return err
  928. // }
  929. // instance, err := dingtalk.Client.GetWorkflow().QueryProcessInstanceDetail(workflow.ProcessInstId)
  930. // if err != nil {
  931. // return fmt.Errorf("查询审批实例详情错误: %s", err.Error())
  932. // }
  933. // fmt.Println(workflow.ProcessInstId, instance.Result.ApproverUserIds)
  934. // approverUserIds := g.Config().GetStrings("dingtalk.approver-user-ids")
  935. // fmt.Println(approverUserIds)
  936. // for _, uid := range approverUserIds {
  937. // resp, err := dingtalk.Client.GetStorage().AddPermission(
  938. // dingtalk.Client.Context.CorpId, spaceId, uid, "DOWNLOADER", "USER")
  939. // if err != nil {
  940. // return fmt.Errorf("添加审核附件权限异常: %s", err.Error())
  941. // }
  942. // fmt.Println(uid, resp)
  943. // }
  944. appendSrv, err := NewCtrContractAppendService(ctx)
  945. if err != nil {
  946. return err
  947. }
  948. _, err = appendSrv.Add(ctx, &model.CtrContractAppendAddReq{
  949. ContractId: contractId,
  950. FileName: resp.Dentry.Name,
  951. FileType: resp.Dentry.Extension,
  952. FileUrl: strings.Join([]string{"dingtalk", resp.Dentry.SpaceId, resp.Dentry.Id}, ":"),
  953. Remark: "",
  954. })
  955. if err != nil {
  956. return err
  957. }
  958. return nil
  959. }
  960. func (s CtrContractService) CommitWithFileUrl(ctx context.Context, req *model.CtrContractCommitWithFileUrlReq) error {
  961. // 数据校验
  962. validErr := gvalid.CheckStruct(ctx, req, nil)
  963. if validErr != nil {
  964. return myerrors.TipsError(validErr.Current().Error())
  965. }
  966. // 校验销售分成数据
  967. if len(req.Shares) == 0 {
  968. return myerrors.TipsError("销售分成信息不能为空")
  969. }
  970. fileinfoByte, err := baseService.UploadDingtalk(s.userInfo.DingtalkId, req.FileUrl, req.FileName)
  971. if err != nil {
  972. return err
  973. }
  974. var fileinfo = []model.DingFileInfo{}
  975. err = json.Unmarshal(fileinfoByte, &fileinfo)
  976. if err != nil {
  977. return err
  978. }
  979. err = s.Commit(ctx, &model.CtrContractCommitReq{
  980. Id: req.Id,
  981. ContractModel: req.ContractModel,
  982. Terms: req.Terms,
  983. PayTerms: req.PayTerms,
  984. File: fileinfo,
  985. })
  986. if err != nil {
  987. return err
  988. }
  989. appendSrv, err := NewCtrContractAppendService(ctx)
  990. if err != nil {
  991. return err
  992. }
  993. _, err = appendSrv.Add(ctx, &model.CtrContractAppendAddReq{
  994. ContractId: req.Id,
  995. FileName: fileinfo[0].FileName,
  996. FileType: fileinfo[0].FileType,
  997. FileUrl: strings.Join([]string{"dingtalk", fileinfo[0].SpaceId, fileinfo[0].FileId}, ":"),
  998. Remark: "",
  999. })
  1000. if err != nil {
  1001. return err
  1002. }
  1003. // 保存销售分成信息
  1004. if len(req.Shares) > 0 {
  1005. saleIds := ""
  1006. amountMap := make(map[int]float64)
  1007. for _, share := range req.Shares {
  1008. share.CreatedBy = s.userInfo.Id
  1009. share.CreatedName = s.userInfo.NickName
  1010. share.CreatedTime = gtime.Now()
  1011. share.UpdatedBy = s.userInfo.Id
  1012. share.UpdatedName = s.userInfo.NickName
  1013. share.UpdatedTime = gtime.Now()
  1014. amountMap[share.SaleId] += share.ShareAmount
  1015. if saleIds == "" {
  1016. saleIds += gconv.String(share.SaleId)
  1017. } else {
  1018. saleIds += "," + gconv.String(share.SaleId)
  1019. }
  1020. }
  1021. year := req.Shares[0].ContractSignTime.Format("Y")
  1022. month := req.Shares[0].ContractSignTime.Format("m")
  1023. // 查询需要更新的销售签约指标
  1024. if saleIds != "" {
  1025. targets, err := s.TargetDao.Where(fmt.Sprintf("sale_id IN (%v) AND year='%v'", saleIds, year)).FindAll()
  1026. if err != nil {
  1027. return err
  1028. }
  1029. // 更新数据
  1030. for _, target := range targets {
  1031. switch month {
  1032. case "01":
  1033. target.Complete1 += amountMap[target.SaleId]
  1034. target.QuarterComplete1 = target.Complete1 + target.Complete2 + target.Complete3
  1035. if target.QuarterPlan1 != 0 {
  1036. target.QuarterCompleteRatio1 = target.QuarterComplete1 / target.QuarterPlan1 * 100
  1037. }
  1038. break
  1039. case "02":
  1040. target.Complete2 += amountMap[target.SaleId]
  1041. target.QuarterComplete1 = target.Complete1 + target.Complete2 + target.Complete3
  1042. if target.QuarterPlan1 != 0 {
  1043. target.QuarterCompleteRatio1 = target.QuarterComplete1 / target.QuarterPlan1 * 100
  1044. }
  1045. break
  1046. case "03":
  1047. target.Complete3 += amountMap[target.SaleId]
  1048. target.QuarterComplete1 = target.Complete1 + target.Complete2 + target.Complete3
  1049. if target.QuarterPlan1 != 0 {
  1050. target.QuarterCompleteRatio1 = target.QuarterComplete1 / target.QuarterPlan1 * 100
  1051. }
  1052. break
  1053. case "04":
  1054. target.Complete4 += amountMap[target.SaleId]
  1055. target.QuarterComplete2 = target.Complete4 + target.Complete5 + target.Complete6
  1056. if target.QuarterPlan2 != 0 {
  1057. target.QuarterCompleteRatio2 = target.QuarterComplete2 / target.QuarterPlan2 * 100
  1058. }
  1059. break
  1060. case "05":
  1061. target.Complete5 += amountMap[target.SaleId]
  1062. target.QuarterComplete2 = target.Complete4 + target.Complete5 + target.Complete6
  1063. if target.QuarterPlan2 != 0 {
  1064. target.QuarterCompleteRatio2 = target.QuarterComplete2 / target.QuarterPlan2 * 100
  1065. }
  1066. break
  1067. case "06":
  1068. target.Complete6 += amountMap[target.SaleId]
  1069. target.QuarterComplete2 = target.Complete4 + target.Complete5 + target.Complete6
  1070. if target.QuarterPlan2 != 0 {
  1071. target.QuarterCompleteRatio2 = target.QuarterComplete2 / target.QuarterPlan2 * 100
  1072. }
  1073. break
  1074. case "07":
  1075. target.Complete7 += amountMap[target.SaleId]
  1076. target.QuarterComplete3 = target.Complete7 + target.Complete8 + target.Complete9
  1077. if target.QuarterPlan3 != 0 {
  1078. target.QuarterCompleteRatio3 = target.QuarterComplete3 / target.QuarterPlan3 * 100
  1079. }
  1080. break
  1081. case "08":
  1082. target.Complete8 += amountMap[target.SaleId]
  1083. target.QuarterComplete3 = target.Complete7 + target.Complete8 + target.Complete9
  1084. if target.QuarterPlan3 != 0 {
  1085. target.QuarterCompleteRatio3 = target.QuarterComplete3 / target.QuarterPlan3 * 100
  1086. }
  1087. break
  1088. case "09":
  1089. target.Complete9 += amountMap[target.SaleId]
  1090. target.QuarterComplete3 = target.Complete7 + target.Complete8 + target.Complete9
  1091. if target.QuarterPlan3 != 0 {
  1092. target.QuarterCompleteRatio3 = target.QuarterComplete3 / target.QuarterPlan3 * 100
  1093. }
  1094. break
  1095. case "10":
  1096. target.Complete10 += amountMap[target.SaleId]
  1097. break
  1098. case "11":
  1099. target.Complete11 += amountMap[target.SaleId]
  1100. break
  1101. case "12":
  1102. target.Complete12 += amountMap[target.SaleId]
  1103. break
  1104. }
  1105. target.UpdatedTime = gtime.Now()
  1106. target.UpdatedBy = s.userInfo.Id
  1107. target.UpdatedName = s.userInfo.NickName
  1108. // 年度数据
  1109. target.YearComplete = target.QuarterComplete1 + target.QuarterComplete2 + target.QuarterComplete3 + target.Complete10 + target.Complete11 + target.Complete12
  1110. if target.YearPlan != 0 {
  1111. target.YearCompleteRatio = target.YearComplete / target.YearPlan * 100
  1112. }
  1113. }
  1114. // 保存销售签约指标数据
  1115. if len(targets) > 0 {
  1116. _, err = s.TargetDao.Save(targets)
  1117. if err != nil {
  1118. return err
  1119. }
  1120. }
  1121. }
  1122. // 保存分成数据
  1123. _, err = s.ShareDao.Save(req.Shares)
  1124. if err != nil {
  1125. return err
  1126. }
  1127. }
  1128. return nil
  1129. }
  1130. func (s CtrContractService) DownloadDingtalkFile(ctx context.Context, id int) (string, error) {
  1131. ent, err := s.AppendDao.Where("id= ?", id).One()
  1132. if err != nil {
  1133. return "", err
  1134. }
  1135. if ent == nil {
  1136. return "", myerrors.TipsError("附件不存在")
  1137. }
  1138. if !strings.HasPrefix(ent.FileUrl, "dingtalk") {
  1139. return "", myerrors.TipsError("此附件不是钉钉附件")
  1140. }
  1141. fileInfo := strings.Split(ent.FileUrl, ":")
  1142. if len(fileInfo) != 3 {
  1143. return "", myerrors.TipsError("钉钉附件地址不合法")
  1144. }
  1145. spaceId := fileInfo[1]
  1146. fileId := fileInfo[2]
  1147. // res, err := dingtalk.Client.GetStorage().AddPermission(dingtalk.Client.Context.CorpId, spaceId, s.userInfo.DingtalkId, "EDITOR", "USER")
  1148. // fmt.Println(res, err)
  1149. // if err != nil {
  1150. // return "", fmt.Errorf("设置权限异常 %s", err.Error())
  1151. // }
  1152. resp, err := dingtalk.Client.GetStorage().QueryFileDownloadInfo(spaceId, fileId, s.userInfo.DingtalkId)
  1153. if err != nil {
  1154. return "", myerrors.TipsError("获取文件下载信息异常")
  1155. }
  1156. fmt.Println(resp, err)
  1157. req, err := http.NewRequest("GET", resp.HeaderSignatureInfo.ResourceUrls[0], nil)
  1158. if err != nil {
  1159. return "", fmt.Errorf("构建文件下载请求异常 %s", err.Error())
  1160. }
  1161. for k, v := range resp.HeaderSignatureInfo.Headers {
  1162. req.Header.Add(k, v)
  1163. }
  1164. fileresp, err := http.DefaultClient.Do(req)
  1165. if err != nil {
  1166. return "", fmt.Errorf("文件下载异常 %s", err.Error())
  1167. }
  1168. data, err := io.ReadAll(fileresp.Body)
  1169. if err != nil {
  1170. return "", fmt.Errorf("读取下载内容异常 %s", err.Error())
  1171. }
  1172. return base64.StdEncoding.EncodeToString(data), nil
  1173. }
  1174. func ContractApplyApproval(ctx context.Context, flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  1175. mtx.Lock()
  1176. defer mtx.Unlock()
  1177. tenant, err := micro_srv.GetTenant(ctx)
  1178. if err != nil {
  1179. return fmt.Errorf("获取租户码异常:%s", err.Error())
  1180. }
  1181. contractDao := dao.NewCtrContractDao(tenant)
  1182. contractId, err := strconv.Atoi(flow.BizCode)
  1183. if err != nil {
  1184. return fmt.Errorf("创建合同审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  1185. }
  1186. contract, err := contractDao.Where("id = ?", contractId).One()
  1187. if err != nil {
  1188. return err
  1189. }
  1190. if contract == nil {
  1191. return fmt.Errorf("合同不存在:%s Id: %d", flow.BizCode, flow.Id)
  1192. }
  1193. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  1194. return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  1195. }
  1196. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  1197. return fmt.Errorf("无法识别的 Result :%s", msg.Result)
  1198. }
  1199. var status string
  1200. if msg.ProcessType == "terminate" {
  1201. status = "50"
  1202. } else {
  1203. pass := msg.Result == "agree"
  1204. if !pass {
  1205. status = "40"
  1206. } else {
  1207. status = "30"
  1208. }
  1209. }
  1210. _, err = contractDao.Where("id = ?", contractId).Data(map[string]interface{}{
  1211. "appro_status": status,
  1212. }).Update()
  1213. if err != nil {
  1214. return err
  1215. }
  1216. if status != "30" {
  1217. return nil
  1218. }
  1219. return contractDao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  1220. // 交付状态(0发起 10项目立项 15进行中 20 完成 30审批拒绝40关闭)
  1221. _, err = worksrv.DeliverOrderAdd(tx, contractId, request.UserInfo{}, nil, "10")
  1222. if err != nil {
  1223. return err
  1224. }
  1225. if contract.ContractId != 0 {
  1226. oldContract, err := contractDao.TX(tx).Where("id = ?", contract.ContractId).One()
  1227. if err != nil {
  1228. return err
  1229. }
  1230. softSub := contract.SoftwareMaintenanceEndTime.Sub(oldContract.SoftwareMaintenanceBeginTime).Hours() / 24 / 365
  1231. SoftwareMaintenanceLimit := int(softSub)
  1232. hardSub := contract.HardwareMaintenanceEndTime.Sub(oldContract.HardwareMaintenanceBeginTime).Hours() / 24 / 365
  1233. HardwareMaintenanceLimit := int(hardSub)
  1234. opnContent := map[string]interface{}{
  1235. "contractId": contract.ContractId,
  1236. "contractName": contract.ContractName,
  1237. "contractCode": contract.ContractCode,
  1238. "oldSoftwareMaintenanceBeginTime": oldContract.SoftwareMaintenanceBeginTime,
  1239. "oldSoftwareMaintenanceEndTime": oldContract.SoftwareMaintenanceEndTime,
  1240. "oldHardwareMaintenanceBeginTime": oldContract.HardwareMaintenanceBeginTime,
  1241. "oldHardwareMaintenanceEndTime": oldContract.HardwareMaintenanceEndTime,
  1242. "newSoftwareMaintenanceBeginTime": contract.SoftwareMaintenanceBeginTime,
  1243. "newSoftwareMaintenanceEndTime": contract.SoftwareMaintenanceEndTime,
  1244. "newHardwareMaintenanceBeginTime": contract.HardwareMaintenanceBeginTime,
  1245. "newHardwareMaintenanceEndTime": contract.HardwareMaintenanceEndTime,
  1246. }
  1247. dynamics := model.CtrContractDynamics{
  1248. ContractId: contract.ContractId,
  1249. OpnPeople: "系统自动创建",
  1250. OpnDate: gtime.Now(),
  1251. OpnType: "续签合同审批通过",
  1252. OpnContent: gconv.String(opnContent),
  1253. }
  1254. _, err = contractDao.DB.Model("ctr_contract_dynamics").TX(tx).Data(dynamics).InsertAndGetId()
  1255. if err != nil {
  1256. return err
  1257. }
  1258. _, err = contractDao.TX(tx).Where("id = ?", contract.ContractId).Data(map[string]interface{}{
  1259. "software_maintenance_end_time": contract.SoftwareMaintenanceEndTime,
  1260. "hardware_maintenance_end_time": contract.HardwareMaintenanceEndTime,
  1261. "software_maintenance_limit": SoftwareMaintenanceLimit,
  1262. "hardware_maintenance_limit": HardwareMaintenanceLimit,
  1263. }).Update()
  1264. if err != nil {
  1265. return err
  1266. }
  1267. }
  1268. return nil
  1269. })
  1270. }
  1271. func (s CtrContractService) Update(ctx context.Context, req *model.CtrContractUpdateReq) error {
  1272. validErr := gvalid.CheckStruct(ctx, req, nil)
  1273. if validErr != nil {
  1274. return myerrors.TipsError(validErr.Current().Error())
  1275. }
  1276. ent, err := s.Dao.Where("id = ?", req.Id).One()
  1277. if err != nil {
  1278. return err
  1279. }
  1280. if ent == nil {
  1281. return myerrors.TipsError(fmt.Sprintf("合同不存在: %d", req.Id))
  1282. }
  1283. // if req.ContractCode != "" {
  1284. // exist, err := s.Dao.Where("contract_code = ?", req.ContractCode).One()
  1285. // if err != nil {
  1286. // return err
  1287. // }
  1288. // if exist != nil && exist.Id != req.Id {
  1289. // return myerrors.NewMsgError(nil, fmt.Sprintf("合同编号:%s 已存在", req.ContractCode))
  1290. // }
  1291. // }
  1292. //if req.ContractName != "" {
  1293. // exist, err := s.Dao.Where("contract_name = ?", req.ContractName).One()
  1294. // if err != nil {
  1295. // return err
  1296. // }
  1297. // if exist != nil && exist.Id != req.Id {
  1298. // return myerrors.TipsError(fmt.Sprintf("合同名称:%s 已存在", req.ContractName))
  1299. // }
  1300. //}
  1301. var nbo *proj.ProjBusiness
  1302. if req.NboId != 0 {
  1303. nbo, err = s.ProjBusinessDao.Where("id = ?", req.NboId).One()
  1304. if err != nil {
  1305. return err
  1306. }
  1307. if nbo == nil {
  1308. return myerrors.TipsError("项目不存在")
  1309. }
  1310. }
  1311. toupdate := map[string]interface{}{}
  1312. // if req.ContractCode != "" {
  1313. // toupdate["contract_code"] = req.ContractCode
  1314. // }
  1315. if req.ContractName != "" {
  1316. toupdate["contract_name"] = req.ContractName
  1317. }
  1318. if req.NboId != 0 {
  1319. toupdate["cust_id"] = nbo.CustId
  1320. toupdate["cust_name"] = nbo.CustName
  1321. toupdate["nbo_id"] = nbo.Id
  1322. toupdate["nbo_name"] = nbo.NboName
  1323. toupdate["is_big"] = nbo.IsBig
  1324. toupdate["product_line"] = nbo.ProductLine
  1325. toupdate["cust_province_id"] = nbo.CustProvinceId
  1326. toupdate["cust_province"] = nbo.CustProvince
  1327. toupdate["cust_city_id"] = nbo.CustCityId
  1328. toupdate["cust_city"] = nbo.CustCity
  1329. }
  1330. // if req.ApproStatus != "" {
  1331. // toupdate["appro_status"] = req.ApproStatus
  1332. // }
  1333. if req.ContractType != "" {
  1334. toupdate["contract_type"] = req.ContractType
  1335. }
  1336. // if req.ContractAmount != 0 {
  1337. // toupdate["contract_amount"] = req.ContractAmount
  1338. // }
  1339. // if req.InvoiceAmount != 0 {
  1340. // toupdate["invoice_amount"] = req.InvoiceAmount
  1341. // }
  1342. // if req.CollectedAmount != 0 {
  1343. // toupdate["collected_amount"] = req.CollectedAmount
  1344. // }
  1345. if req.ContractStartTime != nil {
  1346. toupdate["contract_start_time"] = req.ContractStartTime
  1347. }
  1348. if req.ContractEndTime != nil {
  1349. toupdate["contract_end_time"] = req.ContractEndTime
  1350. }
  1351. if req.ContractSignTime != nil {
  1352. toupdate["contract_sign_time"] = req.ContractSignTime
  1353. }
  1354. //if req.InchargeId != 0 {
  1355. // toupdate["incharge_id"] = req.InchargeId
  1356. //}
  1357. //if req.InchargeName != "" {
  1358. // toupdate["incharge_name"] = req.InchargeName
  1359. //}
  1360. if req.SignatoryId != 0 {
  1361. toupdate["signatory_id"] = req.SignatoryId
  1362. }
  1363. if req.SignatoryName != "" {
  1364. toupdate["signatory_name"] = req.SignatoryName
  1365. }
  1366. if req.SignatoryType != "" {
  1367. toupdate["signatory_type"] = req.SignatoryType
  1368. }
  1369. if req.SignatoryUnit != "" {
  1370. toupdate["signatory_unit"] = req.SignatoryUnit
  1371. }
  1372. if req.EarnestMoney != nil {
  1373. toupdate["earnest_money"] = req.EarnestMoney
  1374. }
  1375. if req.CustSignatoryId != 0 {
  1376. toupdate["cust_signatory_id"] = req.CustSignatoryId
  1377. }
  1378. if req.CustSignatoryName != "" {
  1379. toupdate["cust_signatory_name"] = req.CustSignatoryName
  1380. }
  1381. if req.DistributorId != 0 {
  1382. toupdate["distributor_id"] = req.DistributorId
  1383. }
  1384. if req.DistributorName != "" {
  1385. toupdate["distributor_name"] = req.DistributorName
  1386. }
  1387. if req.Remark != nil {
  1388. toupdate["remark"] = *req.Remark
  1389. }
  1390. if req.Product != nil {
  1391. var contractAmount float64
  1392. for _, p := range *req.Product {
  1393. contractAmount += (p.TranPrice * float64(p.ProdNum))
  1394. }
  1395. toupdate["contract_amount"] = contractAmount
  1396. }
  1397. if len(toupdate) != 0 {
  1398. toupdate["updated_by"] = int(s.userInfo.Id)
  1399. toupdate["updated_name"] = s.userInfo.NickName
  1400. toupdate["updated_time"] = gtime.Now()
  1401. txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  1402. _, err = tx.Update("ctr_contract", toupdate, "id = ?", req.Id)
  1403. if err != nil {
  1404. return err
  1405. }
  1406. if req.Product != nil {
  1407. err = s.BindProduct(tx, req.Id, ent.ContractCode, *req.Product)
  1408. if err != nil {
  1409. return err
  1410. }
  1411. }
  1412. return nil
  1413. })
  1414. if txerr != nil {
  1415. return txerr
  1416. }
  1417. }
  1418. return nil
  1419. }
  1420. func (s CtrContractService) UpdateProduct(ctx context.Context, req *model.CtrContractUpdateProductReq) error {
  1421. validErr := gvalid.CheckStruct(ctx, req, nil)
  1422. if validErr != nil {
  1423. return myerrors.TipsError(validErr.Current().Error())
  1424. }
  1425. ent, err := s.CtrProductDao.Where("id = ?", req.Id).One()
  1426. if err != nil {
  1427. return err
  1428. }
  1429. if ent == nil {
  1430. return myerrors.TipsError(fmt.Sprintf("合同产品记录不存在: %d", req.Id))
  1431. }
  1432. toupdate := map[string]interface{}{}
  1433. if req.MaintainPeriod != nil {
  1434. toupdate["maintain_period"] = req.MaintainPeriod
  1435. }
  1436. if req.WarrantPeriod != nil {
  1437. toupdate["warrant_period"] = req.WarrantPeriod
  1438. }
  1439. if req.MaintainStartTime != nil {
  1440. toupdate["maintain_start_time"] = req.MaintainStartTime
  1441. }
  1442. if req.MaintainRemark != nil {
  1443. toupdate["maintain_remark"] = req.MaintainRemark
  1444. }
  1445. if req.AcceptTime != nil {
  1446. toupdate["accept_time"] = req.AcceptTime
  1447. }
  1448. if req.PurchaseCost != nil {
  1449. toupdate["purchase_cost"] = req.PurchaseCost
  1450. }
  1451. if req.DevCost != nil {
  1452. toupdate["dev_cost"] = req.DevCost
  1453. }
  1454. if req.MaintainCost != nil {
  1455. toupdate["maintain_cost"] = req.MaintainCost
  1456. }
  1457. if req.DirectCost != nil {
  1458. toupdate["direct_cost"] = req.DirectCost
  1459. }
  1460. if len(toupdate) != 0 {
  1461. toupdate["updated_by"] = int(s.userInfo.Id)
  1462. toupdate["updated_name"] = s.userInfo.NickName
  1463. toupdate["updated_time"] = gtime.Now()
  1464. txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  1465. _, err = tx.Update("ctr_contract_product", toupdate, "id = ?", req.Id)
  1466. if err != nil {
  1467. return err
  1468. }
  1469. err = s.AddDynamicsByCurrentUser(tx, ent.ContractId, "更新合同产品信息", toupdate)
  1470. if err != nil {
  1471. return err
  1472. }
  1473. return nil
  1474. })
  1475. if txerr != nil {
  1476. return txerr
  1477. }
  1478. }
  1479. return nil
  1480. }
  1481. func (s CtrContractService) Transfer(ctx context.Context, req *model.CtrContractTransferReq) error {
  1482. if len(req.Id) == 0 {
  1483. return nil
  1484. }
  1485. ents := map[int]*model.CtrContract{}
  1486. for _, i := range req.Id {
  1487. ent, err := s.Dao.Where("id = ?", i).One()
  1488. if err != nil {
  1489. return err
  1490. }
  1491. if ent == nil {
  1492. return myerrors.TipsError(fmt.Sprintf("合同不存在: %d", req.Id))
  1493. }
  1494. ents[ent.Id] = ent
  1495. }
  1496. txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  1497. toupdate := map[string]interface{}{
  1498. "incharge_id": req.InchargeId,
  1499. "incharge_name": req.InchargeName,
  1500. }
  1501. _, err := tx.Update("ctr_contract", toupdate, "id in (?)", req.Id)
  1502. if err != nil {
  1503. return err
  1504. }
  1505. for _, ent := range ents {
  1506. err = s.AddDynamicsByCurrentUser(tx, ent.Id, "转移合同", map[string]interface{}{
  1507. "toInchargeId": req.InchargeId,
  1508. "toInchargeName": req.InchargeName,
  1509. "fromInchargeId": ent.InchargeId,
  1510. "fromInchargeName": ent.InchargeName,
  1511. "operatedId": s.userInfo.Id,
  1512. "operatedName": s.userInfo.NickName,
  1513. })
  1514. if err != nil {
  1515. return err
  1516. }
  1517. }
  1518. return nil
  1519. })
  1520. if txerr != nil {
  1521. return txerr
  1522. }
  1523. return nil
  1524. }
  1525. func (s CtrContractService) UpdateInvoiceAmount(tx *gdb.TX, id int) error {
  1526. ctr := model.CtrContract{}
  1527. err := tx.GetStruct(&ctr, "select * from ctr_contract where id = ?", id)
  1528. if err == sql.ErrNoRows {
  1529. return myerrors.TipsError(fmt.Sprintf("合同不存在 %d", id))
  1530. }
  1531. if err != nil {
  1532. return err
  1533. }
  1534. v, err := tx.GetValue("select sum(invoice_amount) from ctr_contract_invoice where contract_id=? and appro_status='30' and deleted_time is null", id)
  1535. if err != nil {
  1536. return err
  1537. }
  1538. amount := v.Float64()
  1539. _, err = tx.Update("ctr_contract",
  1540. map[string]interface{}{
  1541. "invoice_amount": amount,
  1542. }, "id = ?", id)
  1543. if err != nil {
  1544. return err
  1545. }
  1546. return nil
  1547. }
  1548. func (s CtrContractService) UpdateCollectedAmount(tx *gdb.TX, id int) error {
  1549. ctr := model.CtrContract{}
  1550. err := tx.GetStruct(&ctr, "select * from ctr_contract where id = ?", id)
  1551. if err == sql.ErrNoRows {
  1552. return myerrors.TipsError(fmt.Sprintf("合同不存在 %d", id))
  1553. }
  1554. if err != nil {
  1555. return err
  1556. }
  1557. v, err := tx.GetValue("select sum(collection_amount) from ctr_contract_collection where contract_id=? and appro_status='20' and deleted_time is null", id)
  1558. if err != nil {
  1559. return err
  1560. }
  1561. amount := v.Float64()
  1562. _, err = tx.Update("ctr_contract",
  1563. map[string]interface{}{
  1564. "collected_amount": amount,
  1565. }, "id = ?", id)
  1566. if err != nil {
  1567. return err
  1568. }
  1569. return nil
  1570. }
  1571. func (s CtrContractService) Delete(ctx context.Context, id []int) error {
  1572. if len(id) == 0 {
  1573. return nil
  1574. }
  1575. _, err := s.Dao.Where("Id IN (?)", id).Delete()
  1576. return err
  1577. }
  1578. // GetShares 获取销售分成数据
  1579. func (s CtrContractService) GetShares(ctx context.Context, req *model.GetContractShareReq) ([]*model.CtrContractShare, error) {
  1580. validErr := gvalid.CheckStruct(ctx, req, nil)
  1581. if validErr != nil {
  1582. return nil, myerrors.TipsError(validErr.Current().Error())
  1583. }
  1584. return s.ShareDao.Where("contract_id=?", req.ContractId).FindAll()
  1585. }
  1586. func init() {
  1587. tenant := g.Config().GetString("micro_srv.tenant")
  1588. if tenant == "" {
  1589. panic("定时任务租户码未设置,请前往配置")
  1590. }
  1591. contractDao := dao.NewCtrContractDao(tenant)
  1592. produceDao := dao.NewCtrContractProductDao(tenant)
  1593. job := func() {
  1594. alert := map[int]*[]model.CtrContractProduct{
  1595. 180: {},
  1596. 90: {},
  1597. 30: {},
  1598. 10: {},
  1599. // 7: {},
  1600. }
  1601. where := `DATE_FORMAT(DATE_ADD(maintain_start_time, INTERVAL ? day), "%Y-%m-%d") = DATE_FORMAT(NOW(), "%Y-%m-%d")`
  1602. for day, p := range alert {
  1603. err := produceDao.Where(where, day).Structs(p)
  1604. if err != nil {
  1605. glog.Error(err)
  1606. }
  1607. glog.Infof("运维期到期 %d 天提醒,产品个数 %d", day, len(*p))
  1608. }
  1609. for day, p := range alert {
  1610. for _, i := range *p {
  1611. ctr, err := contractDao.Where("id = ?", i.ContractId).One()
  1612. if err != nil {
  1613. glog.Error(err)
  1614. }
  1615. text := fmt.Sprintf("合同:%s-%s 中的产品:%s 距离运维到期还有 %d 天",
  1616. ctr.ContractCode, ctr.ContractName, i.ProdName, day)
  1617. msg := g.MapStrStr{
  1618. "msgTitle": "运维期到期提醒",
  1619. "msgContent": text,
  1620. "msgType": "20",
  1621. "recvUserIds": strconv.Itoa(ctr.InchargeId),
  1622. "msgStatus": "10",
  1623. "sendType": "10",
  1624. }
  1625. if err := service.CreateSystemMessage(msg); err != nil {
  1626. glog.Error("消息提醒异常:", err)
  1627. }
  1628. glog.Infof("%s", text)
  1629. }
  1630. }
  1631. }
  1632. // 每天凌晨2点执行
  1633. gcron.AddSingleton("0 0 2 * * *", job)
  1634. // job()
  1635. }
  1636. func (s CtrContractService) CtrContractMaintenanceExport(ctx context.Context, req *model.CtrContractListReq) (path string, err error) {
  1637. req.PageNum = 0
  1638. _, list, err := s.List(ctx, req)
  1639. if err != nil {
  1640. return path, err
  1641. }
  1642. exportsData := make([]*model.CtrContractMaintenanceExport, 0)
  1643. if err = gconv.Struct(&list, &exportsData); err != nil {
  1644. return
  1645. }
  1646. path, err = service.CommonExportExcel(ctx, "项目运维信息", model.CtrContractMaintenanceExport{}, gconv.Maps(exportsData), func(item map[string]interface{}, header string) interface{} {
  1647. if header == "softwareMaintenanceBeginTime" {
  1648. return gconv.GTime(item[header]).Format("Y-m-d")
  1649. }
  1650. if header == "softwareMaintenanceEndTime" {
  1651. return gconv.GTime(item[header]).Format("Y-m-d")
  1652. }
  1653. if header == "hardwareMaintenanceBeginTime" {
  1654. return gconv.GTime(item[header]).Format("Y-m-d")
  1655. }
  1656. if header == "hardwareMaintenanceEndTime" {
  1657. return gconv.GTime(item[header]).Format("Y-m-d")
  1658. }
  1659. return item[header]
  1660. })
  1661. if err != nil {
  1662. return path, err
  1663. }
  1664. return path, nil
  1665. }