manifest.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. package godown
  2. import (
  3. "errors"
  4. "fmt"
  5. "gorm.io/gorm"
  6. "server/global"
  7. )
  8. type Manifest struct {
  9. global.GVA_MODEL
  10. ManifestGenre string `json:"manifestGenre" gorm:"comment:'货单类型'"`
  11. Title string `json:"title" gorm:"comment:'标题'"`
  12. Cargos []Cargo `json:"cargos" gorm:"foreignKey:ManifestId"`
  13. Custodian string `json:"custodian" gorm:"comment:管理人"`
  14. }
  15. func (Manifest) TableName() string {
  16. return "manifest"
  17. }
  18. func QueryAllManifest() (manifests []Manifest, err error) {
  19. err = global.GVA_DB.Model(&Manifest{}).Find(&manifests).Error
  20. return
  21. }
  22. func QueryManifestList(limit, offset int, genre, title string) (manifests []Manifest, total int64, err error) {
  23. // 创建db
  24. db := global.GVA_DB.Model(&Manifest{})
  25. // 如果有条件搜索 下方会自动创建搜索语句
  26. if genre != "" {
  27. db = db.Where("manifest_genre LIKE ?", "%"+genre+"%")
  28. }
  29. if title != "" {
  30. db = db.Where("title LIKE ?", "%"+title+"%")
  31. }
  32. err = db.Count(&total).Error
  33. if err != nil {
  34. return
  35. }
  36. err = db.Order("id desc").Limit(limit).Offset(offset).Preload("Cargos").Preload("Cargos.Commodity").Preload("Cargos.Warehouse").Find(&manifests).Error
  37. return manifests, total, err
  38. }
  39. func (m Manifest) CreateManifest() error {
  40. return global.GVA_DB.Create(&m).Error
  41. }
  42. func (m Manifest) UpdateManifest() error {
  43. return global.GVA_DB.Where("id = ?", m.ID).Updates(&m).Error
  44. }
  45. func DeleteManifest(id int) error {
  46. return global.GVA_DB.Where("id = ?", id).Unscoped().Delete(&Manifest{}).Error
  47. }
  48. // CreateInboundManifest 入库
  49. func CreateInboundManifest(manifestGenre, title, custodian string, cargos []Cargo) error {
  50. // 开启事务
  51. return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
  52. // 1. 创建入库货单
  53. manifest := Manifest{
  54. ManifestGenre: manifestGenre, // 如 "采购入库"
  55. Title: title,
  56. Custodian: custodian,
  57. Cargos: cargos,
  58. }
  59. if err := tx.Create(&manifest).Error; err != nil {
  60. return fmt.Errorf("创建货单失败: %v", err)
  61. }
  62. // 2. 更新库存(逐个货物处理)
  63. for _, cargo := range manifest.Cargos {
  64. // 检查是否已存在相同商品、仓库、库区、库位的记录
  65. var goods Goods
  66. err := tx.Where("commodity_id = ? AND warehouse_id = ? AND storage_area_id = ? AND place_id = ?",
  67. cargo.CommodityId, cargo.WarehouseId, cargo.StorageAreaId, cargo.PlaceId).
  68. First(&goods).Error
  69. if err == nil {
  70. // 存在记录:增加数量
  71. goods.Number += cargo.Number
  72. if err := tx.Save(&goods).Error; err != nil {
  73. return fmt.Errorf("更新库存失败: %v", err)
  74. }
  75. } else if errors.Is(err, gorm.ErrRecordNotFound) {
  76. // 不存在记录:新建库存
  77. newGoods := Goods{
  78. CommodityId: cargo.CommodityId,
  79. Number: cargo.Number,
  80. WarehouseId: cargo.WarehouseId,
  81. StorageAreaId: cargo.StorageAreaId,
  82. PlaceId: cargo.PlaceId,
  83. }
  84. if err := tx.Create(&newGoods).Error; err != nil {
  85. return fmt.Errorf("创建库存失败: %v", err)
  86. }
  87. } else {
  88. return fmt.Errorf("查询库存失败: %v", err)
  89. }
  90. }
  91. return nil
  92. })
  93. }
  94. // CreateOutboundManifest 出库
  95. func CreateOutboundManifest(manifestGenre, title, custodian string, cargos []Cargo) error {
  96. // 开启事务
  97. return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
  98. // 1. 检查库存是否充足(预扣减检查)
  99. for _, cargo := range cargos {
  100. var goods Goods
  101. if err := tx.Where("commodity_id = ? AND warehouse_id = ? AND storage_area_id = ? AND place_id = ?",
  102. cargo.CommodityId, cargo.WarehouseId, cargo.StorageAreaId, cargo.PlaceId).
  103. First(&goods).Error; err != nil {
  104. return fmt.Errorf("库存记录不存在: %v", err)
  105. }
  106. if goods.Number < cargo.Number {
  107. return fmt.Errorf("商品 %v 库存不足(当前: %d,需要: %d)",
  108. cargo.Commodity.Name, goods.Number, cargo.Number)
  109. }
  110. }
  111. // 2. 创建出库货单
  112. manifest := Manifest{
  113. ManifestGenre: manifestGenre, // 如 "销售出库"
  114. Title: title,
  115. Custodian: custodian,
  116. Cargos: cargos,
  117. }
  118. if err := tx.Create(&manifest).Error; err != nil {
  119. return fmt.Errorf("创建货单失败: %v", err)
  120. }
  121. // 3. 扣减库存
  122. for _, cargo := range manifest.Cargos {
  123. if err := tx.Model(&Goods{}).
  124. Where("commodity_id = ? AND warehouse_id = ? AND storage_area_id = ? AND place_id = ?",
  125. cargo.CommodityId, cargo.WarehouseId, cargo.StorageAreaId, cargo.PlaceId).
  126. Update("number", gorm.Expr("number - ?", cargo.Number)).
  127. Error; err != nil {
  128. return fmt.Errorf("扣减库存失败: %v", err)
  129. }
  130. }
  131. return nil
  132. })
  133. }