order.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. package calculate
  2. import (
  3. "errors"
  4. "reflect"
  5. "strconv"
  6. "time"
  7. "zhiyuan/models/calc"
  8. "zhiyuan/pkg/config"
  9. "zhiyuan/pkg/db"
  10. "zhiyuan/pkg/utils"
  11. "github.com/gin-gonic/gin"
  12. "github.com/tealeg/xlsx/v3"
  13. )
  14. type ProductFrom struct {
  15. ID int64 `json:"id" label:"ID" binding:"required"`
  16. Name string `json:"name" label:"产品名称" binding:"required"`
  17. Spec map[string]string `json:"spec" label:"规格"`
  18. }
  19. type ItemFrom struct {
  20. ID int64 `json:"id" label:"ID" binding:"required"`
  21. Items []ItemFrom `json:"items" label:"项目""`
  22. Product ProductFrom `json:"product" label:"产品""`
  23. Prop map[int64]string `json:"prop" label:"属性"`
  24. Results map[int64]interface{} `json:"results" label:"结果"`
  25. }
  26. type OrderFrom struct {
  27. ID int64 `json:"id" label:"ID" binding:"required"`
  28. Items []ItemFrom `json:"items" label:"项目""`
  29. Prop map[int64]string `json:"prop" label:"属性"`
  30. Results map[int64]interface{} `json:"results" label:"结果"`
  31. }
  32. type OrderItem struct {
  33. OrderNumber int64 `json:"order_number" label:"序号"`
  34. Item *calc.Item `json:"item" label:"项目"`
  35. From *ItemFrom `json:"from" label:"表单"`
  36. Product *calc.Product `json:"product" label:"产品"`
  37. Childs []*OrderItem `json:"childs" label:"子项目""`
  38. Parent *OrderItem `json:"parent" label:"父项目""`
  39. }
  40. type Order struct {
  41. ID int64 `json:"id" label:"ID"`
  42. AdminId int64 `json:"adminId" label:"AdminID"`
  43. Calc *calc.Calculate `json:"calculate" label:"核算"`
  44. From *OrderFrom `json:"from" label:"表单"`
  45. Items []*OrderItem `json:"items" label:"项目""`
  46. }
  47. type OrderAbstract struct {
  48. Prop map[string]string `json:"prop" label:"属性"`
  49. Results map[string]string `json:"results" label:"结果"`
  50. }
  51. func (item *OrderItem) GetFrom(getall bool) (from ItemFrom) {
  52. from.ID = item.Item.ID
  53. from.Product = item.From.Product
  54. from.Prop = make(map[int64]string)
  55. for _, prop := range item.Item.Props {
  56. if (prop.Type == 2 || prop.Type == 3) && (getall || prop.State == 1) {
  57. from.Prop[prop.ID] = item.From.Prop[prop.ID]
  58. }
  59. }
  60. from.Results = make(map[int64]interface{})
  61. for _, prop := range item.Item.Props {
  62. if prop.Type == 1 && (getall || prop.State == 1) {
  63. from.Results[prop.ID] = item.From.Results[prop.ID]
  64. }
  65. }
  66. from.Items = make([]ItemFrom, 0)
  67. for _, v := range item.Childs {
  68. if getall || v.Item.State == 1 {
  69. from.Items = append(from.Items, v.GetFrom(getall))
  70. }
  71. }
  72. return
  73. }
  74. func (order *Order) GetFrom(getall bool) (from OrderFrom) {
  75. from.ID = order.Calc.ID
  76. from.Prop = make(map[int64]string)
  77. for _, prop := range order.Calc.Props {
  78. if (prop.Type == 2 || prop.Type == 3) && (getall || prop.State == 1) {
  79. from.Prop[prop.ID] = order.From.Prop[prop.ID]
  80. }
  81. }
  82. from.Results = make(map[int64]interface{})
  83. for _, prop := range order.Calc.Props {
  84. if prop.Type == 1 && (getall || prop.State == 1) {
  85. from.Results[prop.ID] = order.From.Results[prop.ID]
  86. }
  87. }
  88. from.Items = make([]ItemFrom, 0)
  89. for _, v := range order.Items {
  90. if getall || v.Item.State == 1 {
  91. from.Items = append(from.Items, v.GetFrom(getall))
  92. }
  93. }
  94. return
  95. }
  96. func propVerify(props []calc.Property, from map[int64]string) error {
  97. for _, v := range props {
  98. if v.Type == 2 || v.Type == 3 {
  99. if _, ok := from[v.ID]; !ok {
  100. return errors.New("属性未填: " + v.Name)
  101. }
  102. if v.DataType == "number" {
  103. if _, err := strconv.ParseFloat(from[v.ID], 64); err != nil {
  104. return errors.New("属性验证失败: " + v.Name)
  105. }
  106. }
  107. if v.DataType == "array" {
  108. var array interface{}
  109. utils.JsonDecode(from[v.ID]).To(&array)
  110. if _, ok := db.ToArray(array); !ok {
  111. return errors.New("属性验证失败: " + v.Name)
  112. }
  113. }
  114. }
  115. }
  116. return nil
  117. }
  118. func productVerify(item *calc.Item, from ProductFrom, create bool) (*calc.Product, error) {
  119. if item.TypeId == 0 && from.ID == 0 {
  120. return nil, nil
  121. }
  122. if create {
  123. if item.TypeId == 0 || from.ID == 0 {
  124. return nil, errors.New("产品选择错误: " + item.Name)
  125. }
  126. }
  127. var product *calc.Product
  128. db.GetModel(map[string]interface{}{"id": from.ID}, &product)
  129. if create {
  130. if product == nil || product.ID == 0 {
  131. return nil, errors.New("产品不存在: " + item.Name)
  132. }
  133. if product.TypeId != item.TypeId {
  134. return nil, errors.New("产品类型错误: " + item.Name)
  135. }
  136. }
  137. return product, nil
  138. }
  139. func createOrderItem(item *calc.Item, from *ItemFrom, create bool) (*OrderItem, error) {
  140. if from == nil {
  141. from = new(ItemFrom)
  142. from.Prop = make(map[int64]string)
  143. }
  144. if create {
  145. from.Results = make(map[int64]interface{})
  146. err := propVerify(item.Props, from.Prop)
  147. if err != nil {
  148. return nil, err
  149. }
  150. }
  151. product, err := productVerify(item, from.Product, create)
  152. if err != nil {
  153. return nil, err
  154. }
  155. order := new(OrderItem)
  156. items, err := itemVerify(item.Childs, from.Items, order, create)
  157. if err != nil {
  158. return nil, err
  159. }
  160. order.Item = item
  161. order.From = from
  162. order.Product = product
  163. order.Childs = items
  164. if order.Product != nil && order.Product.ID != 0 {
  165. order.From.Product.Name = order.Product.Name
  166. }
  167. return order, nil
  168. }
  169. func itemVerify(items []calc.Item, froms []ItemFrom, parent *OrderItem, create bool) ([]*OrderItem, error) {
  170. orderItems := make([]*OrderItem, 0)
  171. orderNumber := int64(0)
  172. for key, item := range items {
  173. if create && item.State == 0 {
  174. for n := int64(0); n < item.Min; n++ {
  175. orderItem, err := createOrderItem(&items[key], nil, create)
  176. if err != nil {
  177. return nil, err
  178. }
  179. orderItem.Parent = parent
  180. orderItem.OrderNumber = orderNumber
  181. orderItems = append(orderItems, orderItem)
  182. orderNumber++
  183. }
  184. } else {
  185. var n int64 = 0
  186. for i, from := range froms {
  187. if from.ID == item.ID {
  188. orderItem, err := createOrderItem(&items[key], &froms[i], create)
  189. if err != nil {
  190. return nil, err
  191. }
  192. orderItem.Parent = parent
  193. orderItem.OrderNumber = orderNumber
  194. orderItems = append(orderItems, orderItem)
  195. orderNumber++
  196. n++
  197. }
  198. }
  199. if create && (n < item.Min || n > item.Max) {
  200. return nil, errors.New("项目数量错误: " + item.Name)
  201. }
  202. }
  203. }
  204. return orderItems, nil
  205. }
  206. func (from *OrderFrom) BindOrder(calc *calc.Calculate, create bool) (*Order, error) {
  207. if calc.ID != from.ID {
  208. return nil, errors.New("核算错误")
  209. }
  210. if create {
  211. from.Results = make(map[int64]interface{})
  212. err := propVerify(calc.Props, from.Prop)
  213. if err != nil {
  214. return nil, err
  215. }
  216. }
  217. order := new(Order)
  218. order.Calc = calc
  219. order.From = from
  220. items, err := itemVerify(calc.Items, from.Items, nil, create)
  221. if err != nil {
  222. return nil, err
  223. }
  224. order.Items = items
  225. return order, nil
  226. }
  227. func (from *OrderFrom) LoadOrder(create bool) (*Order, error) {
  228. calc := calc.GetCalculateModel(from.ID, true)
  229. if calc == nil {
  230. return nil, errors.New("核算不存在")
  231. }
  232. return from.BindOrder(calc, create)
  233. }
  234. func (from *OrderFrom) CreateOrder() (*Order, error) {
  235. return from.LoadOrder(true)
  236. }
  237. func (order *Order) Abstract() (abstract OrderAbstract) {
  238. abstract.Prop = make(map[string]string)
  239. abstract.Results = make(map[string]string)
  240. for _, prop := range order.Calc.Props {
  241. if (prop.Type == 2 || prop.Type == 3) && prop.State == 1 {
  242. if ret, ok := ToDataType(order.From.Prop[prop.ID], prop.DataType); ok {
  243. abstract.Prop[prop.Name] = db.ToString(ret)
  244. }
  245. }
  246. }
  247. for _, prop := range order.Calc.Props {
  248. if prop.Type == 1 && prop.State == 1 {
  249. if ret, ok := ToDataType(order.From.Results[prop.ID], prop.DataType); ok {
  250. abstract.Results[prop.Name] = db.ToString(ret)
  251. }
  252. }
  253. }
  254. return
  255. }
  256. func BindOrder(calc *calc.Calculate, model calc.Order) (*Order, error) {
  257. from := new(OrderFrom)
  258. utils.JsonDecode(model.Content).To(from)
  259. order, err := from.BindOrder(calc, false)
  260. if err != nil {
  261. return nil, err
  262. }
  263. order.ID = model.ID
  264. order.AdminId = model.AdminId
  265. return order, nil
  266. }
  267. func LoadOrder(model calc.Order) (*Order, error) {
  268. from := new(OrderFrom)
  269. utils.JsonDecode(model.Content).To(from)
  270. order, err := from.LoadOrder(false)
  271. if err != nil {
  272. return nil, err
  273. }
  274. order.ID = model.ID
  275. order.AdminId = model.AdminId
  276. return order, nil
  277. }
  278. func (order *Order) Save() error {
  279. data := map[string]interface{}{
  280. "calcId": order.Calc.ID,
  281. "adminId": order.AdminId,
  282. "abstract": utils.JsonEncode(order.Abstract()),
  283. "content": utils.JsonEncode(order.GetFrom(true)),
  284. }
  285. if order.ID == 0 {
  286. id, err := db.InsertModel(reflect.TypeOf(calc.Order{}), data)
  287. if err != nil {
  288. return err
  289. }
  290. order.ID = id
  291. } else {
  292. err := db.UpdateModel(reflect.TypeOf(calc.Order{}), order.ID, data)
  293. if err != nil {
  294. return err
  295. }
  296. }
  297. return nil
  298. }
  299. type exportContext struct {
  300. value string
  301. item *OrderItem
  302. }
  303. func runValue(begin string, formula []string, context *Context) []exportContext {
  304. if len(formula) == 0 {
  305. return []exportContext{{begin, context.Item}}
  306. } else if len(formula) == 1 {
  307. ret, err := context.EvaluableExpression(formula[0])
  308. if err == nil {
  309. begin += db.ToString(ret)
  310. }
  311. return []exportContext{{begin, context.Item}}
  312. }
  313. results := make([]exportContext, 0)
  314. items := context.Order.Items
  315. if context.Item != nil {
  316. items = context.Item.Childs
  317. }
  318. orderNumber := int64(0)
  319. for i, _ := range items {
  320. if formula[0] != "" {
  321. ret, err := context.Exec(formula[0], items[i], int64(i))
  322. if err != nil {
  323. continue
  324. }
  325. if retb, ok := ret.(bool); !ok || !retb {
  326. continue
  327. }
  328. }
  329. context.Push(items[i])
  330. context.OrderNumber = orderNumber
  331. for _, c := range runValue(begin, formula[1:], context) {
  332. c.value = begin + c.value
  333. results = append(results, c)
  334. }
  335. context.Pop()
  336. orderNumber++
  337. }
  338. return results
  339. }
  340. func runContext(contexts []exportContext, value string, context *Context) []exportContext {
  341. results := make([]exportContext, 0)
  342. for i, v := range contexts {
  343. context.Push(v.item)
  344. context.OrderNumber = int64(i)
  345. for _, c := range readValue(value, context) {
  346. c.value = v.value + c.value
  347. results = append(results, c)
  348. }
  349. context.Pop()
  350. }
  351. return results
  352. }
  353. func readValue(value string, context *Context) []exportContext {
  354. result := ""
  355. brackets := false
  356. begin := ""
  357. formula := make([]string, 0)
  358. for i := 0; i < len([]rune(value)); i++ {
  359. switch []rune(value)[i] {
  360. case '\\':
  361. if i+1 < len([]rune(value)) {
  362. if []rune(value)[i+1] == '{' || []rune(value)[i+1] == '}' || []rune(value)[i+1] == ';' {
  363. result += string([]rune(value)[i+1])
  364. i++
  365. } else {
  366. result += string([]rune(value)[i])
  367. }
  368. } else {
  369. result += string([]rune(value)[i])
  370. }
  371. case '{':
  372. if brackets {
  373. result += string([]rune(value)[i])
  374. } else {
  375. begin = result
  376. result = ""
  377. brackets = true
  378. }
  379. case '}':
  380. if brackets {
  381. formula = append(formula, result)
  382. result = ""
  383. return runContext(runValue(begin, formula, context), string([]rune(value)[i+1:]), context)
  384. } else {
  385. result += string([]rune(value)[i])
  386. }
  387. case ';':
  388. if brackets {
  389. formula = append(formula, result)
  390. result = ""
  391. } else {
  392. result += string([]rune(value)[i])
  393. }
  394. default:
  395. result += string([]rune(value)[i])
  396. }
  397. }
  398. if brackets {
  399. formula = append(formula, result)
  400. result = ""
  401. return runValue(begin, formula, context)
  402. }
  403. return []exportContext{{result, context.Item}}
  404. }
  405. func readCells(cells []*xlsx.Cell, context *Context) [][]string {
  406. rows := make([][]string, 0)
  407. if len(cells) == 0 {
  408. rows = append(rows, []string{})
  409. return rows
  410. }
  411. for i, c := range readValue(cells[0].String(), context) {
  412. context.Push(c.item)
  413. context.OrderNumber = int64(i)
  414. for _, s := range readCells(cells[1:], context) {
  415. rows = append(rows, append([]string{c.value}, s...))
  416. }
  417. context.Pop()
  418. }
  419. return rows
  420. }
  421. func (order *Order) Export(filename string, c *gin.Context) string {
  422. template, err := xlsx.OpenFile(filename)
  423. if err != nil {
  424. return ""
  425. }
  426. export := xlsx.NewFile()
  427. for sheetName, sheet := range template.Sheet {
  428. sh, err := export.AddSheet(sheetName)
  429. if err != nil {
  430. return ""
  431. }
  432. sheet.Cols.ForEach(func(idx int, col *xlsx.Col) {
  433. sh.SetColWidth(col.Min, col.Max, *col.Width)
  434. })
  435. err = sheet.ForEachRow(func(r *xlsx.Row) error {
  436. cells := make([]*xlsx.Cell, 0)
  437. err := r.ForEachCell(func(c *xlsx.Cell) error {
  438. cells = append(cells, c)
  439. return nil
  440. })
  441. if err != nil {
  442. return err
  443. }
  444. context := NewContext(order, c)
  445. for _, rowStrings := range readCells(cells, context) {
  446. row := sh.AddRow()
  447. row.SetHeight(r.GetHeight())
  448. row.SetOutlineLevel(r.GetOutlineLevel())
  449. for i, cellStrings := range rowStrings {
  450. c := row.AddCell()
  451. binary, _ := cells[i].MarshalBinary()
  452. c.UnmarshalBinary(binary)
  453. c.SetStyle(cells[i].GetStyle())
  454. c.Value = cellStrings
  455. }
  456. }
  457. return nil
  458. })
  459. if err != nil {
  460. return ""
  461. }
  462. }
  463. exportFileName := utils.ToStr(time.Now().UnixNano()) + ".xlsx"
  464. if err := export.Save(config.Cfg.App.ExportPath + exportFileName); err != nil {
  465. return ""
  466. }
  467. return exportFileName
  468. }