overtime_apply_api.dart 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. import 'dart:convert';
  2. import 'package:flutter_riverpod/flutter_riverpod.dart';
  3. import '../../app.dart';
  4. import '../../core/data/api_cache.dart';
  5. import '../../core/navigation/host_app_channel.dart';
  6. import '../../core/network/api_client.dart';
  7. import '../../shared/models/pagination_model.dart';
  8. import '../expense_apply/expense_apply_api.dart';
  9. import 'overtime_apply_model.dart';
  10. import 'ot_report_model.dart';
  11. final overtimeApplyApiProvider = Provider<OvertimeApplyApi>(
  12. (ref) => OvertimeApplyApi(ref.read(apiClientProvider)),
  13. );
  14. class OvertimeApplyApi {
  15. final ApiClient _client;
  16. final _cache = ApiCache(
  17. keyPrefix:
  18. '${HostAppChannel.sn}_${HostAppChannel.compNo}_${HostAppChannel.usr}',
  19. );
  20. OvertimeApplyApi(this._client);
  21. /// 清除所有基础资料缓存(picker 下拉刷新时调用)。
  22. void clearRefCache() => _cache.clear();
  23. /// 加班申请列表(分页)
  24. Future<PaginatedData<OvertimeApplyModel>> fetchList({
  25. String status = '',
  26. String keyword = '',
  27. String startDate = '',
  28. String endDate = '',
  29. String usr = '',
  30. String sortDir = 'DESC',
  31. int page = 1,
  32. int size = 20,
  33. }) async {
  34. final response = await _client.get<Map<String, dynamic>>(
  35. '/OA/GetOTApplyList',
  36. queryParameters: {
  37. 'status': status,
  38. 'keyword': keyword,
  39. 'startDate': startDate,
  40. 'endDate': endDate,
  41. 'usr': usr,
  42. 'sortDir': sortDir,
  43. 'page': page,
  44. 'size': size,
  45. },
  46. );
  47. return PaginatedData.fromJson(response.data!, OvertimeApplyModel.fromJson);
  48. }
  49. /// 加班申请详情(主表+明细)
  50. Future<OvertimeApplyModel> fetchDetail(String billNo) async {
  51. final response = await _client.get<Map<String, dynamic>>(
  52. '/OA/GetOTApplyDetail',
  53. queryParameters: {'billNo': billNo},
  54. );
  55. return OvertimeApplyModel.fromJson(response.data!);
  56. }
  57. /// 部门
  58. Future<List<DepartmentItem>> getDepartments({
  59. String keyword = '',
  60. bool onlyActive = true,
  61. int page = 1,
  62. int size = 100,
  63. }) async {
  64. final cacheKey = 'getDepartments_${keyword}_${onlyActive}_$page';
  65. return _cache.getOrFetch(cacheKey, () async {
  66. final response = await _client.get<Map<String, dynamic>>(
  67. '/OA/GetDepartments',
  68. queryParameters: {
  69. 'keyword': keyword,
  70. 'onlyActive': onlyActive,
  71. 'page': page,
  72. 'size': size,
  73. },
  74. );
  75. final list = (response.data?['list'] as List<dynamic>?) ?? [];
  76. return list
  77. .map((e) => DepartmentItem.fromJson(e as Map<String, dynamic>))
  78. .toList();
  79. });
  80. }
  81. /// 员工查询
  82. Future<List<EmployeeItem>> getEmployees({
  83. String keyword = '',
  84. String salNo = '',
  85. int page = 1,
  86. int size = 100,
  87. }) async {
  88. final cacheKey = 'getEmployees_${keyword}_${salNo}_$page';
  89. return _cache.getOrFetch(cacheKey, () async {
  90. final response = await _client.get<Map<String, dynamic>>(
  91. '/OA/GetEmployees',
  92. queryParameters: {
  93. 'keyword': keyword,
  94. 'salNo': salNo,
  95. 'page': page,
  96. 'size': size,
  97. },
  98. );
  99. final list = (response.data?['list'] as List<dynamic>?) ?? [];
  100. return list
  101. .map((e) => EmployeeItem.fromJson(e as Map<String, dynamic>))
  102. .toList();
  103. });
  104. }
  105. /// 提交审批,返回申请单号(提取失败时返回 null)
  106. Future<String?> submit(Map<String, dynamic> data) async {
  107. final response = await _client.post<Map<String, dynamic>>(
  108. '/OA/BillSave',
  109. data: {
  110. 'erpCategory': 'MasterService',
  111. 'billId': 'JB',
  112. 'procId': '',
  113. 'data': data,
  114. },
  115. );
  116. final resData = response.data;
  117. if (resData == null) return null;
  118. // 从 resultData 中取
  119. final resultData = resData['resultData'];
  120. if (resultData is Map<String, dynamic>) {
  121. final bilNo = resultData['BIL_NO'] as String?;
  122. if (bilNo != null && bilNo.isNotEmpty) return bilNo;
  123. }
  124. if (resultData is String && resultData.isNotEmpty) {
  125. try {
  126. final parsed = json.decode(resultData) as Map<String, dynamic>;
  127. final bilNo = parsed['BIL_NO'] as String?;
  128. if (bilNo != null && bilNo.isNotEmpty) return bilNo;
  129. } catch (_) {}
  130. }
  131. // 兜底
  132. final rootBilNo = resData['BIL_NO'] as String?;
  133. if (rootBilNo != null && rootBilNo.isNotEmpty) return rootBilNo;
  134. return null;
  135. }
  136. /// 提交审核流
  137. Future<bool> shSubmit({
  138. required String bilNo,
  139. required String bilDd,
  140. String dep = '',
  141. String rem = '',
  142. String usr = '',
  143. bool isCancel = false,
  144. }) async {
  145. try {
  146. final response = await _client.post<Map<String, dynamic>>(
  147. '/OA/SHSubmit',
  148. data: {
  149. 'erpCategory': 'MasterService',
  150. 'bilId': 'JB',
  151. 'bilNo': bilNo,
  152. 'bilDd': bilDd,
  153. 'dep': dep,
  154. 'rem': rem,
  155. 'usr': usr,
  156. 'isCancel': isCancel,
  157. },
  158. );
  159. return response.data?['code'] == 0;
  160. } catch (_) {
  161. return false;
  162. }
  163. }
  164. /// 获取审核配置
  165. Future<Map<String, dynamic>> getBillAuditConfig(String bilId) async {
  166. final response = await _client.get<Map<String, dynamic>>(
  167. '/OA/GetBillAuditConfig',
  168. queryParameters: {'bilId': bilId},
  169. );
  170. return response.data!;
  171. }
  172. /// 获取单据状态
  173. Future<Map<String, dynamic>> getBillStatus(String billNo) async {
  174. final response = await _client.get<Map<String, dynamic>>(
  175. '/OA/GetBillStatus',
  176. queryParameters: {'billId': 'JB', 'billNo': billNo},
  177. );
  178. return response.data!;
  179. }
  180. /// 加班报表汇总
  181. Future<OTReportSummary> getOTReportSummary({
  182. String startDate = '',
  183. String endDate = '',
  184. }) async {
  185. final params = <String, dynamic>{};
  186. if (startDate.isNotEmpty) params['startDate'] = startDate;
  187. if (endDate.isNotEmpty) params['endDate'] = endDate;
  188. final response = await _client.get<Map<String, dynamic>>(
  189. '/OA/GetOTReportSummary',
  190. queryParameters: params,
  191. );
  192. return OTReportSummary.fromJson(response.data!);
  193. }
  194. /// 加班报表月度数据
  195. Future<List<OTMonthlyItem>> getOTReportMonthly({
  196. String startDate = '',
  197. String endDate = '',
  198. }) async {
  199. final params = <String, dynamic>{};
  200. if (startDate.isNotEmpty) params['startDate'] = startDate;
  201. if (endDate.isNotEmpty) params['endDate'] = endDate;
  202. final response = await _client.get<dynamic>(
  203. '/OA/GetOTReportMonthly',
  204. queryParameters: params,
  205. );
  206. final list =
  207. (response.data as List<dynamic>?)
  208. ?.map((e) => OTMonthlyItem.fromJson(e as Map<String, dynamic>))
  209. .toList() ??
  210. [];
  211. return list;
  212. }
  213. /// 加班报表下属对比
  214. Future<List<OTSubordinateItem>> getOTSubordinateReport({
  215. String startDate = '',
  216. String endDate = '',
  217. }) async {
  218. final response = await _client.get<dynamic>(
  219. '/OA/GetOTSubordinateReport',
  220. queryParameters: {
  221. if (startDate.isNotEmpty) 'startDate': startDate,
  222. if (endDate.isNotEmpty) 'endDate': endDate,
  223. },
  224. );
  225. final list =
  226. (response.data as List<dynamic>?)
  227. ?.map((e) => OTSubordinateItem.fromJson(e as Map<String, dynamic>))
  228. .toList() ??
  229. [];
  230. return list;
  231. }
  232. /// 加班报表明细(分页)
  233. Future<Map<String, dynamic>> getOTReportDetail({
  234. String startDate = '',
  235. String endDate = '',
  236. int page = 1,
  237. int size = 20,
  238. }) async {
  239. final response = await _client.get<Map<String, dynamic>>(
  240. '/OA/GetOTReportDetail',
  241. queryParameters: {
  242. if (startDate.isNotEmpty) 'startDate': startDate,
  243. if (endDate.isNotEmpty) 'endDate': endDate,
  244. 'page': page,
  245. 'size': size,
  246. },
  247. );
  248. return response.data!;
  249. }
  250. /// 加班报表表身明细(分页)
  251. Future<Map<String, dynamic>> getOTBodyReport({
  252. String startDate = '',
  253. String endDate = '',
  254. int page = 1,
  255. int size = 20,
  256. }) async {
  257. final response = await _client.get<Map<String, dynamic>>(
  258. '/OA/GetOTBodyReport',
  259. queryParameters: {
  260. if (startDate.isNotEmpty) 'startDate': startDate,
  261. if (endDate.isNotEmpty) 'endDate': endDate,
  262. 'page': page,
  263. 'size': size,
  264. },
  265. );
  266. return response.data!;
  267. }
  268. }