repo.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. package repository
  2. import (
  3. "errors"
  4. "strings"
  5. "time"
  6. "wails-app/internal/dao"
  7. "wails-app/internal/global"
  8. "gorm.io/gorm"
  9. )
  10. type PaymentRepository struct{}
  11. func (r *PaymentRepository) EntryList() ([]dao.PaymentEntryConfig, error) {
  12. var entries []dao.PaymentEntryConfig
  13. if err := global.GVA_DB.Order("sort ASC, id ASC").Find(&entries).Error; err != nil {
  14. return nil, err
  15. }
  16. for i := range entries {
  17. codes, err := r.entryMethodCodes(global.GVA_DB, entries[i].Code)
  18. if err != nil {
  19. if strings.Contains(strings.ToLower(err.Error()), "no such table") {
  20. continue
  21. }
  22. return nil, err
  23. }
  24. entries[i].MethodCodes = codes
  25. }
  26. return entries, nil
  27. }
  28. func (r *PaymentRepository) entryMethodCodes(db *gorm.DB, entryCode string) ([]string, error) {
  29. var codes []string
  30. err := db.Model(&dao.PaymentEntryMethod{}).Where("entry_code = ?", entryCode).
  31. Order("sort ASC, id ASC").Pluck("method_code", &codes).Error
  32. return codes, err
  33. }
  34. func (r *PaymentRepository) MethodList() ([]dao.PaymentMethodConfig, error) {
  35. var methods []dao.PaymentMethodConfig
  36. if err := global.GVA_DB.Where("is_legacy = ?", false).Order("sort ASC, id ASC").Find(&methods).Error; err != nil {
  37. return nil, err
  38. }
  39. for i := range methods {
  40. codes, err := r.methodEntryCodes(global.GVA_DB, methods[i].Code)
  41. if err != nil {
  42. if strings.Contains(strings.ToLower(err.Error()), "no such table") {
  43. continue
  44. }
  45. return nil, err
  46. }
  47. methods[i].EntryCodes = codes
  48. }
  49. return methods, nil
  50. }
  51. func (r *PaymentRepository) methodEntryCodes(db *gorm.DB, methodCode string) ([]string, error) {
  52. var codes []string
  53. err := db.Model(&dao.PaymentEntryMethod{}).Where("method_code = ?", methodCode).
  54. Order("sort ASC, id ASC").Pluck("entry_code", &codes).Error
  55. return codes, err
  56. }
  57. func (r *PaymentRepository) EnabledMethodList(db *gorm.DB, entryCode string) ([]dao.PaymentMethodConfig, error) {
  58. var methods []dao.PaymentMethodConfig
  59. err := db.Table("payment_method_config AS pm").
  60. Select("pm.*").
  61. Joins("INNER JOIN payment_entry_method AS pem ON pem.method_code = pm.code").
  62. Joins("INNER JOIN payment_entry_config AS pec ON pec.code = pem.entry_code").
  63. Where("pem.entry_code = ? AND pem.deleted_at IS NULL AND pec.enabled = ? AND pm.enabled = ? AND pm.is_legacy = ?", entryCode, true, true, false).
  64. Order("pem.sort ASC, pm.sort ASC, pm.id ASC").Scan(&methods).Error
  65. return methods, err
  66. }
  67. func (r *PaymentRepository) IsMethodAllowed(db *gorm.DB, entryCode, methodCode string) (bool, error) {
  68. if db == nil {
  69. db = global.GVA_DB
  70. }
  71. var count int64
  72. err := db.Table("payment_entry_method AS pem").
  73. Joins("INNER JOIN payment_entry_config AS pec ON pec.code = pem.entry_code").
  74. Where("pem.entry_code = ? AND pem.method_code = ? AND pem.deleted_at IS NULL AND pec.deleted_at IS NULL", entryCode, methodCode).
  75. Count(&count).Error
  76. return count > 0, err
  77. }
  78. func (r *PaymentRepository) GetMethodByID(id uint) (*dao.PaymentMethodConfig, error) {
  79. var method dao.PaymentMethodConfig
  80. err := global.GVA_DB.First(&method, id).Error
  81. return &method, err
  82. }
  83. func (r *PaymentRepository) GetMethodByCode(db *gorm.DB, code string) (*dao.PaymentMethodConfig, error) {
  84. if db == nil {
  85. db = global.GVA_DB
  86. }
  87. var method dao.PaymentMethodConfig
  88. err := db.Where("code = ?", code).First(&method).Error
  89. return &method, err
  90. }
  91. func (r *PaymentRepository) GetEntryByID(id uint) (*dao.PaymentEntryConfig, error) {
  92. var entry dao.PaymentEntryConfig
  93. err := global.GVA_DB.First(&entry, id).Error
  94. return &entry, err
  95. }
  96. func (r *PaymentRepository) GetEntryByCode(db *gorm.DB, code string) (*dao.PaymentEntryConfig, error) {
  97. if db == nil {
  98. db = global.GVA_DB
  99. }
  100. var entry dao.PaymentEntryConfig
  101. err := db.Where("code = ?", code).First(&entry).Error
  102. return &entry, err
  103. }
  104. func (r *PaymentRepository) CreateEntry(entry *dao.PaymentEntryConfig) error {
  105. return global.GVA_DB.Create(entry).Error
  106. }
  107. func (r *PaymentRepository) CreateEntryTx(db *gorm.DB, entry *dao.PaymentEntryConfig) error {
  108. return db.Create(entry).Error
  109. }
  110. func (r *PaymentRepository) UpdateEntry(entry *dao.PaymentEntryConfig) error {
  111. return global.GVA_DB.Model(entry).Select("name", "enabled", "sort", "description").Updates(entry).Error
  112. }
  113. func (r *PaymentRepository) UpdateEntryTx(db *gorm.DB, entry *dao.PaymentEntryConfig) error {
  114. return db.Model(entry).Select("name", "enabled", "sort", "description").Updates(entry).Error
  115. }
  116. func (r *PaymentRepository) SetEntryEnabled(id uint, enabled bool) error {
  117. result := global.GVA_DB.Model(&dao.PaymentEntryConfig{}).Where("id = ?", id).Update("enabled", enabled)
  118. if result.Error != nil {
  119. return result.Error
  120. }
  121. if result.RowsAffected == 0 {
  122. return gorm.ErrRecordNotFound
  123. }
  124. return nil
  125. }
  126. func (r *PaymentRepository) CreateMethod(method *dao.PaymentMethodConfig) error {
  127. return global.GVA_DB.Create(method).Error
  128. }
  129. func (r *PaymentRepository) CreateMethodTx(db *gorm.DB, method *dao.PaymentMethodConfig) error {
  130. return db.Create(method).Error
  131. }
  132. func (r *PaymentRepository) UpdateMethod(method *dao.PaymentMethodConfig) error {
  133. return global.GVA_DB.Model(method).Select("name", "input_mode", "enabled", "sort", "description").Updates(method).Error
  134. }
  135. func (r *PaymentRepository) SetMethodEnabled(id uint, enabled bool) error {
  136. result := global.GVA_DB.Model(&dao.PaymentMethodConfig{}).Where("id = ?", id).Update("enabled", enabled)
  137. if result.Error != nil {
  138. return result.Error
  139. }
  140. if result.RowsAffected == 0 {
  141. return gorm.ErrRecordNotFound
  142. }
  143. return nil
  144. }
  145. func (r *PaymentRepository) DeleteMethod(method *dao.PaymentMethodConfig) error {
  146. return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
  147. if err := tx.Unscoped().Where("method_code = ?", method.Code).Delete(&dao.PaymentEntryMethod{}).Error; err != nil {
  148. return err
  149. }
  150. result := tx.Delete(method)
  151. if result.Error != nil {
  152. return result.Error
  153. }
  154. if result.RowsAffected == 0 {
  155. return errors.New("支付方式不存在")
  156. }
  157. return nil
  158. })
  159. }
  160. func (r *PaymentRepository) ReplaceEntryMethods(db *gorm.DB, entryCode string, methodCodes []string) error {
  161. if err := db.Unscoped().Where("entry_code = ?", entryCode).Delete(&dao.PaymentEntryMethod{}).Error; err != nil {
  162. return err
  163. }
  164. for i, code := range methodCodes {
  165. if err := db.Create(&dao.PaymentEntryMethod{EntryCode: entryCode, MethodCode: code, Sort: i * 10}).Error; err != nil {
  166. return err
  167. }
  168. }
  169. return nil
  170. }
  171. func (r *PaymentRepository) ReplaceMethodEntries(db *gorm.DB, methodCode string, entryCodes []string) error {
  172. if err := db.Unscoped().Where("method_code = ?", methodCode).Delete(&dao.PaymentEntryMethod{}).Error; err != nil {
  173. return err
  174. }
  175. for i, code := range entryCodes {
  176. if err := db.Create(&dao.PaymentEntryMethod{EntryCode: code, MethodCode: methodCode, Sort: i * 10}).Error; err != nil {
  177. return err
  178. }
  179. }
  180. return nil
  181. }
  182. func (r *PaymentRepository) DeleteEntry(entry *dao.PaymentEntryConfig) error {
  183. return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
  184. if err := tx.Unscoped().Where("entry_code = ?", entry.Code).Delete(&dao.PaymentEntryMethod{}).Error; err != nil {
  185. return err
  186. }
  187. return tx.Delete(entry).Error
  188. })
  189. }
  190. func (r *PaymentRepository) Create(record *dao.PaymentRecord) error {
  191. return global.GVA_DB.Create(record).Error
  192. }
  193. // PaymentListQuery 收费记录查询参数
  194. type PaymentListQuery struct {
  195. PlateNumber string `form:"plate_number"`
  196. PaymentEntry string `form:"payment_entry"`
  197. PaymentMethod string `form:"payment_method"`
  198. ParkingLotID uint `form:"parking_lot_id"`
  199. StartDate string `form:"start_date"`
  200. EndDate string `form:"end_date"`
  201. Page int `form:"page"`
  202. PageSize int `form:"page_size"`
  203. }
  204. // PaymentListResult 收费记录列表项
  205. type PaymentListResult struct {
  206. ID uint `json:"id"`
  207. PlateNumber string `json:"plate_number"`
  208. VehicleType string `json:"vehicle_type"`
  209. PaymentEntry string `json:"payment_entry"`
  210. PaymentEntryName string `json:"payment_entry_name"`
  211. PaymentMethod string `json:"payment_method"`
  212. PaymentMethodName string `json:"payment_method_name"`
  213. Amount float64 `json:"amount"`
  214. PaidAmount float64 `json:"paid_amount"`
  215. ChangeAmount float64 `json:"change_amount"`
  216. OperatorID uint `json:"operator_id"`
  217. OperatorName string `json:"operator_name"`
  218. ParkingLot string `json:"parking_lot"`
  219. PaidAt string `json:"paid_at"`
  220. EntryTime string `json:"entry_time"`
  221. ExitTime string `json:"exit_time"`
  222. StayTime int64 `json:"stay_time"`
  223. }
  224. // List 查询收费记录列表(关联 vehicle_record + vehicle + vehicle_type)
  225. func (r *PaymentRepository) List(q PaymentListQuery) ([]PaymentListResult, int64, error) {
  226. db := global.GVA_DB.Table("payment_record").
  227. Select(`payment_record.id, vehicle_record.plate_number, vehicle_type.name as vehicle_type, payment_record.payment_entry,
  228. COALESCE(payment_entry_config.name, payment_record.payment_entry) as payment_entry_name, payment_record.payment_method,
  229. COALESCE(payment_method_config.name, CASE WHEN payment_record.payment_method = 'free' THEN '免密放行' ELSE payment_record.payment_method END) as payment_method_name,
  230. payment_record.amount, payment_record.paid_amount, payment_record.change_amount,
  231. payment_record.operator_id, sys_users.nick_name as operator_name, vehicle_record.parking_lot_id, parking_lot.lot_name as parking_lot, payment_record.paid_at,
  232. vehicle_record.entry_time, vehicle_record.exit_time, vehicle_record.stay_time`).
  233. Joins("LEFT JOIN vehicle_record ON vehicle_record.id = payment_record.record_id").
  234. Joins("LEFT JOIN vehicle ON vehicle.plate_number = vehicle_record.plate_number").
  235. Joins("LEFT JOIN vehicle_type ON vehicle_type.id = vehicle.vehicle_type_id").
  236. Joins("LEFT JOIN sys_users ON sys_users.id = payment_record.operator_id").
  237. Joins("LEFT JOIN parking_lot ON parking_lot.id = vehicle_record.parking_lot_id")
  238. db = db.Joins("LEFT JOIN payment_entry_config ON payment_entry_config.code = payment_record.payment_entry")
  239. db = db.Joins("LEFT JOIN payment_method_config ON payment_method_config.code = payment_record.payment_method")
  240. if q.PlateNumber != "" {
  241. db = db.Where("vehicle_record.plate_number LIKE ?", "%"+q.PlateNumber+"%")
  242. }
  243. if q.ParkingLotID > 0 {
  244. db = db.Where("vehicle_record.parking_lot_id = ?", q.ParkingLotID)
  245. }
  246. if q.PaymentMethod != "" {
  247. db = db.Where("payment_record.payment_method = ?", q.PaymentMethod)
  248. }
  249. if q.PaymentEntry != "" {
  250. db = db.Where("payment_record.payment_entry = ?", q.PaymentEntry)
  251. }
  252. if q.StartDate != "" {
  253. db = db.Where("payment_record.paid_at >= ?", q.StartDate)
  254. }
  255. if q.EndDate != "" {
  256. db = db.Where("payment_record.paid_at <= ?", q.EndDate+" 23:59:59")
  257. }
  258. var total int64
  259. db.Count(&total)
  260. if q.Page <= 0 {
  261. q.Page = 1
  262. }
  263. if q.PageSize <= 0 {
  264. q.PageSize = 10
  265. }
  266. offset := (q.Page - 1) * q.PageSize
  267. var results []PaymentListResult
  268. err := db.Order("payment_record.paid_at DESC").Offset(offset).Limit(q.PageSize).Scan(&results).Error
  269. return results, total, err
  270. }
  271. // TodaySummary 当日收费汇总
  272. type TodaySummary struct {
  273. TotalAmount float64 `json:"total_amount"`
  274. CashAmount float64 `json:"cash_amount"`
  275. FreeAmount float64 `json:"free_amount"`
  276. TotalCount int64 `json:"total_count"`
  277. }
  278. // GetTodaySummary 获取当日收费汇总
  279. func (r *PaymentRepository) GetTodaySummary() (TodaySummary, error) {
  280. var s TodaySummary
  281. today := time.Now().Format("2006-01-02")
  282. err := global.GVA_DB.Table("payment_record").
  283. Select(`COALESCE(SUM(amount), 0) as total_amount,
  284. COALESCE(SUM(CASE WHEN payment_method = 'cash' THEN amount ELSE 0 END), 0) as cash_amount,
  285. COALESCE(SUM(CASE WHEN payment_method = 'free' THEN amount ELSE 0 END), 0) as free_amount,
  286. COUNT(*) as total_count`).
  287. Where("paid_at >= ? AND paid_at < ?", today, today+" 23:59:59").
  288. Scan(&s).Error
  289. return s, err
  290. }