expense_apply_controller.dart 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import 'package:flutter_riverpod/flutter_riverpod.dart';
  2. import 'expense_model.dart';
  3. import 'expense_api.dart';
  4. class ExpenseApplyState {
  5. final ExpenseModel expense;
  6. final bool isSubmitting;
  7. const ExpenseApplyState({required this.expense, this.isSubmitting = false});
  8. ExpenseApplyState copyWith({ExpenseModel? expense, bool? isSubmitting}) {
  9. return ExpenseApplyState(
  10. expense: expense ?? this.expense,
  11. isSubmitting: isSubmitting ?? this.isSubmitting,
  12. );
  13. }
  14. }
  15. class ExpenseApplyController extends StateNotifier<ExpenseApplyState> {
  16. final ExpenseApi _api;
  17. ExpenseApplyController(this._api, {ExpenseModel? initial})
  18. : super(
  19. ExpenseApplyState(
  20. expense:
  21. initial ??
  22. ExpenseModel(
  23. id: '',
  24. reportNo: '',
  25. applicantId: '',
  26. applicantName: '',
  27. deptId: '',
  28. deptName: '',
  29. expenseType: '',
  30. totalAmount: 0.0,
  31. purpose: '',
  32. createTime: DateTime.now(),
  33. updateTime: DateTime.now(),
  34. ),
  35. ),
  36. );
  37. void updateCurrencyCode(String code) {
  38. state = state.copyWith(expense: state.expense.copyWith(currencyCode: code));
  39. }
  40. void updateApprovedAmount(double amount) {
  41. state = state.copyWith(expense: state.expense.copyWith(approvedAmount: amount));
  42. }
  43. void updateDetailApprovedAmount(int index, double amount) {
  44. final details = [...state.expense.details];
  45. details[index] = details[index].copyWith(approvedAmount: amount);
  46. state = state.copyWith(expense: state.expense.copyWith(details: details));
  47. }
  48. void updateDetailCustomerVendor(int index, String name) {
  49. final details = [...state.expense.details];
  50. details[index] = details[index].copyWith(customerVendorName: name);
  51. state = state.copyWith(expense: state.expense.copyWith(details: details));
  52. }
  53. void updateDetailProjectCode(int index, String code) {
  54. final details = [...state.expense.details];
  55. details[index] = details[index].copyWith(projectCode: code);
  56. state = state.copyWith(expense: state.expense.copyWith(details: details));
  57. }
  58. void updateDetailSubjectCode(int index, String code) {
  59. final details = [...state.expense.details];
  60. details[index] = details[index].copyWith(subjectCode: code);
  61. state = state.copyWith(expense: state.expense.copyWith(details: details));
  62. }
  63. void updateDetailProjectCategory(int index, String category) {
  64. final details = [...state.expense.details];
  65. details[index] = details[index].copyWith(projectCategory: category);
  66. state = state.copyWith(expense: state.expense.copyWith(details: details));
  67. }
  68. void updateDetailOffsetAmount(int index, double amount) {
  69. final details = [...state.expense.details];
  70. details[index] = details[index].copyWith(offsetAmount: amount);
  71. state = state.copyWith(expense: state.expense.copyWith(details: details));
  72. }
  73. void updatePurpose(String purpose) {
  74. state = state.copyWith(expense: state.expense.copyWith(purpose: purpose));
  75. }
  76. void addDetail(ExpenseDetailModel detail) {
  77. final details = [...state.expense.details, detail];
  78. state = state.copyWith(expense: state.expense.copyWith(details: details));
  79. }
  80. void removeDetail(int index) {
  81. final details = [...state.expense.details]..removeAt(index);
  82. state = state.copyWith(expense: state.expense.copyWith(details: details));
  83. }
  84. void recalculateAmount() {
  85. var totalAmount = 0.0;
  86. var approvedAmount = 0.0;
  87. for (final d in state.expense.details) {
  88. totalAmount += d.totalAmount;
  89. approvedAmount += d.approvedAmount;
  90. }
  91. state = state.copyWith(
  92. expense: state.expense.copyWith(
  93. totalAmount: totalAmount,
  94. approvedAmount: approvedAmount,
  95. ),
  96. );
  97. }
  98. Future<bool> submit() async {
  99. state = state.copyWith(isSubmitting: true);
  100. try {
  101. await _api.submit(state.expense.copyWith(status: 'pending'));
  102. return true;
  103. } catch (_) {
  104. return false;
  105. } finally {
  106. state = state.copyWith(isSubmitting: false);
  107. }
  108. }
  109. Future<bool> saveDraft() async {
  110. state = state.copyWith(isSubmitting: true);
  111. try {
  112. await _api.saveDraft(state.expense);
  113. return true;
  114. } catch (_) {
  115. return false;
  116. } finally {
  117. state = state.copyWith(isSubmitting: false);
  118. }
  119. }
  120. }
  121. final expenseApplyProvider = StateNotifierProvider.autoDispose
  122. .family<ExpenseApplyController, ExpenseApplyState, String?>((ref, editId) {
  123. final api = ref.watch(expenseApiProvider);
  124. return ExpenseApplyController(api);
  125. });