import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/network/api_client.dart'; import '../../core/network/api_response.dart'; import '../../app.dart'; import '../../shared/models/pagination_model.dart'; import 'expense_model.dart'; final expenseApiProvider = Provider( (ref) => ExpenseApi(ref.read(apiClientProvider)), ); // ═══ 参考数据模型(API 返回) ═══ class CostTypeItem { final String typeNo; final String typeName; final String accNo; final String accName; const CostTypeItem({required this.typeNo, required this.typeName, required this.accNo, required this.accName}); factory CostTypeItem.fromJson(Map json) => CostTypeItem( typeNo: json['typeNo'] as String? ?? '', typeName: json['typeName'] as String? ?? '', accNo: json['accNo'] as String? ?? '', accName: json['accName'] as String? ?? '', ); } class ProjectCodeItem { final String objNo; final String name; const ProjectCodeItem({required this.objNo, required this.name}); factory ProjectCodeItem.fromJson(Map json) => ProjectCodeItem( objNo: json['objNo'] as String? ?? '', name: json['name'] as String? ?? '', ); } class DepartmentItem { final String dep; final String name; const DepartmentItem({required this.dep, required this.name}); factory DepartmentItem.fromJson(Map json) => DepartmentItem( dep: json['dep'] as String? ?? '', name: json['name'] as String? ?? '', ); } class CustomerItem { final String cusNo; final String name; const CustomerItem({required this.cusNo, required this.name}); factory CustomerItem.fromJson(Map json) => CustomerItem( cusNo: json['cusNo'] as String? ?? '', name: json['name'] as String? ?? '', ); } class CurrencyItem { final String curId; final String name; const CurrencyItem({required this.curId, required this.name}); factory CurrencyItem.fromJson(Map json) => CurrencyItem( curId: json['curId'] as String? ?? '', name: json['name'] as String? ?? '', ); } class EmployeeItem { final String salNo; final String name; final String dep; final String tel; final String email; final String bnkNo; final String bnkId; final String accName; const EmployeeItem({required this.salNo, required this.name, this.dep = '', this.tel = '', this.email = '', this.bnkNo = '', this.bnkId = '', this.accName = ''}); factory EmployeeItem.fromJson(Map json) => EmployeeItem( salNo: json['salNo'] as String? ?? '', name: json['name'] as String? ?? '', dep: json['dep'] as String? ?? '', tel: json['tel'] as String? ?? '', email: json['email'] as String? ?? '', bnkNo: json['bnkNo'] as String? ?? '', bnkId: json['bnkId'] as String? ?? '', accName: json['accName'] as String? ?? '', ); } class ExpenseApi { final ApiClient _client; ExpenseApi(this._client); /// 费用报销列表(分页) Future> fetchList({ String status = '', String keyword = '', String startDate = '', String endDate = '', String usr = '', int page = 1, int size = 20, }) async { final response = await _client.get>( '/OA/GetExpenseReports', queryParameters: { 'status': status, 'keyword': keyword, 'startDate': startDate, 'endDate': endDate, 'usr': usr, 'page': page, 'size': size, }, ); return PaginatedData.fromJson(response.data!, ExpenseModel.fromJson); } /// 费用报销详情(主表+明细) Future fetchDetail(String billNo) async { final response = await _client.get>( '/OA/GetExpenseReportDetail', queryParameters: {'billNo': billNo}, ); return ExpenseModel.fromJson(response.data!); } /// 提交审批 Future submit(Map data) async { await _client.post('/OA/BillSave', data: { 'erpCategory': 'MasterService', 'billId': 'BX', 'procId': '', 'data': data, }); } /// 财务核销 Future verify(Map data) async { await _client.post('/OA/ExpenseVerify', data: data); } /// 费用类别字典 Future> getCostTypes({String keyword = '', String accNo = ''}) async { final response = await _client.get>( '/OA/GetCostTypes', queryParameters: {'keyword': keyword, 'accNo': accNo, 'page': 1, 'size': 100}, ); final list = (response.data?['list'] as List?) ?? []; return list.map((e) => CostTypeItem.fromJson(e as Map)).toList(); } /// 项目代号 Future> getProjectCodes({String keyword = '', String billDate = ''}) async { final response = await _client.get>( '/OA/GetProjectCodes', queryParameters: {'keyword': keyword, 'billDate': billDate, 'page': 1, 'size': 100}, ); final list = (response.data?['list'] as List?) ?? []; return list.map((e) => ProjectCodeItem.fromJson(e as Map)).toList(); } /// 部门 Future> getDepartments({String keyword = '', bool onlyActive = true}) async { final response = await _client.get>( '/OA/GetDepartments', queryParameters: {'keyword': keyword, 'onlyActive': onlyActive, 'page': 1, 'size': 100}, ); final list = (response.data?['list'] as List?) ?? []; return list.map((e) => DepartmentItem.fromJson(e as Map)).toList(); } /// 客户/厂商 Future> getCustomers({String keyword = ''}) async { final response = await _client.get>( '/OA/GetCustomers', queryParameters: {'keyword': keyword, 'page': 1, 'size': 100}, ); final list = (response.data?['list'] as List?) ?? []; return list.map((e) => CustomerItem.fromJson(e as Map)).toList(); } /// 员工查询 Future> getEmployees({String keyword = '', String salNo = ''}) async { final response = await _client.get>( '/OA/GetEmployees', queryParameters: {'keyword': keyword, 'salNo': salNo, 'page': 1, 'size': 100}, ); final list = (response.data?['list'] as List?) ?? []; return list.map((e) => EmployeeItem.fromJson(e as Map)).toList(); } /// 可转入报销单的费用申请明细 Future> getImportableExpenseApplies({ String aeNo = '', String startDate = '', String endDate = '', int page = 1, int size = 20, }) async { final response = await _client.get>( '/OA/GetImportableExpenseApplies', queryParameters: {'aeNo': aeNo, 'startDate': startDate, 'endDate': endDate, 'page': page, 'size': size}, ); return response.data!; } /// 币别 Future> getCurrencies({String keyword = ''}) async { final response = await _client.get>( '/OA/GetCurrencies', queryParameters: {'keyword': keyword, 'page': 1, 'size': 50}, ); final list = (response.data?['list'] as List?) ?? []; return list.map((e) => CurrencyItem.fromJson(e as Map)).toList(); } /// 币别查询(旧版,保留兼容) Future>> fetchCurrencies({ String keyword = '', int page = 1, int size = 50, }) async { return await _client.get('/OA/GetCurrencies', queryParameters: {'keyword': keyword, 'page': page, 'size': size}); } }