DatabaseHelper.swift 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. //
  2. // DatabaseHelper.swift
  3. // MTP2_iOS
  4. //
  5. // Created by zhongyuan on 2018/6/9.
  6. // Copyright © 2018年 zhongyuan.All rights reserved.
  7. //
  8. import UIKit
  9. import CoreData
  10. enum DataBaseError: Error {
  11. case NoFindUser
  12. case NoFindSelfGoods
  13. }
  14. /// Database Helper
  15. class DatabaseHelper {
  16. // MARK: - 属性列表
  17. /// 全局单例
  18. static let appDelegate = UIApplication.shared.delegate as! AppDelegate
  19. // MARK: - 生命周期
  20. static func firstOpenInitialData() {
  21. /// 判断是否第一次运行
  22. if !UserDefaultsUtils.isFirstOpen() { return }
  23. /// 初始化可能与登录相关的错误码
  24. var errorCodeInfos = [MoErrorInfo]()
  25. errorCodeInfos.append(MoErrorInfo(description: "账号或密码不匹配", errorcode: "1003", errorid: 1003, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  26. errorCodeInfos.append(MoErrorInfo(description: "无效账号", errorcode: "1004", errorid: 1004, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  27. errorCodeInfos.append(MoErrorInfo(description: "账号类型不匹配", errorcode: "1005", errorid: 1005, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  28. errorCodeInfos.append(MoErrorInfo(description: "账号不在线", errorcode: "1006", errorid: 1006, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  29. errorCodeInfos.append(MoErrorInfo(description: "操作权限不够", errorcode: "1007", errorid: 1007, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  30. errorCodeInfos.append(MoErrorInfo(description: "会员无账户在线", errorcode: "1008", errorid: 1008, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  31. errorCodeInfos.append(MoErrorInfo(description: "账户在别处登录", errorcode: "1009", errorid: 1009, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  32. errorCodeInfos.append(MoErrorInfo(description: "值为空", errorcode: "1010", errorid: 1010, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  33. errorCodeInfos.append(MoErrorInfo(description: "登录账户已经存在", errorcode: "1011", errorid: 1011, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  34. errorCodeInfos.append(MoErrorInfo(description: "软件版本过低不能登录", errorcode: "1012", errorid: 1012, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  35. errorCodeInfos.append(MoErrorInfo(description: "IP地址不在允许范围内", errorcode: "1013", errorid: 1013, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  36. errorCodeInfos.append(MoErrorInfo(description: "地址查询错误,请稍候重试", errorcode: "1025", errorid: 1025, modulecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", operatecode: "ERR_ORDERWRTRADE_FIXEDPRICE_PRICE_INVALID", rownumber: ""))
  37. try? updateErrorInfos(errorInfos: errorCodeInfos)
  38. }
  39. // MARK: - 账户相关
  40. /// 获取指定用户id的本地用户信息对象
  41. ///
  42. /// - Parameter userID: 用户id
  43. /// - Returns: 用户信息对象
  44. static func getUser(loginID: String) throws -> UserEntity? {
  45. let fetchRequest: NSFetchRequest<UserEntity> = UserEntity.fetchRequest()
  46. fetchRequest.predicate = NSPredicate(format: "loginID == %@", loginID)
  47. let result = try DatabaseHelper.appDelegate.backGroundObjectContext.fetch(fetchRequest)
  48. return result.count != 0 ? result[0] : nil
  49. }
  50. /// 获取所有保存的用户信息
  51. ///
  52. /// - Parameter type: 类型,0为实盘(默认值);1为模拟盘
  53. /// - Returns: 用户信息数组
  54. /// - Throws: 数据库操作错误
  55. static func getUsers() throws -> [UserEntity]? {
  56. let fetchRequest: NSFetchRequest<UserEntity> = UserEntity.fetchRequest()
  57. fetchRequest.sortDescriptors = [NSSortDescriptor(key: "loginDate", ascending: false)]
  58. let result = try DatabaseHelper.appDelegate.backGroundObjectContext.fetch(fetchRequest)
  59. return result.count != 0 ? result : nil
  60. }
  61. /// - Parameters:
  62. /// - userID: 用户id
  63. /// - loginID: 登录id
  64. /// - type: 类型,0为实盘(默认值);1为模拟盘
  65. /// - Throws: 数据库操作错误
  66. static func addUser(userID: UInt32, loginID: String, _ loginDate: Date = Date()) throws {
  67. if let userEntity = try getUser(loginID: loginID) {
  68. userEntity.loginDate = loginDate
  69. } else {
  70. guard let userEntity = NSEntityDescription.insertNewObject(forEntityName: "UserEntity", into: DatabaseHelper.appDelegate.backGroundObjectContext) as? UserEntity else { return }
  71. userEntity.userID = Int64(Int32(userID))
  72. userEntity.loginID = loginID
  73. userEntity.loginDate = loginDate
  74. }
  75. DatabaseHelper.appDelegate.backGroundObjectContext.perform {
  76. if DatabaseHelper.appDelegate.backGroundObjectContext.hasChanges {
  77. try? DatabaseHelper.appDelegate.backGroundObjectContext.save()
  78. }
  79. }
  80. }
  81. /// 删除用户信息
  82. /// - Parameter loginID: loginID
  83. static func deleteUser(loginID: String) throws {
  84. do {
  85. if let userEntity = try getUser(loginID: loginID) {
  86. DatabaseHelper.appDelegate.backGroundObjectContext.perform {
  87. DatabaseHelper.appDelegate.backGroundObjectContext.delete(appDelegate.backGroundObjectContext.object(with: userEntity.objectID))
  88. if DatabaseHelper.appDelegate.backGroundObjectContext.hasChanges {
  89. try? DatabaseHelper.appDelegate.backGroundObjectContext.save()
  90. }
  91. }
  92. }
  93. } catch {
  94. throw DataBaseError.NoFindUser
  95. }
  96. }
  97. // MARK: - 错误码、枚举相关
  98. static func updateErrorInfos(errorInfos: [MoErrorInfo]) throws {
  99. /// 数据为空不做任何处理
  100. if errorInfos.count <= 0 { return }
  101. appDelegate.backGroundObjectContext.perform {
  102. for moErrorInfo in errorInfos {
  103. if try! getError(errorcode: moErrorInfo.errorcode) == nil {
  104. /// FIXME: 可能会报 EXC_BAD_ACCESS
  105. guard let entity = NSEntityDescription.insertNewObject(forEntityName: "ErrorCodeEntity", into: appDelegate.backGroundObjectContext) as? ErrorCodeEntity else { return }
  106. entity.errordesc = moErrorInfo.description
  107. entity.rownumber = moErrorInfo.rownumber
  108. entity.operatecode = moErrorInfo.operatecode
  109. entity.errorid = Int64(moErrorInfo.errorid)
  110. entity.errorcode = moErrorInfo.errorcode
  111. }
  112. }
  113. if appDelegate.backGroundObjectContext.hasChanges {
  114. try? appDelegate.backGroundObjectContext.save()
  115. }
  116. }
  117. }
  118. /// 移出所有错误码信息
  119. /// - Throws: Throws
  120. static func deleteAllErrorInfos() throws {
  121. let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "ErrorCodeEntity")
  122. let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
  123. try appDelegate.backGroundObjectContext.execute(batchDeleteRequest)
  124. }
  125. /// 获取对应的错误码信息
  126. /// - Parameter errorCode: errorCode
  127. /// - Throws: Throws
  128. /// - Returns: ErrorCodeEntity
  129. static func getError(errorcode: String) throws -> ErrorCodeEntity? {
  130. let fetchRequest: NSFetchRequest<ErrorCodeEntity> = ErrorCodeEntity.fetchRequest()
  131. fetchRequest.predicate = NSPredicate(format: "errorcode == %@", errorcode)
  132. let result = try appDelegate.backGroundObjectContext.fetch(fetchRequest)
  133. return result.count != 0 ? result[0] : nil
  134. }
  135. /// 获取所有得错误码信息
  136. /// - Parameter divisions: divisions
  137. static func getAllErrorInfos() throws -> [ErrorCodeEntity] {
  138. let fetchRequest: NSFetchRequest<ErrorCodeEntity> = ErrorCodeEntity.fetchRequest()
  139. fetchRequest.sortDescriptors = [NSSortDescriptor(key: "errorid", ascending: true)]
  140. let errors = (try? appDelegate.backGroundObjectContext.fetch(fetchRequest)) ?? []
  141. return errors
  142. }
  143. /// 添加枚举到数据库
  144. /// - Parameter enumInfos: enumInfos
  145. /// - Throws: throws
  146. static func addEnumInfos(enumInfos: [MoEnum]) throws {
  147. /// 异常
  148. if enumInfos.count <= 0 { return }
  149. appDelegate.backGroundObjectContext.perform {
  150. for enumInfo in enumInfos {
  151. /// FIXME: 可能会报 EXC_BAD_ACCESS
  152. guard let enumEntity = NSEntityDescription.insertNewObject(forEntityName: "EnumEntity", into: appDelegate.backGroundObjectContext) as? EnumEntity else { return }
  153. enumEntity.setupWith(enumInfo: enumInfo)
  154. }
  155. if appDelegate.backGroundObjectContext.hasChanges {
  156. try? appDelegate.backGroundObjectContext.save()
  157. }
  158. }
  159. }
  160. /// 移出所有的枚举信息
  161. /// - Throws: Throws
  162. static func deleteAllEnumInfos() throws {
  163. let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "EnumEntity")
  164. let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
  165. try appDelegate.backGroundObjectContext.execute(batchDeleteRequest)
  166. }
  167. /// 获取特定的枚举信息
  168. /// - Parameter autoid: autoid
  169. /// - Throws: Throws
  170. /// - Returns: EnumEntity
  171. static func getEnumInfo(autoid: Int16) throws -> EnumEntity? {
  172. let fetchRequest: NSFetchRequest<EnumEntity> = EnumEntity.fetchRequest()
  173. fetchRequest.sortDescriptors = [NSSortDescriptor(key: "autoid", ascending: true)]
  174. fetchRequest.predicate = NSPredicate(format: "autoid == %d", autoid)
  175. let result = try appDelegate.backGroundObjectContext.fetch(fetchRequest)
  176. /// 执行回调
  177. return result.count != 0 ? result[0] : nil
  178. }
  179. /// 获取特定的枚举信息
  180. /// - Parameter enumdiccode: autoid
  181. /// - Throws: Throws
  182. /// - Returns: EnumEntity
  183. static func getEnumInfo(enumdiccode: String?) throws -> [MoEnum]? {
  184. let fetchRequest: NSFetchRequest<EnumEntity> = EnumEntity.fetchRequest()
  185. fetchRequest.sortDescriptors = [NSSortDescriptor(key: "autoid", ascending: true)]
  186. if let code = enumdiccode { fetchRequest.predicate = NSPredicate(format: "enumdiccode == %@", code) }
  187. let result = try appDelegate.backGroundObjectContext.fetch(fetchRequest)
  188. /// 执行回调
  189. return result.count != 0 ? result.compactMap({ $0.toMoEnum() }) : nil
  190. }
  191. // MARK: - 区域信息
  192. /// 添加区域信息到数据库
  193. /// - Parameter divisions: divisions
  194. static func addDivisions(_ divisions: [MoDivisions]) throws {
  195. /// 异常
  196. if divisions.count <= 0 {
  197. return
  198. }
  199. /// 先移出所有的地区区域信息
  200. try deleteAllDivisions()
  201. appDelegate.backGroundObjectContext.perform {
  202. for info in divisions {
  203. /// 可能会报 EXC_BAD_ACCESS
  204. guard let cityEntity = NSEntityDescription.insertNewObject(forEntityName: "CityEntity", into: appDelegate.backGroundObjectContext) as? CityEntity else { return }
  205. cityEntity.setupWith(division: info)
  206. }
  207. if appDelegate.backGroundObjectContext.hasChanges {
  208. try? appDelegate.backGroundObjectContext.save()
  209. }
  210. }
  211. }
  212. /// 移出所有的区域信息
  213. /// - Throws: Throws
  214. static func deleteAllDivisions() throws {
  215. let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "CityEntity")
  216. let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
  217. try appDelegate.backGroundObjectContext.execute(batchDeleteRequest)
  218. }
  219. /// 获取所有的区域信息
  220. /// - Parameter divisions: divisions
  221. static func getAllDivisions() throws -> [MoDivisions] {
  222. let fetchRequest: NSFetchRequest<CityEntity> = CityEntity.fetchRequest()
  223. fetchRequest.sortDescriptors = [NSSortDescriptor(key: "autoid", ascending: true)]
  224. let citys = try appDelegate.backGroundObjectContext.fetch(fetchRequest)
  225. let divisions = citys.compactMap({ $0.toDivisions() })
  226. return divisions
  227. }
  228. // MARK: - 商品相关
  229. static func insertGoodsInfos(_ goodsInfos: [MoGoodsInfo]) throws {
  230. /// 先移出商品
  231. do {
  232. for goods in goodsInfos {
  233. let exist = try? getGoodsInfo(ById: goods.goodsid)
  234. if exist ?? false { removeGoodsInfo(goods.goodsid) }
  235. }
  236. }
  237. appDelegate.backGroundObjectContext.performAndWait {
  238. do {
  239. for obj in goodsInfos {
  240. guard let goodsInfoEntity = NSEntityDescription.insertNewObject(forEntityName: "GoodsInfoEntity", into: appDelegate.backGroundObjectContext) as? GoodsInfoEntity else {
  241. continue
  242. }
  243. goodsInfoEntity.setupWith(goodsInfo: obj)
  244. }
  245. if appDelegate.backGroundObjectContext.hasChanges {
  246. try appDelegate.backGroundObjectContext.save()
  247. } else {
  248. dPrint("商品本地化失败")
  249. }
  250. } catch {
  251. fatalError("商品数据插入失败")
  252. }
  253. }
  254. }
  255. /// 判断指定商品信息是否存在
  256. ///
  257. /// - Parameter Id: 商品ID
  258. /// - Returns: yes: 存在 no: 不存在
  259. /// - Throws:
  260. static func getGoodsInfo(ById Id: Int) throws -> Bool {
  261. let fetchRequest: NSFetchRequest<GoodsInfoEntity> = GoodsInfoEntity.fetchRequest()
  262. fetchRequest.predicate = NSPredicate(format: "goodsid == %ld", Int32(Id))
  263. let count = try appDelegate.backGroundObjectContext.count(for: fetchRequest)
  264. return count > 0
  265. }
  266. /// 获取所有商品信息
  267. ///
  268. /// - Returns: 所有保存的商品信息
  269. /// - Throws:
  270. static func getGoodsInfo() throws -> [MoGoodsInfo] {
  271. let fetchRequest: NSFetchRequest<GoodsInfoEntity> = GoodsInfoEntity.fetchRequest()
  272. fetchRequest.sortDescriptors = [NSSortDescriptor(key: "goodsid", ascending: true)]
  273. let goodsInfos = try appDelegate.backGroundObjectContext.fetch(fetchRequest)
  274. let moGoodsInfos = goodsInfos.compactMap({ $0.toMoGoodsInfo() })
  275. return moGoodsInfos
  276. }
  277. /// 判断本地数据库是否有数据
  278. ///
  279. /// - Returns: yes: 存在 no: 不存在
  280. /// - Throws:
  281. static func goodsInfoIsExist() -> Bool {
  282. let fetchRequest: NSFetchRequest<GoodsInfoEntity> = GoodsInfoEntity.fetchRequest()
  283. do {
  284. let count = try appDelegate.backGroundObjectContext.count(for: fetchRequest)
  285. return count > 0
  286. } catch {
  287. fatalError()
  288. }
  289. }
  290. /// 根据查询条件获取符合条件的商品
  291. ///
  292. /// - Parameter searchCondition: 查询条件
  293. /// - Returns: 符合条件的商品
  294. /// - Throws:
  295. static func getGoodsInfo(ByCondition searchCondition: String) throws -> [MoGoodsInfo] {
  296. guard !searchCondition.isEmpty else { return [] }
  297. let fetchRequest: NSFetchRequest<GoodsInfoEntity> = GoodsInfoEntity.fetchRequest()
  298. if RegularUtils.checkNumber(with: searchCondition) {
  299. let regularString = ".*\(searchCondition).*"
  300. fetchRequest.predicate = NSPredicate(format: "searchCondition MATCHES %@", regularString)
  301. } else {
  302. var regularString = ".*"
  303. for s in searchCondition.uppercased() {
  304. regularString.append(s)
  305. regularString.append(".*")
  306. }
  307. fetchRequest.predicate = NSPredicate(format: "searchCondition MATCHES %@", regularString)
  308. }
  309. /// 排序
  310. fetchRequest.sortDescriptors = [NSSortDescriptor(key: "goodscode", ascending: true)]
  311. let goodsInfos = try appDelegate.backGroundObjectContext.fetch(fetchRequest)
  312. let moGoodsInfos = goodsInfos.compactMap({ $0.toMoGoodsInfo() })
  313. return moGoodsInfos
  314. }
  315. /// 删除所有的商品数据信息
  316. static func removeAllGoodsInfo() {
  317. /// 获取上下文对象
  318. let viewContext = appDelegate.persistentContainer.viewContext
  319. /// 获取实例
  320. let entity = NSFetchRequest<NSFetchRequestResult>(entityName: "GoodsInfoEntity")
  321. let deleteRequest = NSBatchDeleteRequest(fetchRequest: entity)
  322. let _ = try? viewContext.persistentStoreCoordinator?.execute(deleteRequest, with: viewContext)
  323. appDelegate.backGroundObjectContext.perform {
  324. if appDelegate.backGroundObjectContext.hasChanges {
  325. do {
  326. _ = try? viewContext.persistentStoreCoordinator?.execute(deleteRequest, with: viewContext)
  327. }
  328. }
  329. }
  330. }
  331. /// 删除所有的商品数据信息
  332. static func removeGoodsInfo(_ goodsid: Int) {
  333. /// 获取上下文对象
  334. let viewContext = appDelegate.persistentContainer.viewContext
  335. /// 获取实例
  336. let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "GoodsInfoEntity")
  337. fetchRequest.predicate = NSPredicate(format: "goodsid == %ld", Int64(goodsid))
  338. let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
  339. let _ = try? viewContext.persistentStoreCoordinator?.execute(deleteRequest, with: viewContext)
  340. appDelegate.backGroundObjectContext.perform {
  341. if appDelegate.backGroundObjectContext.hasChanges {
  342. do {
  343. _ = try? viewContext.persistentStoreCoordinator?.execute(deleteRequest, with: viewContext)
  344. }
  345. }
  346. }
  347. }
  348. /// 根据goodsid获取对应的商品数据
  349. /// - Parameter goodsid: goodsid
  350. static func getMoGoodsInfo(where goodsids: [Int]) throws -> [MoGoodsInfo]? {
  351. /// 获取商品数据
  352. var goodsInfo: [MoGoodsInfo] = []
  353. let fetchRequest: NSFetchRequest<GoodsInfoEntity> = GoodsInfoEntity.fetchRequest()
  354. for goodsid in goodsids {
  355. fetchRequest.predicate = NSPredicate(format: "goodsid == %ld", Int64(goodsid))
  356. let goodsInfos = try appDelegate.backGroundObjectContext.fetch(fetchRequest)
  357. if goodsInfos.count != 0 { goodsInfo.append(goodsInfos[0].toMoGoodsInfo()) }
  358. }
  359. return goodsInfo
  360. }
  361. }