expense_api.dart 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import 'package:flutter_riverpod/flutter_riverpod.dart';
  2. import '../../core/network/api_client.dart';
  3. import '../../core/network/api_response.dart';
  4. import '../../app.dart';
  5. import '../../shared/models/pagination_model.dart';
  6. import 'expense_model.dart';
  7. final expenseApiProvider = Provider<ExpenseApi>(
  8. (ref) => ExpenseApi(ref.read(apiClientProvider)),
  9. );
  10. // ═══ 参考数据模型(API 返回) ═══
  11. class CostTypeItem {
  12. final String typeNo;
  13. final String typeName;
  14. final String accNo;
  15. final String accName;
  16. const CostTypeItem({required this.typeNo, required this.typeName, required this.accNo, required this.accName});
  17. factory CostTypeItem.fromJson(Map<String, dynamic> json) => CostTypeItem(
  18. typeNo: json['typeNo'] as String? ?? '',
  19. typeName: json['typeName'] as String? ?? '',
  20. accNo: json['accNo'] as String? ?? '',
  21. accName: json['accName'] as String? ?? '',
  22. );
  23. }
  24. class ProjectCodeItem {
  25. final String objNo;
  26. final String name;
  27. const ProjectCodeItem({required this.objNo, required this.name});
  28. factory ProjectCodeItem.fromJson(Map<String, dynamic> json) => ProjectCodeItem(
  29. objNo: json['objNo'] as String? ?? '',
  30. name: json['name'] as String? ?? '',
  31. );
  32. }
  33. class DepartmentItem {
  34. final String dep;
  35. final String name;
  36. const DepartmentItem({required this.dep, required this.name});
  37. factory DepartmentItem.fromJson(Map<String, dynamic> json) => DepartmentItem(
  38. dep: json['dep'] as String? ?? '',
  39. name: json['name'] as String? ?? '',
  40. );
  41. }
  42. class CustomerItem {
  43. final String cusNo;
  44. final String name;
  45. const CustomerItem({required this.cusNo, required this.name});
  46. factory CustomerItem.fromJson(Map<String, dynamic> json) => CustomerItem(
  47. cusNo: json['cusNo'] as String? ?? '',
  48. name: json['name'] as String? ?? '',
  49. );
  50. }
  51. class CurrencyItem {
  52. final String curId;
  53. final String name;
  54. const CurrencyItem({required this.curId, required this.name});
  55. factory CurrencyItem.fromJson(Map<String, dynamic> json) => CurrencyItem(
  56. curId: json['curId'] as String? ?? '',
  57. name: json['name'] as String? ?? '',
  58. );
  59. }
  60. class EmployeeItem {
  61. final String salNo;
  62. final String name;
  63. final String dep;
  64. final String tel;
  65. final String email;
  66. final String bnkNo;
  67. final String bnkId;
  68. final String accName;
  69. const EmployeeItem({required this.salNo, required this.name, this.dep = '', this.tel = '', this.email = '', this.bnkNo = '', this.bnkId = '', this.accName = ''});
  70. factory EmployeeItem.fromJson(Map<String, dynamic> json) => EmployeeItem(
  71. salNo: json['salNo'] as String? ?? '',
  72. name: json['name'] as String? ?? '',
  73. dep: json['dep'] as String? ?? '',
  74. tel: json['tel'] as String? ?? '',
  75. email: json['email'] as String? ?? '',
  76. bnkNo: json['bnkNo'] as String? ?? '',
  77. bnkId: json['bnkId'] as String? ?? '',
  78. accName: json['accName'] as String? ?? '',
  79. );
  80. }
  81. class ExpenseApi {
  82. final ApiClient _client;
  83. ExpenseApi(this._client);
  84. /// 费用报销列表(分页)
  85. Future<PaginatedData<ExpenseModel>> fetchList({
  86. String status = '',
  87. String keyword = '',
  88. String startDate = '',
  89. String endDate = '',
  90. String usr = '',
  91. int page = 1,
  92. int size = 20,
  93. }) async {
  94. final response = await _client.get<Map<String, dynamic>>(
  95. '/OA/GetExpenseReports',
  96. queryParameters: {
  97. 'status': status,
  98. 'keyword': keyword,
  99. 'startDate': startDate,
  100. 'endDate': endDate,
  101. 'usr': usr,
  102. 'page': page,
  103. 'size': size,
  104. },
  105. );
  106. return PaginatedData.fromJson(response.data!, ExpenseModel.fromJson);
  107. }
  108. /// 费用报销详情(主表+明细)
  109. Future<ExpenseModel> fetchDetail(String billNo) async {
  110. final response = await _client.get<Map<String, dynamic>>(
  111. '/OA/GetExpenseReportDetail',
  112. queryParameters: {'billNo': billNo},
  113. );
  114. return ExpenseModel.fromJson(response.data!);
  115. }
  116. /// 提交审批
  117. Future<void> submit(Map<String, dynamic> data) async {
  118. await _client.post('/OA/BillSave', data: {
  119. 'erpCategory': 'MasterService',
  120. 'billId': 'BX',
  121. 'procId': '',
  122. 'data': data,
  123. });
  124. }
  125. /// 财务核销
  126. Future<void> verify(Map<String, dynamic> data) async {
  127. await _client.post('/OA/ExpenseVerify', data: data);
  128. }
  129. /// 费用类别字典
  130. Future<List<CostTypeItem>> getCostTypes({String keyword = '', String accNo = ''}) async {
  131. final response = await _client.get<Map<String, dynamic>>(
  132. '/OA/GetCostTypes',
  133. queryParameters: {'keyword': keyword, 'accNo': accNo, 'page': 1, 'size': 100},
  134. );
  135. final list = (response.data?['list'] as List<dynamic>?) ?? [];
  136. return list.map((e) => CostTypeItem.fromJson(e as Map<String, dynamic>)).toList();
  137. }
  138. /// 项目代号
  139. Future<List<ProjectCodeItem>> getProjectCodes({String keyword = '', String billDate = ''}) async {
  140. final response = await _client.get<Map<String, dynamic>>(
  141. '/OA/GetProjectCodes',
  142. queryParameters: {'keyword': keyword, 'billDate': billDate, 'page': 1, 'size': 100},
  143. );
  144. final list = (response.data?['list'] as List<dynamic>?) ?? [];
  145. return list.map((e) => ProjectCodeItem.fromJson(e as Map<String, dynamic>)).toList();
  146. }
  147. /// 部门
  148. Future<List<DepartmentItem>> getDepartments({String keyword = '', bool onlyActive = true}) async {
  149. final response = await _client.get<Map<String, dynamic>>(
  150. '/OA/GetDepartments',
  151. queryParameters: {'keyword': keyword, 'onlyActive': onlyActive, 'page': 1, 'size': 100},
  152. );
  153. final list = (response.data?['list'] as List<dynamic>?) ?? [];
  154. return list.map((e) => DepartmentItem.fromJson(e as Map<String, dynamic>)).toList();
  155. }
  156. /// 客户/厂商
  157. Future<List<CustomerItem>> getCustomers({String keyword = ''}) async {
  158. final response = await _client.get<Map<String, dynamic>>(
  159. '/OA/GetCustomers',
  160. queryParameters: {'keyword': keyword, 'page': 1, 'size': 100},
  161. );
  162. final list = (response.data?['list'] as List<dynamic>?) ?? [];
  163. return list.map((e) => CustomerItem.fromJson(e as Map<String, dynamic>)).toList();
  164. }
  165. /// 员工查询
  166. Future<List<EmployeeItem>> getEmployees({String keyword = '', String salNo = ''}) async {
  167. final response = await _client.get<Map<String, dynamic>>(
  168. '/OA/GetEmployees',
  169. queryParameters: {'keyword': keyword, 'salNo': salNo, 'page': 1, 'size': 100},
  170. );
  171. final list = (response.data?['list'] as List<dynamic>?) ?? [];
  172. return list.map((e) => EmployeeItem.fromJson(e as Map<String, dynamic>)).toList();
  173. }
  174. /// 可转入报销单的费用申请明细
  175. Future<Map<String, dynamic>> getImportableExpenseApplies({
  176. String aeNo = '', String startDate = '', String endDate = '', int page = 1, int size = 20,
  177. }) async {
  178. final response = await _client.get<Map<String, dynamic>>(
  179. '/OA/GetImportableExpenseApplies',
  180. queryParameters: {'aeNo': aeNo, 'startDate': startDate, 'endDate': endDate, 'page': page, 'size': size},
  181. );
  182. return response.data!;
  183. }
  184. /// 币别
  185. Future<List<CurrencyItem>> getCurrencies({String keyword = ''}) async {
  186. final response = await _client.get<Map<String, dynamic>>(
  187. '/OA/GetCurrencies',
  188. queryParameters: {'keyword': keyword, 'page': 1, 'size': 50},
  189. );
  190. final list = (response.data?['list'] as List<dynamic>?) ?? [];
  191. return list.map((e) => CurrencyItem.fromJson(e as Map<String, dynamic>)).toList();
  192. }
  193. /// 币别查询(旧版,保留兼容)
  194. Future<ApiResponse<Map<String, dynamic>>> fetchCurrencies({
  195. String keyword = '',
  196. int page = 1,
  197. int size = 50,
  198. }) async {
  199. return await _client.get('/OA/GetCurrencies',
  200. queryParameters: {'keyword': keyword, 'page': page, 'size': size});
  201. }
  202. }