expense_list_controller.dart 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. import 'package:flutter_riverpod/flutter_riverpod.dart';
  2. import '../../shared/models/approval_status.dart';
  3. import 'expense_model.dart';
  4. final expenseStatusFilterProvider = StateProvider<String>((ref) => '');
  5. final expenseScopeProvider = StateProvider<String>((ref) => 'mine');
  6. final mockExpenses = <ExpenseModel>[
  7. ExpenseModel(
  8. id: 'exp-001',
  9. reportNo: 'BX202605001',
  10. applicantId: 'u-001',
  11. applicantName: '张三',
  12. deptId: 'dept-001',
  13. deptName: '市场部',
  14. expenseType: '差旅费',
  15. totalAmount: 2580.00,
  16. invoiceCount: 3,
  17. status: 'pending',
  18. purpose: '北京出差拜访客户',
  19. accountBankName: '中国银行',
  20. accountHolderName: '张三',
  21. accountName: '张三',
  22. accountId: '6217001234567890123',
  23. paymentStatus: 'unpaid',
  24. projectName: '华北区客户拓展',
  25. budgetSubjectName: '差旅费预算',
  26. sourceApplicationId: 'EA001',
  27. sourceImportAmount: 2000.00,
  28. attachments: ['http://example.com/invoice1.jpg'],
  29. createTime: DateTime(2026, 5, 20),
  30. updateTime: DateTime(2026, 5, 20),
  31. details: [
  32. ExpenseDetailModel(
  33. id: 'det-001',
  34. expenseId: 'exp-001',
  35. expenseDate: DateTime(2026, 5, 19),
  36. expenseType: '交通费',
  37. expenseDesc: '北京-上海高铁',
  38. amount: 553.00,
  39. taxAmount: 27.65,
  40. totalAmount: 580.65,
  41. baseAmount: 580.65,
  42. currency: 'CNY',
  43. exchangeRate: 1.0,
  44. invoiceType: 'general',
  45. invoiceNo: 'INV20260519001',
  46. invoiceCode: '3100234567',
  47. taxRate: 0.05,
  48. ),
  49. ExpenseDetailModel(
  50. id: 'det-002',
  51. expenseId: 'exp-001',
  52. expenseDate: DateTime(2026, 5, 19),
  53. expenseType: '住宿费',
  54. expenseDesc: '上海酒店住宿',
  55. amount: 800.00,
  56. taxAmount: 40.00,
  57. totalAmount: 840.00,
  58. baseAmount: 840.00,
  59. currency: 'CNY',
  60. exchangeRate: 1.0,
  61. invoiceType: 'special',
  62. invoiceNo: 'INV20260519002',
  63. invoiceCode: '3100456789',
  64. taxRate: 0.05,
  65. ),
  66. ExpenseDetailModel(
  67. id: 'det-003',
  68. expenseId: 'exp-001',
  69. expenseDate: DateTime(2026, 5, 20),
  70. expenseType: '餐饮费',
  71. expenseDesc: '客户午餐',
  72. amount: 1100.00,
  73. taxAmount: 55.00,
  74. totalAmount: 1155.00,
  75. baseAmount: 1155.00,
  76. currency: 'CNY',
  77. exchangeRate: 1.0,
  78. invoiceType: 'general',
  79. invoiceNo: 'INV20260520003',
  80. invoiceCode: '3100567890',
  81. taxRate: 0.05,
  82. ),
  83. ],
  84. approvalRecords: [
  85. ApprovalRecord(
  86. id: 'ar-001',
  87. bizId: 'exp-001',
  88. bizType: 'expense',
  89. approverId: 'u-mgr',
  90. approverName: '李经理',
  91. approvalLevel: 1,
  92. action: 'pending',
  93. opinion: '',
  94. approvalTime: DateTime(2026, 5, 21),
  95. ),
  96. ],
  97. ),
  98. ExpenseModel(
  99. id: 'exp-002',
  100. reportNo: 'BX202605002',
  101. applicantId: 'u-001',
  102. applicantName: '张三',
  103. deptId: 'dept-001',
  104. deptName: '市场部',
  105. expenseType: '办公用品',
  106. totalAmount: 1280.50,
  107. invoiceCount: 2,
  108. status: 'approved',
  109. purpose: '部门办公用品采购',
  110. accountBankName: '中国银行',
  111. accountHolderName: '张三',
  112. accountName: '张三',
  113. accountId: '6217001234567890123',
  114. paymentStatus: 'paid',
  115. voucherNo: 'V202606001',
  116. projectName: '办公运营',
  117. budgetSubjectName: '办公费预算',
  118. createTime: DateTime(2026, 5, 15),
  119. updateTime: DateTime(2026, 5, 18),
  120. details: [
  121. ExpenseDetailModel(
  122. id: 'det-004',
  123. expenseId: 'exp-002',
  124. expenseDate: DateTime(2026, 5, 14),
  125. expenseType: '办公用品',
  126. expenseDesc: '打印纸、墨盒',
  127. amount: 1280.50,
  128. taxAmount: 64.03,
  129. totalAmount: 1344.53,
  130. baseAmount: 1344.53,
  131. currency: 'CNY',
  132. exchangeRate: 1.0,
  133. invoiceType: 'special',
  134. invoiceNo: 'INV20260514001',
  135. invoiceCode: '4400123456',
  136. taxRate: 0.05,
  137. ),
  138. ],
  139. approvalRecords: [
  140. ApprovalRecord(
  141. id: 'ar-002',
  142. bizId: 'exp-002',
  143. bizType: 'expense',
  144. approverId: 'u-mgr',
  145. approverName: '李经理',
  146. approvalLevel: 1,
  147. action: 'approve',
  148. opinion: '同意',
  149. approvalTime: DateTime(2026, 5, 18),
  150. ),
  151. ],
  152. ),
  153. ExpenseModel(
  154. id: 'exp-003',
  155. reportNo: 'BX202605003',
  156. applicantId: 'u-003',
  157. applicantName: '赵六',
  158. deptId: 'dept-003',
  159. deptName: '财务部',
  160. expenseType: '业务招待费',
  161. totalAmount: 3600.00,
  162. invoiceCount: 1,
  163. status: 'rejected',
  164. purpose: '客户答谢晚宴',
  165. accountBankName: '工商银行',
  166. accountHolderName: '赵六',
  167. accountName: '赵六',
  168. accountId: '6222009876543210987',
  169. paymentStatus: 'unpaid',
  170. createTime: DateTime(2026, 5, 10),
  171. updateTime: DateTime(2026, 5, 12),
  172. details: [
  173. ExpenseDetailModel(
  174. id: 'det-005',
  175. expenseId: 'exp-003',
  176. expenseDate: DateTime(2026, 5, 9),
  177. expenseType: '招待费',
  178. expenseDesc: '客户晚宴',
  179. amount: 3600.00,
  180. taxAmount: 0.0,
  181. totalAmount: 3600.00,
  182. baseAmount: 3600.00,
  183. currency: 'CNY',
  184. exchangeRate: 1.0,
  185. invoiceType: 'none',
  186. invoiceNo: '',
  187. invoiceCode: '',
  188. taxRate: 0.0,
  189. ),
  190. ],
  191. approvalRecords: [
  192. ApprovalRecord(
  193. id: 'ar-003',
  194. bizId: 'exp-003',
  195. bizType: 'expense',
  196. approverId: 'u-mgr',
  197. approverName: '李经理',
  198. approvalLevel: 1,
  199. action: 'reject',
  200. opinion: '发票不符合规定',
  201. approvalTime: DateTime(2026, 5, 12),
  202. ),
  203. ],
  204. ),
  205. ExpenseModel(
  206. id: 'exp-004',
  207. reportNo: 'BX202605004',
  208. applicantId: 'u-004',
  209. applicantName: '钱七',
  210. deptId: 'dept-004',
  211. deptName: '技术部',
  212. expenseType: '交通费',
  213. totalAmount: 890.00,
  214. invoiceCount: 1,
  215. status: 'pending',
  216. purpose: '市内出行',
  217. accountBankName: '建设银行',
  218. accountHolderName: '钱七',
  219. accountName: '钱七',
  220. accountId: '6217001111222233334',
  221. paymentStatus: 'unpaid',
  222. createTime: DateTime(2026, 5, 22),
  223. updateTime: DateTime(2026, 5, 22),
  224. details: [
  225. ExpenseDetailModel(
  226. id: 'det-006',
  227. expenseId: 'exp-004',
  228. expenseDate: DateTime(2026, 5, 21),
  229. expenseType: '交通费',
  230. expenseDesc: '市内打车',
  231. amount: 890.00,
  232. taxAmount: 44.50,
  233. totalAmount: 934.50,
  234. baseAmount: 934.50,
  235. currency: 'CNY',
  236. exchangeRate: 1.0,
  237. invoiceType: 'general',
  238. invoiceNo: 'INV20260521001',
  239. invoiceCode: '5100123456',
  240. taxRate: 0.05,
  241. ),
  242. ],
  243. ),
  244. ExpenseModel(
  245. id: 'exp-005',
  246. reportNo: 'BX202605005',
  247. applicantId: 'u-001',
  248. applicantName: '张三',
  249. deptId: 'dept-001',
  250. deptName: '市场部',
  251. expenseType: '差旅费',
  252. totalAmount: 4200.00,
  253. invoiceCount: 4,
  254. status: 'approved',
  255. purpose: '深圳出差',
  256. accountBankName: '中国银行',
  257. accountHolderName: '张三',
  258. accountName: '张三',
  259. accountId: '6217001234567890123',
  260. paymentStatus: 'unpaid',
  261. voucherNo: '',
  262. projectName: '华南区客户拓展',
  263. budgetSubjectName: '差旅费预算',
  264. createTime: DateTime(2026, 5, 25),
  265. updateTime: DateTime(2026, 5, 28),
  266. details: [
  267. ExpenseDetailModel(
  268. id: 'det-007',
  269. expenseId: 'exp-005',
  270. expenseDate: DateTime(2026, 5, 24),
  271. expenseType: '交通费',
  272. expenseDesc: '深圳往返机票',
  273. amount: 2500.00,
  274. taxAmount: 125.00,
  275. totalAmount: 2625.00,
  276. baseAmount: 2625.00,
  277. currency: 'CNY',
  278. exchangeRate: 1.0,
  279. invoiceType: 'special',
  280. invoiceNo: 'INV20260524001',
  281. invoiceCode: '4400789012',
  282. taxRate: 0.05,
  283. ),
  284. ExpenseDetailModel(
  285. id: 'det-008',
  286. expenseId: 'exp-005',
  287. expenseDate: DateTime(2026, 5, 24),
  288. expenseType: '住宿费',
  289. expenseDesc: '深圳酒店住宿',
  290. amount: 1200.00,
  291. taxAmount: 60.00,
  292. totalAmount: 1260.00,
  293. baseAmount: 1260.00,
  294. currency: 'CNY',
  295. exchangeRate: 1.0,
  296. invoiceType: 'special',
  297. invoiceNo: 'INV20260524002',
  298. invoiceCode: '4400789013',
  299. taxRate: 0.05,
  300. ),
  301. ],
  302. approvalRecords: [
  303. ApprovalRecord(
  304. id: 'ar-004',
  305. bizId: 'exp-005',
  306. bizType: 'expense',
  307. approverId: 'u-mgr',
  308. approverName: '李经理',
  309. approvalLevel: 1,
  310. action: 'approve',
  311. opinion: '同意',
  312. approvalTime: DateTime(2026, 5, 28),
  313. ),
  314. ],
  315. ),
  316. ExpenseModel(
  317. id: 'exp-006',
  318. reportNo: 'BX202605006',
  319. applicantId: 'u-001',
  320. applicantName: '张三',
  321. deptId: 'dept-001',
  322. deptName: '市场部',
  323. expenseType: '交通费',
  324. totalAmount: 350.00,
  325. invoiceCount: 1,
  326. status: 'draft',
  327. purpose: '日常办公用车',
  328. accountBankName: '中国银行',
  329. accountHolderName: '张三',
  330. accountName: '张三',
  331. accountId: '6217001234567890123',
  332. paymentStatus: 'unpaid',
  333. createTime: DateTime(2026, 6, 1),
  334. updateTime: DateTime(2026, 6, 1),
  335. details: [
  336. ExpenseDetailModel(
  337. id: 'det-009',
  338. expenseId: 'exp-006',
  339. expenseDate: DateTime(2026, 6, 1),
  340. expenseType: '交通费',
  341. expenseDesc: '打车',
  342. amount: 350.00,
  343. taxAmount: 17.50,
  344. totalAmount: 367.50,
  345. baseAmount: 367.50,
  346. currency: 'CNY',
  347. exchangeRate: 1.0,
  348. invoiceType: 'general',
  349. invoiceNo: 'INV20260601001',
  350. invoiceCode: '5100789012',
  351. taxRate: 0.05,
  352. ),
  353. ],
  354. ),
  355. ];
  356. final expensePageProvider = StateProvider<int>((ref) => 1);
  357. final expenseDateStartProvider = StateProvider<DateTime?>((ref) => null);
  358. final expenseDateEndProvider = StateProvider<DateTime?>((ref) => null);
  359. final expenseRefreshProvider = StateProvider<int>((ref) => 0);
  360. final expenseListProvider = FutureProvider.autoDispose.family<List<ExpenseModel>, String>((ref, status) async {
  361. ref.watch(expensePageProvider);
  362. ref.watch(expenseDateStartProvider);
  363. ref.watch(expenseDateEndProvider);
  364. ref.watch(expenseRefreshProvider);
  365. // 模拟网络延迟,使骨架屏可见
  366. await Future.delayed(const Duration(milliseconds: 1000));
  367. var list = status.isEmpty
  368. ? mockExpenses
  369. : mockExpenses.where((e) => e.status == status).toList();
  370. final dateStart = ref.read(expenseDateStartProvider);
  371. final dateEnd = ref.read(expenseDateEndProvider);
  372. if (dateStart != null) {
  373. list = list.where((e) =>
  374. e.createTime.isAfter(dateStart.subtract(const Duration(days: 1)))).toList();
  375. }
  376. if (dateEnd != null) {
  377. list = list.where((e) =>
  378. e.createTime.isBefore(dateEnd.add(const Duration(days: 1)))).toList();
  379. }
  380. return list;
  381. });