Full Code of markliu2013/bookkeeping for AI

main 10dbfc0ff078 cached
1544 files
3.2 MB
928.8k tokens
3013 symbols
1 requests
Download .txt
Showing preview only (3,899K chars total). Download the full file or copy to clipboard to get everything.
Repository: markliu2013/bookkeeping
Branch: main
Commit: 10dbfc0ff078
Files: 1544
Total size: 3.2 MB

Directory structure:
gitextract_uxeyvckg/

├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── bookkeeping-user-api/
│   ├── .mvn/
│   │   └── wrapper/
│   │       ├── MavenWrapperDownloader.java
│   │       ├── maven-wrapper.jar
│   │       └── maven-wrapper.properties
│   ├── Dockerfile
│   ├── mvnw
│   ├── mvnw.cmd
│   ├── pom.xml
│   ├── restart.sh
│   ├── src/
│   │   └── main/
│   │       ├── java/
│   │       │   └── com/
│   │       │       └── jiukuaitech/
│   │       │           └── bookkeeping/
│   │       │               └── user/
│   │       │                   ├── Application.java
│   │       │                   ├── RegexTest.java
│   │       │                   ├── account/
│   │       │                   │   ├── Account.java
│   │       │                   │   ├── AccountAddRequest.java
│   │       │                   │   ├── AccountAdjustBalanceNotValidException.java
│   │       │                   │   ├── AccountController.java
│   │       │                   │   ├── AccountExceptionHandler.java
│   │       │                   │   ├── AccountHasTransactionException.java
│   │       │                   │   ├── AccountMaxCountException.java
│   │       │                   │   ├── AccountNameExistsException.java
│   │       │                   │   ├── AccountQueryRequest.java
│   │       │                   │   ├── AccountRepository.java
│   │       │                   │   ├── AccountService.java
│   │       │                   │   ├── AccountSpec.java
│   │       │                   │   ├── AccountSumVO.java
│   │       │                   │   ├── AccountUpdateRequest.java
│   │       │                   │   ├── AccountVOForExtend.java
│   │       │                   │   ├── AccountVOForList.java
│   │       │                   │   ├── DefaultExpenseAccountException.java
│   │       │                   │   ├── DefaultIncomeAccountException.java
│   │       │                   │   ├── DefaultTransferFromAccountException.java
│   │       │                   │   └── DefaultTransferToAccountException.java
│   │       │                   ├── adjust_balance/
│   │       │                   │   ├── AdjustBalance.java
│   │       │                   │   ├── AdjustBalanceAddRequest.java
│   │       │                   │   ├── AdjustBalanceController.java
│   │       │                   │   ├── AdjustBalanceRepository.java
│   │       │                   │   ├── AdjustBalanceService.java
│   │       │                   │   └── AdjustBalanceVOForList.java
│   │       │                   ├── aop/
│   │       │                   │   └── TestAspect.java
│   │       │                   ├── asset_account/
│   │       │                   │   ├── AssetAccount.java
│   │       │                   │   ├── AssetAccountController.java
│   │       │                   │   ├── AssetAccountRepository.java
│   │       │                   │   ├── AssetAccountService.java
│   │       │                   │   └── AssetAccountVOForList.java
│   │       │                   ├── balance_flow/
│   │       │                   │   ├── AccountInvalidateException.java
│   │       │                   │   ├── AmountInvalidateException.java
│   │       │                   │   ├── BalanceFlow.java
│   │       │                   │   ├── BalanceFlowAddRequest.java
│   │       │                   │   ├── BalanceFlowController.java
│   │       │                   │   ├── BalanceFlowExceptionHandler.java
│   │       │                   │   ├── BalanceFlowQueryRequest.java
│   │       │                   │   ├── BalanceFlowQueryResultVO.java
│   │       │                   │   ├── BalanceFlowRepository.java
│   │       │                   │   ├── BalanceFlowService.java
│   │       │                   │   ├── BalanceFlowSpec.java
│   │       │                   │   ├── BalanceFlowUpdateRequest.java
│   │       │                   │   ├── BalanceFlowVOForExtend.java
│   │       │                   │   ├── BalanceFlowVOForList.java
│   │       │                   │   └── StatusNotValidateException.java
│   │       │                   ├── balance_log/
│   │       │                   │   ├── BalanceLog.java
│   │       │                   │   ├── BalanceLogAddRequest.java
│   │       │                   │   ├── BalanceLogController.java
│   │       │                   │   ├── BalanceLogRepository.java
│   │       │                   │   ├── BalanceLogService.java
│   │       │                   │   └── BalanceLogVOForList.java
│   │       │                   ├── base/
│   │       │                   │   ├── BaseController.java
│   │       │                   │   ├── BaseEntity.java
│   │       │                   │   ├── BaseRepository.java
│   │       │                   │   ├── BaseRepositoryFactoryBean.java
│   │       │                   │   ├── BaseRepositoryImpl.java
│   │       │                   │   ├── BookNameNotesEnableEntity.java
│   │       │                   │   ├── BookNameNotesEnableSpec.java
│   │       │                   │   ├── HasBookEntity.java
│   │       │                   │   ├── HasBookRepository.java
│   │       │                   │   ├── JpaDataConfig.java
│   │       │                   │   ├── NameNotesEnableEntity.java
│   │       │                   │   └── TestController.java
│   │       │                   ├── book/
│   │       │                   │   ├── Book.java
│   │       │                   │   ├── BookAddRequest.java
│   │       │                   │   ├── BookController.java
│   │       │                   │   ├── BookExceptionHandler.java
│   │       │                   │   ├── BookMaxCountException.java
│   │       │                   │   ├── BookRepository.java
│   │       │                   │   ├── BookService.java
│   │       │                   │   ├── BookUpdateRequest.java
│   │       │                   │   └── BookVOForList.java
│   │       │                   ├── category/
│   │       │                   │   ├── Category.java
│   │       │                   │   ├── CategoryAddRequest.java
│   │       │                   │   ├── CategoryController.java
│   │       │                   │   ├── CategoryExceptionHandler.java
│   │       │                   │   ├── CategoryHasDealException.java
│   │       │                   │   ├── CategoryIsDefaultExpenseException.java
│   │       │                   │   ├── CategoryIsDefaultIncomeException.java
│   │       │                   │   ├── CategoryLevelException.java
│   │       │                   │   ├── CategoryMaxCountException.java
│   │       │                   │   ├── CategoryNameExistsException.java
│   │       │                   │   ├── CategoryQueryRequest.java
│   │       │                   │   ├── CategoryRepository.java
│   │       │                   │   ├── CategoryService.java
│   │       │                   │   ├── CategorySimpleVO.java
│   │       │                   │   ├── CategorySpec.java
│   │       │                   │   ├── CategoryTreeVO.java
│   │       │                   │   ├── CategoryUpdateRequest.java
│   │       │                   │   ├── DefaultExpenseCategoryException.java
│   │       │                   │   ├── DefaultIncomeCategoryException.java
│   │       │                   │   └── ParentCategoryNotEnableException.java
│   │       │                   ├── category_relation/
│   │       │                   │   ├── CategoryRelation.java
│   │       │                   │   ├── CategoryRelationAddRequest.java
│   │       │                   │   ├── CategoryRelationRepository.java
│   │       │                   │   └── CategoryRelationVOForList.java
│   │       │                   ├── checking_account/
│   │       │                   │   ├── CheckingAccount.java
│   │       │                   │   ├── CheckingAccountController.java
│   │       │                   │   ├── CheckingAccountRepository.java
│   │       │                   │   └── CheckingAccountService.java
│   │       │                   ├── credit_account/
│   │       │                   │   ├── CreditAccount.java
│   │       │                   │   ├── CreditAccountAddRequest.java
│   │       │                   │   ├── CreditAccountController.java
│   │       │                   │   ├── CreditAccountRepository.java
│   │       │                   │   ├── CreditAccountService.java
│   │       │                   │   ├── CreditAccountSumVO.java
│   │       │                   │   └── CreditAccountVOForList.java
│   │       │                   ├── currency/
│   │       │                   │   ├── Currency.java
│   │       │                   │   ├── CurrencyController.java
│   │       │                   │   ├── CurrencyRepository.java
│   │       │                   │   └── CurrencyService.java
│   │       │                   ├── dashboard/
│   │       │                   │   ├── AssetOverviewVO.java
│   │       │                   │   ├── DashboardController.java
│   │       │                   │   └── DashboardService.java
│   │       │                   ├── deal/
│   │       │                   │   ├── CategoryConflictException.java
│   │       │                   │   ├── Deal.java
│   │       │                   │   ├── DealAddRequest.java
│   │       │                   │   ├── DealController.java
│   │       │                   │   ├── DealExceptionHandler.java
│   │       │                   │   ├── DealQueryResultVO.java
│   │       │                   │   ├── DealRepository.java
│   │       │                   │   ├── DealService.java
│   │       │                   │   ├── DealSpec.java
│   │       │                   │   ├── DealUpdateRequest.java
│   │       │                   │   └── DealVOForList.java
│   │       │                   ├── debt_account/
│   │       │                   │   ├── DebtAccount.java
│   │       │                   │   ├── DebtAccountAddRequest.java
│   │       │                   │   ├── DebtAccountController.java
│   │       │                   │   ├── DebtAccountRepository.java
│   │       │                   │   ├── DebtAccountService.java
│   │       │                   │   ├── DebtAccountSumVO.java
│   │       │                   │   └── DebtAccountVOForList.java
│   │       │                   ├── exception/
│   │       │                   │   ├── GlobalExceptionHandler.java
│   │       │                   │   ├── InputNotValidException.java
│   │       │                   │   ├── ItemNotFoundException.java
│   │       │                   │   ├── NameExistsException.java
│   │       │                   │   ├── PermissionException.java
│   │       │                   │   ├── TokenEmptyException.java
│   │       │                   │   └── TokenNotValidException.java
│   │       │                   ├── expense/
│   │       │                   │   ├── Expense.java
│   │       │                   │   ├── ExpenseController.java
│   │       │                   │   ├── ExpenseRepository.java
│   │       │                   │   └── ExpenseService.java
│   │       │                   ├── expense_category/
│   │       │                   │   ├── ExpenseCategory.java
│   │       │                   │   └── ExpenseCategoryController.java
│   │       │                   ├── flow_images/
│   │       │                   │   ├── FlowImage.java
│   │       │                   │   ├── FlowImageController.java
│   │       │                   │   ├── FlowImageExceptionHandler.java
│   │       │                   │   ├── FlowImageRepository.java
│   │       │                   │   ├── FlowImageService.java
│   │       │                   │   ├── FlowImageVOForList.java
│   │       │                   │   ├── ImageExistsException.java
│   │       │                   │   ├── UploadCallbackRequest.java
│   │       │                   │   └── UploadKeyEmptyException.java
│   │       │                   ├── group/
│   │       │                   │   ├── Group.java
│   │       │                   │   ├── GroupAddRequest.java
│   │       │                   │   ├── GroupController.java
│   │       │                   │   ├── GroupExceptionHandler.java
│   │       │                   │   ├── GroupHasBookException.java
│   │       │                   │   ├── GroupMaxCountException.java
│   │       │                   │   ├── GroupRepository.java
│   │       │                   │   ├── GroupService.java
│   │       │                   │   ├── GroupUpdateRequest.java
│   │       │                   │   └── GroupVOForList.java
│   │       │                   ├── income/
│   │       │                   │   ├── Income.java
│   │       │                   │   ├── IncomeController.java
│   │       │                   │   ├── IncomeRepository.java
│   │       │                   │   └── IncomeService.java
│   │       │                   ├── income_category/
│   │       │                   │   ├── IncomeCategory.java
│   │       │                   │   └── IncomeCategoryController.java
│   │       │                   ├── interceptor/
│   │       │                   │   ├── AuthInterceptor.java
│   │       │                   │   ├── MvcInterceptorConfig.java
│   │       │                   │   └── StringTrimModule.java
│   │       │                   ├── item/
│   │       │                   │   ├── Item.java
│   │       │                   │   ├── ItemAddRequest.java
│   │       │                   │   ├── ItemController.java
│   │       │                   │   ├── ItemCountException.java
│   │       │                   │   ├── ItemExceptionHandler.java
│   │       │                   │   ├── ItemQueryRequest.java
│   │       │                   │   ├── ItemRepository.java
│   │       │                   │   ├── ItemService.java
│   │       │                   │   ├── ItemSpec.java
│   │       │                   │   ├── ItemUpdateRequest.java
│   │       │                   │   └── ItemVOForList.java
│   │       │                   ├── payee/
│   │       │                   │   ├── Payee.java
│   │       │                   │   ├── PayeeAddRequest.java
│   │       │                   │   ├── PayeeController.java
│   │       │                   │   ├── PayeeExceptionHandler.java
│   │       │                   │   ├── PayeeHasDealException.java
│   │       │                   │   ├── PayeeMaxCountException.java
│   │       │                   │   ├── PayeeQueryRequest.java
│   │       │                   │   ├── PayeeRepository.java
│   │       │                   │   ├── PayeeService.java
│   │       │                   │   ├── PayeeSpec.java
│   │       │                   │   ├── PayeeUpdateRequest.java
│   │       │                   │   └── PayeeVOForList.java
│   │       │                   ├── permission/
│   │       │                   │   ├── PermissionCheck.java
│   │       │                   │   └── PermissionCheckAspect.java
│   │       │                   ├── refund/
│   │       │                   │   ├── Refund.java
│   │       │                   │   ├── RefundRepository.java
│   │       │                   │   └── RefundService.java
│   │       │                   ├── reports/
│   │       │                   │   ├── BreakOutOfMaxException.java
│   │       │                   │   ├── ChartVO.java
│   │       │                   │   ├── ChartVO2.java
│   │       │                   │   ├── ExpenseIncomeTrendQueryRequest.java
│   │       │                   │   ├── ReportController.java
│   │       │                   │   ├── ReportService.java
│   │       │                   │   ├── ReportsExceptionHandler.java
│   │       │                   │   └── TrendTimeQueryRequest.java
│   │       │                   ├── response/
│   │       │                   │   ├── BaseResponse.java
│   │       │                   │   ├── DataResponse.java
│   │       │                   │   ├── ErrorResponse.java
│   │       │                   │   └── HasNameVO.java
│   │       │                   ├── scheduled/
│   │       │                   │   ├── Scheduled.java
│   │       │                   │   ├── ScheduledAddRequest.java
│   │       │                   │   ├── ScheduledController.java
│   │       │                   │   ├── ScheduledExpenseAddRequest.java
│   │       │                   │   ├── ScheduledRepository.java
│   │       │                   │   └── ScheduledService.java
│   │       │                   ├── setting/
│   │       │                   │   └── Setting.java
│   │       │                   ├── tag/
│   │       │                   │   ├── Tag.java
│   │       │                   │   ├── TagAddRequest.java
│   │       │                   │   ├── TagController.java
│   │       │                   │   ├── TagExceptionHandler.java
│   │       │                   │   ├── TagHasTransactionException.java
│   │       │                   │   ├── TagMaxCountException.java
│   │       │                   │   ├── TagQueryRequest.java
│   │       │                   │   ├── TagRepository.java
│   │       │                   │   ├── TagService.java
│   │       │                   │   ├── TagSpec.java
│   │       │                   │   ├── TagTreeVO.java
│   │       │                   │   ├── TagUpdateRequest.java
│   │       │                   │   └── TagVOForList.java
│   │       │                   ├── tag_relation/
│   │       │                   │   ├── TagRelation.java
│   │       │                   │   ├── TagRelationController.java
│   │       │                   │   ├── TagRelationRepository.java
│   │       │                   │   ├── TagRelationService.java
│   │       │                   │   ├── TagRelationUpdateRequest.java
│   │       │                   │   └── TagRelationVOForList.java
│   │       │                   ├── transaction/
│   │       │                   │   ├── Transaction.java
│   │       │                   │   ├── TransactionAddRequest.java
│   │       │                   │   ├── TransactionRepository.java
│   │       │                   │   ├── TransactionSpec.java
│   │       │                   │   ├── TransactionUpdateRequest.java
│   │       │                   │   └── TransactionVOForList.java
│   │       │                   ├── transfer/
│   │       │                   │   ├── Transfer.java
│   │       │                   │   ├── TransferAddRequest.java
│   │       │                   │   ├── TransferController.java
│   │       │                   │   ├── TransferExceptionHandler.java
│   │       │                   │   ├── TransferFromEqualsToException.java
│   │       │                   │   ├── TransferQueryResultVO.java
│   │       │                   │   ├── TransferRepository.java
│   │       │                   │   ├── TransferService.java
│   │       │                   │   ├── TransferSpec.java
│   │       │                   │   ├── TransferUpdateRequest.java
│   │       │                   │   └── TransferVOForList.java
│   │       │                   ├── user/
│   │       │                   │   ├── InviteCodeErrorException.java
│   │       │                   │   ├── IpNotAllowedException.java
│   │       │                   │   ├── OldPasswordErrorException.java
│   │       │                   │   ├── RegisterNameExistsException.java
│   │       │                   │   ├── SessionUserNotFoundException.java
│   │       │                   │   ├── SessionVO.java
│   │       │                   │   ├── SigninFailedException.java
│   │       │                   │   ├── UploadNotImageException.java
│   │       │                   │   ├── User.java
│   │       │                   │   ├── UserController.java
│   │       │                   │   ├── UserDisabledException.java
│   │       │                   │   ├── UserExceptionHandler.java
│   │       │                   │   ├── UserGroupRelation.java
│   │       │                   │   ├── UserGroupRelationRepository.java
│   │       │                   │   ├── UserRegisterRequest.java
│   │       │                   │   ├── UserRepository.java
│   │       │                   │   ├── UserService.java
│   │       │                   │   ├── UserSessionVO.java
│   │       │                   │   ├── UserSignInRequest.java
│   │       │                   │   ├── UserSignInResponse.java
│   │       │                   │   └── UserUpdatePasswordRequest.java
│   │       │                   ├── user_log/
│   │       │                   │   ├── FlowMaxCountException.java
│   │       │                   │   ├── UserActionExceptionHandler.java
│   │       │                   │   ├── UserActionLog.java
│   │       │                   │   ├── UserActionLogRepository.java
│   │       │                   │   └── UserActionLogService.java
│   │       │                   ├── utils/
│   │       │                   │   ├── CalendarUtils.java
│   │       │                   │   ├── CommonUtils.java
│   │       │                   │   └── EnumUtils.java
│   │       │                   └── validation/
│   │       │                       ├── AmountAccumulateValidator.java
│   │       │                       ├── AmountValidator.java
│   │       │                       ├── AprValidator.java
│   │       │                       ├── AvatarValidator.java
│   │       │                       ├── BalanceValidator.java
│   │       │                       ├── BillDayValidator.java
│   │       │                       ├── CreditLimitValidator.java
│   │       │                       ├── DescriptionValidator.java
│   │       │                       ├── NameValidator.java
│   │       │                       ├── NoValidator.java
│   │       │                       ├── NotesValidator.java
│   │       │                       ├── PasswordValidator.java
│   │       │                       ├── TimeValidator.java
│   │       │                       ├── TransactionStatusValidator.java
│   │       │                       └── UserNameValidator.java
│   │       └── resources/
│   │           ├── application.properties
│   │           └── i18n/
│   │               └── messages.properties
│   ├── start.sh
│   ├── startup.sh
│   └── stop.sh
├── bookkeeping-user-fe/
│   ├── .editorconfig
│   ├── .eslintrc
│   ├── .prettierignore
│   ├── .prettierrc
│   ├── .umirc.js
│   ├── Dockerfile
│   ├── docker/
│   │   ├── gzip.conf
│   │   ├── nginx.conf
│   │   └── nginx.conf.template
│   ├── mock/
│   │   └── .gitkeep
│   ├── package.json
│   ├── src/
│   │   ├── app.js
│   │   ├── components/
│   │   │   ├── AccountRecordTable/
│   │   │   │   └── index.jsx
│   │   │   ├── AdjustBalanceModal/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── AlertTotalSearch/
│   │   │   │   └── index.jsx
│   │   │   ├── AmountInput/
│   │   │   │   └── index.jsx
│   │   │   ├── AmountInputPositive/
│   │   │   │   └── index.jsx
│   │   │   ├── AvatarDropdown/
│   │   │   │   ├── UpdatePasswordModal.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── Breadcrumb/
│   │   │   │   └── index.jsx
│   │   │   ├── ExpenseModal/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── FlagTag/
│   │   │   │   └── index.jsx
│   │   │   ├── FlowButtons/
│   │   │   │   └── index.jsx
│   │   │   ├── FlowImageUploadModal/
│   │   │   │   └── index.jsx
│   │   │   ├── FlowRecordTable/
│   │   │   │   └── index.jsx
│   │   │   ├── FlowStatusDisplay/
│   │   │   │   └── index.jsx
│   │   │   ├── FlowTagDisplay/
│   │   │   │   ├── TagModal.jsx
│   │   │   │   └── index.jsx
│   │   │   ├── Footer/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── FormItemAccount/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemAccounts/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemAmountRange/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemCategories/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemCategoryReport/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemCreateTime/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemDateRange/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemDateRangeWithBreak/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemDescription/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemDescriptionSearch/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemPayee/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemPayees/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemStatus/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemTag/
│   │   │   │   ├── AddTagModal.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── FormItemTagReport/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemTags/
│   │   │   │   └── index.jsx
│   │   │   ├── FormListCategory/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── FormModal/
│   │   │   │   └── index.jsx
│   │   │   ├── HeaderDropdown/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── IncomeModal/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── Loading/
│   │   │   │   └── index.jsx
│   │   │   ├── ModalRoot/
│   │   │   │   └── index.jsx
│   │   │   ├── PrimaryMenu/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── TransferModal/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   └── charts/
│   │   │       ├── Bar/
│   │   │       │   ├── index.jsx
│   │   │       │   └── index.less
│   │   │       ├── Line/
│   │   │       │   ├── index.jsx
│   │   │       │   └── index.less
│   │   │       ├── Pie/
│   │   │       │   ├── index.jsx
│   │   │       │   └── index.less
│   │   │       └── Pie2/
│   │   │           ├── index.jsx
│   │   │           └── index.less
│   │   ├── global.less
│   │   ├── layouts/
│   │   │   ├── BasicLayout.jsx
│   │   │   ├── BasicLayout.less
│   │   │   ├── UserLayout.jsx
│   │   │   ├── UserLayout.less
│   │   │   └── index.js
│   │   ├── locales/
│   │   │   ├── en-US/
│   │   │   │   ├── account.js
│   │   │   │   ├── book.js
│   │   │   │   ├── category.js
│   │   │   │   ├── common.js
│   │   │   │   ├── dashboard.js
│   │   │   │   ├── flow.js
│   │   │   │   ├── footer.js
│   │   │   │   ├── group.js
│   │   │   │   ├── header.js
│   │   │   │   ├── menu.js
│   │   │   │   ├── register.js
│   │   │   │   ├── report.js
│   │   │   │   ├── rules.js
│   │   │   │   ├── schedule.js
│   │   │   │   └── signin.js
│   │   │   ├── en-US.js
│   │   │   ├── zh-CN/
│   │   │   │   ├── account.js
│   │   │   │   ├── book.js
│   │   │   │   ├── category.js
│   │   │   │   ├── common.js
│   │   │   │   ├── flow.js
│   │   │   │   ├── footer.js
│   │   │   │   ├── group.js
│   │   │   │   ├── menu.js
│   │   │   │   ├── report.js
│   │   │   │   ├── rules.js
│   │   │   │   ├── schedule.js
│   │   │   │   └── user.js
│   │   │   └── zh-CN.js
│   │   ├── models/
│   │   │   ├── account.js
│   │   │   ├── currency.js
│   │   │   ├── expenseCategory.js
│   │   │   ├── flow.js
│   │   │   ├── incomeCategory.js
│   │   │   ├── modal.js
│   │   │   ├── payee.js
│   │   │   ├── session.js
│   │   │   └── tag.js
│   │   ├── pages/
│   │   │   ├── accounts/
│   │   │   │   ├── AssetAccountModal.jsx
│   │   │   │   ├── AssetAccountTable.jsx
│   │   │   │   ├── CheckingAccountModal.jsx
│   │   │   │   ├── CheckingAccountTable.jsx
│   │   │   │   ├── CreditAccountModal.jsx
│   │   │   │   ├── CreditAccountTable.jsx
│   │   │   │   ├── DebtAccountModal.jsx
│   │   │   │   ├── DebtAccountTable.jsx
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── model.js
│   │   │   ├── asset-accounts/
│   │   │   │   ├── GeneralBar.jsx
│   │   │   │   ├── ItemCard.jsx
│   │   │   │   ├── List.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── audit/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── TotalAlert.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── model.js
│   │   │   ├── balance-logs/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── OperationModal.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── books/
│   │   │   │   ├── ConfigModal.jsx
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── OperationModal.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── categories/
│   │   │   │   ├── ExpenseCategoryFilterBar.jsx
│   │   │   │   ├── ExpenseCategoryModal.jsx
│   │   │   │   ├── ExpenseCategoryTable.jsx
│   │   │   │   ├── IncomeCategoryFilterBar.jsx
│   │   │   │   ├── IncomeCategoryModal.jsx
│   │   │   │   ├── IncomeCategoryTable.jsx
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── PayeeFilterBar.jsx
│   │   │   │   ├── PayeeModal.jsx
│   │   │   │   ├── PayeeTable.jsx
│   │   │   │   ├── TagFilterBar.jsx
│   │   │   │   ├── TagModal.jsx
│   │   │   │   ├── TagTable.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── checking-accounts/
│   │   │   │   ├── GeneralBar.jsx
│   │   │   │   ├── ItemCard.jsx
│   │   │   │   ├── List.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── credit-accounts/
│   │   │   │   ├── GeneralBar.jsx
│   │   │   │   ├── ItemCard.jsx
│   │   │   │   ├── List.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── dashboard/
│   │   │   │   ├── AssetBar.jsx
│   │   │   │   ├── CardExtra.jsx
│   │   │   │   ├── ExpenseCategory.jsx
│   │   │   │   ├── ExpenseTrend.jsx
│   │   │   │   ├── IncomeCategory.jsx
│   │   │   │   ├── IncomeTrend.jsx
│   │   │   │   ├── TransactionTable.jsx
│   │   │   │   ├── TransactionTable.less
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── debt-accounts/
│   │   │   │   ├── GeneralBar.jsx
│   │   │   │   ├── ItemCard.jsx
│   │   │   │   ├── List.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── document.ejs
│   │   │   ├── expenses/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── TotalAlert.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── model.js
│   │   │   ├── flows/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── TotalAlert.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── model.js
│   │   │   ├── groups/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── OperationModal.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── incomes/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── TotalAlert.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── model.js
│   │   │   ├── index.jsx
│   │   │   ├── items/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── OperationModal.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── register/
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── reports/
│   │   │   │   ├── asset-debt-trend/
│   │   │   │   │   ├── Chart.jsx
│   │   │   │   │   ├── OperationBar.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   ├── balance-sheet/
│   │   │   │   │   ├── AssetCategory.jsx
│   │   │   │   │   ├── DebtCategory.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   ├── expense-category/
│   │   │   │   │   ├── CategoryPie.jsx
│   │   │   │   │   ├── OperationBar.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   ├── expense-income-trend/
│   │   │   │   │   ├── Chart.jsx
│   │   │   │   │   ├── OperationBar.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   ├── expense-tag/
│   │   │   │   │   ├── OperationBar.jsx
│   │   │   │   │   ├── TagPie.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   ├── income-category/
│   │   │   │   │   ├── CategoryPie.jsx
│   │   │   │   │   ├── OperationBar.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   └── income-tag/
│   │   │   │       ├── OperationBar.jsx
│   │   │   │       ├── TagPie.jsx
│   │   │   │       ├── index.jsx
│   │   │   │       └── model.js
│   │   │   ├── scheduled/
│   │   │   │   └── index.jsx
│   │   │   ├── settings/
│   │   │   │   └── index.jsx
│   │   │   ├── signin/
│   │   │   │   ├── RememberDropDown.js
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── test/
│   │   │   │   └── index.jsx
│   │   │   └── transfers/
│   │   │       ├── OperationBar.jsx
│   │   │       ├── RecordTable.jsx
│   │   │       ├── TotalAlert.jsx
│   │   │       ├── index.jsx
│   │   │       └── model.js
│   │   ├── services/
│   │   │   ├── account.js
│   │   │   ├── adjust-balance.js
│   │   │   ├── asset-account.js
│   │   │   ├── book.js
│   │   │   ├── category.js
│   │   │   ├── checking-account.js
│   │   │   ├── credit-account.js
│   │   │   ├── currency.js
│   │   │   ├── dashboard.js
│   │   │   ├── deal.js
│   │   │   ├── debt-account.js
│   │   │   ├── expense-category.js
│   │   │   ├── expense.js
│   │   │   ├── flow-image.js
│   │   │   ├── flow.js
│   │   │   ├── group.js
│   │   │   ├── income-category.js
│   │   │   ├── income.js
│   │   │   ├── item.js
│   │   │   ├── log.js
│   │   │   ├── payee.js
│   │   │   ├── report.js
│   │   │   ├── schedule.js
│   │   │   ├── tag-relation.js
│   │   │   ├── tag.js
│   │   │   ├── transfer.js
│   │   │   └── user.js
│   │   └── utils/
│   │       ├── columns.js
│   │       ├── flow.js
│   │       ├── hooks.js
│   │       ├── model.js
│   │       ├── request.js
│   │       ├── rules.js
│   │       ├── translate.js
│   │       ├── util.js
│   │       └── var.js
│   └── webpack.config.js
├── bookkeeping_user_flutter/
│   ├── .gitignore
│   ├── .metadata
│   ├── README.md
│   ├── analysis_options.yaml
│   ├── android/
│   │   ├── .gitignore
│   │   ├── app/
│   │   │   ├── build.gradle
│   │   │   └── src/
│   │   │       ├── debug/
│   │   │       │   └── AndroidManifest.xml
│   │   │       ├── main/
│   │   │       │   ├── AndroidManifest.xml
│   │   │       │   ├── kotlin/
│   │   │       │   │   └── com/
│   │   │       │   │       └── whlcsj/
│   │   │       │   │           └── bookkeeping_user_flutter/
│   │   │       │   │               └── MainActivity.kt
│   │   │       │   └── res/
│   │   │       │       ├── drawable/
│   │   │       │       │   └── launch_background.xml
│   │   │       │       ├── drawable-v21/
│   │   │       │       │   └── launch_background.xml
│   │   │       │       ├── values/
│   │   │       │       │   └── styles.xml
│   │   │       │       └── values-night/
│   │   │       │           └── styles.xml
│   │   │       └── profile/
│   │   │           └── AndroidManifest.xml
│   │   ├── build.gradle
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       └── gradle-wrapper.properties
│   │   ├── gradle.properties
│   │   └── settings.gradle
│   ├── ios/
│   │   ├── .gitignore
│   │   ├── Flutter/
│   │   │   ├── AppFrameworkInfo.plist
│   │   │   ├── Debug.xcconfig
│   │   │   └── Release.xcconfig
│   │   ├── Podfile
│   │   ├── Runner/
│   │   │   ├── AppDelegate.swift
│   │   │   ├── Assets.xcassets/
│   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── LaunchImage.imageset/
│   │   │   │       ├── Contents.json
│   │   │   │       └── README.md
│   │   │   ├── Base.lproj/
│   │   │   │   ├── LaunchScreen.storyboard
│   │   │   │   └── Main.storyboard
│   │   │   ├── Info.plist
│   │   │   └── Runner-Bridging-Header.h
│   │   ├── Runner.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   ├── project.xcworkspace/
│   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   └── xcshareddata/
│   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           └── Runner.xcscheme
│   │   └── Runner.xcworkspace/
│   │       ├── contents.xcworkspacedata
│   │       └── xcshareddata/
│   │           ├── IDEWorkspaceChecks.plist
│   │           └── WorkspaceSettings.xcsettings
│   ├── lib/
│   │   ├── accounts/
│   │   │   ├── accounts.dart
│   │   │   ├── bloc/
│   │   │   │   ├── account_adjust_balance/
│   │   │   │   │   ├── account_adjust_balance_bloc.dart
│   │   │   │   │   ├── account_adjust_balance_event.dart
│   │   │   │   │   └── account_adjust_balance_state.dart
│   │   │   │   ├── account_enable/
│   │   │   │   │   ├── account_enable_bloc.dart
│   │   │   │   │   ├── account_enable_event.dart
│   │   │   │   │   └── account_enable_state.dart
│   │   │   │   ├── account_expenseable/
│   │   │   │   │   ├── account_expenseable_bloc.dart
│   │   │   │   │   ├── account_expenseable_event.dart
│   │   │   │   │   └── account_expenseable_state.dart
│   │   │   │   ├── account_fetch/
│   │   │   │   │   ├── account_fetch_bloc.dart
│   │   │   │   │   ├── account_fetch_event.dart
│   │   │   │   │   └── account_fetch_state.dart
│   │   │   │   ├── account_form/
│   │   │   │   │   ├── account_form_bloc.dart
│   │   │   │   │   ├── account_form_event.dart
│   │   │   │   │   └── account_form_state.dart
│   │   │   │   ├── account_incomeable/
│   │   │   │   │   ├── account_incomeable_bloc.dart
│   │   │   │   │   ├── account_incomeable_event.dart
│   │   │   │   │   └── account_incomeable_state.dart
│   │   │   │   ├── account_transfer_from_able/
│   │   │   │   │   ├── account_transfer_from_able_bloc.dart
│   │   │   │   │   ├── account_transfer_from_able_event.dart
│   │   │   │   │   └── account_transfer_from_able_state.dart
│   │   │   │   ├── account_transfer_to_able/
│   │   │   │   │   ├── account_transfer_to_able_bloc.dart
│   │   │   │   │   ├── account_transfer_to_able_event.dart
│   │   │   │   │   └── account_transfer_to_able_state.dart
│   │   │   │   └── accounts/
│   │   │   │       ├── accounts_bloc.dart
│   │   │   │       ├── accounts_event.dart
│   │   │   │       └── accounts_state.dart
│   │   │   ├── data/
│   │   │   │   ├── account_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── account.dart
│   │   │   │       ├── account.g.dart
│   │   │   │       ├── account_form_request.dart
│   │   │   │       ├── account_form_request.g.dart
│   │   │   │       ├── account_query_request.dart
│   │   │   │       ├── account_query_request.g.dart
│   │   │   │       ├── adjust_balance_request.dart
│   │   │   │       ├── adjust_balance_request.g.dart
│   │   │   │       └── credit_account.dart
│   │   │   └── ui/
│   │   │       ├── account_adjust_balance.dart
│   │   │       ├── account_detail_page.dart
│   │   │       ├── account_form_page.dart
│   │   │       ├── accounts_page.dart
│   │   │       ├── asset_account_form_page.dart
│   │   │       ├── checking_account_form_page.dart
│   │   │       ├── credit_account_form_page.dart
│   │   │       ├── debt_account_form_page.dart
│   │   │       └── widgets/
│   │   │           ├── account_form/
│   │   │           │   ├── account_apr_input.dart
│   │   │           │   ├── account_balance_input.dart
│   │   │           │   ├── account_billday_input.dart
│   │   │           │   ├── account_limit_input.dart
│   │   │           │   ├── currency_input.dart
│   │   │           │   ├── expenseable_input.dart
│   │   │           │   ├── inclue_input.dart
│   │   │           │   ├── incomeable_input.dart
│   │   │           │   ├── name_input.dart
│   │   │           │   ├── no_input.dart
│   │   │           │   ├── notes_input.dart
│   │   │           │   ├── transfer_from_able_input.dart
│   │   │           │   └── transfer_to_able_input.dart
│   │   │           ├── adjust_balance/
│   │   │           │   ├── adjust_balance_form.dart
│   │   │           │   ├── balance_input.dart
│   │   │           │   ├── date_time_input.dart
│   │   │           │   ├── description_input.dart
│   │   │           │   └── notes_input.dart
│   │   │           └── order_button.dart
│   │   ├── add_flow/
│   │   │   ├── add_flow.dart
│   │   │   ├── bloc/
│   │   │   │   ├── add_expense/
│   │   │   │   │   ├── add_expense_bloc.dart
│   │   │   │   │   ├── add_expense_event.dart
│   │   │   │   │   └── add_expense_state.dart
│   │   │   │   ├── add_income/
│   │   │   │   │   ├── add_income_bloc.dart
│   │   │   │   │   ├── add_income_event.dart
│   │   │   │   │   └── add_income_state.dart
│   │   │   │   ├── add_transfer/
│   │   │   │   │   ├── add_transfer_bloc.dart
│   │   │   │   │   ├── add_transfer_event.dart
│   │   │   │   │   └── add_transfer_state.dart
│   │   │   │   └── models/
│   │   │   │       ├── deal_add_request.dart
│   │   │   │       ├── deal_add_request.g.dart
│   │   │   │       ├── transfer_add_request.dart
│   │   │   │       └── transfer_add_request.g.dart
│   │   │   └── ui/
│   │   │       ├── add_flow_page.dart
│   │   │       ├── no_tab_page.dart
│   │   │       ├── tab_page.dart
│   │   │       └── widgets/
│   │   │           ├── expense/
│   │   │           │   ├── account_input.dart
│   │   │           │   ├── add_expense_form.dart
│   │   │           │   ├── category_input.dart
│   │   │           │   ├── date_time_input.dart
│   │   │           │   ├── description_input.dart
│   │   │           │   ├── is_confirm_input.dart
│   │   │           │   ├── notes_input.dart
│   │   │           │   ├── payee_input.dart
│   │   │           │   ├── tag_input.dart
│   │   │           │   └── widgets.dart
│   │   │           ├── income/
│   │   │           │   ├── account_input.dart
│   │   │           │   ├── add_income_form.dart
│   │   │           │   ├── category_input.dart
│   │   │           │   ├── date_time_input.dart
│   │   │           │   ├── description_input.dart
│   │   │           │   ├── is_confirm_input.dart
│   │   │           │   ├── notes_input.dart
│   │   │           │   ├── payee_input.dart
│   │   │           │   ├── tag_input.dart
│   │   │           │   └── widgets.dart
│   │   │           └── transfer/
│   │   │               ├── add_transfer_form.dart
│   │   │               ├── amount_input.dart
│   │   │               ├── converted_amount_input.dart
│   │   │               ├── date_time_input.dart
│   │   │               ├── description_input.dart
│   │   │               ├── from_input.dart
│   │   │               ├── is_confirm_input.dart
│   │   │               ├── notes_input.dart
│   │   │               ├── tag_input.dart
│   │   │               ├── to_input.dart
│   │   │               └── widgets.dart
│   │   ├── app.dart
│   │   ├── books/
│   │   │   ├── bloc/
│   │   │   │   ├── book_fetch/
│   │   │   │   │   ├── book_fetch_bloc.dart
│   │   │   │   │   ├── book_fetch_event.dart
│   │   │   │   │   └── book_fetch_state.dart
│   │   │   │   └── books/
│   │   │   │       ├── books_bloc.dart
│   │   │   │       ├── books_event.dart
│   │   │   │       └── books_state.dart
│   │   │   ├── books.dart
│   │   │   ├── data/
│   │   │   │   ├── book_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── book.dart
│   │   │   │       ├── book.g.dart
│   │   │   │       ├── book_query_request.dart
│   │   │   │       └── book_query_request.g.dart
│   │   │   └── ui/
│   │   │       ├── book_detail_page.dart
│   │   │       └── books_page.dart
│   │   ├── categories/
│   │   │   ├── bloc/
│   │   │   │   ├── category_fetch/
│   │   │   │   │   ├── category_fetch_bloc.dart
│   │   │   │   │   ├── category_fetch_event.dart
│   │   │   │   │   └── category_fetch_state.dart
│   │   │   │   ├── category_form/
│   │   │   │   │   ├── category_form_bloc.dart
│   │   │   │   │   ├── category_form_event.dart
│   │   │   │   │   └── category_form_state.dart
│   │   │   │   ├── category_tree/
│   │   │   │   │   ├── category_tree_bloc.dart
│   │   │   │   │   ├── category_tree_event.dart
│   │   │   │   │   └── category_tree_state.dart
│   │   │   │   ├── expense_category_select/
│   │   │   │   │   ├── expense_category_select_bloc.dart
│   │   │   │   │   ├── expense_category_select_event.dart
│   │   │   │   │   └── expense_category_select_state.dart
│   │   │   │   └── income_category_select/
│   │   │   │       ├── income_category_select_bloc.dart
│   │   │   │       ├── income_category_select_event.dart
│   │   │   │       └── income_category_select_state.dart
│   │   │   ├── categories.dart
│   │   │   ├── data/
│   │   │   │   ├── category_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── category.dart
│   │   │   │       ├── category.g.dart
│   │   │   │       ├── category_form_request.dart
│   │   │   │       ├── category_form_request.g.dart
│   │   │   │       ├── category_tree.dart
│   │   │   │       └── category_tree.g.dart
│   │   │   └── ui/
│   │   │       ├── category_detail_page.dart
│   │   │       ├── category_form_page.dart
│   │   │       ├── expense_categories_page.dart
│   │   │       ├── expense_category_form_page.dart
│   │   │       ├── income_categories_page.dart
│   │   │       ├── income_category_form_page.dart
│   │   │       └── widgets/
│   │   │           └── category_form/
│   │   │               ├── expense_category_input.dart
│   │   │               ├── income_category_input.dart
│   │   │               ├── name_input.dart
│   │   │               └── notes_input.dart
│   │   ├── charts/
│   │   │   ├── bloc/
│   │   │   │   ├── report_asset/
│   │   │   │   │   ├── report_asset_bloc.dart
│   │   │   │   │   ├── report_asset_event.dart
│   │   │   │   │   └── report_asset_state.dart
│   │   │   │   ├── report_debt/
│   │   │   │   │   ├── report_debt_bloc.dart
│   │   │   │   │   ├── report_debt_event.dart
│   │   │   │   │   └── report_debt_state.dart
│   │   │   │   ├── report_expense_category/
│   │   │   │   │   ├── report_expense_category_bloc.dart
│   │   │   │   │   ├── report_expense_category_event.dart
│   │   │   │   │   └── report_expense_category_state.dart
│   │   │   │   └── report_income_category/
│   │   │   │       ├── report_income_category_bloc.dart
│   │   │   │       ├── report_income_category_event.dart
│   │   │   │       └── report_income_category_state.dart
│   │   │   ├── charts.dart
│   │   │   ├── data/
│   │   │   │   ├── models/
│   │   │   │   │   ├── category_query_request.dart
│   │   │   │   │   ├── category_query_request.g.dart
│   │   │   │   │   ├── x_y.dart
│   │   │   │   │   └── x_y.g.dart
│   │   │   │   └── report_repository.dart
│   │   │   └── ui/
│   │   │       ├── charts_expense_category_filter_page.dart
│   │   │       ├── charts_income_category_filter_page.dart
│   │   │       ├── charts_page.dart
│   │   │       └── widgets/
│   │   │           ├── asset_sheet.dart
│   │   │           ├── circular_legend.dart
│   │   │           ├── date_input_expense.dart
│   │   │           ├── date_input_income.dart
│   │   │           ├── debt_sheet.dart
│   │   │           ├── expense_category.dart
│   │   │           ├── expense_category_input.dart
│   │   │           ├── income_category.dart
│   │   │           └── income_category_input.dart
│   │   ├── commons/
│   │   │   ├── common_util.dart
│   │   │   ├── commons.dart
│   │   │   ├── enums.dart
│   │   │   ├── http_client.dart
│   │   │   ├── id_name_model.dart
│   │   │   ├── id_name_model.g.dart
│   │   │   ├── session.dart
│   │   │   ├── web_view_page.dart
│   │   │   └── widget_util.dart
│   │   ├── components/
│   │   │   ├── components.dart
│   │   │   ├── date_range_picker.dart
│   │   │   ├── date_time_input.dart
│   │   │   ├── empty.dart
│   │   │   ├── lazy_indexed_stack.dart
│   │   │   ├── page_error.dart
│   │   │   ├── page_loading.dart
│   │   │   └── popup_menu.dart
│   │   ├── currency/
│   │   │   ├── bloc/
│   │   │   │   └── currency_all/
│   │   │   │       ├── currency_all_bloc.dart
│   │   │   │       ├── currency_all_event.dart
│   │   │   │       └── currency_all_state.dart
│   │   │   ├── currency.dart
│   │   │   └── data/
│   │   │       ├── currency_repository.dart
│   │   │       └── models/
│   │   │           ├── currency.dart
│   │   │           └── currency.g.dart
│   │   ├── flows/
│   │   │   ├── bloc/
│   │   │   │   ├── flow_fetch/
│   │   │   │   │   ├── flow_fetch_bloc.dart
│   │   │   │   │   ├── flow_fetch_event.dart
│   │   │   │   │   └── flow_fetch_state.dart
│   │   │   │   └── flows/
│   │   │   │       ├── flows_bloc.dart
│   │   │   │       ├── flows_event.dart
│   │   │   │       └── flows_state.dart
│   │   │   ├── data/
│   │   │   │   ├── flow_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── adjust_balance.dart
│   │   │   │       ├── adjust_balance.g.dart
│   │   │   │       ├── category.dart
│   │   │   │       ├── category.g.dart
│   │   │   │       ├── deal.dart
│   │   │   │       ├── deal.g.dart
│   │   │   │       ├── flow.dart
│   │   │   │       ├── flow.g.dart
│   │   │   │       ├── flow_image.dart
│   │   │   │       ├── flow_image.g.dart
│   │   │   │       ├── flow_query_request.dart
│   │   │   │       ├── flow_query_request.g.dart
│   │   │   │       ├── tag.dart
│   │   │   │       ├── tag.g.dart
│   │   │   │       ├── transfer.dart
│   │   │   │       └── transfer.g.dart
│   │   │   ├── flows.dart
│   │   │   └── ui/
│   │   │       ├── flow_detail.dart
│   │   │       ├── flows_filter.dart
│   │   │       ├── flows_page.dart
│   │   │       └── widgets/
│   │   │           ├── account_input.dart
│   │   │           ├── date_input.dart
│   │   │           ├── expense_category_input.dart
│   │   │           ├── income_category_input.dart
│   │   │           ├── order_button.dart
│   │   │           ├── payee_input.dart
│   │   │           ├── status_input.dart
│   │   │           ├── tag_input.dart
│   │   │           ├── type_input.dart
│   │   │           └── widgets.dart
│   │   ├── groups/
│   │   │   ├── data/
│   │   │   │   └── models/
│   │   │   │       ├── group.dart
│   │   │   │       └── group.g.dart
│   │   │   └── groups.dart
│   │   ├── index.dart
│   │   ├── items/
│   │   │   ├── bloc/
│   │   │   │   ├── item_form/
│   │   │   │   │   ├── item_form_bloc.dart
│   │   │   │   │   ├── item_form_event.dart
│   │   │   │   │   ├── item_form_state.dart
│   │   │   │   │   └── models/
│   │   │   │   │       ├── models.dart
│   │   │   │   │       └── title.dart
│   │   │   │   └── items/
│   │   │   │       ├── items_bloc.dart
│   │   │   │       ├── items_event.dart
│   │   │   │       └── items_state.dart
│   │   │   ├── data/
│   │   │   │   ├── item_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── item.dart
│   │   │   │       ├── item.g.dart
│   │   │   │       ├── item_add_request.dart
│   │   │   │       ├── item_add_request.g.dart
│   │   │   │       ├── item_query_request.dart
│   │   │   │       └── item_query_request.g.dart
│   │   │   ├── items.dart
│   │   │   └── ui/
│   │   │       ├── item_form/
│   │   │       │   ├── date_input.dart
│   │   │       │   └── title_input.dart
│   │   │       ├── item_form_page.dart
│   │   │       ├── items_index.dart
│   │   │       └── items_page.dart
│   │   ├── login/
│   │   │   ├── bloc/
│   │   │   │   ├── auth/
│   │   │   │   │   ├── auth_bloc.dart
│   │   │   │   │   ├── auth_event.dart
│   │   │   │   │   └── auth_state.dart
│   │   │   │   └── login/
│   │   │   │       ├── login_bloc.dart
│   │   │   │       ├── login_event.dart
│   │   │   │       ├── login_state.dart
│   │   │   │       └── models/
│   │   │   │           ├── ApiUrl.dart
│   │   │   │           ├── password.dart
│   │   │   │           └── username.dart
│   │   │   ├── data/
│   │   │   │   ├── login_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── session.dart
│   │   │   │       ├── session.g.dart
│   │   │   │       ├── user.dart
│   │   │   │       └── user.g.dart
│   │   │   ├── login.dart
│   │   │   └── ui/
│   │   │       ├── login_page.dart
│   │   │       └── widgets/
│   │   │           ├── api_url_input.dart
│   │   │           ├── login_form.dart
│   │   │           ├── password_input.dart
│   │   │           ├── submit_btn.dart
│   │   │           └── user_name_input.dart
│   │   ├── main.dart
│   │   ├── my/
│   │   │   ├── my.dart
│   │   │   └── my_page.dart
│   │   ├── observer.dart
│   │   ├── payees/
│   │   │   ├── bloc/
│   │   │   │   ├── payee_enable/
│   │   │   │   │   ├── payee_enable_bloc.dart
│   │   │   │   │   ├── payee_enable_event.dart
│   │   │   │   │   └── payee_enable_state.dart
│   │   │   │   ├── payee_expenseable/
│   │   │   │   │   ├── payee_expenseable_bloc.dart
│   │   │   │   │   ├── payee_expenseable_event.dart
│   │   │   │   │   └── payee_expenseable_state.dart
│   │   │   │   ├── payee_fetch/
│   │   │   │   │   ├── payee_fetch_bloc.dart
│   │   │   │   │   ├── payee_fetch_event.dart
│   │   │   │   │   └── payee_fetch_state.dart
│   │   │   │   ├── payee_form/
│   │   │   │   │   ├── payee_form_bloc.dart
│   │   │   │   │   ├── payee_form_event.dart
│   │   │   │   │   └── payee_form_state.dart
│   │   │   │   ├── payee_incomeable/
│   │   │   │   │   ├── payee_incomeable_bloc.dart
│   │   │   │   │   ├── payee_incomeable_event.dart
│   │   │   │   │   └── payee_incomeable_state.dart
│   │   │   │   └── payees/
│   │   │   │       ├── payees_bloc.dart
│   │   │   │       ├── payees_event.dart
│   │   │   │       └── payees_state.dart
│   │   │   ├── data/
│   │   │   │   ├── models/
│   │   │   │   │   ├── payee.dart
│   │   │   │   │   ├── payee.g.dart
│   │   │   │   │   ├── payee_form_request.dart
│   │   │   │   │   ├── payee_form_request.g.dart
│   │   │   │   │   ├── payee_query_request.dart
│   │   │   │   │   └── payee_query_request.g.dart
│   │   │   │   └── payee_repository.dart
│   │   │   ├── payees.dart
│   │   │   └── ui/
│   │   │       ├── payee_detail_page.dart
│   │   │       ├── payee_form/
│   │   │       │   ├── expenseable_input.dart
│   │   │       │   ├── incomeable_input.dart
│   │   │       │   ├── name_input.dart
│   │   │       │   └── notes_input.dart
│   │   │       ├── payee_form_page.dart
│   │   │       └── payees_page.dart
│   │   ├── routes.dart
│   │   ├── start_page.dart
│   │   ├── tags/
│   │   │   ├── bloc/
│   │   │   │   ├── tag_enable/
│   │   │   │   │   ├── tag_enable_bloc.dart
│   │   │   │   │   ├── tag_enable_event.dart
│   │   │   │   │   └── tag_enable_state.dart
│   │   │   │   ├── tag_expenseable/
│   │   │   │   │   ├── tag_expenseable_bloc.dart
│   │   │   │   │   ├── tag_expenseable_event.dart
│   │   │   │   │   └── tag_expenseable_state.dart
│   │   │   │   ├── tag_fetch/
│   │   │   │   │   ├── tag_fetch_bloc.dart
│   │   │   │   │   ├── tag_fetch_event.dart
│   │   │   │   │   └── tag_fetch_state.dart
│   │   │   │   ├── tag_form/
│   │   │   │   │   ├── tag_form_bloc.dart
│   │   │   │   │   ├── tag_form_event.dart
│   │   │   │   │   └── tag_form_state.dart
│   │   │   │   ├── tag_incomeable/
│   │   │   │   │   ├── tag_incomeable_bloc.dart
│   │   │   │   │   ├── tag_incomeable_event.dart
│   │   │   │   │   └── tag_incomeable_state.dart
│   │   │   │   ├── tag_transferable/
│   │   │   │   │   ├── tag_transferable_bloc.dart
│   │   │   │   │   ├── tag_transferable_event.dart
│   │   │   │   │   └── tag_transferable_state.dart
│   │   │   │   └── tag_tree/
│   │   │   │       ├── tag_tree_bloc.dart
│   │   │   │       ├── tag_tree_event.dart
│   │   │   │       └── tag_tree_state.dart
│   │   │   ├── data/
│   │   │   │   ├── models/
│   │   │   │   │   ├── tag.dart
│   │   │   │   │   ├── tag.g.dart
│   │   │   │   │   ├── tag_form_request.dart
│   │   │   │   │   ├── tag_form_request.g.dart
│   │   │   │   │   ├── tag_tree.dart
│   │   │   │   │   └── tag_tree.g.dart
│   │   │   │   └── tag_repository.dart
│   │   │   ├── tags.dart
│   │   │   └── ui/
│   │   │       ├── tag_detail_page.dart
│   │   │       ├── tag_form_page.dart
│   │   │       ├── tags_page.dart
│   │   │       └── widgets/
│   │   │           └── tag_form/
│   │   │               ├── expenseable_input.dart
│   │   │               ├── incomeable_input.dart
│   │   │               ├── name_input.dart
│   │   │               ├── notes_input.dart
│   │   │               ├── parent_input.dart
│   │   │               └── transferable_input.dart
│   │   └── themes.dart
│   ├── linux/
│   │   ├── .gitignore
│   │   ├── CMakeLists.txt
│   │   ├── flutter/
│   │   │   ├── CMakeLists.txt
│   │   │   ├── generated_plugin_registrant.cc
│   │   │   ├── generated_plugin_registrant.h
│   │   │   └── generated_plugins.cmake
│   │   ├── main.cc
│   │   ├── my_application.cc
│   │   └── my_application.h
│   ├── macos/
│   │   ├── .gitignore
│   │   ├── Flutter/
│   │   │   ├── Flutter-Debug.xcconfig
│   │   │   ├── Flutter-Release.xcconfig
│   │   │   └── GeneratedPluginRegistrant.swift
│   │   ├── Podfile
│   │   ├── Runner/
│   │   │   ├── AppDelegate.swift
│   │   │   ├── Assets.xcassets/
│   │   │   │   └── AppIcon.appiconset/
│   │   │   │       └── Contents.json
│   │   │   ├── Base.lproj/
│   │   │   │   └── MainMenu.xib
│   │   │   ├── Configs/
│   │   │   │   ├── AppInfo.xcconfig
│   │   │   │   ├── Debug.xcconfig
│   │   │   │   ├── Release.xcconfig
│   │   │   │   └── Warnings.xcconfig
│   │   │   ├── DebugProfile.entitlements
│   │   │   ├── Info.plist
│   │   │   ├── MainFlutterWindow.swift
│   │   │   └── Release.entitlements
│   │   ├── Runner.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   ├── project.xcworkspace/
│   │   │   │   └── xcshareddata/
│   │   │   │       └── IDEWorkspaceChecks.plist
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           └── Runner.xcscheme
│   │   └── Runner.xcworkspace/
│   │       ├── contents.xcworkspacedata
│   │       └── xcshareddata/
│   │           └── IDEWorkspaceChecks.plist
│   ├── pubspec.yaml
│   ├── test/
│   │   └── widget_test.dart
│   └── windows/
│       ├── .gitignore
│       ├── CMakeLists.txt
│       ├── flutter/
│       │   ├── CMakeLists.txt
│       │   ├── generated_plugin_registrant.cc
│       │   ├── generated_plugin_registrant.h
│       │   └── generated_plugins.cmake
│       └── runner/
│           ├── CMakeLists.txt
│           ├── Runner.rc
│           ├── flutter_window.cpp
│           ├── flutter_window.h
│           ├── main.cpp
│           ├── resource.h
│           ├── runner.exe.manifest
│           ├── utils.cpp
│           ├── utils.h
│           ├── win32_window.cpp
│           └── win32_window.h
├── bookkeeping_user_uniapp/
│   ├── App.vue
│   ├── components/
│   │   ├── accounts/
│   │   │   └── accounts.vue
│   │   ├── expense-form/
│   │   │   └── expense-form.vue
│   │   ├── flows/
│   │   │   └── flows.vue
│   │   ├── income-form/
│   │   │   └── income-form.vue
│   │   ├── tab-bar/
│   │   │   └── tab-bar.vue
│   │   └── transfer-form/
│   │       └── transfer-form.vue
│   ├── config/
│   │   ├── api.js
│   │   └── request.js
│   ├── index.html
│   ├── main.js
│   ├── manifest.json
│   ├── package.json
│   ├── pages/
│   │   ├── account-detail/
│   │   │   └── account-detail.vue
│   │   ├── accounts/
│   │   │   └── accounts.vue
│   │   ├── books/
│   │   │   └── books.vue
│   │   ├── charts/
│   │   │   └── charts.vue
│   │   ├── flow-detail/
│   │   │   └── flow-detail.vue
│   │   ├── flow-form/
│   │   │   └── flow-form.vue
│   │   ├── flows/
│   │   │   └── flows.vue
│   │   ├── index/
│   │   │   └── index.vue
│   │   ├── login/
│   │   │   └── login.vue
│   │   ├── my/
│   │   │   └── my.vue
│   │   ├── select/
│   │   │   └── select.vue
│   │   └── test/
│   │       └── test.vue
│   ├── pages.json
│   ├── store/
│   │   ├── index.js
│   │   └── modules/
│   │       ├── account.js
│   │       ├── expenseCategory.js
│   │       ├── incomeCategory.js
│   │       ├── modelForm.js
│   │       ├── payee.js
│   │       ├── select.js
│   │       ├── session.js
│   │       └── tag.js
│   ├── uni.scss
│   └── uni_modules/
│       ├── qiun-data-charts/
│       │   ├── changelog.md
│       │   ├── components/
│       │   │   ├── qiun-data-charts/
│       │   │   │   └── qiun-data-charts.vue
│       │   │   ├── qiun-error/
│       │   │   │   └── qiun-error.vue
│       │   │   └── qiun-loading/
│       │   │       ├── loading1.vue
│       │   │       ├── loading2.vue
│       │   │       ├── loading3.vue
│       │   │       ├── loading4.vue
│       │   │       ├── loading5.vue
│       │   │       └── qiun-loading.vue
│       │   ├── js_sdk/
│       │   │   └── u-charts/
│       │   │       ├── config-echarts.js
│       │   │       ├── config-ucharts.js
│       │   │       ├── readme.md
│       │   │       └── u-charts.js
│       │   ├── license.md
│       │   ├── package.json
│       │   └── readme.md
│       ├── uni-datetime-picker/
│       │   ├── changelog.md
│       │   ├── components/
│       │   │   └── uni-datetime-picker/
│       │   │       ├── calendar-item.vue
│       │   │       ├── calendar.vue
│       │   │       ├── i18n/
│       │   │       │   ├── en.json
│       │   │       │   ├── index.js
│       │   │       │   ├── zh-Hans.json
│       │   │       │   └── zh-Hant.json
│       │   │       ├── keypress.js
│       │   │       ├── time-picker.vue
│       │   │       ├── uni-datetime-picker.vue
│       │   │       └── util.js
│       │   ├── package.json
│       │   └── readme.md
│       ├── uni-icons/
│       │   ├── changelog.md
│       │   ├── components/
│       │   │   └── uni-icons/
│       │   │       ├── icons.js
│       │   │       ├── uni-icons.vue
│       │   │       └── uniicons.css
│       │   ├── package.json
│       │   └── readme.md
│       ├── uni-list/
│       │   ├── changelog.md
│       │   ├── components/
│       │   │   ├── uni-list/
│       │   │   │   ├── uni-list.vue
│       │   │   │   ├── uni-refresh.vue
│       │   │   │   └── uni-refresh.wxs
│       │   │   ├── uni-list-ad/
│       │   │   │   └── uni-list-ad.vue
│       │   │   ├── uni-list-chat/
│       │   │   │   ├── uni-list-chat.scss
│       │   │   │   └── uni-list-chat.vue
│       │   │   └── uni-list-item/
│       │   │       └── uni-list-item.vue
│       │   ├── package.json
│       │   └── readme.md
│       └── uview-ui/
│           ├── LICENSE
│           ├── README.md
│           ├── changelog.md
│           ├── components/
│           │   ├── u--form/
│           │   │   └── u--form.vue
│           │   ├── u--image/
│           │   │   └── u--image.vue
│           │   ├── u--input/
│           │   │   └── u--input.vue
│           │   ├── u--text/
│           │   │   └── u--text.vue
│           │   ├── u--textarea/
│           │   │   └── u--textarea.vue
│           │   ├── u-action-sheet/
│           │   │   ├── props.js
│           │   │   └── u-action-sheet.vue
│           │   ├── u-album/
│           │   │   ├── props.js
│           │   │   └── u-album.vue
│           │   ├── u-alert/
│           │   │   ├── props.js
│           │   │   └── u-alert.vue
│           │   ├── u-avatar/
│           │   │   ├── props.js
│           │   │   └── u-avatar.vue
│           │   ├── u-avatar-group/
│           │   │   ├── props.js
│           │   │   └── u-avatar-group.vue
│           │   ├── u-back-top/
│           │   │   ├── props.js
│           │   │   └── u-back-top.vue
│           │   ├── u-badge/
│           │   │   ├── props.js
│           │   │   └── u-badge.vue
│           │   ├── u-button/
│           │   │   ├── nvue.scss
│           │   │   ├── props.js
│           │   │   ├── u-button.vue
│           │   │   └── vue.scss
│           │   ├── u-calendar/
│           │   │   ├── header.vue
│           │   │   ├── month.vue
│           │   │   ├── props.js
│           │   │   ├── u-calendar.vue
│           │   │   └── util.js
│           │   ├── u-car-keyboard/
│           │   │   ├── props.js
│           │   │   └── u-car-keyboard.vue
│           │   ├── u-cell/
│           │   │   ├── props.js
│           │   │   └── u-cell.vue
│           │   ├── u-cell-group/
│           │   │   ├── props.js
│           │   │   └── u-cell-group.vue
│           │   ├── u-checkbox/
│           │   │   ├── props.js
│           │   │   └── u-checkbox.vue
│           │   ├── u-checkbox-group/
│           │   │   ├── props.js
│           │   │   └── u-checkbox-group.vue
│           │   ├── u-circle-progress/
│           │   │   ├── props.js
│           │   │   └── u-circle-progress.vue
│           │   ├── u-code/
│           │   │   ├── props.js
│           │   │   └── u-code.vue
│           │   ├── u-code-input/
│           │   │   ├── props.js
│           │   │   └── u-code-input.vue
│           │   ├── u-col/
│           │   │   ├── props.js
│           │   │   └── u-col.vue
│           │   ├── u-collapse/
│           │   │   ├── props.js
│           │   │   └── u-collapse.vue
│           │   ├── u-collapse-item/
│           │   │   ├── props.js
│           │   │   └── u-collapse-item.vue
│           │   ├── u-column-notice/
│           │   │   ├── props.js
│           │   │   └── u-column-notice.vue
│           │   ├── u-count-down/
│           │   │   ├── props.js
│           │   │   ├── u-count-down.vue
│           │   │   └── utils.js
│           │   ├── u-count-to/
│           │   │   ├── props.js
│           │   │   └── u-count-to.vue
│           │   ├── u-datetime-picker/
│           │   │   ├── props.js
│           │   │   └── u-datetime-picker.vue
│           │   ├── u-divider/
│           │   │   ├── props.js
│           │   │   └── u-divider.vue
│           │   ├── u-dropdown/
│           │   │   ├── props.js
│           │   │   └── u-dropdown.vue
│           │   ├── u-dropdown-item/
│           │   │   ├── props.js
│           │   │   └── u-dropdown-item.vue
│           │   ├── u-empty/
│           │   │   ├── props.js
│           │   │   └── u-empty.vue
│           │   ├── u-form/
│           │   │   ├── props.js
│           │   │   └── u-form.vue
│           │   ├── u-form-item/
│           │   │   ├── props.js
│           │   │   └── u-form-item.vue
│           │   ├── u-gap/
│           │   │   ├── props.js
│           │   │   └── u-gap.vue
│           │   ├── u-grid/
│           │   │   ├── props.js
│           │   │   └── u-grid.vue
│           │   ├── u-grid-item/
│           │   │   ├── props.js
│           │   │   └── u-grid-item.vue
│           │   ├── u-icon/
│           │   │   ├── icons.js
│           │   │   ├── props.js
│           │   │   └── u-icon.vue
│           │   ├── u-image/
│           │   │   ├── props.js
│           │   │   └── u-image.vue
│           │   ├── u-index-anchor/
│           │   │   ├── props.js
│           │   │   └── u-index-anchor.vue
│           │   ├── u-index-item/
│           │   │   ├── props.js
│           │   │   └── u-index-item.vue
│           │   ├── u-index-list/
│           │   │   ├── props.js
│           │   │   └── u-index-list.vue
│           │   ├── u-input/
│           │   │   ├── props.js
│           │   │   └── u-input.vue
│           │   ├── u-keyboard/
│           │   │   ├── props.js
│           │   │   └── u-keyboard.vue
│           │   ├── u-line/
│           │   │   ├── props.js
│           │   │   └── u-line.vue
│           │   ├── u-line-progress/
│           │   │   ├── props.js
│           │   │   └── u-line-progress.vue
│           │   ├── u-link/
│           │   │   ├── props.js
│           │   │   └── u-link.vue
│           │   ├── u-list/
│           │   │   ├── props.js
│           │   │   └── u-list.vue
│           │   ├── u-list-item/
│           │   │   ├── props.js
│           │   │   └── u-list-item.vue
│           │   ├── u-loading-icon/
│           │   │   ├── props.js
│           │   │   └── u-loading-icon.vue
│           │   ├── u-loading-page/
│           │   │   ├── props.js
│           │   │   └── u-loading-page.vue
│           │   ├── u-loadmore/
│           │   │   ├── props.js
│           │   │   └── u-loadmore.vue
│           │   ├── u-modal/
│           │   │   ├── props.js
│           │   │   └── u-modal.vue
│           │   ├── u-navbar/
│           │   │   ├── props.js
│           │   │   └── u-navbar.vue
│           │   ├── u-no-network/
│           │   │   ├── props.js
│           │   │   └── u-no-network.vue
│           │   ├── u-notice-bar/
│           │   │   ├── props.js
│           │   │   └── u-notice-bar.vue
│           │   ├── u-notify/
│           │   │   ├── props.js
│           │   │   └── u-notify.vue
│           │   ├── u-number-box/
│           │   │   ├── props.js
│           │   │   └── u-number-box.vue
│           │   ├── u-number-keyboard/
│           │   │   ├── props.js
│           │   │   └── u-number-keyboard.vue
│           │   ├── u-overlay/
│           │   │   ├── props.js
│           │   │   └── u-overlay.vue
│           │   ├── u-parse/
│           │   │   ├── node/
│           │   │   │   └── node.vue
│           │   │   ├── parser.js
│           │   │   ├── props.js
│           │   │   └── u-parse.vue
│           │   ├── u-picker/
│           │   │   ├── props.js
│           │   │   └── u-picker.vue
│           │   ├── u-picker-column/
│           │   │   ├── props.js
│           │   │   └── u-picker-column.vue
│           │   ├── u-popup/
│           │   │   ├── props.js
│           │   │   └── u-popup.vue
│           │   ├── u-radio/
│           │   │   ├── props.js
│           │   │   └── u-radio.vue
│           │   ├── u-radio-group/
│           │   │   ├── props.js
│           │   │   └── u-radio-group.vue
│           │   ├── u-rate/
│           │   │   ├── props.js
│           │   │   └── u-rate.vue
│           │   ├── u-read-more/
│           │   │   ├── props.js
│           │   │   └── u-read-more.vue
│           │   ├── u-row/
│           │   │   ├── props.js
│           │   │   └── u-row.vue
│           │   ├── u-row-notice/
│           │   │   ├── props.js
│           │   │   └── u-row-notice.vue
│           │   ├── u-safe-bottom/
│           │   │   ├── props.js
│           │   │   └── u-safe-bottom.vue
│           │   ├── u-scroll-list/
│           │   │   ├── nvue.js
│           │   │   ├── other.js
│           │   │   ├── props.js
│           │   │   ├── scrollWxs.wxs
│           │   │   └── u-scroll-list.vue
│           │   ├── u-search/
│           │   │   ├── props.js
│           │   │   └── u-search.vue
│           │   ├── u-skeleton/
│           │   │   ├── props.js
│           │   │   └── u-skeleton.vue
│           │   ├── u-slider/
│           │   │   ├── mpother.js
│           │   │   ├── mpwxs.js
│           │   │   ├── mpwxs.wxs
│           │   │   ├── nvue - 副本.js
│           │   │   ├── nvue.js
│           │   │   ├── props.js
│           │   │   └── u-slider.vue
│           │   ├── u-status-bar/
│           │   │   ├── props.js
│           │   │   └── u-status-bar.vue
│           │   ├── u-steps/
│           │   │   ├── props.js
│           │   │   └── u-steps.vue
│           │   ├── u-steps-item/
│           │   │   ├── props.js
│           │   │   └── u-steps-item.vue
│           │   ├── u-sticky/
│           │   │   ├── props.js
│           │   │   └── u-sticky.vue
│           │   ├── u-subsection/
│           │   │   ├── props.js
│           │   │   └── u-subsection.vue
│           │   ├── u-swipe-action/
│           │   │   ├── props.js
│           │   │   └── u-swipe-action.vue
│           │   ├── u-swipe-action-item/
│           │   │   ├── index - backup.wxs
│           │   │   ├── index.wxs
│           │   │   ├── nvue - backup.js
│           │   │   ├── nvue.js
│           │   │   ├── props.js
│           │   │   ├── u-swipe-action-item.vue
│           │   │   └── wxs.js
│           │   ├── u-swiper/
│           │   │   ├── props.js
│           │   │   └── u-swiper.vue
│           │   ├── u-swiper-indicator/
│           │   │   ├── props.js
│           │   │   └── u-swiper-indicator.vue
│           │   ├── u-switch/
│           │   │   ├── props.js
│           │   │   └── u-switch.vue
│           │   ├── u-tabbar/
│           │   │   ├── props.js
│           │   │   └── u-tabbar.vue
│           │   ├── u-tabbar-item/
│           │   │   ├── props.js
│           │   │   └── u-tabbar-item.vue
│           │   ├── u-table/
│           │   │   ├── props.js
│           │   │   └── u-table.vue
│           │   ├── u-tabs/
│           │   │   ├── props.js
│           │   │   └── u-tabs.vue
│           │   ├── u-tabs-item/
│           │   │   ├── props.js
│           │   │   └── u-tabs-item.vue
│           │   ├── u-tag/
│           │   │   ├── props.js
│           │   │   └── u-tag.vue
│           │   ├── u-td/
│           │   │   ├── props.js
│           │   │   └── u-td.vue
│           │   ├── u-text/
│           │   │   ├── props.js
│           │   │   ├── u-text.vue
│           │   │   └── value.js
│           │   ├── u-textarea/
│           │   │   ├── props.js
│           │   │   └── u-textarea.vue
│           │   ├── u-toast/
│           │   │   └── u-toast.vue
│           │   ├── u-toolbar/
│           │   │   ├── props.js
│           │   │   └── u-toolbar.vue
│           │   ├── u-tooltip/
│           │   │   ├── props.js
│           │   │   └── u-tooltip.vue
│           │   ├── u-tr/
│           │   │   ├── props.js
│           │   │   └── u-tr.vue
│           │   ├── u-transition/
│           │   │   ├── nvue.ani-map.js
│           │   │   ├── props.js
│           │   │   ├── transition.js
│           │   │   ├── u-transition.vue
│           │   │   └── vue.ani-style.scss
│           │   ├── u-upload/
│           │   │   ├── mixin.js
│           │   │   ├── props.js
│           │   │   ├── u-upload.vue
│           │   │   └── utils.js
│           │   └── uview-ui/
│           │       └── uview-ui.vue
│           ├── index.js
│           ├── index.scss
│           ├── libs/
│           │   ├── config/
│           │   │   ├── color.js
│           │   │   ├── config.js
│           │   │   ├── props/
│           │   │   │   ├── actionSheet.js
│           │   │   │   ├── album.js
│           │   │   │   ├── alert.js
│           │   │   │   ├── avatar.js
│           │   │   │   ├── avatarGroup.js
│           │   │   │   ├── backtop.js
│           │   │   │   ├── badge.js
│           │   │   │   ├── button.js
│           │   │   │   ├── calendar.js
│           │   │   │   ├── carKeyboard.js
│           │   │   │   ├── cell.js
│           │   │   │   ├── cellGroup.js
│           │   │   │   ├── checkbox.js
│           │   │   │   ├── checkboxGroup.js
│           │   │   │   ├── circleProgress.js
│           │   │   │   ├── code.js
│           │   │   │   ├── codeInput.js
│           │   │   │   ├── col.js
│           │   │   │   ├── collapse.js
│           │   │   │   ├── collapseItem.js
│           │   │   │   ├── columnNotice.js
│           │   │   │   ├── countDown.js
│           │   │   │   ├── countTo.js
│           │   │   │   ├── datetimePicker.js
│           │   │   │   ├── divider.js
│           │   │   │   ├── empty.js
│           │   │   │   ├── form.js
│           │   │   │   ├── formItem.js
│           │   │   │   ├── gap.js
│           │   │   │   ├── grid.js
│           │   │   │   ├── gridItem.js
│           │   │   │   ├── icon.js
│           │   │   │   ├── image.js
│           │   │   │   ├── indexAnchor.js
│           │   │   │   ├── indexList.js
│           │   │   │   ├── input.js
│           │   │   │   ├── keyboard.js
│           │   │   │   ├── line.js
│           │   │   │   ├── lineProgress.js
│           │   │   │   ├── link.js
│           │   │   │   ├── list.js
│           │   │   │   ├── listItem.js
│           │   │   │   ├── loadingIcon.js
│           │   │   │   ├── loadingPage.js
│           │   │   │   ├── loadmore.js
│           │   │   │   ├── modal.js
│           │   │   │   ├── navbar.js
│           │   │   │   ├── noNetwork.js
│           │   │   │   ├── noticeBar.js
│           │   │   │   ├── notify.js
│           │   │   │   ├── numberBox.js
│           │   │   │   ├── numberKeyboard.js
│           │   │   │   ├── overlay.js
│           │   │   │   ├── parse.js
│           │   │   │   ├── picker.js
│           │   │   │   ├── popup.js
│           │   │   │   ├── radio.js
│           │   │   │   ├── radioGroup.js
│           │   │   │   ├── rate.js
│           │   │   │   ├── readMore.js
│           │   │   │   ├── row.js
│           │   │   │   ├── rowNotice.js
│           │   │   │   ├── scrollList.js
│           │   │   │   ├── search.js
│           │   │   │   ├── section.js
│           │   │   │   ├── skeleton.js
│           │   │   │   ├── slider.js
│           │   │   │   ├── statusBar.js
│           │   │   │   ├── steps.js
│           │   │   │   ├── stepsItem.js
│           │   │   │   ├── sticky.js
│           │   │   │   ├── subsection.js
│           │   │   │   ├── swipeAction.js
│           │   │   │   ├── swipeActionItem.js
│           │   │   │   ├── swiper.js
│           │   │   │   ├── swipterIndicator.js
│           │   │   │   ├── switch.js
│           │   │   │   ├── tabbar.js
│           │   │   │   ├── tabbarItem.js
│           │   │   │   ├── tabs.js
│           │   │   │   ├── tag.js
│           │   │   │   ├── text.js
│           │   │   │   ├── textarea.js
│           │   │   │   ├── toast.js
│           │   │   │   ├── toolbar.js
│           │   │   │   ├── tooltip.js
│           │   │   │   ├── transition.js
│           │   │   │   └── upload.js
│           │   │   ├── props.js
│           │   │   └── zIndex.js
│           │   ├── css/
│           │   │   ├── color.scss
│           │   │   ├── common.scss
│           │   │   ├── components.scss
│           │   │   ├── flex.scss
│           │   │   ├── h5.scss
│           │   │   ├── mixin.scss
│           │   │   ├── mp.scss
│           │   │   ├── nvue.scss
│           │   │   └── vue.scss
│           │   ├── function/
│           │   │   ├── colorGradient.js
│           │   │   ├── debounce.js
│           │   │   ├── digit.js
│           │   │   ├── index.js
│           │   │   ├── platform.js
│           │   │   ├── test.js
│           │   │   └── throttle.js
│           │   ├── luch-request/
│           │   │   ├── adapters/
│           │   │   │   └── index.js
│           │   │   ├── core/
│           │   │   │   ├── InterceptorManager.js
│           │   │   │   ├── Request.js
│           │   │   │   ├── buildFullPath.js
│           │   │   │   ├── defaults.js
│           │   │   │   ├── dispatchRequest.js
│           │   │   │   ├── mergeConfig.js
│           │   │   │   └── settle.js
│           │   │   ├── helpers/
│           │   │   │   ├── buildURL.js
│           │   │   │   ├── combineURLs.js
│           │   │   │   └── isAbsoluteURL.js
│           │   │   ├── index.d.ts
│           │   │   ├── index.js
│           │   │   ├── utils/
│           │   │   │   └── clone.js
│           │   │   └── utils.js
│           │   ├── mixin/
│           │   │   ├── button.js
│           │   │   ├── mixin.js
│           │   │   ├── mpMixin.js
│           │   │   ├── mpShare.js
│           │   │   ├── openType.js
│           │   │   ├── style.js
│           │   │   └── touch.js
│           │   └── util/
│           │       ├── async-validator.js
│           │       ├── calendar.js
│           │       ├── dayjs.js
│           │       ├── emitter.js
│           │       └── route.js
│           ├── package.json
│           └── theme.scss
├── docker/
│   └── mysql/
│       ├── bookkeeping.sql
│       ├── config/
│       │   └── my.cnf
│       └── currency.sql
├── docker-compose.yaml
├── docker-compose2.yaml
└── notes.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
# https://github.com/alexkaratarakis/gitattributes
# Handle line endings automatically for files detected as text
# and leave all files detected as binary untouched.
* text=auto

#
# The above will handle all files NOT found below
#
# These files are text and should be normalized (Convert crlf => lf)
*.css           text
*.df            text
*.htm           text
*.html          text
*.java          text
*.js            text
*.json          text
*.jsp           text
*.jspf          text
*.jspx          text
*.properties    text
*.sh            text
*.tld           text
*.txt           text
*.tag           text
*.tagx          text
*.xml           text
*.yml           text

# These files are binary and should be left untouched
# (binary is a macro for -text -diff)
*.class         binary
*.dll           binary
*.ear           binary
*.gif           binary
*.ico           binary
*.jar           binary
*.jpg           binary
*.jpeg          binary
*.png           binary
*.so            binary
*.war           binary

================================================
FILE: .gitignore
================================================
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
nbproject/private/
nbbuild/
dist/
nbdist/
.nb-gradle/
build/

### VS Code ###
.vscode/
.gradle/

bin/

.DS_Store
build/
.apt_generated_tests/


# dependencies
node_modules
npm-debug.log*
yarn-error.log


# umi
.umi
.umi-production

#dist
dist
.hbuilderx
unpackage

.env

================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [2022] [feiyu-rs]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

================================================
FILE: README.md
================================================
# DEPRECATED 

This is no longer supported, please consider using [https://github.com/getmoneynote/moneynote-api](https://github.com/getmoneynote/moneynote-api) instead.


================================================
FILE: bookkeeping-user-api/.mvn/wrapper/MavenWrapperDownloader.java
================================================
/*
 * Copyright 2007-present the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;

public class MavenWrapperDownloader {

    private static final String WRAPPER_VERSION = "0.5.6";
    /**
     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
     */
    private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
        + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";

    /**
     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
     * use instead of the default one.
     */
    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
            ".mvn/wrapper/maven-wrapper.properties";

    /**
     * Path where the maven-wrapper.jar will be saved to.
     */
    private static final String MAVEN_WRAPPER_JAR_PATH =
            ".mvn/wrapper/maven-wrapper.jar";

    /**
     * Name of the property which should be used to override the default download url for the wrapper.
     */
    private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";

    public static void main(String args[]) {
        System.out.println("- Downloader started");
        File baseDirectory = new File(args[0]);
        System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());

        // If the maven-wrapper.properties exists, read it and check if it contains a custom
        // wrapperUrl parameter.
        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
        String url = DEFAULT_DOWNLOAD_URL;
        if(mavenWrapperPropertyFile.exists()) {
            FileInputStream mavenWrapperPropertyFileInputStream = null;
            try {
                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
                Properties mavenWrapperProperties = new Properties();
                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
            } catch (IOException e) {
                System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
            } finally {
                try {
                    if(mavenWrapperPropertyFileInputStream != null) {
                        mavenWrapperPropertyFileInputStream.close();
                    }
                } catch (IOException e) {
                    // Ignore ...
                }
            }
        }
        System.out.println("- Downloading from: " + url);

        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
        if(!outputFile.getParentFile().exists()) {
            if(!outputFile.getParentFile().mkdirs()) {
                System.out.println(
                        "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
            }
        }
        System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
        try {
            downloadFileFromURL(url, outputFile);
            System.out.println("Done");
            System.exit(0);
        } catch (Throwable e) {
            System.out.println("- Error downloading");
            e.printStackTrace();
            System.exit(1);
        }
    }

    private static void downloadFileFromURL(String urlString, File destination) throws Exception {
        if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
            String username = System.getenv("MVNW_USERNAME");
            char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
            Authenticator.setDefault(new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
        }
        URL website = new URL(urlString);
        ReadableByteChannel rbc;
        rbc = Channels.newChannel(website.openStream());
        FileOutputStream fos = new FileOutputStream(destination);
        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
        fos.close();
        rbc.close();
    }

}


================================================
FILE: bookkeeping-user-api/.mvn/wrapper/maven-wrapper.properties
================================================
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar


================================================
FILE: bookkeeping-user-api/Dockerfile
================================================
#FROM openjdk:11-slim
#COPY target/*.jar app.jar
#ENTRYPOINT ["java","-jar","/app.jar"]

FROM openjdk:11-slim as build
WORKDIR /workspace/app
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw -B -DskipTests clean package

FROM openjdk:11-slim
VOLUME /tmp
COPY --from=build /workspace/app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

================================================
FILE: bookkeeping-user-api/mvnw
================================================
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#    https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------

# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
#   JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
#   M2_HOME - location of maven2's installed home dir
#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
#     e.g. to debug Maven itself, use
#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------

if [ -z "$MAVEN_SKIP_RC" ] ; then

  if [ -f /etc/mavenrc ] ; then
    . /etc/mavenrc
  fi

  if [ -f "$HOME/.mavenrc" ] ; then
    . "$HOME/.mavenrc"
  fi

fi

# OS specific support.  $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
  CYGWIN*) cygwin=true ;;
  MINGW*) mingw=true;;
  Darwin*) darwin=true
    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
    if [ -z "$JAVA_HOME" ]; then
      if [ -x "/usr/libexec/java_home" ]; then
        export JAVA_HOME="`/usr/libexec/java_home`"
      else
        export JAVA_HOME="/Library/Java/Home"
      fi
    fi
    ;;
esac

if [ -z "$JAVA_HOME" ] ; then
  if [ -r /etc/gentoo-release ] ; then
    JAVA_HOME=`java-config --jre-home`
  fi
fi

if [ -z "$M2_HOME" ] ; then
  ## resolve links - $0 may be a link to maven's home
  PRG="$0"

  # need this for relative symlinks
  while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
      PRG="$link"
    else
      PRG="`dirname "$PRG"`/$link"
    fi
  done

  saveddir=`pwd`

  M2_HOME=`dirname "$PRG"`/..

  # make it fully qualified
  M2_HOME=`cd "$M2_HOME" && pwd`

  cd "$saveddir"
  # echo Using m2 at $M2_HOME
fi

# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
  [ -n "$M2_HOME" ] &&
    M2_HOME=`cygpath --unix "$M2_HOME"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
  [ -n "$CLASSPATH" ] &&
    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi

# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
  [ -n "$M2_HOME" ] &&
    M2_HOME="`(cd "$M2_HOME"; pwd)`"
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi

if [ -z "$JAVA_HOME" ]; then
  javaExecutable="`which javac`"
  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
    # readlink(1) is not available as standard on Solaris 10.
    readLink=`which readlink`
    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
      if $darwin ; then
        javaHome="`dirname \"$javaExecutable\"`"
        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
      else
        javaExecutable="`readlink -f \"$javaExecutable\"`"
      fi
      javaHome="`dirname \"$javaExecutable\"`"
      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
      JAVA_HOME="$javaHome"
      export JAVA_HOME
    fi
  fi
fi

if [ -z "$JAVACMD" ] ; then
  if [ -n "$JAVA_HOME"  ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
      # IBM's JDK on AIX uses strange locations for the executables
      JAVACMD="$JAVA_HOME/jre/sh/java"
    else
      JAVACMD="$JAVA_HOME/bin/java"
    fi
  else
    JAVACMD="`which java`"
  fi
fi

if [ ! -x "$JAVACMD" ] ; then
  echo "Error: JAVA_HOME is not defined correctly." >&2
  echo "  We cannot execute $JAVACMD" >&2
  exit 1
fi

if [ -z "$JAVA_HOME" ] ; then
  echo "Warning: JAVA_HOME environment variable is not set."
fi

CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher

# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {

  if [ -z "$1" ]
  then
    echo "Path not specified to find_maven_basedir"
    return 1
  fi

  basedir="$1"
  wdir="$1"
  while [ "$wdir" != '/' ] ; do
    if [ -d "$wdir"/.mvn ] ; then
      basedir=$wdir
      break
    fi
    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
    if [ -d "${wdir}" ]; then
      wdir=`cd "$wdir/.."; pwd`
    fi
    # end of workaround
  done
  echo "${basedir}"
}

# concatenates all lines of a file
concat_lines() {
  if [ -f "$1" ]; then
    echo "$(tr -s '\n' ' ' < "$1")"
  fi
}

BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
  exit 1;
fi

##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Found .mvn/wrapper/maven-wrapper.jar"
    fi
else
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
    fi
    if [ -n "$MVNW_REPOURL" ]; then
      jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
    else
      jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
    fi
    while IFS="=" read key value; do
      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
      esac
    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Downloading from: $jarUrl"
    fi
    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
    if $cygwin; then
      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
    fi

    if command -v wget > /dev/null; then
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Found wget ... using wget"
        fi
        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
            wget "$jarUrl" -O "$wrapperJarPath"
        else
            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
        fi
    elif command -v curl > /dev/null; then
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Found curl ... using curl"
        fi
        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
            curl -o "$wrapperJarPath" "$jarUrl" -f
        else
            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
        fi

    else
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Falling back to using Java to download"
        fi
        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
        # For Cygwin, switch paths to Windows format before running javac
        if $cygwin; then
          javaClass=`cygpath --path --windows "$javaClass"`
        fi
        if [ -e "$javaClass" ]; then
            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
                if [ "$MVNW_VERBOSE" = true ]; then
                  echo " - Compiling MavenWrapperDownloader.java ..."
                fi
                # Compiling the Java class
                ("$JAVA_HOME/bin/javac" "$javaClass")
            fi
            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
                # Running the downloader
                if [ "$MVNW_VERBOSE" = true ]; then
                  echo " - Running MavenWrapperDownloader.java ..."
                fi
                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
            fi
        fi
    fi
fi
##########################################################################################
# End of extension
##########################################################################################

export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
  echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"

# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
  [ -n "$M2_HOME" ] &&
    M2_HOME=`cygpath --path --windows "$M2_HOME"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
  [ -n "$CLASSPATH" ] &&
    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi

# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS

WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain

exec "$JAVACMD" \
  $MAVEN_OPTS \
  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"


================================================
FILE: bookkeeping-user-api/mvnw.cmd
================================================
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements.  See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership.  The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License.  You may obtain a copy of the License at
@REM
@REM    https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied.  See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------

@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM     e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------

@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%

@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")

@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre

@setlocal

set ERROR_CODE=0

@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal

@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome

echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error

:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init

echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error

@REM ==== END VALIDATION ====

:init

@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.

set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir

set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir

:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir

:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"

:endDetectBaseDir

IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig

@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%

:endReadAdditionalConfig

SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain

set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"

FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)

@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
    if "%MVNW_VERBOSE%" == "true" (
        echo Found %WRAPPER_JAR%
    )
) else (
    if not "%MVNW_REPOURL%" == "" (
        SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
    )
    if "%MVNW_VERBOSE%" == "true" (
        echo Couldn't find %WRAPPER_JAR%, downloading it ...
        echo Downloading from: %DOWNLOAD_URL%
    )

    powershell -Command "&{"^
		"$webclient = new-object System.Net.WebClient;"^
		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
		"}"^
		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
		"}"
    if "%MVNW_VERBOSE%" == "true" (
        echo Finished downloading %WRAPPER_JAR%
    )
)
@REM End of extension

@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*

%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end

:error
set ERROR_CODE=1

:end
@endlocal & set ERROR_CODE=%ERROR_CODE%

if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost

@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause

if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%

exit /B %ERROR_CODE%


================================================
FILE: bookkeeping-user-api/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.0</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.jiukuaitech</groupId>
    <artifactId>bookkeeping-user</artifactId>
    <version>0.1</version>
    <name>bookkeeping-user</name>
    <description>Bookkeeping API for User</description>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.qiniu</groupId>
            <artifactId>qiniu-java-sdk</artifactId>
            <version>[7.7.0, 7.7.99]</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-jpamodelgen</artifactId>
            <version>5.5.6.Final</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <compilerArguments>
                        <processor>
                            org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor
                        </processor>
                    </compilerArguments>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

================================================
FILE: bookkeeping-user-api/restart.sh
================================================
#!/bin/bash
. stop.sh
rm -rf 1.log
. startup.sh

================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/Application.java
================================================
package com.jiukuaitech.bookkeeping.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/RegexTest.java
================================================
package com.jiukuaitech.bookkeeping.user;

public class RegexTest implements Runnable {


    private static int i;

    public synchronized static void change() {
        for (int j = 0; j < 5000000; j++) {
            i++;
        }
    }

    @Override
    public void run() {
        synchronized ("123".intern()) {
            for (int j = 0; j < 5000000; j++) {
                i++;
            }
        }
    }

    public static void main(String[] args) throws Exception {
        new Thread(new RegexTest()).start();
        new Thread(new RegexTest()).start();
        Thread.sleep(3000);
        System.out.println(i);
    }
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/Account.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import com.jiukuaitech.bookkeeping.user.base.NameNotesEnableEntity;
import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.validation.BalanceValidator;
import com.jiukuaitech.bookkeeping.user.validation.NoValidator;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;

@Entity
@Table(name = "t_account", uniqueConstraints = {@UniqueConstraint(columnNames = {"group_id", "name"})})
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.INTEGER, columnDefinition = "TINYINT(1)")
@Getter
@Setter
public class Account extends NameNotesEnableEntity {

    @Column(insertable = false, updatable = false)
    private Integer type; //1活期,2信用,3贷款,4资产

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "group_id")
    @NotNull
    private Group group; // 账簿必须属于某个组

    @Column(length = 32)
    @NoValidator
    private String no; //卡号

    @Column(nullable = false) //最多9亿
    @NotNull
    @BalanceValidator
    private BigDecimal balance; // 当前余额

    @Column(nullable = false)
    @NotNull
    private Boolean include = true; //净资产是否包含

    @Column(nullable = false)
    @NotNull
    private Boolean expenseable = true; //是否可支出

    @Column(nullable = false)
    @NotNull
    private Boolean incomeable = true; //是否可收入

    @Column(nullable = false)
    @NotNull
    private Boolean transferFromAble = true; //是否转账可转出

    @Column(nullable = false)
    @NotNull
    private Boolean transferToAble = true; //是否转账可转入

    @Column(nullable = false, length = 8)
    @NotNull
    private String currencyCode;

    @Column
    @BalanceValidator
    private BigDecimal initialBalance; // 期初余额

    public Account() { }

    public Account(Integer id) {
        super.setId(id);
    }
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountAddRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import java.math.BigDecimal;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

import com.jiukuaitech.bookkeeping.user.validation.BalanceValidator;
import com.jiukuaitech.bookkeeping.user.validation.NameValidator;
import com.jiukuaitech.bookkeeping.user.validation.NoValidator;
import com.jiukuaitech.bookkeeping.user.validation.NotesValidator;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class AccountAddRequest {

    @NotBlank(message="name must not be blank")
    @NameValidator
    private String name;

    @NoValidator
    private String no;

    @NotNull
    @BalanceValidator
    private BigDecimal balance;

    private Boolean include = true;
    private Boolean transferFromAble = true;
    private Boolean transferToAble = true;
    private Boolean expenseable = true;
    private Boolean incomeable = true;

    @NotesValidator
    private String notes;

    @NotBlank
    private String currencyCode;

    public void copyPrimitive(Account po) {
        po.setName(name);
        po.setNo(no);
        po.setBalance(balance);
        po.setInitialBalance(balance);
        po.setInclude(include);
        po.setTransferFromAble(transferFromAble);
        po.setTransferToAble(transferToAble);
        po.setExpenseable(expenseable);
        po.setIncomeable(incomeable);
        po.setNotes(notes);
        po.setCurrencyCode(currencyCode);
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountAdjustBalanceNotValidException.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

public class AccountAdjustBalanceNotValidException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountController.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import com.jiukuaitech.bookkeeping.user.adjust_balance.AdjustBalanceAddRequest;
import com.jiukuaitech.bookkeeping.user.base.BaseController;
import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.DataResponse;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;

@RestController
@RequestMapping("/accounts")
public class AccountController extends BaseController {

    @Resource
    private AccountService accountService;

    // 搜索流水的下拉框需要显示所有可用的account
    @RequestMapping(method = RequestMethod.GET, value = "/enable")
    public BaseResponse handleEnable(@RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.getEnable(userSignInId));
    }

    @RequestMapping(method = RequestMethod.GET, value = "/expenseable")
    public BaseResponse handleExpenseble(@RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.getAllExpenseable(userSignInId));
    }
    
    @RequestMapping(method = RequestMethod.GET, value = "/incomeable")
    public BaseResponse handleIncomeble(@RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.getAllIncomeable(userSignInId));
    }

    @RequestMapping(method = RequestMethod.GET, value = "/transfer-from-able")
    public BaseResponse handleTransferFromAble(@RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.getAllTransferFromAble(userSignInId));
    }

    @RequestMapping(method = RequestMethod.GET, value = "/transfer-to-able")
    public BaseResponse handleTransferToAble(@RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.getAllTransferToAble(userSignInId));
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    public BaseResponse handleGet(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.get(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.POST, value = "/{id}/adjust-balance")
    public BaseResponse handleAdjustBalance(
            @PathVariable("id") Integer id,
            @Valid @RequestBody AdjustBalanceAddRequest request,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.adjustBalance(id, request, userSignInId));
    }

    @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    public BaseResponse handleDelete(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.remove(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggle")
    public BaseResponse handleToggle(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.toggle(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggleInclude")
    public BaseResponse handleToggleInclude(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.toggleInclude(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggleExpenseable")
    public BaseResponse handleToggleExpenseable(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.toggleExpenseable(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggleIncomeable")
    public BaseResponse handleToggleIncomeable(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.toggleIncomeable(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggleTransferFromAble")
    public BaseResponse handleToggleTransferFromAble(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.toggleTransferFromAble(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggleTransferToAble")
    public BaseResponse handleToggleTransferToAble(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.toggleTransferToAble(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}")
    public BaseResponse handleUpdate(
            @PathVariable("id") Integer id,
            @Valid @RequestBody AccountUpdateRequest request,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.update(id, request, userSignInId));
    }

}

================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountExceptionHandler.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.ErrorResponse;
import org.springframework.context.MessageSource;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.annotation.Resource;
import java.util.Locale;

@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AccountExceptionHandler {

    private static final Locale LANG = Locale.CHINA;

    @Resource
    private MessageSource messageSource;

    @ExceptionHandler(value = AccountNameExistsException.class)
//    @ResponseStatus(HttpStatus.CONFLICT)
    @ResponseBody
    public BaseResponse handleException(AccountNameExistsException e) {
        return new ErrorResponse(409, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = AccountMaxCountException.class)
    @ResponseBody
    public BaseResponse handleException(AccountMaxCountException e) {
        return new ErrorResponse(501, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = AccountHasTransactionException.class)
    @ResponseBody
    public BaseResponse handleException(AccountHasTransactionException e) {
        return new ErrorResponse(601, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = AccountAdjustBalanceNotValidException.class)
    @ResponseBody
    public BaseResponse handleException(AccountAdjustBalanceNotValidException e) {
        return new ErrorResponse(602, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = DefaultExpenseAccountException.class)
    @ResponseBody
    public BaseResponse handleException(DefaultExpenseAccountException e) {
        return new ErrorResponse(603, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = DefaultIncomeAccountException.class)
    @ResponseBody
    public BaseResponse handleException(DefaultIncomeAccountException e) {
        return new ErrorResponse(604, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = DefaultTransferFromAccountException.class)
    @ResponseBody
    public BaseResponse handleException(DefaultTransferFromAccountException e) {
        return new ErrorResponse(605, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = DefaultTransferToAccountException.class)
    @ResponseBody
    public BaseResponse handleException(DefaultTransferToAccountException e) {
        return new ErrorResponse(606, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountHasTransactionException.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

public class AccountHasTransactionException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountMaxCountException.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

public class AccountMaxCountException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountNameExistsException.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

public class AccountNameExistsException extends RuntimeException {
    
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountQueryRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class AccountQueryRequest {

    private Boolean enable;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountRepository.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import com.jiukuaitech.bookkeeping.user.base.BaseRepository;
import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.user.User;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface AccountRepository extends BaseRepository<Account, Integer> {

    Optional<Account> findOneByGroupAndName(Group group, String name);

    Optional<Account> findOneByGroupAndId(Group group, Integer id);

    long countByGroup(Group group);

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountService.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import com.jiukuaitech.bookkeeping.user.adjust_balance.AdjustBalance;
import com.jiukuaitech.bookkeeping.user.adjust_balance.AdjustBalanceAddRequest;
import com.jiukuaitech.bookkeeping.user.adjust_balance.AdjustBalanceRepository;
import com.jiukuaitech.bookkeeping.user.asset_account.AssetAccount;
import com.jiukuaitech.bookkeeping.user.book.Book;
import com.jiukuaitech.bookkeeping.user.checking_account.CheckingAccount;
import com.jiukuaitech.bookkeeping.user.credit_account.CreditAccount;
import com.jiukuaitech.bookkeeping.user.debt_account.DebtAccount;
import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.user.User;
import com.jiukuaitech.bookkeeping.user.credit_account.CreditAccountAddRequest;
import com.jiukuaitech.bookkeeping.user.currency.CurrencyService;
import com.jiukuaitech.bookkeeping.user.debt_account.DebtAccountAddRequest;
import com.jiukuaitech.bookkeeping.user.exception.ItemNotFoundException;
import com.jiukuaitech.bookkeeping.user.transaction.TransactionRepository;
import com.jiukuaitech.bookkeeping.user.transfer.TransferRepository;
import com.jiukuaitech.bookkeeping.user.user.UserService;
import com.jiukuaitech.bookkeeping.user.user_log.UserActionLog;
import com.jiukuaitech.bookkeeping.user.user_log.UserActionLogRepository;
import com.jiukuaitech.bookkeeping.user.user_log.UserActionLogService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AccountService {

    @Resource
    private UserService userService;

    @Resource
    private AccountRepository accountRepository;
    
    @Resource
    private AdjustBalanceRepository adjustBalanceRepository;

    @Resource
    private TransactionRepository transactionRepository;

    @Resource
    private TransferRepository transferRepository;

    @Resource
    private UserActionLogRepository userActionLogRepository;

    @Resource
    private CurrencyService currencyService;

    @Resource
    private UserActionLogService userActionLogService;

    @Value("${account.max.count}")
    private Integer accountMaxCount;

    public List<AccountVOForExtend> getEnable(Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        List<Account> entityList = accountRepository.findAll(AccountSpec.inGroupAndEnable(group));
        return entityList.stream().map(AccountVOForExtend::fromEntity).collect(Collectors.toList());
    }

    public List<AccountVOForExtend> getAllExpenseable(Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        List<Account> entityList = accountRepository.findAll(AccountSpec.inGroupAndExpenseable(group));
        return entityList.stream().map(AccountVOForExtend::fromEntity).collect(Collectors.toList());
    }
    
    public List<AccountVOForExtend> getAllIncomeable(Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        List<Account> entityList = accountRepository.findAll(AccountSpec.inGroupAndIncomeable(group));
        return entityList.stream().map(AccountVOForExtend::fromEntity).collect(Collectors.toList());
    }

    public List<AccountVOForExtend> getAllTransferFromAble(Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        List<Account> entityList = accountRepository.findAll(AccountSpec.inGroupAndTransferFromAble(group));
        return entityList.stream().map(AccountVOForExtend::fromEntity).collect(Collectors.toList());
    }
    
    public List<AccountVOForExtend> getAllTransferToAble(Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        List<Account> entityList = accountRepository.findAll(AccountSpec.inGroupAndTransferToAble(group));
        return entityList.stream().map(AccountVOForExtend::fromEntity).collect(Collectors.toList());
    }

    public AccountVOForList get(Integer id, Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        Account po = accountRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        AccountVOForList vo = new AccountVOForList();
        vo.setValue(po);
        vo.setConvertedBalance(currencyService.convert(vo.getBalance(), vo.getCurrencyCode(), group.getDefaultCurrencyCode()));
        if (po instanceof CreditAccount) {
            CreditAccount po2 = (CreditAccount) po;
            vo.setLimit(po2.getLimit());
            vo.setBillDay(po2.getBillDay());
        }
        if (po instanceof DebtAccount) {
            DebtAccount po2 = (DebtAccount) po;
            vo.setApr(po2.getApr());
            vo.setLimit(po2.getLimit());
        }
        if (po instanceof AssetAccount) {
            AssetAccount po2 = (AssetAccount) po;
            vo.setAsOfDate(po2.getAsOfDate());
        }
        return vo;
    }

    @Transactional
    public AccountVOForExtend adjustBalance(Integer id, AdjustBalanceAddRequest request, Integer userSignInId) {
        User user = userService.getUser(userSignInId);

        Group group = user.getDefaultGroup();
        Account account = accountRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        if (account.getBalance().compareTo(request.getBalance()) == 0) {
            throw new AccountAdjustBalanceNotValidException();
        }
        BigDecimal adjustAmount = request.getBalance().subtract(account.getBalance());
        account.setBalance(request.getBalance());
        // 如果是资产账户改一下截止日期
        if (account instanceof AssetAccount) {
            AssetAccount assetAccount = (AssetAccount) account;
            assetAccount.setAsOfDate(request.getCreateTime());
        }
        accountRepository.save(account);

        AdjustBalance po = new AdjustBalance();
        request.copyPrimitive(po);
        po.setCreator(user);
        po.setBook(user.getDefaultBook());
        po.setGroup(user.getDefaultGroup());
        po.setAmount(adjustAmount);
        po.setAccount(account);
        po.setStatus(1);

        adjustBalanceRepository.save(po);
        userActionLogRepository.save(new UserActionLog(user, 1, Instant.now().toEpochMilli()));
        return AccountVOForExtend.fromEntity(po.getAccount());
    }

    // 1. 余额调整记录删除,2. 日志删除
    @Transactional
    public AccountVOForExtend remove(Integer id, Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        Account po = accountRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        // 检查关联性,有账单关联的不能删除
        if (transactionRepository.countByAccount_id(id) > 0 || transferRepository.countByTo_id(id) > 0) {
            throw new AccountHasTransactionException();
        }
        adjustBalanceRepository.deleteByAccount_Id(id);
        accountRepository.delete(po);
        return AccountVOForExtend.fromEntity(po);
    }

    public AccountVOForExtend toggle(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        Account po = accountRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        Book book = user.getDefaultBook();
        if (po.equals(book.getDefaultExpenseAccount())) throw new DefaultExpenseAccountException();
        if (po.equals(book.getDefaultIncomeAccount())) throw new DefaultIncomeAccountException();
        po.setEnable(!po.getEnable());
        accountRepository.save(po);
        return AccountVOForExtend.fromEntity(accountRepository.save(po));
    }

    public boolean toggleInclude(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        Account po = accountRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        po.setInclude(!po.getInclude());
        accountRepository.save(po);
        return true;
    }

    public boolean toggleExpenseable(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        Account po = accountRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        Book book = user.getDefaultBook();
        if (po.equals(book.getDefaultExpenseAccount())) throw new DefaultExpenseAccountException();
        po.setExpenseable(!po.getExpenseable());
        accountRepository.save(po);
        return true;
    }

    public boolean toggleIncomeable(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        Account po = accountRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        Book book = user.getDefaultBook();
        if (po.equals(book.getDefaultIncomeAccount())) throw new DefaultIncomeAccountException();
        po.setIncomeable(!po.getIncomeable());
        accountRepository.save(po);
        return true;
    }

    public boolean toggleTransferFromAble(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        Account po = accountRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        Book book = user.getDefaultBook();
        if (po.equals(book.getDefaultTransferFromAccount())) throw new DefaultTransferFromAccountException();
        po.setTransferFromAble(!po.getTransferFromAble());
        accountRepository.save(po);
        return true;
    }

    public boolean toggleTransferToAble(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        Account po = accountRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        Book book = user.getDefaultBook();
        if (po.equals(book.getDefaultTransferToAccount())) throw new DefaultTransferToAccountException();
        po.setTransferToAble(!po.getTransferToAble());
        accountRepository.save(po);
        return true;
    }

    public boolean add(Integer type, AccountAddRequest request, Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        if (accountRepository.countByGroup(group) >= accountMaxCount) {
            throw new AccountMaxCountException();
        }
        if (accountRepository.findOneByGroupAndName(group, request.getName()).isPresent()) {
            throw new AccountNameExistsException();
        }
        currencyService.checkCode(request.getCurrencyCode());
        Account po = null;
        switch (type) {
            case 1:
                po = new CheckingAccount();
                request.copyPrimitive(po);
                break;
            case 2:
                po = new CreditAccount();
                ((CreditAccountAddRequest) request).copyPrimitive((CreditAccount) po);
                break;
            case 3:
                po = new DebtAccount();
                ((DebtAccountAddRequest) request).copyPrimitive((DebtAccount) po);
                break;
            case 4:
                po = new AssetAccount();
                request.copyPrimitive(po);
                ((AssetAccount)po).setAsOfDate(Instant.now().toEpochMilli());
                break;
        }
        po.setGroup(group);
        accountRepository.save(po);
        return true;
    }

    public AccountVOForExtend update(Integer id, AccountUpdateRequest request, Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        Account po = accountRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        if (StringUtils.hasText(request.getName())) {
            if (!po.getName().equals(request.getName())) {
                if (accountRepository.findOneByGroupAndName(group, request.getName()).isPresent()) {
                    throw new AccountNameExistsException();
                }
            }
        }
        request.updatePrimitive(po);
        accountRepository.save(po);
        return AccountVOForExtend.fromEntity(po);
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountSpec.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.base.BookNameNotesEnableSpec;
import org.springframework.data.jpa.domain.Specification;

public final class AccountSpec {

    public static<T extends Account> Specification<T> includeTrue() {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(Account_.include), true);
    }

    public static<T extends Account> Specification<T> expenseable() {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(Account_.expenseable), true);
    }

    public static<T extends Account> Specification<T> incomeable() {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(Account_.incomeable), true);
    }

    public static<T extends Account> Specification<T> transferFromAble() {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(Account_.transferFromAble), true);
    }

    public static<T extends Account> Specification<T> transferToAble() {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(Account_.transferToAble), true);
    }

    public static<T extends Account> Specification<T> inGroup(Group group) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(Account_.group), group);
    }

    public static<T extends Account> Specification<T> inGroupAndEnable(Group group) {
        Specification<T> specification = inGroup(group);
        return specification.and(BookNameNotesEnableSpec.enable());
    }

    public static<T extends Account> Specification<T> inGroupAndInclude(Group group) {
        Specification<T> specification = inGroupAndEnable(group);
        return specification.and(includeTrue());
    }

    public static<T extends Account> Specification<T> inGroupAndExpenseable(Group group) {
        Specification<T> specification = inGroupAndEnable(group);
        return specification.and(expenseable());
    }

    public static<T extends Account> Specification<T> inGroupAndIncomeable(Group group) {
        Specification<T> specification = inGroupAndEnable(group);
        return specification.and(incomeable());
    }

    public static<T extends Account> Specification<T> inGroupAndTransferFromAble(Group group) {
        Specification<T> specification = inGroupAndEnable(group);
        return specification.and(transferFromAble());
    }

    public static<T extends Account> Specification<T> inGroupAndTransferToAble(Group group) {
        Specification<T> specification = inGroupAndEnable(group);
        return specification.and(transferToAble());
    }

    public static<T extends Account> Specification<T> buildSpecification(AccountQueryRequest request, Group group) {
        Specification<T> specification = inGroup(group);
        if (request.getEnable() != null) {
            specification = specification.and(BookNameNotesEnableSpec.isEnable(request.getEnable()));
        }
        return specification;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountSumVO.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import lombok.Getter;
import lombok.Setter;

import java.math.BigDecimal;

@Getter
@Setter
public class AccountSumVO {

    private BigDecimal balance;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountUpdateRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import java.math.BigDecimal;

import com.jiukuaitech.bookkeeping.user.credit_account.CreditAccount;
import com.jiukuaitech.bookkeeping.user.debt_account.DebtAccount;
import com.jiukuaitech.bookkeeping.user.validation.*;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class AccountUpdateRequest {

    @NameValidator
    private String name;
    @NoValidator
    private String no;
    private Boolean include;
    private Boolean transferFromAble;
    private Boolean transferToAble;
    private Boolean expenseable;
    private Boolean incomeable;
    @NotesValidator
    private String notes;

    // For Credit
    @CreditLimitValidator
    private BigDecimal limit; // 信用额度
    @BillDayValidator
    private Integer billDay; // 每月多少号是账单日

    @AprValidator
    private BigDecimal apr;

    public void updatePrimitive(Account po) {
        if (name != null) po.setName(name);
        if (no != null) po.setNo(no);
        if (include != null) po.setInclude(include);
        if (transferFromAble != null) po.setTransferFromAble(transferFromAble);
        if (transferToAble != null) po.setTransferToAble(transferToAble);
        if (expenseable != null) po.setExpenseable(expenseable);
        if (incomeable != null) po.setIncomeable(incomeable);
        if (notes != null) po.setNotes(notes);
        if (po instanceof CreditAccount) {
            if (limit != null) ((CreditAccount)po).setLimit(limit);
            if (billDay != null) ((CreditAccount)po).setBillDay(billDay);
        } else if (po instanceof DebtAccount) {
            if (limit != null) ((DebtAccount)po).setLimit(limit);
            if (apr != null) ((DebtAccount)po).setApr(apr);
        }
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountVOForExtend.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import com.jiukuaitech.bookkeeping.user.utils.EnumUtils;
import lombok.Getter;
import lombok.Setter;

import java.math.BigDecimal;

@Getter
@Setter
public class AccountVOForExtend {

    private Integer type; //1活期,2信用,3贷款,4资产
    private Integer id;
    private String name;
    private String no;
    private BigDecimal balance;
    private BigDecimal convertedBalance;
    private String currencyCode;
    private Boolean enable;
    private Boolean include;
    private Boolean expenseable;
    private Boolean incomeable;
    private Boolean transferFromAble;
    private Boolean transferToAble;
    private BigDecimal initialBalance;
    private String notes;

    public void setValue(Account po) {
        setType(po.getType());
        setId(po.getId());
        setName(po.getName());
        setNo(po.getNo());
        setBalance(po.getBalance());
        setEnable(po.getEnable());
        setInclude(po.getInclude());
        setExpenseable(po.getExpenseable());
        setIncomeable(po.getIncomeable());
        setTransferFromAble(po.getTransferFromAble());
        setTransferToAble(po.getTransferToAble());
        setInitialBalance(po.getInitialBalance());
        setNotes(po.getNotes());
        setCurrencyCode(po.getCurrencyCode());
    }

    public static AccountVOForExtend fromEntity(Account po) {
        if (po == null) return null;
        AccountVOForExtend vo = new AccountVOForExtend();
        vo.setValue(po);
        return vo;
    }

    public String getTypeName() {
        return EnumUtils.translateAccountType(type);
    }

    public String getBalanceFormatted() {
        return String.format("%.2f", balance);
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountVOForList.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

import lombok.Getter;
import lombok.Setter;

import java.math.BigDecimal;

@Getter
@Setter
public class AccountVOForList extends AccountVOForExtend {

    private BigDecimal limit;
    private Integer billDay;

    private BigDecimal apr;
    private Long asOfDate;

    public BigDecimal getRemainLimit() {
        if (limit == null) return null;
        return limit.add(getBalance());
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultExpenseAccountException.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

public class DefaultExpenseAccountException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultIncomeAccountException.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

public class DefaultIncomeAccountException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultTransferFromAccountException.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

public class DefaultTransferFromAccountException extends RuntimeException {

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultTransferToAccountException.java
================================================
package com.jiukuaitech.bookkeeping.user.account;

public class DefaultTransferToAccountException extends RuntimeException {

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalance.java
================================================
package com.jiukuaitech.bookkeeping.user.adjust_balance;

import com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlow;

import javax.persistence.*;

@Entity
@DiscriminatorValue(value = "4")
public class AdjustBalance extends BalanceFlow {
    
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceAddRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.adjust_balance;

import com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlowAddRequest;
import lombok.Getter;
import lombok.Setter;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;

@Getter
@Setter
public class AdjustBalanceAddRequest extends BalanceFlowAddRequest {

    @NotNull
    private BigDecimal balance;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceController.java
================================================
package com.jiukuaitech.bookkeeping.user.adjust_balance;

import com.jiukuaitech.bookkeeping.user.base.BaseController;
import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.DataResponse;
import com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlowUpdateRequest;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;


@RestController
@RequestMapping("/adjust-balances")
public class AdjustBalanceController extends BaseController {

    @Resource
    private AdjustBalanceService adjustBalanceService;

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}")
    public BaseResponse handleUpdate(
            @PathVariable("id") Integer id,
            @Valid @RequestBody BalanceFlowUpdateRequest request,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(adjustBalanceService.update(id, request, userSignInId));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceRepository.java
================================================
package com.jiukuaitech.bookkeeping.user.adjust_balance;

import com.jiukuaitech.bookkeeping.user.base.HasBookRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AdjustBalanceRepository extends HasBookRepository<AdjustBalance> {

    void deleteByAccount_Id(Integer id);

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceService.java
================================================
package com.jiukuaitech.bookkeeping.user.adjust_balance;

import com.jiukuaitech.bookkeeping.user.account.Account;
import com.jiukuaitech.bookkeeping.user.account.AccountRepository;
import com.jiukuaitech.bookkeeping.user.account.AccountVOForExtend;
import com.jiukuaitech.bookkeeping.user.book.Book;
import com.jiukuaitech.bookkeeping.user.user.User;
import com.jiukuaitech.bookkeeping.user.user.UserService;
import com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlowUpdateRequest;
import com.jiukuaitech.bookkeeping.user.exception.ItemNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Service
public class AdjustBalanceService {

    @Resource
    private UserService userService;

    @Resource
    private AccountRepository accountRepository;

    @Resource
    private AdjustBalanceRepository adjustBalanceRepository;

    @Transactional
    public AccountVOForExtend remove(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        AdjustBalance po = adjustBalanceRepository.findOneByBookAndId(user.getDefaultBook(), id).orElseThrow(ItemNotFoundException::new);
        // 处理退款
        Account account = po.getAccount();
        account.setBalance(account.getBalance().subtract(po.getAmount()));
        accountRepository.save(account);
        adjustBalanceRepository.delete(po);
        return AccountVOForExtend.fromEntity(po.getAccount());
    }

    public boolean update(Integer id, BalanceFlowUpdateRequest request, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        AdjustBalance po = adjustBalanceRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        request.updatePrimitive(po);
        adjustBalanceRepository.save(po);
        return true;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceVOForList.java
================================================
package com.jiukuaitech.bookkeeping.user.adjust_balance;

import com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlowVOForExtend;


public class AdjustBalanceVOForList extends BalanceFlowVOForExtend {

    public static AdjustBalanceVOForList fromEntity(AdjustBalance po) {
        AdjustBalanceVOForList vo = new AdjustBalanceVOForList();
        vo.setValue(po);
        return vo;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/aop/TestAspect.java
================================================
package com.jiukuaitech.bookkeeping.user.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

@Aspect
@Configuration
public class TestAspect {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Before("execution(* com.jiukuaitech.bookkeeping.user.service.*.*(..))")
    public void before(JoinPoint joinPoint) {
        logger.info(" Check before-------------------------------------------------------- ");
        logger.info(" Allowed execution for {}", "");
        logger.info(Arrays.toString(joinPoint.getArgs()));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccount.java
================================================
package com.jiukuaitech.bookkeeping.user.asset_account;

import com.jiukuaitech.bookkeeping.user.account.Account;
import com.jiukuaitech.bookkeeping.user.validation.TimeValidator;
import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Entity
@DiscriminatorValue(value = "4")
@Getter
@Setter
public class AssetAccount extends Account {

    @TimeValidator
    private Long asOfDate; //截止时间,资产余额对应的时间

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountController.java
================================================
package com.jiukuaitech.bookkeeping.user.asset_account;

import com.jiukuaitech.bookkeeping.user.account.AccountQueryRequest;
import com.jiukuaitech.bookkeeping.user.account.AccountService;
import com.jiukuaitech.bookkeeping.user.base.BaseController;
import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.DataResponse;
import com.jiukuaitech.bookkeeping.user.account.AccountAddRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;


@RestController
@RequestMapping("/asset-accounts")
public class AssetAccountController extends BaseController {

    @Resource
    private AssetAccountService assetAccountService;

    @Resource
    private AccountService accountService;

    @RequestMapping(method = RequestMethod.GET, value = "")
    public BaseResponse handleQuery(
            @Valid AccountQueryRequest request,
            @PageableDefault(sort = "balance", direction = Sort.Direction.DESC) Pageable page,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(assetAccountService.query(request, page, userSignInId));
    }

    @RequestMapping(method = RequestMethod.POST, value = "")
    public BaseResponse handleAdd(
            @Valid @RequestBody AccountAddRequest request,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(accountService.add(4, request, userSignInId));
    }

    @RequestMapping(method = RequestMethod.GET, value = "/sum")
    public BaseResponse handleSum(@RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(assetAccountService.sum(userSignInId));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountRepository.java
================================================
package com.jiukuaitech.bookkeeping.user.asset_account;

import com.jiukuaitech.bookkeeping.user.base.BaseRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AssetAccountRepository extends BaseRepository<AssetAccount, Integer> {

/*
    @Query("SELECT COALESCE(SUM(p.balance), 0), " +
            "COALESCE(SUM(p.expense), 0), " +
            "COALESCE(SUM(p.income), 0), " +
            "COALESCE(SUM(p.transferFrom), 0), " +
            "COALESCE(SUM(p.transferTo), 0) " +
            "FROM AssetAccount p WHERE p.book = :book AND p.enable = true")
    List<BigDecimal[]> findSum(Book book);

    @Query("SELECT COALESCE(SUM(p.balance), 0) FROM AssetAccount p WHERE p.book = :book AND p.enable = true AND p.include = true")
    BigDecimal findSumBalance(Book book);
*/

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountService.java
================================================
package com.jiukuaitech.bookkeeping.user.asset_account;

import com.jiukuaitech.bookkeeping.user.account.Account;
import com.jiukuaitech.bookkeeping.user.account.AccountQueryRequest;
import com.jiukuaitech.bookkeeping.user.account.AccountSpec;
import com.jiukuaitech.bookkeeping.user.currency.CurrencyService;
import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.user.UserService;
import com.jiukuaitech.bookkeeping.user.account.AccountSumVO;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

@Service
public class AssetAccountService {

    @Resource
    private UserService userService;

    @Resource
    private AssetAccountRepository assetAccountRepository;

    @Resource
    private CurrencyService currencyService;

    public Page<AssetAccountVOForList> query(AccountQueryRequest request, Pageable page, Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        Specification<AssetAccount> specification = AccountSpec.buildSpecification(request, group);
        Page<AssetAccount> poPage = assetAccountRepository.findAll(specification, page);
        Page<AssetAccountVOForList> voPage = poPage.map(AssetAccountVOForList::fromEntity);
        voPage.map(vo->{
            vo.setConvertedBalance(currencyService.convert(vo.getBalance(), vo.getCurrencyCode(), group.getDefaultCurrencyCode()));
            return vo;
        });
        return voPage;
    }

    public AccountSumVO sum(Integer userSignInId) {
        AccountSumVO vo = new AccountSumVO();
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        List<AssetAccount> accounts = assetAccountRepository.findAll(AccountSpec.inGroupAndEnable(group));
        BigDecimal balance = BigDecimal.ZERO;
        for (int i = 0; i < accounts.size(); i++) {
            Account account = accounts.get(i);
            balance = balance.add(currencyService.convert(account.getBalance(), account.getCurrencyCode(), group.getDefaultCurrencyCode()));
        }
        vo.setBalance(balance);
        return vo;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountVOForList.java
================================================
package com.jiukuaitech.bookkeeping.user.asset_account;

import com.jiukuaitech.bookkeeping.user.account.AccountVOForExtend;
import lombok.Getter;
import lombok.Setter;


@Getter
@Setter
public class AssetAccountVOForList extends AccountVOForExtend {

    private Long asOfDate;

    public static AssetAccountVOForList fromEntity(AssetAccount po) {
        AssetAccountVOForList vo = new AssetAccountVOForList();
        vo.setValue(po);
        vo.setAsOfDate(po.getAsOfDate());
        return vo;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/AccountInvalidateException.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

public class AccountInvalidateException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/AmountInvalidateException.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

public class AmountInvalidateException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlow.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import com.jiukuaitech.bookkeeping.user.account.Account;
import com.jiukuaitech.bookkeeping.user.base.HasBookEntity;
import com.jiukuaitech.bookkeeping.user.flow_images.FlowImage;
import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.user.User;
import com.jiukuaitech.bookkeeping.user.validation.*;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name="t_balance_flow")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.INTEGER, columnDefinition = "TINYINT(1)")
@Getter
@Setter
public class BalanceFlow extends HasBookEntity {

    @Column(nullable = false)
    @NotNull
    @AmountValidator
    private BigDecimal amount; // 金额

    @AmountValidator
    private BigDecimal convertedAmount; //汇率换算之后的金额

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @NotNull
    private Account account;

    @Column(nullable = false)
    @NotNull
    @TimeValidator
    private Long createTime;

    @Column(nullable = false, columnDefinition = "TINYINT(1)")
    @NotNull
    @TransactionStatusValidator
    private Integer status = 1; // 1正常 2是待确认 3是已退款

    @Column(insertable = false, updatable = false)
    private Integer type; //1支出,2收入,3转账,4余额调整

    @Column(length = 16)
    @DescriptionValidator
    private String description; //描述

    @Column(length = 1024)
    @NotesValidator
    private String notes; //备注

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @NotNull
    private User creator;

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @NotNull
    private Group group;

    @OneToMany(mappedBy = "flow", fetch = FetchType.LAZY)
    private Set<FlowImage> images = new HashSet<>();

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowAddRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import com.jiukuaitech.bookkeeping.user.validation.DescriptionValidator;
import com.jiukuaitech.bookkeeping.user.validation.NotesValidator;
import com.jiukuaitech.bookkeeping.user.validation.TimeValidator;
import lombok.Getter;
import lombok.Setter;

import java.time.Instant;

@Getter
@Setter
public class BalanceFlowAddRequest {

    @TimeValidator
    private Long createTime;

    @DescriptionValidator
    private String description;

    @NotesValidator
    private String notes;

    public void copyPrimitive(BalanceFlow po) {
        if (createTime == null) {
            po.setCreateTime(Instant.now().toEpochMilli());
        } else {
            po.setCreateTime(createTime);
        }
        po.setDescription(description);
        po.setNotes(notes);
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowController.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.DataResponse;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Set;

@RestController
@RequestMapping("/flows")
public class BalanceFlowController {

    @Resource
    private BalanceFlowService balanceFlowService;

    @RequestMapping(method = RequestMethod.GET, value = "")
    public BaseResponse handleQuery(
            @Valid BalanceFlowQueryRequest request,
            @PageableDefault(sort = {"createTime", "id"}, direction = Sort.Direction.DESC) Pageable page,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceFlowService.queryWithDefaultBook(request, page, userSignInId));
    }

    @RequestMapping(method = RequestMethod.GET, value = "audit")
    public BaseResponse handleAudit(
            @Valid BalanceFlowQueryRequest request,
            @PageableDefault(sort = {"createTime", "id"}, direction = Sort.Direction.DESC) Pageable page,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceFlowService.query(request, page, userSignInId));
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    public BaseResponse handleGet(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceFlowService.get(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    public BaseResponse handleDelete(
            @PathVariable("id") Integer id,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceFlowService.remove(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}/confirm")
    public BaseResponse handleConfirm(
            @PathVariable("id") Integer id,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceFlowService.confirm(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}/images")
    public BaseResponse handleImages(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceFlowService.getImages(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.POST, value = "/{id}/images")
    public BaseResponse handleUpdateImages(
            @PathVariable("id") Integer id,
            @Valid @RequestBody Set<Integer> images,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceFlowService.updateImages(id, images, userSignInId));
    }

    @RequestMapping(method = RequestMethod.POST, value = "/{id}/image")
    public BaseResponse handleAddImage(
            @PathVariable("id") Integer id,
            @Valid @RequestBody Integer imageId,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceFlowService.addImage(id, imageId, userSignInId));
    }

}

================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowExceptionHandler.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.ErrorResponse;
import org.springframework.context.MessageSource;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.annotation.Resource;
import java.util.Locale;

@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class BalanceFlowExceptionHandler {

    private static final Locale LANG = Locale.CHINA;

    @Resource
    private MessageSource messageSource;

    @ExceptionHandler(value = AccountInvalidateException.class)
    @ResponseBody
    public BaseResponse handleException(AccountInvalidateException e) {
        return new ErrorResponse(702, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = StatusNotValidateException.class)
    @ResponseBody
    public BaseResponse handleException(StatusNotValidateException e) {
        return new ErrorResponse(703, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = AmountInvalidateException.class)
    @ResponseBody
    public BaseResponse handleException(AmountInvalidateException e) {
        return new ErrorResponse(704, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowQueryRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import java.util.Set;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class BalanceFlowQueryRequest {

    private Double minAmount;
    private Double maxAmount;
    private Long minTime;
    private Long maxTime;

    private Integer bookId;
    private Integer accountId;
    private Set<Integer> accounts;
    private Integer status;
    private Integer type;
    private String description;
    private Integer creatorId;
    private Set<Integer> tags;
    private Set<Integer> categories;
    private Set<Integer> payees;

    private Set<Integer> fromAccounts;
    private Set<Integer> toAccounts;

    // 统计支出分类用到
    private Integer categoryId;

    // 按id查询,比如找出退款对应的两条记录
    private Set<Integer> id;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowQueryResultVO.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import lombok.Getter;
import lombok.Setter;
import org.springframework.data.domain.Page;
import java.math.BigDecimal;

@Getter
@Setter
public class BalanceFlowQueryResultVO {

    private Page<BalanceFlowVOForList> result;
    private BigDecimal expense;
    private BigDecimal income;

    public BigDecimal getSurplus() {
        return income.subtract(expense);
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowRepository.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import com.jiukuaitech.bookkeeping.user.base.HasBookRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface BalanceFlowRepository extends HasBookRepository<BalanceFlow> {

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowService.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import com.jiukuaitech.bookkeeping.user.book.Book;
import com.jiukuaitech.bookkeeping.user.expense.Expense;
import com.jiukuaitech.bookkeeping.user.flow_images.FlowImageRepository;
import com.jiukuaitech.bookkeeping.user.flow_images.FlowImageVOForList;
import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.income.Income;
import com.jiukuaitech.bookkeeping.user.transfer.Transfer;
import com.jiukuaitech.bookkeeping.user.user.User;
import com.jiukuaitech.bookkeeping.user.user.UserService;
import com.jiukuaitech.bookkeeping.user.adjust_balance.AdjustBalanceService;
import com.jiukuaitech.bookkeeping.user.deal.DealService;
import com.jiukuaitech.bookkeeping.user.deal.DealSpec;
import com.jiukuaitech.bookkeeping.user.exception.ItemNotFoundException;
import com.jiukuaitech.bookkeeping.user.expense.Expense_;
import com.jiukuaitech.bookkeeping.user.flow_images.FlowImage;
import com.jiukuaitech.bookkeeping.user.income.Income_;
import com.jiukuaitech.bookkeeping.user.transfer.TransferService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class BalanceFlowService {

    @Resource
    private UserService userService;

    @Resource
    private BalanceFlowRepository balanceFlowRepository;

    @Resource
    private DealService dealService;

    @Resource
    private TransferService transferService;

    @Resource
    private AdjustBalanceService adjustBalanceService;

    @Resource
    private FlowImageRepository flowImageRepository;

    public BalanceFlowQueryResultVO queryWithDefaultBook(BalanceFlowQueryRequest request, Pageable page, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        request.setBookId(user.getDefaultBook().getId());
        return query(request, page, userSignInId);
    }

    public BalanceFlowQueryResultVO query(BalanceFlowQueryRequest request, Pageable page, Integer userSignInId) {
        BalanceFlowQueryResultVO result = new BalanceFlowQueryResultVO();
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        Specification<BalanceFlow> specification = BalanceFlowSpec.buildFlowSpecification(request, group);
        Page<BalanceFlow> poPage = balanceFlowRepository.findAll(specification, page);
        Page<BalanceFlowVOForList> voPage = poPage.map(flow-> {
            BalanceFlowVOForList vo = BalanceFlowVOForList.fromEntity(flow);
            vo.setCurrencyCode(flow.getAccount().getCurrencyCode());
            if (flow.getType() == 1 || flow.getType() == 2) {
                if (flow.getBook().getDefaultCurrencyCode().equals(flow.getAccount().getCurrencyCode())) {
                    vo.setNeedConvert(false);
                } else {
                    vo.setNeedConvert(true);
                    vo.setToCurrencyCode(flow.getBook().getDefaultCurrencyCode());
                }
            } else if (flow.getType() == 3) {
                String toCurrencyCode = ((Transfer) flow).getTo().getCurrencyCode();
                if (flow.getAccount().getCurrencyCode().equals(toCurrencyCode)) {
                    vo.setNeedConvert(false);
                } else {
                    vo.setNeedConvert(true);
                    vo.setToCurrencyCode(toCurrencyCode);
                }
            } else {
                vo.setNeedConvert(false);
            }
            return vo;
        });
        result.setResult(voPage);

        Specification<Expense> specification1 = DealSpec.buildSpecification(request, group);
        if (request.getType() == null || request.getType() == 1) { //只有支出类型才需要计算总额
            result.setExpense(balanceFlowRepository.calcAggregate(specification1, Expense_.convertedAmount, Expense.class));
        } else { //不是查询的支出类型,则支出总额肯定为空
            result.setExpense(BigDecimal.ZERO);
        }
        Specification<Income> specification2 = DealSpec.buildSpecification(request, group);
        if (request.getType() == null || request.getType() == 2) {
            result.setIncome(balanceFlowRepository.calcAggregate(specification2, Income_.convertedAmount, Income.class));
        } else {
            result.setIncome(BigDecimal.ZERO);
        }
        return result;
    }

    public BalanceFlowVOForList get(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Book book = user.getDefaultBook();
        BalanceFlow flow = balanceFlowRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        BalanceFlowVOForList vo = BalanceFlowVOForList.fromEntity(flow);
        vo.setCurrencyCode(flow.getAccount().getCurrencyCode());
        if (flow.getType() == 1 || flow.getType() == 2) {
            if (flow.getBook().getDefaultCurrencyCode().equals(flow.getAccount().getCurrencyCode())) {
                vo.setNeedConvert(false);
            } else {
                vo.setNeedConvert(true);
                vo.setToCurrencyCode(flow.getBook().getDefaultCurrencyCode());
            }
        } else if (flow.getType() == 3) {
            String toCurrencyCode = ((Transfer) flow).getTo().getCurrencyCode();
            if (flow.getAccount().getCurrencyCode().equals(toCurrencyCode)) {
                vo.setNeedConvert(false);
            } else {
                vo.setNeedConvert(true);
                vo.setToCurrencyCode(toCurrencyCode);
            }
        } else {
            vo.setNeedConvert(false);
        }
        return vo;
    }

    public boolean remove(Integer id, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        BalanceFlow flow = balanceFlowRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        switch (flow.getType()) {
            case 1:
                return dealService.remove(1, id, userSignInId);
            case 2:
                return dealService.remove(2, id, userSignInId);
            case 3:
                return transferService.remove(id, userSignInId);
            case 4:
                adjustBalanceService.remove(id, userSignInId);
                return true;
            default:
                throw new ItemNotFoundException();
        }
    }

    public boolean confirm(Integer id, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        BalanceFlow flow = balanceFlowRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        switch (flow.getType()) {
            case 1:
                return dealService.confirm(1, id, userSignInId);
            case 2:
                return dealService.confirm(2, id, userSignInId);
            case 3:
                return transferService.confirm(id, userSignInId);
            default:
                throw new ItemNotFoundException();
        }
    }

    public boolean updateImages(Integer id, Set<Integer> images, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Book book = user.getDefaultBook();
        BalanceFlow po = balanceFlowRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        po.getImages().forEach(i -> {
            i.setFlow(null);
            flowImageRepository.save(i);
        });
        images.forEach(i -> {
            FlowImage image = flowImageRepository.getById(i);
            image.setFlow(po); //必须加上这个才能关联上
            po.getImages().add(image);
        });
        balanceFlowRepository.save(po);
        return true;
    }

    public List<FlowImageVOForList> getImages(Integer id, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        BalanceFlow po = balanceFlowRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        List<FlowImage> images = flowImageRepository.findByFlow(po);
        return images.stream().map(FlowImageVOForList::fromEntity).collect(Collectors.toList());
    }

    public boolean addImage(Integer id, Integer imageId, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Book book = user.getDefaultBook();
        BalanceFlow po = balanceFlowRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        FlowImage image = flowImageRepository.getById(imageId);
        image.setFlow(po);
        flowImageRepository.save(image);
        return true;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowSpec.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import com.jiukuaitech.bookkeeping.user.account.Account;
import com.jiukuaitech.bookkeeping.user.book.Book;
import com.jiukuaitech.bookkeeping.user.category_relation.CategoryRelation;
import com.jiukuaitech.bookkeeping.user.deal.Deal;
import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.payee.Payee;
import com.jiukuaitech.bookkeeping.user.tag_relation.TagRelation;
import com.jiukuaitech.bookkeeping.user.transfer.Transfer;
import com.jiukuaitech.bookkeeping.user.user.User;
import com.jiukuaitech.bookkeeping.user.base.BookNameNotesEnableSpec;
import com.jiukuaitech.bookkeeping.user.category_relation.CategoryRelation_;
import com.jiukuaitech.bookkeeping.user.deal.Deal_;
import com.jiukuaitech.bookkeeping.user.tag_relation.TagRelation_;
import com.jiukuaitech.bookkeeping.user.transaction.Transaction;
import com.jiukuaitech.bookkeeping.user.transaction.Transaction_;
import com.jiukuaitech.bookkeeping.user.transfer.Transfer_;
import com.jiukuaitech.bookkeeping.user.utils.CalendarUtils;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.*;
import java.util.Set;

public final class BalanceFlowSpec {
    
    public static<T extends BalanceFlow> Specification<T> amountGreaterThanOrEqualTo(Double amount) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.ge(root.get(BalanceFlow_.AMOUNT), amount);
    }

    public static<T extends BalanceFlow> Specification<T> amountLessThanOrEqualTo(Double amount) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.le(root.get(BalanceFlow_.AMOUNT), amount);
    }

    public static<T extends BalanceFlow> Specification<T> createTimeGreaterThanOrEqualTo(Long time) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.ge(root.get(BalanceFlow_.CREATE_TIME), time);
    }

    public static<T extends BalanceFlow> Specification<T> createTimeLessThanOrEqualTo(Long time) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.le(root.get(BalanceFlow_.CREATE_TIME), time);
    }

    public static<T extends BalanceFlow> Specification<T> creatorEqual(User user) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(BalanceFlow_.CREATOR), user);
    }

    public static<T extends BalanceFlow> Specification<T> accountIn(Set<Integer> accounts) {
        return (root, query, criteriaBuilder) -> {
            CriteriaBuilder.In<Account> in = criteriaBuilder.in(root.get(BalanceFlow_.ACCOUNT));
            accounts.forEach(i -> in.value(new Account(i)));
            return in;
        };
    }

    public static<T extends BalanceFlow> Specification<T> idIn(Set<Integer> id) {
        return (root, query, criteriaBuilder) -> {
            CriteriaBuilder.In<Integer> in = criteriaBuilder.in(root.get(BalanceFlow_.ID));
            id.forEach(i -> in.value(i));
            return in;
        };
    }

    public static<T extends BalanceFlow> Specification<T> typeEqual(Integer type) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(BalanceFlow_.TYPE), type);
    }

    public static<T extends BalanceFlow> Specification<T> isGroup(Group group) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(BalanceFlow_.GROUP), group);
    }

    public static<T extends BalanceFlow> Specification<T> statusEqual(Integer status) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(BalanceFlow_.STATUS), status);
    }

    // 不是待确认的状态
    public static<T extends BalanceFlow> Specification<T> statusConfirmed() {
        return (root, query, criteriaBuilder) -> criteriaBuilder.notEqual(root.get(BalanceFlow_.STATUS), 2);
    }

    public static<T extends BalanceFlow> Specification<T> descriptionEqual(String description) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(BalanceFlow_.DESCRIPTION), description);
    }

    public static<T extends BalanceFlow> Specification<T> distinct() {
        return (root, query, cb) -> {
            query.distinct(true);
//            query.groupBy(root.get(BalanceFlow_.id));
            return null;
        };
    }

    private static<T extends BalanceFlow> Specification<T> buildBaseSpecification(BalanceFlowQueryRequest request, Group group) {
        Specification<T> specification = isGroup(group);
        if (request.getBookId() != null) {
            specification = specification.and(BookNameNotesEnableSpec.isBook(new Book(request.getBookId())));
        }
        if (request.getMinAmount() != null) {
            specification = specification.and(amountGreaterThanOrEqualTo(request.getMinAmount()));
        }
        if (request.getMaxAmount() != null) {
            specification = specification.and(amountLessThanOrEqualTo(request.getMaxAmount()));
        }
        if (request.getMinTime() != null) {
            specification = specification.and(createTimeGreaterThanOrEqualTo(CalendarUtils.getStartOfDay(request.getMinTime())));
        }
        if (request.getMaxTime() != null) {
            specification = specification.and(createTimeLessThanOrEqualTo(CalendarUtils.getEndOfDay(request.getMaxTime())));
        }
        if (request.getCreatorId() != null) {
            specification = specification.and(creatorEqual(new User(request.getCreatorId())));
        }
        if (request.getStatus() != null) {
            specification = specification.and(statusEqual(request.getStatus()));
        }
        if (StringUtils.hasText(request.getDescription())) {
            specification = specification.and(descriptionEqual(request.getDescription()));
        }
        if (!CollectionUtils.isEmpty(request.getId())) {
            specification = specification.and(idIn(request.getId()));
        }
        specification = specification.and(distinct());
        return specification;
    }

    // 给子类调用
    public static<T extends BalanceFlow> Specification<T> buildSpecification(BalanceFlowQueryRequest request, Group group) {
        Specification<T> specification = buildBaseSpecification(request, group);
        if (!CollectionUtils.isEmpty(request.getAccounts())) {
            specification = specification.and(accountIn(request.getAccounts()));
        }
        return specification;
    }

    public static Specification<BalanceFlow> buildFlowSpecification(BalanceFlowQueryRequest request, Group group) {
        Specification<BalanceFlow> specification = buildBaseSpecification(request, group);

        if (request.getAccountId() != null) {
            specification = specification.and((Specification<BalanceFlow>) (root, query, criteriaBuilder) -> {
                Account account = new Account(request.getAccountId());
                Predicate predicate1 = criteriaBuilder.equal(root.get(BalanceFlow_.account), account);
                // https://stackoverflow.com/questions/34251930/jpa-criteria-api-query-subclass-property
//                Root<Transfer> transferRoot = criteriaBuilder.treat(root, Transfer.class);
                @SuppressWarnings("unchecked")
                Root<Transfer> transferRoot = (Root<Transfer>) (Root<?>) root;
                Predicate predicate2 = criteriaBuilder.equal(transferRoot.get(Transfer_.to), account);
                return criteriaBuilder.or(predicate1, predicate2);
            });
        } else if (!CollectionUtils.isEmpty(request.getAccounts())) {
            specification = specification.and((Specification<BalanceFlow>) (root, query, criteriaBuilder) -> {
                CriteriaBuilder.In<Account> in1 = criteriaBuilder.in(root.get(BalanceFlow_.account));
                request.getAccounts().forEach(i -> in1.value(new Account(i)));
                @SuppressWarnings("unchecked")
                Root<Transfer> transferRoot = (Root<Transfer>) (Root<?>) root;
                CriteriaBuilder.In<Account> in2 = criteriaBuilder.in(transferRoot.get(Transfer_.to));
                request.getAccounts().forEach(i -> in2.value(new Account(i)));
                return criteriaBuilder.or(in1, in2);
            });
        }

        if (!CollectionUtils.isEmpty(request.getPayees())) {
            specification = specification.and((Specification<BalanceFlow>) (root, query, criteriaBuilder) -> {
//                Root<Deal> dealRoot = criteriaBuilder.treat(root, Deal.class);
                Root<Deal> dealRoot = (Root<Deal>) (Root<?>) root;
                CriteriaBuilder.In<Payee> in = criteriaBuilder.in(dealRoot.get(Deal_.payee));
                request.getPayees().forEach(i -> in.value(new Payee(i)));
                return in;
            });
        }

        if (!CollectionUtils.isEmpty(request.getCategories())) {
            specification = specification.and((Specification<BalanceFlow>) (root, query, criteriaBuilder) -> {
                Root<Deal> dealRoot = (Root<Deal>) (Root<?>) root;
                Join<Deal, CategoryRelation> join = dealRoot.join(Deal_.categories);
                return join.get(CategoryRelation_.category).in(request.getCategories());
            });
        }

        if (!CollectionUtils.isEmpty(request.getTags())) {
            specification = specification.and((Specification<BalanceFlow>) (root, query, criteriaBuilder) -> {
                Root<Transaction> transactionRoot = criteriaBuilder.treat(root, Transaction.class);
                Join<Transaction, TagRelation> join = transactionRoot.join(Transaction_.tags);
                return join.get(TagRelation_.tag).in(request.getTags());
            });
        }
        if (request.getType() != null) {
            specification = specification.and(typeEqual(request.getType()));
        }

        return specification;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowUpdateRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import com.jiukuaitech.bookkeeping.user.validation.DescriptionValidator;
import com.jiukuaitech.bookkeeping.user.validation.NotesValidator;
import com.jiukuaitech.bookkeeping.user.validation.TimeValidator;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class BalanceFlowUpdateRequest {

    @TimeValidator
    private Long createTime;

    @DescriptionValidator
    private String description;

    @NotesValidator
    private String notes;

    public void updatePrimitive(BalanceFlow po) {
        if (createTime != null) po.setCreateTime(createTime);
        if (description != null) po.setDescription(description);
        if (notes != null) po.setNotes(notes);
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowVOForExtend.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import com.jiukuaitech.bookkeeping.user.account.AccountVOForExtend;
import com.jiukuaitech.bookkeeping.user.utils.EnumUtils;
import com.jiukuaitech.bookkeeping.user.response.HasNameVO;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;

@Getter
@Setter
public class BalanceFlowVOForExtend {

    private Integer id;
    private HasNameVO book;
    private BigDecimal amount;
    private BigDecimal convertedAmount;
    private String currencyCode;
    private Boolean needConvert;
    private String toCurrencyCode;
    private AccountVOForExtend account;
    private String accountName;
    private Long createTime;
    private String description;
    private String notes;
    private Integer status;

    public void setValue(BalanceFlow po) {
        setId(po.getId());
        setBook(new HasNameVO(po.getBook().getId(), po.getBook().getName()));
        setAmount(po.getAmount());
        setConvertedAmount(po.getConvertedAmount());
        if (po.getAccount() != null) setAccount(AccountVOForExtend.fromEntity(po.getAccount()));
        setAccountName(getAccount() == null ? null : getAccount().getName());
        setCreateTime(po.getCreateTime());
        setDescription(po.getDescription());
        setNotes(po.getNotes());
        setStatus(po.getStatus());
    }

    public static BalanceFlowVOForExtend fromEntity(BalanceFlow balanceFlow) {
        BalanceFlowVOForExtend result = new BalanceFlowVOForExtend();
        result.setValue(balanceFlow);
        return result;
    }

    public String getStatusName() {
        return EnumUtils.translateFlowStatus(getStatus());
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowVOForList.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

import com.jiukuaitech.bookkeeping.user.adjust_balance.AdjustBalance;
import com.jiukuaitech.bookkeeping.user.category_relation.CategoryRelationVOForList;
import com.jiukuaitech.bookkeeping.user.deal.DealVOForList;
import com.jiukuaitech.bookkeeping.user.expense.Expense;
import com.jiukuaitech.bookkeeping.user.income.Income;
import com.jiukuaitech.bookkeeping.user.tag_relation.TagRelationVOForList;
import com.jiukuaitech.bookkeeping.user.transfer.Transfer;
import com.jiukuaitech.bookkeeping.user.utils.EnumUtils;
import com.jiukuaitech.bookkeeping.user.adjust_balance.AdjustBalanceVOForList;
import com.jiukuaitech.bookkeeping.user.response.HasNameVO;
import com.jiukuaitech.bookkeeping.user.transfer.TransferVOForList;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Getter
@Setter
public class BalanceFlowVOForList {

    private Integer id;
    private Integer type; // 1是expense,2是income,3是transfer,4是调整余额
    private DealVOForList expense;
    private DealVOForList income;
    private TransferVOForList transfer;
    private AdjustBalanceVOForList adjustBalance;

    private BigDecimal amount;
    private BigDecimal convertedAmount;
    private String currencyCode;
    private Boolean needConvert;
    private String toCurrencyCode;
    private Long createTime;
    private Integer status;
    private String description;

    private Integer accountId;
    private Integer toId;
    private String accountName;
    private String fromAccountName;
    private String toAccountName;
    private String categoryName;
    private Set<CategoryRelationVOForList> categories = new HashSet<>();
    private String bookName;
    private Set<TagRelationVOForList> tags = new HashSet<>();
    private HasNameVO payee;
    private String notes;

    public static BalanceFlowVOForList fromEntity(BalanceFlow po) {
        if (po == null) return null;
        BalanceFlowVOForList vo = new BalanceFlowVOForList();
        vo.setId(po.getId());
        vo.setBookName(po.getBook().getName());
        vo.setType(po.getType());
        vo.setStatus(po.getStatus());
        vo.setDescription(po.getDescription());
        vo.setAmount(po.getAmount());
        vo.setConvertedAmount(po.getConvertedAmount());
        vo.setCreateTime(po.getCreateTime());
        vo.setNotes(po.getNotes());
        if (po instanceof Expense) {
            vo.setExpense(DealVOForList.fromEntity((Expense) po));
            vo.setAccountId(vo.getExpense().getAccount().getId());
            vo.setAccountName(vo.getExpense().getAccountName());
            vo.setCategoryName(vo.getExpense().getCategoryName());
            vo.setCategories(vo.getExpense().getCategories());
            vo.setTags(vo.getExpense().getTags());
            vo.setPayee(vo.getExpense().getPayee());
        } else if (po instanceof Income) {
            vo.setIncome(DealVOForList.fromEntity((Income) po));
            vo.setAccountId(vo.getIncome().getAccount().getId());
            vo.setAccountName(vo.getIncome().getAccountName());
            vo.setCategoryName(vo.getIncome().getCategoryName());
            vo.setCategories(vo.getIncome().getCategories());
            vo.setTags(vo.getIncome().getTags());
            vo.setPayee(vo.getIncome().getPayee());
        } else if (po instanceof Transfer) {
            vo.setTransfer(TransferVOForList.fromEntity((Transfer) po));
            vo.setAccountId(vo.getTransfer().getFromId());
            vo.setToId(vo.getTransfer().getToId());
            vo.setAccountName(vo.getTransfer().getAccountName());
            vo.setFromAccountName(vo.getTransfer().getFrom().getName());
            vo.setToAccountName(vo.getTransfer().getTo().getName());
            vo.setTags(vo.getTransfer().getTags());
        } else if (po instanceof AdjustBalance) {
            vo.setAdjustBalance(AdjustBalanceVOForList.fromEntity((AdjustBalance) po));
            vo.setAccountName(vo.getAdjustBalance().getAccountName());
        }
        return vo;
    }

    public String getCreateTimeFormatted() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return simpleDateFormat.format(new Date(createTime));
    }

    private String getCreateDateFormatted() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return simpleDateFormat.format(new Date(createTime));
    }

    public String getAmountFormatted() {
        return String.format("%.2f", amount);
    }

    public String getTitle() {
        StringBuilder result = new StringBuilder();
        if (StringUtils.hasText(description)) {
            result.append(description);
        } else {
            if (type == 1) {
                result.append(expense.getCategories().stream().map(CategoryRelationVOForList::getCategoryName).collect(Collectors.joining(", ")));
            } else if (type == 2) {
                result.append(income.getCategories().stream().map(CategoryRelationVOForList::getCategoryName).collect(Collectors.joining(", ")));
            } else if (type == 3) {
                result.append(accountName);
            } else {
                result.append("调整余额");
            }
        }
        if (getPayee() != null) {
            result.append(" - ").append(getPayee().getName());
        }
        return result.toString();
    }

    public String getSubTitle() {
        return getTypeName() + " " + getCreateDateFormatted() + " " + getTagsName();
    }

    public String getTagsName() {
        if (type == 1) {
            return expense.getTags().stream().map(TagRelationVOForList::getTagName).collect(Collectors.joining(", "));
        }
        if (type == 2) {
            return income.getTags().stream().map(TagRelationVOForList::getTagName).collect(Collectors.joining(", "));
        }
        if (type == 3) {
            return transfer.getTags().stream().map(TagRelationVOForList::getTagName).collect(Collectors.joining(", "));
        }
        return "";
    }

    public String getTypeName() {
        return EnumUtils.translateFlowType(type);
    }

    public String getStatusName() {
        return EnumUtils.translateFlowStatus(status);
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/StatusNotValidateException.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_flow;

public class StatusNotValidateException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLog.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_log;

import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.user.User;
import com.jiukuaitech.bookkeeping.user.validation.BalanceValidator;
import com.jiukuaitech.bookkeeping.user.validation.TimeValidator;
import com.jiukuaitech.bookkeeping.user.base.BaseEntity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;

@Entity
@Table(name="t_balance_log")
@Getter
@Setter
public class BalanceLog extends BaseEntity {

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "group_id")
    @NotNull
    private Group group; // 账簿必须属于某个组

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @NotNull
    private User creator;

    @Column(nullable = false) //最多9亿
    @NotNull
    @BalanceValidator
    private BigDecimal asset;

    @Column(nullable = false) //最多9亿
    @NotNull
    @BalanceValidator
    private BigDecimal debt;

    @Column(nullable = false)
    @NotNull
    @TimeValidator
    private Long createTime;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogAddRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_log;

import com.jiukuaitech.bookkeeping.user.validation.BalanceValidator;
import com.jiukuaitech.bookkeeping.user.validation.TimeValidator;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;

@Getter
@Setter
public class BalanceLogAddRequest {

    @NotNull
    @BalanceValidator
    private BigDecimal asset;

    @NotNull
    @BalanceValidator
    private BigDecimal debt;

    @Column(nullable = false)
    @NotNull
    @TimeValidator
    private Long createTime;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogController.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_log;

import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.DataResponse;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;

@RestController
@RequestMapping("/logs")
public class BalanceLogController {

    @Resource
    private BalanceLogService balanceLogService;

    @RequestMapping(method = RequestMethod.GET, value = "")
    public BaseResponse handleQuery(
            @PageableDefault(sort = "createTime", direction = Sort.Direction.DESC) Pageable page,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceLogService.query(page, userSignInId));
    }

    @RequestMapping(method = RequestMethod.POST, value = "")
    public BaseResponse handleAdd(
            @Valid @RequestBody BalanceLogAddRequest request,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceLogService.add(request, userSignInId));
    }

    @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    public BaseResponse handleDelete(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(balanceLogService.remove(id, userSignInId));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogRepository.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_log;

import com.jiukuaitech.bookkeeping.user.base.BaseRepository;
import com.jiukuaitech.bookkeeping.user.group.Group;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;


@Repository
public interface BalanceLogRepository extends BaseRepository<BalanceLog, Integer> {

    Optional<BalanceLog> findOneByGroupAndId(Group group, Integer integer);

    List<BalanceLog> findByGroupAndCreateTimeBetweenOrderByCreateTime(Group group, Long min, Long max);

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogService.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_log;

import com.jiukuaitech.bookkeeping.user.exception.ItemNotFoundException;
import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.user.User;
import com.jiukuaitech.bookkeeping.user.user.UserService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;


@Service
public class BalanceLogService {

    @Resource
    private BalanceLogRepository balanceLogRepository;

    @Resource
    private UserService userService;

    public Page<BalanceLogVOForList> query(Pageable page, Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        Specification<BalanceLog> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            predicates.add(criteriaBuilder.equal(root.get(BalanceLog_.group), group));
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        Page<BalanceLog> poPage = balanceLogRepository.findAll(specification, page);
        return poPage.map(BalanceLogVOForList::fromEntity);
    }

    public BalanceLogVOForList add(BalanceLogAddRequest request, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        BalanceLog po = new BalanceLog();
        po.setGroup(group);
        po.setCreator(user);
        po.setAsset(request.getAsset());
        po.setDebt(request.getDebt());
        po.setCreateTime(request.getCreateTime());
        return BalanceLogVOForList.fromEntity(balanceLogRepository.save(po));
    }

    public BalanceLogVOForList remove(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        BalanceLog po = balanceLogRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        balanceLogRepository.delete(po);
        return BalanceLogVOForList.fromEntity(po);
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogVOForList.java
================================================
package com.jiukuaitech.bookkeeping.user.balance_log;

import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;

@Getter
@Setter
public class BalanceLogVOForList {

    private Integer id;
    private BigDecimal asset;
    private BigDecimal debt;
    private Long createTime;

    public static BalanceLogVOForList fromEntity(BalanceLog po) {
        BalanceLogVOForList vo = new BalanceLogVOForList();
        vo.setId(po.getId());
        vo.setAsset(po.getAsset());
        vo.setDebt(po.getDebt());
        vo.setCreateTime(po.getCreateTime());
        return vo;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseController.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import lombok.Getter;
import lombok.Setter;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Getter
@Setter
public class BaseController {

    @Resource
    private HttpServletRequest request;

    @Resource
    private HttpServletResponse response;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseEntity.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

@MappedSuperclass
@Getter
@Setter
public abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    // 不要用id重写hashcode和equals,之前的tag更新出了Bug

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseRepository.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;

import javax.persistence.metamodel.SingularAttribute;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;

/*
https://www.baeldung.com/spring-data-jpa-method-in-all-repositories
https://github.com/pkainulainen/spring-data-jpa-examples/blob/master/custom-method-all-repos/src/main/java/net/petrikainulainen/springdata/jpa/common/BaseRepository.java
 */
@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {

    // P extends Number  change to BigDecimal
    <E> BigDecimal calcAggregate(Specification<E> spec, SingularAttribute<?, BigDecimal> column, Class<E> clazz);

    <E> List<BigDecimal> calcAggregate(Specification<E> spec, List<SingularAttribute<?, BigDecimal>> columns, Class<E> clazz);

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseRepositoryFactoryBean.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import javax.persistence.EntityManager;
import java.io.Serializable;

public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T,
        I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> {

    public BaseRepositoryFactoryBean(Class<? extends R> repositoryInterface) {
        super(repositoryInterface);
    }

    @SuppressWarnings("rawtypes")
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
        return new CustomRepositoryFactory(em);
    }

    private static class CustomRepositoryFactory<T, I extends Serializable>
            extends JpaRepositoryFactory {

        private final EntityManager em;

        public CustomRepositoryFactory(EntityManager em) {
            super(em);
            this.em = em;
        }

        @SuppressWarnings("unchecked")
        protected Object getTargetRepository(RepositoryMetadata metadata) {
            return new BaseRepositoryImpl<T, I>(
                    (Class<T>) metadata.getDomainType(), em);
        }

        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return BaseRepositoryImpl.class;
        }
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseRepositoryImpl.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import com.jiukuaitech.bookkeeping.user.utils.CommonUtils;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Selection;
import javax.persistence.metamodel.SingularAttribute;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/*
https://stackoverflow.com/questions/38934549/spring-specification-with-sum-function
 */
public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {

    private final EntityManager entityManager;

    public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
        super(domainClass, entityManager);
        this.entityManager = entityManager;
    }

    public BaseRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
    }

    @Override
    public <E> BigDecimal calcAggregate(Specification<E> spec, SingularAttribute<?, BigDecimal> column, Class<E> clazz) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<BigDecimal> query = criteriaBuilder.createQuery(column.getJavaType());
        Root<E> root = query.from(clazz);
        if (spec != null) {
            query.where(spec.toPredicate(root, query, criteriaBuilder));
        }
        query.select(criteriaBuilder.sum(root.get(column.getName())));
        TypedQuery<BigDecimal> typedQuery = entityManager.createQuery(query);
        BigDecimal result = typedQuery.getSingleResult();
        if (result == null) return BigDecimal.valueOf(0);
        return result;
    }

    @Override
    public <E> List<BigDecimal> calcAggregate(Specification<E> spec, List<SingularAttribute<?, BigDecimal>> columns, Class<E> clazz) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<BigDecimal[]> query = criteriaBuilder.createQuery(BigDecimal[].class);
        Root<E> root = query.from(clazz);
        if (spec != null) {
            query.where(spec.toPredicate(root, query, criteriaBuilder));
        }
        List<Selection<?>> selectionList = new ArrayList<>();
        columns.forEach(i -> selectionList.add(criteriaBuilder.sum(root.get(i.getName()))));
        query.multiselect(selectionList);
        Object[] result = entityManager.createQuery(query).getSingleResult();
        return CommonUtils.coalesce(Arrays.copyOf(result, result.length, BigDecimal[].class));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BookNameNotesEnableEntity.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import com.jiukuaitech.bookkeeping.user.validation.NameValidator;
import com.jiukuaitech.bookkeeping.user.validation.NotesValidator;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import javax.validation.constraints.NotNull;

@MappedSuperclass
@Getter
@Setter
public abstract class BookNameNotesEnableEntity extends HasBookEntity {

    @Column(length = 16, nullable = false)
    @NotNull
    @NameValidator
    private String name;

    @Column(length = 128)
    @NotesValidator
    private String notes;

    @Column(nullable = false)
    @NotNull
    private Boolean enable = true;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BookNameNotesEnableSpec.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import com.jiukuaitech.bookkeeping.user.book.Book;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.CriteriaBuilder;
import java.util.Set;

public final class BookNameNotesEnableSpec {

    public static<T> Specification<T> isBook(Book book) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(BookNameNotesEnableEntity_.BOOK), book);
    }

    public static<T> Specification<T> inBooks(Set<Integer> books) {
        return (root, query, criteriaBuilder) -> {
            CriteriaBuilder.In<Integer> in = criteriaBuilder.in(root.get(BookNameNotesEnableEntity_.BOOK));
            books.forEach(i -> in.value(i));
            return in;
        };
    }

    public static<T> Specification<T> enable() {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(BookNameNotesEnableEntity_.ENABLE), true);
    }

    public static<T> Specification<T> isEnable(Boolean enable) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(BookNameNotesEnableEntity_.ENABLE), enable);
    }

    public static<T> Specification<T> nameLike(String name) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.like(root.get(BookNameNotesEnableEntity_.NAME), "%"+name+"%");
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/HasBookEntity.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import com.jiukuaitech.bookkeeping.user.book.Book;
import lombok.Getter;
import lombok.Setter;

import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.validation.constraints.NotNull;

@MappedSuperclass
@Getter
@Setter
public abstract class HasBookEntity extends BaseEntity {

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "book_id")
    @NotNull
    private Book book;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/HasBookRepository.java
================================================
package com.jiukuaitech.bookkeeping.user.base;


import com.jiukuaitech.bookkeeping.user.book.Book;
import org.springframework.data.repository.NoRepositoryBean;
import java.util.Optional;

@NoRepositoryBean
public interface HasBookRepository<T extends HasBookEntity> extends BaseRepository<T, Integer>  {

    Optional<T> findOneByBookAndId(Book book, Integer id);

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/JpaDataConfig.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.web.config.EnableSpringDataWebSupport;

@Configuration
@EnableJpaRepositories(basePackages = "com.jiukuaitech.bookkeeping.user",
        repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)
@EnableSpringDataWebSupport
public class JpaDataConfig {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/NameNotesEnableEntity.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import com.jiukuaitech.bookkeeping.user.validation.NameValidator;
import com.jiukuaitech.bookkeeping.user.validation.NotesValidator;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.validation.constraints.NotNull;

@MappedSuperclass
@Getter
@Setter
public abstract class NameNotesEnableEntity extends BaseEntity {

    @Column(length = 16, nullable = false)
    @NotNull
    @NameValidator
    private String name;

    @Column(length = 1024)
    @NotesValidator
    private String notes;

    @Column(nullable = false)
    @NotNull
    private Boolean enable = true;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/TestController.java
================================================
package com.jiukuaitech.bookkeeping.user.base;

import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.DataResponse;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;


@RestController
public class TestController {

    @RequestMapping(method = RequestMethod.GET, value = "/test1")
    public BaseResponse handleTest1() {
        return new DataResponse<>(19);
    }

    @GetMapping("/test2")
    public BaseResponse getBaseUrl(HttpServletRequest request) {
        String baseUrl = ServletUriComponentsBuilder
                .fromRequestUri(request)
                .replacePath(null)
                .build()
                .toUriString();
        return new DataResponse<>(baseUrl);
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/Book.java
================================================
package com.jiukuaitech.bookkeeping.user.book;

import com.jiukuaitech.bookkeeping.user.expense_category.ExpenseCategory;
import com.jiukuaitech.bookkeeping.user.income_category.IncomeCategory;
import com.jiukuaitech.bookkeeping.user.account.Account;
import com.jiukuaitech.bookkeeping.user.base.NameNotesEnableEntity;
import com.jiukuaitech.bookkeeping.user.group.Group;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import javax.validation.constraints.NotNull;

@Entity
@Table(name="t_book", uniqueConstraints = {@UniqueConstraint(columnNames = {"group_id", "name"})})
@Getter
@Setter
/**
 * 账簿类,它属于某个组管理。下面会有很多账户。
 * group+name决定一个账簿。
 */
public class Book extends NameNotesEnableEntity {

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "group_id")
    @NotNull
    private Group group; // 账簿必须属于某个组

    @OneToOne
    private Account defaultExpenseAccount;

    @OneToOne
    private Account defaultIncomeAccount;

    @OneToOne
    private Account defaultTransferFromAccount;

    @OneToOne
    private Account defaultTransferToAccount;

    @OneToOne
    private ExpenseCategory defaultExpenseCategory;

    @OneToOne
    private IncomeCategory defaultIncomeCategory;

    @Column(nullable = false)
    @NotNull
    private Boolean descriptionEnable = true;

    @Column(nullable = false)
    @NotNull
    private Boolean timeEnable = false;

    @Column(nullable = false)
    @NotNull
    private Boolean imageEnable = false;

    @Column(nullable = false, length = 8)
    @NotNull
    private String defaultCurrencyCode;//默认的币种

    public Book() { }

    public Book(Integer id) {
        super.setId(id);
    }
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookAddRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.book;

import com.jiukuaitech.bookkeeping.user.validation.NameValidator;
import com.jiukuaitech.bookkeeping.user.validation.NotesValidator;
import lombok.Getter;
import lombok.Setter;

import javax.validation.constraints.NotBlank;

@Getter
@Setter
public class BookAddRequest {

    @NotBlank
    @NameValidator
    private String name;

    @NotesValidator
    private String notes;

    private Boolean descriptionEnable = true;
    private Boolean timeEnable = false;
    private Boolean imageEnable = false;

    @NotBlank
    private String defaultCurrencyCode;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookController.java
================================================
package com.jiukuaitech.bookkeeping.user.book;

import com.jiukuaitech.bookkeeping.user.base.BaseController;
import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.DataResponse;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;

@RestController
@RequestMapping("/books")
public class BookController extends BaseController {

    @Resource
    private BookService bookService;

    /*
    @RequestMapping(method = RequestMethod.GET, value = "")
    public BaseResponse handleGetAll(@RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(bookService.getAll(userSignInId));
    }
    */

    @RequestMapping(method = RequestMethod.GET, value = "")
    public BaseResponse handleQuery(
            @PageableDefault(sort = "id", direction = Sort.Direction.DESC) Pageable page,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(bookService.query(page, userSignInId));
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    public BaseResponse handleGet(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(bookService.get(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.POST, value = "")
    public BaseResponse handleAdd(@Valid @RequestBody BookAddRequest request, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new BaseResponse(bookService.add(request, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}")
    public BaseResponse handleUpdate(
            @PathVariable("id") Integer id,
            @Valid @RequestBody BookUpdateRequest request,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(bookService.update(id, request, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/config")
    public BaseResponse handleConfig(
            @Valid @RequestBody BookUpdateRequest request,
            @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(bookService.config(request, userSignInId));
    }

    @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    public BaseResponse handleDelete(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new BaseResponse(bookService.remove(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggle")
    public BaseResponse handleToggle(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(bookService.toggle(id, userSignInId));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookExceptionHandler.java
================================================
package com.jiukuaitech.bookkeeping.user.book;

import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.ErrorResponse;
import org.springframework.context.MessageSource;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.annotation.Resource;
import java.util.Locale;

@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class BookExceptionHandler {

    private static final Locale LANG = Locale.CHINA;

    @Resource
    private MessageSource messageSource;

    @ExceptionHandler(value = BookMaxCountException.class)
    @ResponseBody
    public BaseResponse handleException(BookMaxCountException e) {
        return new ErrorResponse(602, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookMaxCountException.java
================================================
package com.jiukuaitech.bookkeeping.user.book;

public class BookMaxCountException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookRepository.java
================================================
package com.jiukuaitech.bookkeeping.user.book;

import com.jiukuaitech.bookkeeping.user.base.BaseRepository;
import com.jiukuaitech.bookkeeping.user.group.Group;
import org.springframework.stereotype.Repository;
import java.util.Optional;

@Repository
public interface BookRepository extends BaseRepository<Book, Integer> {
    
    Integer countByGroup_id(Integer groupId);

    Optional<Book> findOneByGroupAndId(Group group, Integer id);

    Optional<Book> findOneByGroupAndName(Group group, String name);

    long deleteByGroup_id(Integer groupId);

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookService.java
================================================
package com.jiukuaitech.bookkeeping.user.book;

import java.util.ArrayList;
import java.util.List;

import com.jiukuaitech.bookkeeping.user.currency.CurrencyService;
import com.jiukuaitech.bookkeeping.user.expense_category.ExpenseCategory;
import com.jiukuaitech.bookkeeping.user.group.Group;
import com.jiukuaitech.bookkeeping.user.group.GroupRepository;
import com.jiukuaitech.bookkeeping.user.income_category.IncomeCategory;
import com.jiukuaitech.bookkeeping.user.user.*;
import com.jiukuaitech.bookkeeping.user.account.AccountRepository;
import com.jiukuaitech.bookkeeping.user.exception.ItemNotFoundException;
import com.jiukuaitech.bookkeeping.user.exception.NameExistsException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;

@Service
public class BookService {

    @Resource
    private UserRepository userRepository;

    @Resource
    private UserService userService;

    @Resource
    private GroupRepository groupRepository;

    @Resource
    private BookRepository bookRepository;

    @Resource
    private AccountRepository accountRepository;

    @Resource
    private CurrencyService currencyService;

    @Value("${book.max.count}")
    private Integer maxCount;

    public Page<BookVOForList> query(Pageable page, Integer userSignInId) {
        Specification<Book> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            User user = userService.getUser(userSignInId);
            predicates.add(criteriaBuilder.equal(root.get(Book_.group), user.getDefaultGroup()));
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        Page<Book> poPage = bookRepository.findAll(specification, page);
        return poPage.map(BookVOForList::fromEntity);
    }

    public BookVOForList get(Integer id, Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        Book po = bookRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        return BookVOForList.fromEntity(po);
    }

    public boolean add(BookAddRequest request, Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        if (bookRepository.findOneByGroupAndName(group, request.getName()).isPresent()) {
            throw new NameExistsException();
        }
        if (bookRepository.countByGroup_id(group.getId()) >= maxCount) {
            throw new BookMaxCountException();
        }
        currencyService.checkCode(request.getDefaultCurrencyCode());
        Book po = new Book();
        po.setName(request.getName());
        po.setDefaultCurrencyCode(request.getDefaultCurrencyCode());
        po.setNotes(request.getNotes());
        po.setGroup(group);
        po.setDescriptionEnable(request.getDescriptionEnable());
        po.setTimeEnable(request.getTimeEnable());
        po.setImageEnable(request.getImageEnable());
        bookRepository.save(po);
        return true;
    }

    public BookVOForList update(Integer id, BookUpdateRequest request, Integer userSignInId) {
        Group group = userService.getUser(userSignInId).getDefaultGroup();
        Book po = bookRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        if (StringUtils.hasText(request.getName())) {
            if (!po.getName().equals(request.getName())) {
                if (bookRepository.findOneByGroupAndName(po.getGroup(), request.getName()).isPresent()) {
                    throw new NameExistsException();
                }
            }
        }
        if (StringUtils.hasText(request.getName())) po.setName(request.getName());
        if (request.getNotes() != null) po.setNotes(request.getNotes());
        bookRepository.save(po);
        return BookVOForList.fromEntity(po);
    }

    public BookVOForList config(BookUpdateRequest request, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Book po = user.getDefaultBook();
        // 不检查默认的账户和分类是不是该账本下的了,后果就是无法记账默认值而已。
        if (request.getDefaultExpenseAccountId() != null) {
            po.setDefaultExpenseAccount(accountRepository.getById(request.getDefaultExpenseAccountId()));
        } else {
            po.setDefaultExpenseAccount(null);
        }

        if (request.getDefaultIncomeAccountId() != null) {
            po.setDefaultIncomeAccount(accountRepository.getById(request.getDefaultIncomeAccountId()));
        } else {
            po.setDefaultIncomeAccount(null);
        }

        if (request.getDefaultTransferFromAccountId() != null) {
            po.setDefaultTransferFromAccount(accountRepository.getById(request.getDefaultTransferFromAccountId()));
        } else {
            po.setDefaultTransferFromAccount(null);
        }

        if (request.getDefaultTransferToAccountId() != null) {
            po.setDefaultTransferToAccount(accountRepository.getById(request.getDefaultTransferToAccountId()));
        } else {
            po.setDefaultTransferToAccount(null);
        }

        if (request.getDefaultExpenseCategoryId() != null) {
            po.setDefaultExpenseCategory(new ExpenseCategory(request.getDefaultExpenseCategoryId()));
        } else {
            po.setDefaultExpenseCategory(null);
        }

        if (request.getDefaultIncomeCategoryId() != null) {
            po.setDefaultIncomeCategory(new IncomeCategory(request.getDefaultIncomeCategoryId()));
        } else {
            po.setDefaultIncomeCategory(null);
        }

        if (request.getDescriptionEnable() != null) po.setDescriptionEnable(request.getDescriptionEnable());
        if (request.getTimeEnable() != null) po.setTimeEnable(request.getTimeEnable());
        if (request.getImageEnable() != null) po.setImageEnable(request.getImageEnable());

        bookRepository.save(po);
        return BookVOForList.fromEntity(po);
    }

    public boolean remove(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        Book po = bookRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
//        UserGroupRelation userGroupRelation = userGroupRelationRepository.findOneByUserAndGroup(user, group);
//        if (userGroupRelation == null || userGroupRelation.getRole() != 1) {
//            throw new PermissionException("No Permission");
//        }
        if (user.getDefaultBook().getId().equals(po.getId())) {
            user.setDefaultBook(null);
            userRepository.save(user);
        }
        if (group.getDefaultBook().getId().equals(po.getId())) {
            group.setDefaultBook(null);
            groupRepository.save(group);
        }
        bookRepository.delete(po);
        return true;
    }

    public boolean toggle(Integer id, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Group group = user.getDefaultGroup();
        Book po = bookRepository.findOneByGroupAndId(group, id).orElseThrow(ItemNotFoundException::new);
        if (user.getDefaultBook().equals(po)) {
            throw new ItemNotFoundException();
        }
        po.setEnable(!po.getEnable());
        bookRepository.save(po);
        return true;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookUpdateRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.book;

import com.jiukuaitech.bookkeeping.user.validation.NameValidator;
import com.jiukuaitech.bookkeeping.user.validation.NotesValidator;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class BookUpdateRequest {

    @NameValidator
    private String name;

    @NotesValidator
    private String notes;

    private Integer defaultExpenseAccountId;
    private Integer defaultIncomeAccountId;
    private Integer defaultTransferFromAccountId;
    private Integer defaultTransferToAccountId;
    private Integer defaultExpenseCategoryId;
    private Integer defaultIncomeCategoryId;
    private Boolean descriptionEnable;
    private Boolean timeEnable;
    private Boolean imageEnable;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookVOForList.java
================================================
package com.jiukuaitech.bookkeeping.user.book;

import com.jiukuaitech.bookkeeping.user.account.AccountVOForExtend;
import com.jiukuaitech.bookkeeping.user.response.HasNameVO;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class BookVOForList {

    private Integer id;
    private String name;
    private String notes;
    private HasNameVO group;
    private AccountVOForExtend defaultExpenseAccount;
    private AccountVOForExtend defaultIncomeAccount;
    private AccountVOForExtend defaultTransferFromAccount;
    private AccountVOForExtend defaultTransferToAccount;
    private HasNameVO defaultExpenseCategory;
    private HasNameVO defaultIncomeCategory;
    private Boolean descriptionEnable;
    private Boolean timeEnable;
    private Boolean imageEnable;
    private Boolean enable;
    private String defaultCurrencyCode;

    public static BookVOForList fromEntity(Book po) {
        BookVOForList vo = new BookVOForList();
        vo.setId(po.getId());
        vo.setName(po.getName());
        vo.setDefaultCurrencyCode(po.getDefaultCurrencyCode());
        vo.setNotes(po.getNotes());
        vo.setGroup(new HasNameVO(po.getGroup().getId(), po.getGroup().getName()));
        vo.setDescriptionEnable(po.getDescriptionEnable());
        vo.setTimeEnable(po.getTimeEnable());
        vo.setImageEnable(po.getImageEnable());
        vo.setEnable(po.getEnable());
        if (po.getDefaultExpenseAccount() != null) {
            vo.setDefaultExpenseAccount(AccountVOForExtend.fromEntity(po.getDefaultExpenseAccount()));
        }
        if (po.getDefaultIncomeAccount() != null) {
            vo.setDefaultIncomeAccount(AccountVOForExtend.fromEntity(po.getDefaultIncomeAccount()));
        }
        if (po.getDefaultTransferFromAccount() != null) {
            vo.setDefaultTransferFromAccount(AccountVOForExtend.fromEntity(po.getDefaultTransferFromAccount()));
        }
        if (po.getDefaultTransferToAccount() != null) {
            vo.setDefaultTransferToAccount(AccountVOForExtend.fromEntity(po.getDefaultTransferToAccount()));
        }
        if (po.getDefaultExpenseCategory() != null) {
            vo.setDefaultExpenseCategory(new HasNameVO(po.getDefaultExpenseCategory().getId(), po.getDefaultExpenseCategory().getName()));
        }
        if (po.getDefaultIncomeCategory() != null) {
            vo.setDefaultIncomeCategory(new HasNameVO(po.getDefaultIncomeCategory().getId(), po.getDefaultIncomeCategory().getName()));
        }
        return vo;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/Category.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import com.jiukuaitech.bookkeeping.user.base.BookNameNotesEnableEntity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name="t_category", uniqueConstraints = {@UniqueConstraint(columnNames = {"parent_id", "name"})})
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.INTEGER, columnDefinition = "TINYINT(1)")
@Getter
@Setter
@NoArgsConstructor
public class Category extends BookNameNotesEnableEntity {

    @Column(insertable = false, updatable = false)
    private Integer type; //1支出分类,2收入分类

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    private Category parent;
    
    @Column(nullable = false)
    @NotNull
    private Integer level;

    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    private List<Category> children = new ArrayList<>();

    public Category(Integer id) {
        super.setId(id);
    }

    public List<Category> getChildren(List<Category> categories) {
        List<Category> result = new ArrayList<>();
        for (Category item : categories) {
            if (item.getParent() != null && this.getId().equals(item.getParent().getId())) {
                result.add(item);
            }
        }
        return result;
    }

    public List<Category> getOffspring(List<Category> categories) {
        List<Category> result = new ArrayList<>();
        List<Category> children = this.getChildren(categories);
        if (!CollectionUtils.isEmpty(children)) {
            result.addAll(children);
            for (Category item : children) {
                result.addAll(item.getOffspring(categories));
            }
        }
        return result;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryAddRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import com.jiukuaitech.bookkeeping.user.validation.NameValidator;
import com.jiukuaitech.bookkeeping.user.validation.NotesValidator;
import lombok.Getter;
import lombok.Setter;

import javax.validation.constraints.NotBlank;

@Getter
@Setter
public class CategoryAddRequest {

    @NotBlank
    @NameValidator
    private String name;

    @NotesValidator
    private String notes;

    private Integer parentId;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryController.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import com.jiukuaitech.bookkeeping.user.base.BaseController;
import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.DataResponse;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@RestController
@RequestMapping("/categories")
public class CategoryController extends BaseController {

    @Resource
    private CategoryService categoryService;

    @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    public BaseResponse handleDelete(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new BaseResponse(categoryService.remove(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggle")
    public BaseResponse handleToggle(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new BaseResponse(categoryService.toggle(id, userSignInId));
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    public BaseResponse handleGet(@PathVariable("id") Integer id, @RequestAttribute("userSignInId") Integer userSignInId) {
        return new DataResponse<>(categoryService.get(id, userSignInId));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryExceptionHandler.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import com.jiukuaitech.bookkeeping.user.response.BaseResponse;
import com.jiukuaitech.bookkeeping.user.response.ErrorResponse;
import org.springframework.context.MessageSource;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.annotation.Resource;
import java.util.Locale;

@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CategoryExceptionHandler {

    private static final Locale LANG = Locale.CHINA;

    @Resource
    private MessageSource messageSource;

    @ExceptionHandler(value = ParentCategoryNotEnableException.class)
    @ResponseBody
    public BaseResponse handleException(ParentCategoryNotEnableException e) {
        return new ErrorResponse(607, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = CategoryNameExistsException.class)
    @ResponseStatus(HttpStatus.CONFLICT)
    public BaseResponse handleException(CategoryNameExistsException e) {
        return new ErrorResponse(409, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = CategoryHasDealException.class)
    @ResponseBody
    public BaseResponse handleException(CategoryHasDealException e) {
        return new ErrorResponse(410, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = CategoryLevelException.class)
    @ResponseBody
    public BaseResponse handleException(CategoryLevelException e) {
        return new ErrorResponse(703, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = CategoryIsDefaultExpenseException.class)
    @ResponseBody
    public BaseResponse handleException(CategoryIsDefaultExpenseException e) {
        return new ErrorResponse(704, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = CategoryIsDefaultIncomeException.class)
    @ResponseBody
    public BaseResponse handleException(CategoryIsDefaultIncomeException e) {
        return new ErrorResponse(705, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

    @ExceptionHandler(value = CategoryMaxCountException.class)
    @ResponseBody
    public BaseResponse handleException(CategoryMaxCountException e) {
        return new ErrorResponse(706, messageSource.getMessage(e.getClass().getSimpleName(), null, LANG));
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryHasDealException.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

/*
删除有账单的分类
 */
public class CategoryHasDealException extends RuntimeException {

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryIsDefaultExpenseException.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

/*
CategoryIsDefaultExpenseException
 */
public class CategoryIsDefaultExpenseException extends RuntimeException {

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryIsDefaultIncomeException.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

/*
账本的默认收入类别不能删除
 */
public class CategoryIsDefaultIncomeException extends RuntimeException {

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryLevelException.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

/*
添加支出时,层级超过
 */
public class CategoryLevelException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryMaxCountException.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

public class CategoryMaxCountException extends RuntimeException {

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryNameExistsException.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

/*
添加分类时,名称重复
 */
public class CategoryNameExistsException extends RuntimeException {

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryQueryRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class CategoryQueryRequest {

    private String name;
    private Boolean enable;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryRepository.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import com.jiukuaitech.bookkeeping.user.book.Book;
import com.jiukuaitech.bookkeeping.user.base.HasBookRepository;
import com.jiukuaitech.bookkeeping.user.group.Group;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;

@Repository
public interface CategoryRepository extends HasBookRepository<Category> {

    Optional<Category> findOneByBookAndNameAndParentAndType(Book book, String name, Category parent, Integer type);

    List<Category> findAllByBookAndType(Book book, Integer type);

    List<Category> findAllByBook(Book book);

    List<Category> findAllByBookAndTypeAndEnable(Book book, Integer type, Boolean enable);

    long countByBookAndType(Book book, Integer type);

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryService.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import com.jiukuaitech.bookkeeping.user.book.Book;
import com.jiukuaitech.bookkeeping.user.expense_category.ExpenseCategory;
import com.jiukuaitech.bookkeeping.user.income_category.IncomeCategory;
import com.jiukuaitech.bookkeeping.user.user.User;
import com.jiukuaitech.bookkeeping.user.base.BookNameNotesEnableSpec;
import com.jiukuaitech.bookkeeping.user.category_relation.CategoryRelationRepository;
import com.jiukuaitech.bookkeeping.user.exception.ItemNotFoundException;
import com.jiukuaitech.bookkeeping.user.user.UserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CategoryService {

    @Resource
    private CategoryRepository categoryRepository;

    @Resource
    private CategoryRelationRepository categoryRelationRepository;

    @Resource
    private UserService userService;

    @Value("${category.max.level}")
    private Integer maxLevel;

    @Value("${category.max.count}")
    private Integer maxCount;

    /*
    删除分类需要检查:1. 有无支出;2. 有无账本的默认; 3. 有无子类
     */
    public boolean remove(Integer id, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        Category po = categoryRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        // 检查关联性,有账单关联的不能删除
        if (categoryRelationRepository.countByCategory_id(id) > 0) {
            throw new CategoryHasDealException();
        }
        if (po.equals(book.getDefaultExpenseCategory())) throw new CategoryIsDefaultExpenseException();
        if (po.equals(book.getDefaultIncomeCategory())) throw new CategoryIsDefaultIncomeException();
        categoryRepository.delete(po);
        return true;
    }

    @Transactional
    public boolean toggle(Integer id, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        Category po = categoryRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        List<Category> entityList = categoryRepository.findAll(BookNameNotesEnableSpec.isBook(po.getBook()));
        List<Category> offSpring = po.getOffspring(entityList);
        offSpring.add(po);
        for (Category item : offSpring) {
            if (item.equals(book.getDefaultExpenseCategory())) throw new CategoryIsDefaultExpenseException();
            if (item.equals(book.getDefaultIncomeCategory())) throw new CategoryIsDefaultIncomeException();
            item.setEnable(!po.getEnable());
        }
        categoryRepository.saveAll(offSpring);
        return true;
    }

    public boolean add(Integer type, CategoryAddRequest request, Integer userSignInId) {
        User user = userService.getUser(userSignInId);
        Book book = user.getDefaultBook();
        Category parent = null;
        if (request.getParentId() != null) {
            parent = categoryRepository.findOneByBookAndId(book, request.getParentId()).orElseThrow(ItemNotFoundException::new);
            if (!parent.getEnable()) {
                throw new ParentCategoryNotEnableException();
            }
            if (parent.getLevel().equals(maxLevel-1)) {
                throw new CategoryLevelException();
            }
        }
        if (categoryRepository.countByBookAndType(book, type) >= maxCount) {
            throw new CategoryMaxCountException();
        }
        if (categoryRepository.findOneByBookAndNameAndParentAndType(book, request.getName(), parent, type).isPresent()) {
            throw new CategoryNameExistsException();
        }
        Category po = null;
        if (type == 1) {
            po = new ExpenseCategory();
        } else {
            po = new IncomeCategory();
        }
        po.setName(request.getName());
        po.setNotes(request.getNotes());
        po.setBook(book);
        po.setParent(parent);
        if (parent == null) po.setLevel(0);
        else po.setLevel(parent.getLevel()+1);
        categoryRepository.save(po);
        return true;
    }

    public boolean update(Integer type, Integer id, CategoryUpdateRequest request, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        Category po = categoryRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        Category parent = null;
        if (request.getParentId() != null) {
            parent = categoryRepository.findOneByBookAndId(book, request.getParentId()).orElseThrow(ItemNotFoundException::new);
            if (!parent.getEnable()) {
                throw new ParentCategoryNotEnableException();
            }
            if (parent.getLevel().equals(maxLevel-1)) {
                throw new CategoryLevelException();
            }
        }
        po.setParent(parent);
        if (StringUtils.hasText(request.getName())) {
            if(!request.getName().equals(po.getName())) {
                if (categoryRepository.findOneByBookAndNameAndParentAndType(book, request.getName(), parent, type).isPresent()) {
                    throw new CategoryNameExistsException();
                }
                po.setName(request.getName());
            }
        }
        if (request.getNotes() != null) po.setNotes(request.getNotes());
        if (parent == null) po.setLevel(0);
        else po.setLevel(parent.getLevel()+1);
        categoryRepository.save(po);
        return true;
    }

    public List<CategorySimpleVO> getAllEnable(Integer type, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        List<Category> entityList = categoryRepository.findAllByBookAndTypeAndEnable(book, type, true);
        return entityList.stream().map(CategorySimpleVO::fromEntity).collect(Collectors.toList());
    }

    public List<CategoryTreeVO> getAllTree(CategoryQueryRequest request, Integer type, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        Specification<Category> specification = CategorySpec.buildSpecification(request, type, book);
        List<Category> entityList = categoryRepository.findAll(specification);
        return CategoryTreeVO.valueOfList(entityList);
    }

    public Page<CategorySimpleVO> query(Integer type, Pageable page, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        Specification<Category> specification = CategorySpec.buildSpecification(null, type, book);
        Page<Category> poPage = categoryRepository.findAll(specification, page);
        return poPage.map(CategorySimpleVO::fromEntity);
    }

    public CategoryTreeVO get(Integer id, Integer userSignInId) {
        Book book = userService.getUser(userSignInId).getDefaultBook();
        Category category = categoryRepository.findOneByBookAndId(book, id).orElseThrow(ItemNotFoundException::new);
        return CategoryTreeVO.valueOf(category);
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategorySimpleVO.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class CategorySimpleVO {

    private Integer id;
    private String name;
    private String notes;
    private Boolean enable;
    private Integer parentId;

    public static CategorySimpleVO fromEntity(Category po) {
        if (po == null) return null;
        CategorySimpleVO vo =  new CategorySimpleVO();
        vo.setId(po.getId());
        vo.setName(po.getName());
        vo.setNotes(po.getNotes());
        vo.setEnable(po.getEnable());
        vo.setParentId(po.getParent() != null ? po.getParent().getId() : 0);
        return vo;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategorySpec.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import com.jiukuaitech.bookkeeping.user.book.Book;
import com.jiukuaitech.bookkeeping.user.base.BookNameNotesEnableSpec;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;

public final class CategorySpec {

    public static Specification<Category> typeEqual(Integer type) {
        return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(Category_.type), type);
    }

    public static Specification<Category> buildSpecification(CategoryQueryRequest request, Integer type, Book book) {
        Specification<Category> specification = BookNameNotesEnableSpec.isBook(book);
        if (request != null) {
            if (StringUtils.hasText(request.getName())) {
                specification = specification.and(BookNameNotesEnableSpec.nameLike(request.getName()));
            }
            if (request.getEnable() != null) {
                specification = specification.and(BookNameNotesEnableSpec.isEnable(request.getEnable()));
            }
        }
        specification = specification.and(typeEqual(type));
        return specification;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryTreeVO.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

@Getter
@Setter
public class CategoryTreeVO {

    private Integer id;
    private String name;
    private String notes;
    private Boolean enable;
    private List<CategoryTreeVO> children;
    private Integer parentId;
    private String parentName;

    public static List<CategoryTreeVO> valueOfList(List<Category> categories) {
        List<CategoryTreeVO> categoryTreeVOList = new ArrayList<>();
        for (Category item : categories) {
            if (item.getParent() == null) {
                categoryTreeVOList.add(CategoryTreeVO.valueOf(item, categories));
            }
        }
        return categoryTreeVOList;
    }

    public static CategoryTreeVO valueOf(Category category, List<Category> categories) {
        CategoryTreeVO categoryTreeVO = new CategoryTreeVO();
        categoryTreeVO.setId(category.getId());
        categoryTreeVO.setName(category.getName());
        categoryTreeVO.setNotes(category.getNotes());
        categoryTreeVO.setEnable(category.getEnable());
        categoryTreeVO.setParentId(category.getParent() == null ? null : category.getParent().getId());
        categoryTreeVO.setParentName(category.getParent() == null ? null : category.getParent().getName());
        if (!CollectionUtils.isEmpty(category.getChildren(categories))) {
            for (Category item : category.getChildren(categories)) {
                if (categoryTreeVO.getChildren() == null) {
                    categoryTreeVO.setChildren(new ArrayList<>());
                }
                categoryTreeVO.getChildren().add(valueOf(item, categories));
            }
        }
        return categoryTreeVO;
    }

    public static CategoryTreeVO valueOf(Category category) {
        CategoryTreeVO categoryTreeVO = new CategoryTreeVO();
        categoryTreeVO.setId(category.getId());
        categoryTreeVO.setName(category.getName());
        categoryTreeVO.setNotes(category.getNotes());
        categoryTreeVO.setEnable(category.getEnable());
        if (category.getParent() != null) categoryTreeVO.setParentId(category.getParent().getId());
        if (category.getParent() != null) categoryTreeVO.setParentName(category.getParent().getName());
        return categoryTreeVO;
    }

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryUpdateRequest.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

import com.jiukuaitech.bookkeeping.user.validation.NameValidator;
import com.jiukuaitech.bookkeeping.user.validation.NotesValidator;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class CategoryUpdateRequest {

    @NameValidator
    private String name;

    @NotesValidator
    private String notes;

    private Integer parentId;

}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/DefaultExpenseCategoryException.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

public class DefaultExpenseCategoryException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/DefaultIncomeCategoryException.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

public class DefaultIncomeCategoryException extends RuntimeException {
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/ParentCategoryNotEnableException.java
================================================
package com.jiukuaitech.bookkeeping.user.category;

/*
添加子分类时,父分类不可用
 */
public class ParentCategoryNotEnableException extends RuntimeException {
    
}


================================================
FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category_relation/CategoryRelation.java
================================================
package com.jiukuaitech.bookkeeping.user.category_relation;

import com.jiukuaitech.bookkeeping.user.category.Category;
import com.jiukuaitech.bookkeeping.user.deal.Deal;
import com.jiukuaitech.bookkeeping.user.validation.AmountValidator;
import com.jiukuaitech.bookkeeping.user.base.BaseEntity;
import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import javax.validation.constrain
Download .txt
gitextract_uxeyvckg/

├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── bookkeeping-user-api/
│   ├── .mvn/
│   │   └── wrapper/
│   │       ├── MavenWrapperDownloader.java
│   │       ├── maven-wrapper.jar
│   │       └── maven-wrapper.properties
│   ├── Dockerfile
│   ├── mvnw
│   ├── mvnw.cmd
│   ├── pom.xml
│   ├── restart.sh
│   ├── src/
│   │   └── main/
│   │       ├── java/
│   │       │   └── com/
│   │       │       └── jiukuaitech/
│   │       │           └── bookkeeping/
│   │       │               └── user/
│   │       │                   ├── Application.java
│   │       │                   ├── RegexTest.java
│   │       │                   ├── account/
│   │       │                   │   ├── Account.java
│   │       │                   │   ├── AccountAddRequest.java
│   │       │                   │   ├── AccountAdjustBalanceNotValidException.java
│   │       │                   │   ├── AccountController.java
│   │       │                   │   ├── AccountExceptionHandler.java
│   │       │                   │   ├── AccountHasTransactionException.java
│   │       │                   │   ├── AccountMaxCountException.java
│   │       │                   │   ├── AccountNameExistsException.java
│   │       │                   │   ├── AccountQueryRequest.java
│   │       │                   │   ├── AccountRepository.java
│   │       │                   │   ├── AccountService.java
│   │       │                   │   ├── AccountSpec.java
│   │       │                   │   ├── AccountSumVO.java
│   │       │                   │   ├── AccountUpdateRequest.java
│   │       │                   │   ├── AccountVOForExtend.java
│   │       │                   │   ├── AccountVOForList.java
│   │       │                   │   ├── DefaultExpenseAccountException.java
│   │       │                   │   ├── DefaultIncomeAccountException.java
│   │       │                   │   ├── DefaultTransferFromAccountException.java
│   │       │                   │   └── DefaultTransferToAccountException.java
│   │       │                   ├── adjust_balance/
│   │       │                   │   ├── AdjustBalance.java
│   │       │                   │   ├── AdjustBalanceAddRequest.java
│   │       │                   │   ├── AdjustBalanceController.java
│   │       │                   │   ├── AdjustBalanceRepository.java
│   │       │                   │   ├── AdjustBalanceService.java
│   │       │                   │   └── AdjustBalanceVOForList.java
│   │       │                   ├── aop/
│   │       │                   │   └── TestAspect.java
│   │       │                   ├── asset_account/
│   │       │                   │   ├── AssetAccount.java
│   │       │                   │   ├── AssetAccountController.java
│   │       │                   │   ├── AssetAccountRepository.java
│   │       │                   │   ├── AssetAccountService.java
│   │       │                   │   └── AssetAccountVOForList.java
│   │       │                   ├── balance_flow/
│   │       │                   │   ├── AccountInvalidateException.java
│   │       │                   │   ├── AmountInvalidateException.java
│   │       │                   │   ├── BalanceFlow.java
│   │       │                   │   ├── BalanceFlowAddRequest.java
│   │       │                   │   ├── BalanceFlowController.java
│   │       │                   │   ├── BalanceFlowExceptionHandler.java
│   │       │                   │   ├── BalanceFlowQueryRequest.java
│   │       │                   │   ├── BalanceFlowQueryResultVO.java
│   │       │                   │   ├── BalanceFlowRepository.java
│   │       │                   │   ├── BalanceFlowService.java
│   │       │                   │   ├── BalanceFlowSpec.java
│   │       │                   │   ├── BalanceFlowUpdateRequest.java
│   │       │                   │   ├── BalanceFlowVOForExtend.java
│   │       │                   │   ├── BalanceFlowVOForList.java
│   │       │                   │   └── StatusNotValidateException.java
│   │       │                   ├── balance_log/
│   │       │                   │   ├── BalanceLog.java
│   │       │                   │   ├── BalanceLogAddRequest.java
│   │       │                   │   ├── BalanceLogController.java
│   │       │                   │   ├── BalanceLogRepository.java
│   │       │                   │   ├── BalanceLogService.java
│   │       │                   │   └── BalanceLogVOForList.java
│   │       │                   ├── base/
│   │       │                   │   ├── BaseController.java
│   │       │                   │   ├── BaseEntity.java
│   │       │                   │   ├── BaseRepository.java
│   │       │                   │   ├── BaseRepositoryFactoryBean.java
│   │       │                   │   ├── BaseRepositoryImpl.java
│   │       │                   │   ├── BookNameNotesEnableEntity.java
│   │       │                   │   ├── BookNameNotesEnableSpec.java
│   │       │                   │   ├── HasBookEntity.java
│   │       │                   │   ├── HasBookRepository.java
│   │       │                   │   ├── JpaDataConfig.java
│   │       │                   │   ├── NameNotesEnableEntity.java
│   │       │                   │   └── TestController.java
│   │       │                   ├── book/
│   │       │                   │   ├── Book.java
│   │       │                   │   ├── BookAddRequest.java
│   │       │                   │   ├── BookController.java
│   │       │                   │   ├── BookExceptionHandler.java
│   │       │                   │   ├── BookMaxCountException.java
│   │       │                   │   ├── BookRepository.java
│   │       │                   │   ├── BookService.java
│   │       │                   │   ├── BookUpdateRequest.java
│   │       │                   │   └── BookVOForList.java
│   │       │                   ├── category/
│   │       │                   │   ├── Category.java
│   │       │                   │   ├── CategoryAddRequest.java
│   │       │                   │   ├── CategoryController.java
│   │       │                   │   ├── CategoryExceptionHandler.java
│   │       │                   │   ├── CategoryHasDealException.java
│   │       │                   │   ├── CategoryIsDefaultExpenseException.java
│   │       │                   │   ├── CategoryIsDefaultIncomeException.java
│   │       │                   │   ├── CategoryLevelException.java
│   │       │                   │   ├── CategoryMaxCountException.java
│   │       │                   │   ├── CategoryNameExistsException.java
│   │       │                   │   ├── CategoryQueryRequest.java
│   │       │                   │   ├── CategoryRepository.java
│   │       │                   │   ├── CategoryService.java
│   │       │                   │   ├── CategorySimpleVO.java
│   │       │                   │   ├── CategorySpec.java
│   │       │                   │   ├── CategoryTreeVO.java
│   │       │                   │   ├── CategoryUpdateRequest.java
│   │       │                   │   ├── DefaultExpenseCategoryException.java
│   │       │                   │   ├── DefaultIncomeCategoryException.java
│   │       │                   │   └── ParentCategoryNotEnableException.java
│   │       │                   ├── category_relation/
│   │       │                   │   ├── CategoryRelation.java
│   │       │                   │   ├── CategoryRelationAddRequest.java
│   │       │                   │   ├── CategoryRelationRepository.java
│   │       │                   │   └── CategoryRelationVOForList.java
│   │       │                   ├── checking_account/
│   │       │                   │   ├── CheckingAccount.java
│   │       │                   │   ├── CheckingAccountController.java
│   │       │                   │   ├── CheckingAccountRepository.java
│   │       │                   │   └── CheckingAccountService.java
│   │       │                   ├── credit_account/
│   │       │                   │   ├── CreditAccount.java
│   │       │                   │   ├── CreditAccountAddRequest.java
│   │       │                   │   ├── CreditAccountController.java
│   │       │                   │   ├── CreditAccountRepository.java
│   │       │                   │   ├── CreditAccountService.java
│   │       │                   │   ├── CreditAccountSumVO.java
│   │       │                   │   └── CreditAccountVOForList.java
│   │       │                   ├── currency/
│   │       │                   │   ├── Currency.java
│   │       │                   │   ├── CurrencyController.java
│   │       │                   │   ├── CurrencyRepository.java
│   │       │                   │   └── CurrencyService.java
│   │       │                   ├── dashboard/
│   │       │                   │   ├── AssetOverviewVO.java
│   │       │                   │   ├── DashboardController.java
│   │       │                   │   └── DashboardService.java
│   │       │                   ├── deal/
│   │       │                   │   ├── CategoryConflictException.java
│   │       │                   │   ├── Deal.java
│   │       │                   │   ├── DealAddRequest.java
│   │       │                   │   ├── DealController.java
│   │       │                   │   ├── DealExceptionHandler.java
│   │       │                   │   ├── DealQueryResultVO.java
│   │       │                   │   ├── DealRepository.java
│   │       │                   │   ├── DealService.java
│   │       │                   │   ├── DealSpec.java
│   │       │                   │   ├── DealUpdateRequest.java
│   │       │                   │   └── DealVOForList.java
│   │       │                   ├── debt_account/
│   │       │                   │   ├── DebtAccount.java
│   │       │                   │   ├── DebtAccountAddRequest.java
│   │       │                   │   ├── DebtAccountController.java
│   │       │                   │   ├── DebtAccountRepository.java
│   │       │                   │   ├── DebtAccountService.java
│   │       │                   │   ├── DebtAccountSumVO.java
│   │       │                   │   └── DebtAccountVOForList.java
│   │       │                   ├── exception/
│   │       │                   │   ├── GlobalExceptionHandler.java
│   │       │                   │   ├── InputNotValidException.java
│   │       │                   │   ├── ItemNotFoundException.java
│   │       │                   │   ├── NameExistsException.java
│   │       │                   │   ├── PermissionException.java
│   │       │                   │   ├── TokenEmptyException.java
│   │       │                   │   └── TokenNotValidException.java
│   │       │                   ├── expense/
│   │       │                   │   ├── Expense.java
│   │       │                   │   ├── ExpenseController.java
│   │       │                   │   ├── ExpenseRepository.java
│   │       │                   │   └── ExpenseService.java
│   │       │                   ├── expense_category/
│   │       │                   │   ├── ExpenseCategory.java
│   │       │                   │   └── ExpenseCategoryController.java
│   │       │                   ├── flow_images/
│   │       │                   │   ├── FlowImage.java
│   │       │                   │   ├── FlowImageController.java
│   │       │                   │   ├── FlowImageExceptionHandler.java
│   │       │                   │   ├── FlowImageRepository.java
│   │       │                   │   ├── FlowImageService.java
│   │       │                   │   ├── FlowImageVOForList.java
│   │       │                   │   ├── ImageExistsException.java
│   │       │                   │   ├── UploadCallbackRequest.java
│   │       │                   │   └── UploadKeyEmptyException.java
│   │       │                   ├── group/
│   │       │                   │   ├── Group.java
│   │       │                   │   ├── GroupAddRequest.java
│   │       │                   │   ├── GroupController.java
│   │       │                   │   ├── GroupExceptionHandler.java
│   │       │                   │   ├── GroupHasBookException.java
│   │       │                   │   ├── GroupMaxCountException.java
│   │       │                   │   ├── GroupRepository.java
│   │       │                   │   ├── GroupService.java
│   │       │                   │   ├── GroupUpdateRequest.java
│   │       │                   │   └── GroupVOForList.java
│   │       │                   ├── income/
│   │       │                   │   ├── Income.java
│   │       │                   │   ├── IncomeController.java
│   │       │                   │   ├── IncomeRepository.java
│   │       │                   │   └── IncomeService.java
│   │       │                   ├── income_category/
│   │       │                   │   ├── IncomeCategory.java
│   │       │                   │   └── IncomeCategoryController.java
│   │       │                   ├── interceptor/
│   │       │                   │   ├── AuthInterceptor.java
│   │       │                   │   ├── MvcInterceptorConfig.java
│   │       │                   │   └── StringTrimModule.java
│   │       │                   ├── item/
│   │       │                   │   ├── Item.java
│   │       │                   │   ├── ItemAddRequest.java
│   │       │                   │   ├── ItemController.java
│   │       │                   │   ├── ItemCountException.java
│   │       │                   │   ├── ItemExceptionHandler.java
│   │       │                   │   ├── ItemQueryRequest.java
│   │       │                   │   ├── ItemRepository.java
│   │       │                   │   ├── ItemService.java
│   │       │                   │   ├── ItemSpec.java
│   │       │                   │   ├── ItemUpdateRequest.java
│   │       │                   │   └── ItemVOForList.java
│   │       │                   ├── payee/
│   │       │                   │   ├── Payee.java
│   │       │                   │   ├── PayeeAddRequest.java
│   │       │                   │   ├── PayeeController.java
│   │       │                   │   ├── PayeeExceptionHandler.java
│   │       │                   │   ├── PayeeHasDealException.java
│   │       │                   │   ├── PayeeMaxCountException.java
│   │       │                   │   ├── PayeeQueryRequest.java
│   │       │                   │   ├── PayeeRepository.java
│   │       │                   │   ├── PayeeService.java
│   │       │                   │   ├── PayeeSpec.java
│   │       │                   │   ├── PayeeUpdateRequest.java
│   │       │                   │   └── PayeeVOForList.java
│   │       │                   ├── permission/
│   │       │                   │   ├── PermissionCheck.java
│   │       │                   │   └── PermissionCheckAspect.java
│   │       │                   ├── refund/
│   │       │                   │   ├── Refund.java
│   │       │                   │   ├── RefundRepository.java
│   │       │                   │   └── RefundService.java
│   │       │                   ├── reports/
│   │       │                   │   ├── BreakOutOfMaxException.java
│   │       │                   │   ├── ChartVO.java
│   │       │                   │   ├── ChartVO2.java
│   │       │                   │   ├── ExpenseIncomeTrendQueryRequest.java
│   │       │                   │   ├── ReportController.java
│   │       │                   │   ├── ReportService.java
│   │       │                   │   ├── ReportsExceptionHandler.java
│   │       │                   │   └── TrendTimeQueryRequest.java
│   │       │                   ├── response/
│   │       │                   │   ├── BaseResponse.java
│   │       │                   │   ├── DataResponse.java
│   │       │                   │   ├── ErrorResponse.java
│   │       │                   │   └── HasNameVO.java
│   │       │                   ├── scheduled/
│   │       │                   │   ├── Scheduled.java
│   │       │                   │   ├── ScheduledAddRequest.java
│   │       │                   │   ├── ScheduledController.java
│   │       │                   │   ├── ScheduledExpenseAddRequest.java
│   │       │                   │   ├── ScheduledRepository.java
│   │       │                   │   └── ScheduledService.java
│   │       │                   ├── setting/
│   │       │                   │   └── Setting.java
│   │       │                   ├── tag/
│   │       │                   │   ├── Tag.java
│   │       │                   │   ├── TagAddRequest.java
│   │       │                   │   ├── TagController.java
│   │       │                   │   ├── TagExceptionHandler.java
│   │       │                   │   ├── TagHasTransactionException.java
│   │       │                   │   ├── TagMaxCountException.java
│   │       │                   │   ├── TagQueryRequest.java
│   │       │                   │   ├── TagRepository.java
│   │       │                   │   ├── TagService.java
│   │       │                   │   ├── TagSpec.java
│   │       │                   │   ├── TagTreeVO.java
│   │       │                   │   ├── TagUpdateRequest.java
│   │       │                   │   └── TagVOForList.java
│   │       │                   ├── tag_relation/
│   │       │                   │   ├── TagRelation.java
│   │       │                   │   ├── TagRelationController.java
│   │       │                   │   ├── TagRelationRepository.java
│   │       │                   │   ├── TagRelationService.java
│   │       │                   │   ├── TagRelationUpdateRequest.java
│   │       │                   │   └── TagRelationVOForList.java
│   │       │                   ├── transaction/
│   │       │                   │   ├── Transaction.java
│   │       │                   │   ├── TransactionAddRequest.java
│   │       │                   │   ├── TransactionRepository.java
│   │       │                   │   ├── TransactionSpec.java
│   │       │                   │   ├── TransactionUpdateRequest.java
│   │       │                   │   └── TransactionVOForList.java
│   │       │                   ├── transfer/
│   │       │                   │   ├── Transfer.java
│   │       │                   │   ├── TransferAddRequest.java
│   │       │                   │   ├── TransferController.java
│   │       │                   │   ├── TransferExceptionHandler.java
│   │       │                   │   ├── TransferFromEqualsToException.java
│   │       │                   │   ├── TransferQueryResultVO.java
│   │       │                   │   ├── TransferRepository.java
│   │       │                   │   ├── TransferService.java
│   │       │                   │   ├── TransferSpec.java
│   │       │                   │   ├── TransferUpdateRequest.java
│   │       │                   │   └── TransferVOForList.java
│   │       │                   ├── user/
│   │       │                   │   ├── InviteCodeErrorException.java
│   │       │                   │   ├── IpNotAllowedException.java
│   │       │                   │   ├── OldPasswordErrorException.java
│   │       │                   │   ├── RegisterNameExistsException.java
│   │       │                   │   ├── SessionUserNotFoundException.java
│   │       │                   │   ├── SessionVO.java
│   │       │                   │   ├── SigninFailedException.java
│   │       │                   │   ├── UploadNotImageException.java
│   │       │                   │   ├── User.java
│   │       │                   │   ├── UserController.java
│   │       │                   │   ├── UserDisabledException.java
│   │       │                   │   ├── UserExceptionHandler.java
│   │       │                   │   ├── UserGroupRelation.java
│   │       │                   │   ├── UserGroupRelationRepository.java
│   │       │                   │   ├── UserRegisterRequest.java
│   │       │                   │   ├── UserRepository.java
│   │       │                   │   ├── UserService.java
│   │       │                   │   ├── UserSessionVO.java
│   │       │                   │   ├── UserSignInRequest.java
│   │       │                   │   ├── UserSignInResponse.java
│   │       │                   │   └── UserUpdatePasswordRequest.java
│   │       │                   ├── user_log/
│   │       │                   │   ├── FlowMaxCountException.java
│   │       │                   │   ├── UserActionExceptionHandler.java
│   │       │                   │   ├── UserActionLog.java
│   │       │                   │   ├── UserActionLogRepository.java
│   │       │                   │   └── UserActionLogService.java
│   │       │                   ├── utils/
│   │       │                   │   ├── CalendarUtils.java
│   │       │                   │   ├── CommonUtils.java
│   │       │                   │   └── EnumUtils.java
│   │       │                   └── validation/
│   │       │                       ├── AmountAccumulateValidator.java
│   │       │                       ├── AmountValidator.java
│   │       │                       ├── AprValidator.java
│   │       │                       ├── AvatarValidator.java
│   │       │                       ├── BalanceValidator.java
│   │       │                       ├── BillDayValidator.java
│   │       │                       ├── CreditLimitValidator.java
│   │       │                       ├── DescriptionValidator.java
│   │       │                       ├── NameValidator.java
│   │       │                       ├── NoValidator.java
│   │       │                       ├── NotesValidator.java
│   │       │                       ├── PasswordValidator.java
│   │       │                       ├── TimeValidator.java
│   │       │                       ├── TransactionStatusValidator.java
│   │       │                       └── UserNameValidator.java
│   │       └── resources/
│   │           ├── application.properties
│   │           └── i18n/
│   │               └── messages.properties
│   ├── start.sh
│   ├── startup.sh
│   └── stop.sh
├── bookkeeping-user-fe/
│   ├── .editorconfig
│   ├── .eslintrc
│   ├── .prettierignore
│   ├── .prettierrc
│   ├── .umirc.js
│   ├── Dockerfile
│   ├── docker/
│   │   ├── gzip.conf
│   │   ├── nginx.conf
│   │   └── nginx.conf.template
│   ├── mock/
│   │   └── .gitkeep
│   ├── package.json
│   ├── src/
│   │   ├── app.js
│   │   ├── components/
│   │   │   ├── AccountRecordTable/
│   │   │   │   └── index.jsx
│   │   │   ├── AdjustBalanceModal/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── AlertTotalSearch/
│   │   │   │   └── index.jsx
│   │   │   ├── AmountInput/
│   │   │   │   └── index.jsx
│   │   │   ├── AmountInputPositive/
│   │   │   │   └── index.jsx
│   │   │   ├── AvatarDropdown/
│   │   │   │   ├── UpdatePasswordModal.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── Breadcrumb/
│   │   │   │   └── index.jsx
│   │   │   ├── ExpenseModal/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── FlagTag/
│   │   │   │   └── index.jsx
│   │   │   ├── FlowButtons/
│   │   │   │   └── index.jsx
│   │   │   ├── FlowImageUploadModal/
│   │   │   │   └── index.jsx
│   │   │   ├── FlowRecordTable/
│   │   │   │   └── index.jsx
│   │   │   ├── FlowStatusDisplay/
│   │   │   │   └── index.jsx
│   │   │   ├── FlowTagDisplay/
│   │   │   │   ├── TagModal.jsx
│   │   │   │   └── index.jsx
│   │   │   ├── Footer/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── FormItemAccount/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemAccounts/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemAmountRange/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemCategories/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemCategoryReport/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemCreateTime/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemDateRange/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemDateRangeWithBreak/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemDescription/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemDescriptionSearch/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemPayee/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemPayees/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemStatus/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemTag/
│   │   │   │   ├── AddTagModal.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── FormItemTagReport/
│   │   │   │   └── index.jsx
│   │   │   ├── FormItemTags/
│   │   │   │   └── index.jsx
│   │   │   ├── FormListCategory/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── FormModal/
│   │   │   │   └── index.jsx
│   │   │   ├── HeaderDropdown/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── IncomeModal/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── Loading/
│   │   │   │   └── index.jsx
│   │   │   ├── ModalRoot/
│   │   │   │   └── index.jsx
│   │   │   ├── PrimaryMenu/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   ├── TransferModal/
│   │   │   │   ├── index.jsx
│   │   │   │   └── index.less
│   │   │   └── charts/
│   │   │       ├── Bar/
│   │   │       │   ├── index.jsx
│   │   │       │   └── index.less
│   │   │       ├── Line/
│   │   │       │   ├── index.jsx
│   │   │       │   └── index.less
│   │   │       ├── Pie/
│   │   │       │   ├── index.jsx
│   │   │       │   └── index.less
│   │   │       └── Pie2/
│   │   │           ├── index.jsx
│   │   │           └── index.less
│   │   ├── global.less
│   │   ├── layouts/
│   │   │   ├── BasicLayout.jsx
│   │   │   ├── BasicLayout.less
│   │   │   ├── UserLayout.jsx
│   │   │   ├── UserLayout.less
│   │   │   └── index.js
│   │   ├── locales/
│   │   │   ├── en-US/
│   │   │   │   ├── account.js
│   │   │   │   ├── book.js
│   │   │   │   ├── category.js
│   │   │   │   ├── common.js
│   │   │   │   ├── dashboard.js
│   │   │   │   ├── flow.js
│   │   │   │   ├── footer.js
│   │   │   │   ├── group.js
│   │   │   │   ├── header.js
│   │   │   │   ├── menu.js
│   │   │   │   ├── register.js
│   │   │   │   ├── report.js
│   │   │   │   ├── rules.js
│   │   │   │   ├── schedule.js
│   │   │   │   └── signin.js
│   │   │   ├── en-US.js
│   │   │   ├── zh-CN/
│   │   │   │   ├── account.js
│   │   │   │   ├── book.js
│   │   │   │   ├── category.js
│   │   │   │   ├── common.js
│   │   │   │   ├── flow.js
│   │   │   │   ├── footer.js
│   │   │   │   ├── group.js
│   │   │   │   ├── menu.js
│   │   │   │   ├── report.js
│   │   │   │   ├── rules.js
│   │   │   │   ├── schedule.js
│   │   │   │   └── user.js
│   │   │   └── zh-CN.js
│   │   ├── models/
│   │   │   ├── account.js
│   │   │   ├── currency.js
│   │   │   ├── expenseCategory.js
│   │   │   ├── flow.js
│   │   │   ├── incomeCategory.js
│   │   │   ├── modal.js
│   │   │   ├── payee.js
│   │   │   ├── session.js
│   │   │   └── tag.js
│   │   ├── pages/
│   │   │   ├── accounts/
│   │   │   │   ├── AssetAccountModal.jsx
│   │   │   │   ├── AssetAccountTable.jsx
│   │   │   │   ├── CheckingAccountModal.jsx
│   │   │   │   ├── CheckingAccountTable.jsx
│   │   │   │   ├── CreditAccountModal.jsx
│   │   │   │   ├── CreditAccountTable.jsx
│   │   │   │   ├── DebtAccountModal.jsx
│   │   │   │   ├── DebtAccountTable.jsx
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── model.js
│   │   │   ├── asset-accounts/
│   │   │   │   ├── GeneralBar.jsx
│   │   │   │   ├── ItemCard.jsx
│   │   │   │   ├── List.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── audit/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── TotalAlert.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── model.js
│   │   │   ├── balance-logs/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── OperationModal.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── books/
│   │   │   │   ├── ConfigModal.jsx
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── OperationModal.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── categories/
│   │   │   │   ├── ExpenseCategoryFilterBar.jsx
│   │   │   │   ├── ExpenseCategoryModal.jsx
│   │   │   │   ├── ExpenseCategoryTable.jsx
│   │   │   │   ├── IncomeCategoryFilterBar.jsx
│   │   │   │   ├── IncomeCategoryModal.jsx
│   │   │   │   ├── IncomeCategoryTable.jsx
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── PayeeFilterBar.jsx
│   │   │   │   ├── PayeeModal.jsx
│   │   │   │   ├── PayeeTable.jsx
│   │   │   │   ├── TagFilterBar.jsx
│   │   │   │   ├── TagModal.jsx
│   │   │   │   ├── TagTable.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── checking-accounts/
│   │   │   │   ├── GeneralBar.jsx
│   │   │   │   ├── ItemCard.jsx
│   │   │   │   ├── List.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── credit-accounts/
│   │   │   │   ├── GeneralBar.jsx
│   │   │   │   ├── ItemCard.jsx
│   │   │   │   ├── List.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── dashboard/
│   │   │   │   ├── AssetBar.jsx
│   │   │   │   ├── CardExtra.jsx
│   │   │   │   ├── ExpenseCategory.jsx
│   │   │   │   ├── ExpenseTrend.jsx
│   │   │   │   ├── IncomeCategory.jsx
│   │   │   │   ├── IncomeTrend.jsx
│   │   │   │   ├── TransactionTable.jsx
│   │   │   │   ├── TransactionTable.less
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── debt-accounts/
│   │   │   │   ├── GeneralBar.jsx
│   │   │   │   ├── ItemCard.jsx
│   │   │   │   ├── List.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── document.ejs
│   │   │   ├── expenses/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── TotalAlert.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── model.js
│   │   │   ├── flows/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── TotalAlert.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── model.js
│   │   │   ├── groups/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── OperationModal.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── incomes/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── TotalAlert.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   └── model.js
│   │   │   ├── index.jsx
│   │   │   ├── items/
│   │   │   │   ├── OperationBar.jsx
│   │   │   │   ├── OperationModal.jsx
│   │   │   │   ├── RecordTable.jsx
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── register/
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── reports/
│   │   │   │   ├── asset-debt-trend/
│   │   │   │   │   ├── Chart.jsx
│   │   │   │   │   ├── OperationBar.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   ├── balance-sheet/
│   │   │   │   │   ├── AssetCategory.jsx
│   │   │   │   │   ├── DebtCategory.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   ├── expense-category/
│   │   │   │   │   ├── CategoryPie.jsx
│   │   │   │   │   ├── OperationBar.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   ├── expense-income-trend/
│   │   │   │   │   ├── Chart.jsx
│   │   │   │   │   ├── OperationBar.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   ├── expense-tag/
│   │   │   │   │   ├── OperationBar.jsx
│   │   │   │   │   ├── TagPie.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   ├── income-category/
│   │   │   │   │   ├── CategoryPie.jsx
│   │   │   │   │   ├── OperationBar.jsx
│   │   │   │   │   ├── index.jsx
│   │   │   │   │   └── model.js
│   │   │   │   └── income-tag/
│   │   │   │       ├── OperationBar.jsx
│   │   │   │       ├── TagPie.jsx
│   │   │   │       ├── index.jsx
│   │   │   │       └── model.js
│   │   │   ├── scheduled/
│   │   │   │   └── index.jsx
│   │   │   ├── settings/
│   │   │   │   └── index.jsx
│   │   │   ├── signin/
│   │   │   │   ├── RememberDropDown.js
│   │   │   │   ├── index.jsx
│   │   │   │   ├── index.less
│   │   │   │   └── model.js
│   │   │   ├── test/
│   │   │   │   └── index.jsx
│   │   │   └── transfers/
│   │   │       ├── OperationBar.jsx
│   │   │       ├── RecordTable.jsx
│   │   │       ├── TotalAlert.jsx
│   │   │       ├── index.jsx
│   │   │       └── model.js
│   │   ├── services/
│   │   │   ├── account.js
│   │   │   ├── adjust-balance.js
│   │   │   ├── asset-account.js
│   │   │   ├── book.js
│   │   │   ├── category.js
│   │   │   ├── checking-account.js
│   │   │   ├── credit-account.js
│   │   │   ├── currency.js
│   │   │   ├── dashboard.js
│   │   │   ├── deal.js
│   │   │   ├── debt-account.js
│   │   │   ├── expense-category.js
│   │   │   ├── expense.js
│   │   │   ├── flow-image.js
│   │   │   ├── flow.js
│   │   │   ├── group.js
│   │   │   ├── income-category.js
│   │   │   ├── income.js
│   │   │   ├── item.js
│   │   │   ├── log.js
│   │   │   ├── payee.js
│   │   │   ├── report.js
│   │   │   ├── schedule.js
│   │   │   ├── tag-relation.js
│   │   │   ├── tag.js
│   │   │   ├── transfer.js
│   │   │   └── user.js
│   │   └── utils/
│   │       ├── columns.js
│   │       ├── flow.js
│   │       ├── hooks.js
│   │       ├── model.js
│   │       ├── request.js
│   │       ├── rules.js
│   │       ├── translate.js
│   │       ├── util.js
│   │       └── var.js
│   └── webpack.config.js
├── bookkeeping_user_flutter/
│   ├── .gitignore
│   ├── .metadata
│   ├── README.md
│   ├── analysis_options.yaml
│   ├── android/
│   │   ├── .gitignore
│   │   ├── app/
│   │   │   ├── build.gradle
│   │   │   └── src/
│   │   │       ├── debug/
│   │   │       │   └── AndroidManifest.xml
│   │   │       ├── main/
│   │   │       │   ├── AndroidManifest.xml
│   │   │       │   ├── kotlin/
│   │   │       │   │   └── com/
│   │   │       │   │       └── whlcsj/
│   │   │       │   │           └── bookkeeping_user_flutter/
│   │   │       │   │               └── MainActivity.kt
│   │   │       │   └── res/
│   │   │       │       ├── drawable/
│   │   │       │       │   └── launch_background.xml
│   │   │       │       ├── drawable-v21/
│   │   │       │       │   └── launch_background.xml
│   │   │       │       ├── values/
│   │   │       │       │   └── styles.xml
│   │   │       │       └── values-night/
│   │   │       │           └── styles.xml
│   │   │       └── profile/
│   │   │           └── AndroidManifest.xml
│   │   ├── build.gradle
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       └── gradle-wrapper.properties
│   │   ├── gradle.properties
│   │   └── settings.gradle
│   ├── ios/
│   │   ├── .gitignore
│   │   ├── Flutter/
│   │   │   ├── AppFrameworkInfo.plist
│   │   │   ├── Debug.xcconfig
│   │   │   └── Release.xcconfig
│   │   ├── Podfile
│   │   ├── Runner/
│   │   │   ├── AppDelegate.swift
│   │   │   ├── Assets.xcassets/
│   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── LaunchImage.imageset/
│   │   │   │       ├── Contents.json
│   │   │   │       └── README.md
│   │   │   ├── Base.lproj/
│   │   │   │   ├── LaunchScreen.storyboard
│   │   │   │   └── Main.storyboard
│   │   │   ├── Info.plist
│   │   │   └── Runner-Bridging-Header.h
│   │   ├── Runner.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   ├── project.xcworkspace/
│   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   └── xcshareddata/
│   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           └── Runner.xcscheme
│   │   └── Runner.xcworkspace/
│   │       ├── contents.xcworkspacedata
│   │       └── xcshareddata/
│   │           ├── IDEWorkspaceChecks.plist
│   │           └── WorkspaceSettings.xcsettings
│   ├── lib/
│   │   ├── accounts/
│   │   │   ├── accounts.dart
│   │   │   ├── bloc/
│   │   │   │   ├── account_adjust_balance/
│   │   │   │   │   ├── account_adjust_balance_bloc.dart
│   │   │   │   │   ├── account_adjust_balance_event.dart
│   │   │   │   │   └── account_adjust_balance_state.dart
│   │   │   │   ├── account_enable/
│   │   │   │   │   ├── account_enable_bloc.dart
│   │   │   │   │   ├── account_enable_event.dart
│   │   │   │   │   └── account_enable_state.dart
│   │   │   │   ├── account_expenseable/
│   │   │   │   │   ├── account_expenseable_bloc.dart
│   │   │   │   │   ├── account_expenseable_event.dart
│   │   │   │   │   └── account_expenseable_state.dart
│   │   │   │   ├── account_fetch/
│   │   │   │   │   ├── account_fetch_bloc.dart
│   │   │   │   │   ├── account_fetch_event.dart
│   │   │   │   │   └── account_fetch_state.dart
│   │   │   │   ├── account_form/
│   │   │   │   │   ├── account_form_bloc.dart
│   │   │   │   │   ├── account_form_event.dart
│   │   │   │   │   └── account_form_state.dart
│   │   │   │   ├── account_incomeable/
│   │   │   │   │   ├── account_incomeable_bloc.dart
│   │   │   │   │   ├── account_incomeable_event.dart
│   │   │   │   │   └── account_incomeable_state.dart
│   │   │   │   ├── account_transfer_from_able/
│   │   │   │   │   ├── account_transfer_from_able_bloc.dart
│   │   │   │   │   ├── account_transfer_from_able_event.dart
│   │   │   │   │   └── account_transfer_from_able_state.dart
│   │   │   │   ├── account_transfer_to_able/
│   │   │   │   │   ├── account_transfer_to_able_bloc.dart
│   │   │   │   │   ├── account_transfer_to_able_event.dart
│   │   │   │   │   └── account_transfer_to_able_state.dart
│   │   │   │   └── accounts/
│   │   │   │       ├── accounts_bloc.dart
│   │   │   │       ├── accounts_event.dart
│   │   │   │       └── accounts_state.dart
│   │   │   ├── data/
│   │   │   │   ├── account_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── account.dart
│   │   │   │       ├── account.g.dart
│   │   │   │       ├── account_form_request.dart
│   │   │   │       ├── account_form_request.g.dart
│   │   │   │       ├── account_query_request.dart
│   │   │   │       ├── account_query_request.g.dart
│   │   │   │       ├── adjust_balance_request.dart
│   │   │   │       ├── adjust_balance_request.g.dart
│   │   │   │       └── credit_account.dart
│   │   │   └── ui/
│   │   │       ├── account_adjust_balance.dart
│   │   │       ├── account_detail_page.dart
│   │   │       ├── account_form_page.dart
│   │   │       ├── accounts_page.dart
│   │   │       ├── asset_account_form_page.dart
│   │   │       ├── checking_account_form_page.dart
│   │   │       ├── credit_account_form_page.dart
│   │   │       ├── debt_account_form_page.dart
│   │   │       └── widgets/
│   │   │           ├── account_form/
│   │   │           │   ├── account_apr_input.dart
│   │   │           │   ├── account_balance_input.dart
│   │   │           │   ├── account_billday_input.dart
│   │   │           │   ├── account_limit_input.dart
│   │   │           │   ├── currency_input.dart
│   │   │           │   ├── expenseable_input.dart
│   │   │           │   ├── inclue_input.dart
│   │   │           │   ├── incomeable_input.dart
│   │   │           │   ├── name_input.dart
│   │   │           │   ├── no_input.dart
│   │   │           │   ├── notes_input.dart
│   │   │           │   ├── transfer_from_able_input.dart
│   │   │           │   └── transfer_to_able_input.dart
│   │   │           ├── adjust_balance/
│   │   │           │   ├── adjust_balance_form.dart
│   │   │           │   ├── balance_input.dart
│   │   │           │   ├── date_time_input.dart
│   │   │           │   ├── description_input.dart
│   │   │           │   └── notes_input.dart
│   │   │           └── order_button.dart
│   │   ├── add_flow/
│   │   │   ├── add_flow.dart
│   │   │   ├── bloc/
│   │   │   │   ├── add_expense/
│   │   │   │   │   ├── add_expense_bloc.dart
│   │   │   │   │   ├── add_expense_event.dart
│   │   │   │   │   └── add_expense_state.dart
│   │   │   │   ├── add_income/
│   │   │   │   │   ├── add_income_bloc.dart
│   │   │   │   │   ├── add_income_event.dart
│   │   │   │   │   └── add_income_state.dart
│   │   │   │   ├── add_transfer/
│   │   │   │   │   ├── add_transfer_bloc.dart
│   │   │   │   │   ├── add_transfer_event.dart
│   │   │   │   │   └── add_transfer_state.dart
│   │   │   │   └── models/
│   │   │   │       ├── deal_add_request.dart
│   │   │   │       ├── deal_add_request.g.dart
│   │   │   │       ├── transfer_add_request.dart
│   │   │   │       └── transfer_add_request.g.dart
│   │   │   └── ui/
│   │   │       ├── add_flow_page.dart
│   │   │       ├── no_tab_page.dart
│   │   │       ├── tab_page.dart
│   │   │       └── widgets/
│   │   │           ├── expense/
│   │   │           │   ├── account_input.dart
│   │   │           │   ├── add_expense_form.dart
│   │   │           │   ├── category_input.dart
│   │   │           │   ├── date_time_input.dart
│   │   │           │   ├── description_input.dart
│   │   │           │   ├── is_confirm_input.dart
│   │   │           │   ├── notes_input.dart
│   │   │           │   ├── payee_input.dart
│   │   │           │   ├── tag_input.dart
│   │   │           │   └── widgets.dart
│   │   │           ├── income/
│   │   │           │   ├── account_input.dart
│   │   │           │   ├── add_income_form.dart
│   │   │           │   ├── category_input.dart
│   │   │           │   ├── date_time_input.dart
│   │   │           │   ├── description_input.dart
│   │   │           │   ├── is_confirm_input.dart
│   │   │           │   ├── notes_input.dart
│   │   │           │   ├── payee_input.dart
│   │   │           │   ├── tag_input.dart
│   │   │           │   └── widgets.dart
│   │   │           └── transfer/
│   │   │               ├── add_transfer_form.dart
│   │   │               ├── amount_input.dart
│   │   │               ├── converted_amount_input.dart
│   │   │               ├── date_time_input.dart
│   │   │               ├── description_input.dart
│   │   │               ├── from_input.dart
│   │   │               ├── is_confirm_input.dart
│   │   │               ├── notes_input.dart
│   │   │               ├── tag_input.dart
│   │   │               ├── to_input.dart
│   │   │               └── widgets.dart
│   │   ├── app.dart
│   │   ├── books/
│   │   │   ├── bloc/
│   │   │   │   ├── book_fetch/
│   │   │   │   │   ├── book_fetch_bloc.dart
│   │   │   │   │   ├── book_fetch_event.dart
│   │   │   │   │   └── book_fetch_state.dart
│   │   │   │   └── books/
│   │   │   │       ├── books_bloc.dart
│   │   │   │       ├── books_event.dart
│   │   │   │       └── books_state.dart
│   │   │   ├── books.dart
│   │   │   ├── data/
│   │   │   │   ├── book_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── book.dart
│   │   │   │       ├── book.g.dart
│   │   │   │       ├── book_query_request.dart
│   │   │   │       └── book_query_request.g.dart
│   │   │   └── ui/
│   │   │       ├── book_detail_page.dart
│   │   │       └── books_page.dart
│   │   ├── categories/
│   │   │   ├── bloc/
│   │   │   │   ├── category_fetch/
│   │   │   │   │   ├── category_fetch_bloc.dart
│   │   │   │   │   ├── category_fetch_event.dart
│   │   │   │   │   └── category_fetch_state.dart
│   │   │   │   ├── category_form/
│   │   │   │   │   ├── category_form_bloc.dart
│   │   │   │   │   ├── category_form_event.dart
│   │   │   │   │   └── category_form_state.dart
│   │   │   │   ├── category_tree/
│   │   │   │   │   ├── category_tree_bloc.dart
│   │   │   │   │   ├── category_tree_event.dart
│   │   │   │   │   └── category_tree_state.dart
│   │   │   │   ├── expense_category_select/
│   │   │   │   │   ├── expense_category_select_bloc.dart
│   │   │   │   │   ├── expense_category_select_event.dart
│   │   │   │   │   └── expense_category_select_state.dart
│   │   │   │   └── income_category_select/
│   │   │   │       ├── income_category_select_bloc.dart
│   │   │   │       ├── income_category_select_event.dart
│   │   │   │       └── income_category_select_state.dart
│   │   │   ├── categories.dart
│   │   │   ├── data/
│   │   │   │   ├── category_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── category.dart
│   │   │   │       ├── category.g.dart
│   │   │   │       ├── category_form_request.dart
│   │   │   │       ├── category_form_request.g.dart
│   │   │   │       ├── category_tree.dart
│   │   │   │       └── category_tree.g.dart
│   │   │   └── ui/
│   │   │       ├── category_detail_page.dart
│   │   │       ├── category_form_page.dart
│   │   │       ├── expense_categories_page.dart
│   │   │       ├── expense_category_form_page.dart
│   │   │       ├── income_categories_page.dart
│   │   │       ├── income_category_form_page.dart
│   │   │       └── widgets/
│   │   │           └── category_form/
│   │   │               ├── expense_category_input.dart
│   │   │               ├── income_category_input.dart
│   │   │               ├── name_input.dart
│   │   │               └── notes_input.dart
│   │   ├── charts/
│   │   │   ├── bloc/
│   │   │   │   ├── report_asset/
│   │   │   │   │   ├── report_asset_bloc.dart
│   │   │   │   │   ├── report_asset_event.dart
│   │   │   │   │   └── report_asset_state.dart
│   │   │   │   ├── report_debt/
│   │   │   │   │   ├── report_debt_bloc.dart
│   │   │   │   │   ├── report_debt_event.dart
│   │   │   │   │   └── report_debt_state.dart
│   │   │   │   ├── report_expense_category/
│   │   │   │   │   ├── report_expense_category_bloc.dart
│   │   │   │   │   ├── report_expense_category_event.dart
│   │   │   │   │   └── report_expense_category_state.dart
│   │   │   │   └── report_income_category/
│   │   │   │       ├── report_income_category_bloc.dart
│   │   │   │       ├── report_income_category_event.dart
│   │   │   │       └── report_income_category_state.dart
│   │   │   ├── charts.dart
│   │   │   ├── data/
│   │   │   │   ├── models/
│   │   │   │   │   ├── category_query_request.dart
│   │   │   │   │   ├── category_query_request.g.dart
│   │   │   │   │   ├── x_y.dart
│   │   │   │   │   └── x_y.g.dart
│   │   │   │   └── report_repository.dart
│   │   │   └── ui/
│   │   │       ├── charts_expense_category_filter_page.dart
│   │   │       ├── charts_income_category_filter_page.dart
│   │   │       ├── charts_page.dart
│   │   │       └── widgets/
│   │   │           ├── asset_sheet.dart
│   │   │           ├── circular_legend.dart
│   │   │           ├── date_input_expense.dart
│   │   │           ├── date_input_income.dart
│   │   │           ├── debt_sheet.dart
│   │   │           ├── expense_category.dart
│   │   │           ├── expense_category_input.dart
│   │   │           ├── income_category.dart
│   │   │           └── income_category_input.dart
│   │   ├── commons/
│   │   │   ├── common_util.dart
│   │   │   ├── commons.dart
│   │   │   ├── enums.dart
│   │   │   ├── http_client.dart
│   │   │   ├── id_name_model.dart
│   │   │   ├── id_name_model.g.dart
│   │   │   ├── session.dart
│   │   │   ├── web_view_page.dart
│   │   │   └── widget_util.dart
│   │   ├── components/
│   │   │   ├── components.dart
│   │   │   ├── date_range_picker.dart
│   │   │   ├── date_time_input.dart
│   │   │   ├── empty.dart
│   │   │   ├── lazy_indexed_stack.dart
│   │   │   ├── page_error.dart
│   │   │   ├── page_loading.dart
│   │   │   └── popup_menu.dart
│   │   ├── currency/
│   │   │   ├── bloc/
│   │   │   │   └── currency_all/
│   │   │   │       ├── currency_all_bloc.dart
│   │   │   │       ├── currency_all_event.dart
│   │   │   │       └── currency_all_state.dart
│   │   │   ├── currency.dart
│   │   │   └── data/
│   │   │       ├── currency_repository.dart
│   │   │       └── models/
│   │   │           ├── currency.dart
│   │   │           └── currency.g.dart
│   │   ├── flows/
│   │   │   ├── bloc/
│   │   │   │   ├── flow_fetch/
│   │   │   │   │   ├── flow_fetch_bloc.dart
│   │   │   │   │   ├── flow_fetch_event.dart
│   │   │   │   │   └── flow_fetch_state.dart
│   │   │   │   └── flows/
│   │   │   │       ├── flows_bloc.dart
│   │   │   │       ├── flows_event.dart
│   │   │   │       └── flows_state.dart
│   │   │   ├── data/
│   │   │   │   ├── flow_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── adjust_balance.dart
│   │   │   │       ├── adjust_balance.g.dart
│   │   │   │       ├── category.dart
│   │   │   │       ├── category.g.dart
│   │   │   │       ├── deal.dart
│   │   │   │       ├── deal.g.dart
│   │   │   │       ├── flow.dart
│   │   │   │       ├── flow.g.dart
│   │   │   │       ├── flow_image.dart
│   │   │   │       ├── flow_image.g.dart
│   │   │   │       ├── flow_query_request.dart
│   │   │   │       ├── flow_query_request.g.dart
│   │   │   │       ├── tag.dart
│   │   │   │       ├── tag.g.dart
│   │   │   │       ├── transfer.dart
│   │   │   │       └── transfer.g.dart
│   │   │   ├── flows.dart
│   │   │   └── ui/
│   │   │       ├── flow_detail.dart
│   │   │       ├── flows_filter.dart
│   │   │       ├── flows_page.dart
│   │   │       └── widgets/
│   │   │           ├── account_input.dart
│   │   │           ├── date_input.dart
│   │   │           ├── expense_category_input.dart
│   │   │           ├── income_category_input.dart
│   │   │           ├── order_button.dart
│   │   │           ├── payee_input.dart
│   │   │           ├── status_input.dart
│   │   │           ├── tag_input.dart
│   │   │           ├── type_input.dart
│   │   │           └── widgets.dart
│   │   ├── groups/
│   │   │   ├── data/
│   │   │   │   └── models/
│   │   │   │       ├── group.dart
│   │   │   │       └── group.g.dart
│   │   │   └── groups.dart
│   │   ├── index.dart
│   │   ├── items/
│   │   │   ├── bloc/
│   │   │   │   ├── item_form/
│   │   │   │   │   ├── item_form_bloc.dart
│   │   │   │   │   ├── item_form_event.dart
│   │   │   │   │   ├── item_form_state.dart
│   │   │   │   │   └── models/
│   │   │   │   │       ├── models.dart
│   │   │   │   │       └── title.dart
│   │   │   │   └── items/
│   │   │   │       ├── items_bloc.dart
│   │   │   │       ├── items_event.dart
│   │   │   │       └── items_state.dart
│   │   │   ├── data/
│   │   │   │   ├── item_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── item.dart
│   │   │   │       ├── item.g.dart
│   │   │   │       ├── item_add_request.dart
│   │   │   │       ├── item_add_request.g.dart
│   │   │   │       ├── item_query_request.dart
│   │   │   │       └── item_query_request.g.dart
│   │   │   ├── items.dart
│   │   │   └── ui/
│   │   │       ├── item_form/
│   │   │       │   ├── date_input.dart
│   │   │       │   └── title_input.dart
│   │   │       ├── item_form_page.dart
│   │   │       ├── items_index.dart
│   │   │       └── items_page.dart
│   │   ├── login/
│   │   │   ├── bloc/
│   │   │   │   ├── auth/
│   │   │   │   │   ├── auth_bloc.dart
│   │   │   │   │   ├── auth_event.dart
│   │   │   │   │   └── auth_state.dart
│   │   │   │   └── login/
│   │   │   │       ├── login_bloc.dart
│   │   │   │       ├── login_event.dart
│   │   │   │       ├── login_state.dart
│   │   │   │       └── models/
│   │   │   │           ├── ApiUrl.dart
│   │   │   │           ├── password.dart
│   │   │   │           └── username.dart
│   │   │   ├── data/
│   │   │   │   ├── login_repository.dart
│   │   │   │   └── models/
│   │   │   │       ├── session.dart
│   │   │   │       ├── session.g.dart
│   │   │   │       ├── user.dart
│   │   │   │       └── user.g.dart
│   │   │   ├── login.dart
│   │   │   └── ui/
│   │   │       ├── login_page.dart
│   │   │       └── widgets/
│   │   │           ├── api_url_input.dart
│   │   │           ├── login_form.dart
│   │   │           ├── password_input.dart
│   │   │           ├── submit_btn.dart
│   │   │           └── user_name_input.dart
│   │   ├── main.dart
│   │   ├── my/
│   │   │   ├── my.dart
│   │   │   └── my_page.dart
│   │   ├── observer.dart
│   │   ├── payees/
│   │   │   ├── bloc/
│   │   │   │   ├── payee_enable/
│   │   │   │   │   ├── payee_enable_bloc.dart
│   │   │   │   │   ├── payee_enable_event.dart
│   │   │   │   │   └── payee_enable_state.dart
│   │   │   │   ├── payee_expenseable/
│   │   │   │   │   ├── payee_expenseable_bloc.dart
│   │   │   │   │   ├── payee_expenseable_event.dart
│   │   │   │   │   └── payee_expenseable_state.dart
│   │   │   │   ├── payee_fetch/
│   │   │   │   │   ├── payee_fetch_bloc.dart
│   │   │   │   │   ├── payee_fetch_event.dart
│   │   │   │   │   └── payee_fetch_state.dart
│   │   │   │   ├── payee_form/
│   │   │   │   │   ├── payee_form_bloc.dart
│   │   │   │   │   ├── payee_form_event.dart
│   │   │   │   │   └── payee_form_state.dart
│   │   │   │   ├── payee_incomeable/
│   │   │   │   │   ├── payee_incomeable_bloc.dart
│   │   │   │   │   ├── payee_incomeable_event.dart
│   │   │   │   │   └── payee_incomeable_state.dart
│   │   │   │   └── payees/
│   │   │   │       ├── payees_bloc.dart
│   │   │   │       ├── payees_event.dart
│   │   │   │       └── payees_state.dart
│   │   │   ├── data/
│   │   │   │   ├── models/
│   │   │   │   │   ├── payee.dart
│   │   │   │   │   ├── payee.g.dart
│   │   │   │   │   ├── payee_form_request.dart
│   │   │   │   │   ├── payee_form_request.g.dart
│   │   │   │   │   ├── payee_query_request.dart
│   │   │   │   │   └── payee_query_request.g.dart
│   │   │   │   └── payee_repository.dart
│   │   │   ├── payees.dart
│   │   │   └── ui/
│   │   │       ├── payee_detail_page.dart
│   │   │       ├── payee_form/
│   │   │       │   ├── expenseable_input.dart
│   │   │       │   ├── incomeable_input.dart
│   │   │       │   ├── name_input.dart
│   │   │       │   └── notes_input.dart
│   │   │       ├── payee_form_page.dart
│   │   │       └── payees_page.dart
│   │   ├── routes.dart
│   │   ├── start_page.dart
│   │   ├── tags/
│   │   │   ├── bloc/
│   │   │   │   ├── tag_enable/
│   │   │   │   │   ├── tag_enable_bloc.dart
│   │   │   │   │   ├── tag_enable_event.dart
│   │   │   │   │   └── tag_enable_state.dart
│   │   │   │   ├── tag_expenseable/
│   │   │   │   │   ├── tag_expenseable_bloc.dart
│   │   │   │   │   ├── tag_expenseable_event.dart
│   │   │   │   │   └── tag_expenseable_state.dart
│   │   │   │   ├── tag_fetch/
│   │   │   │   │   ├── tag_fetch_bloc.dart
│   │   │   │   │   ├── tag_fetch_event.dart
│   │   │   │   │   └── tag_fetch_state.dart
│   │   │   │   ├── tag_form/
│   │   │   │   │   ├── tag_form_bloc.dart
│   │   │   │   │   ├── tag_form_event.dart
│   │   │   │   │   └── tag_form_state.dart
│   │   │   │   ├── tag_incomeable/
│   │   │   │   │   ├── tag_incomeable_bloc.dart
│   │   │   │   │   ├── tag_incomeable_event.dart
│   │   │   │   │   └── tag_incomeable_state.dart
│   │   │   │   ├── tag_transferable/
│   │   │   │   │   ├── tag_transferable_bloc.dart
│   │   │   │   │   ├── tag_transferable_event.dart
│   │   │   │   │   └── tag_transferable_state.dart
│   │   │   │   └── tag_tree/
│   │   │   │       ├── tag_tree_bloc.dart
│   │   │   │       ├── tag_tree_event.dart
│   │   │   │       └── tag_tree_state.dart
│   │   │   ├── data/
│   │   │   │   ├── models/
│   │   │   │   │   ├── tag.dart
│   │   │   │   │   ├── tag.g.dart
│   │   │   │   │   ├── tag_form_request.dart
│   │   │   │   │   ├── tag_form_request.g.dart
│   │   │   │   │   ├── tag_tree.dart
│   │   │   │   │   └── tag_tree.g.dart
│   │   │   │   └── tag_repository.dart
│   │   │   ├── tags.dart
│   │   │   └── ui/
│   │   │       ├── tag_detail_page.dart
│   │   │       ├── tag_form_page.dart
│   │   │       ├── tags_page.dart
│   │   │       └── widgets/
│   │   │           └── tag_form/
│   │   │               ├── expenseable_input.dart
│   │   │               ├── incomeable_input.dart
│   │   │               ├── name_input.dart
│   │   │               ├── notes_input.dart
│   │   │               ├── parent_input.dart
│   │   │               └── transferable_input.dart
│   │   └── themes.dart
│   ├── linux/
│   │   ├── .gitignore
│   │   ├── CMakeLists.txt
│   │   ├── flutter/
│   │   │   ├── CMakeLists.txt
│   │   │   ├── generated_plugin_registrant.cc
│   │   │   ├── generated_plugin_registrant.h
│   │   │   └── generated_plugins.cmake
│   │   ├── main.cc
│   │   ├── my_application.cc
│   │   └── my_application.h
│   ├── macos/
│   │   ├── .gitignore
│   │   ├── Flutter/
│   │   │   ├── Flutter-Debug.xcconfig
│   │   │   ├── Flutter-Release.xcconfig
│   │   │   └── GeneratedPluginRegistrant.swift
│   │   ├── Podfile
│   │   ├── Runner/
│   │   │   ├── AppDelegate.swift
│   │   │   ├── Assets.xcassets/
│   │   │   │   └── AppIcon.appiconset/
│   │   │   │       └── Contents.json
│   │   │   ├── Base.lproj/
│   │   │   │   └── MainMenu.xib
│   │   │   ├── Configs/
│   │   │   │   ├── AppInfo.xcconfig
│   │   │   │   ├── Debug.xcconfig
│   │   │   │   ├── Release.xcconfig
│   │   │   │   └── Warnings.xcconfig
│   │   │   ├── DebugProfile.entitlements
│   │   │   ├── Info.plist
│   │   │   ├── MainFlutterWindow.swift
│   │   │   └── Release.entitlements
│   │   ├── Runner.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   ├── project.xcworkspace/
│   │   │   │   └── xcshareddata/
│   │   │   │       └── IDEWorkspaceChecks.plist
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           └── Runner.xcscheme
│   │   └── Runner.xcworkspace/
│   │       ├── contents.xcworkspacedata
│   │       └── xcshareddata/
│   │           └── IDEWorkspaceChecks.plist
│   ├── pubspec.yaml
│   ├── test/
│   │   └── widget_test.dart
│   └── windows/
│       ├── .gitignore
│       ├── CMakeLists.txt
│       ├── flutter/
│       │   ├── CMakeLists.txt
│       │   ├── generated_plugin_registrant.cc
│       │   ├── generated_plugin_registrant.h
│       │   └── generated_plugins.cmake
│       └── runner/
│           ├── CMakeLists.txt
│           ├── Runner.rc
│           ├── flutter_window.cpp
│           ├── flutter_window.h
│           ├── main.cpp
│           ├── resource.h
│           ├── runner.exe.manifest
│           ├── utils.cpp
│           ├── utils.h
│           ├── win32_window.cpp
│           └── win32_window.h
├── bookkeeping_user_uniapp/
│   ├── App.vue
│   ├── components/
│   │   ├── accounts/
│   │   │   └── accounts.vue
│   │   ├── expense-form/
│   │   │   └── expense-form.vue
│   │   ├── flows/
│   │   │   └── flows.vue
│   │   ├── income-form/
│   │   │   └── income-form.vue
│   │   ├── tab-bar/
│   │   │   └── tab-bar.vue
│   │   └── transfer-form/
│   │       └── transfer-form.vue
│   ├── config/
│   │   ├── api.js
│   │   └── request.js
│   ├── index.html
│   ├── main.js
│   ├── manifest.json
│   ├── package.json
│   ├── pages/
│   │   ├── account-detail/
│   │   │   └── account-detail.vue
│   │   ├── accounts/
│   │   │   └── accounts.vue
│   │   ├── books/
│   │   │   └── books.vue
│   │   ├── charts/
│   │   │   └── charts.vue
│   │   ├── flow-detail/
│   │   │   └── flow-detail.vue
│   │   ├── flow-form/
│   │   │   └── flow-form.vue
│   │   ├── flows/
│   │   │   └── flows.vue
│   │   ├── index/
│   │   │   └── index.vue
│   │   ├── login/
│   │   │   └── login.vue
│   │   ├── my/
│   │   │   └── my.vue
│   │   ├── select/
│   │   │   └── select.vue
│   │   └── test/
│   │       └── test.vue
│   ├── pages.json
│   ├── store/
│   │   ├── index.js
│   │   └── modules/
│   │       ├── account.js
│   │       ├── expenseCategory.js
│   │       ├── incomeCategory.js
│   │       ├── modelForm.js
│   │       ├── payee.js
│   │       ├── select.js
│   │       ├── session.js
│   │       └── tag.js
│   ├── uni.scss
│   └── uni_modules/
│       ├── qiun-data-charts/
│       │   ├── changelog.md
│       │   ├── components/
│       │   │   ├── qiun-data-charts/
│       │   │   │   └── qiun-data-charts.vue
│       │   │   ├── qiun-error/
│       │   │   │   └── qiun-error.vue
│       │   │   └── qiun-loading/
│       │   │       ├── loading1.vue
│       │   │       ├── loading2.vue
│       │   │       ├── loading3.vue
│       │   │       ├── loading4.vue
│       │   │       ├── loading5.vue
│       │   │       └── qiun-loading.vue
│       │   ├── js_sdk/
│       │   │   └── u-charts/
│       │   │       ├── config-echarts.js
│       │   │       ├── config-ucharts.js
│       │   │       ├── readme.md
│       │   │       └── u-charts.js
│       │   ├── license.md
│       │   ├── package.json
│       │   └── readme.md
│       ├── uni-datetime-picker/
│       │   ├── changelog.md
│       │   ├── components/
│       │   │   └── uni-datetime-picker/
│       │   │       ├── calendar-item.vue
│       │   │       ├── calendar.vue
│       │   │       ├── i18n/
│       │   │       │   ├── en.json
│       │   │       │   ├── index.js
│       │   │       │   ├── zh-Hans.json
│       │   │       │   └── zh-Hant.json
│       │   │       ├── keypress.js
│       │   │       ├── time-picker.vue
│       │   │       ├── uni-datetime-picker.vue
│       │   │       └── util.js
│       │   ├── package.json
│       │   └── readme.md
│       ├── uni-icons/
│       │   ├── changelog.md
│       │   ├── components/
│       │   │   └── uni-icons/
│       │   │       ├── icons.js
│       │   │       ├── uni-icons.vue
│       │   │       └── uniicons.css
│       │   ├── package.json
│       │   └── readme.md
│       ├── uni-list/
│       │   ├── changelog.md
│       │   ├── components/
│       │   │   ├── uni-list/
│       │   │   │   ├── uni-list.vue
│       │   │   │   ├── uni-refresh.vue
│       │   │   │   └── uni-refresh.wxs
│       │   │   ├── uni-list-ad/
│       │   │   │   └── uni-list-ad.vue
│       │   │   ├── uni-list-chat/
│       │   │   │   ├── uni-list-chat.scss
│       │   │   │   └── uni-list-chat.vue
│       │   │   └── uni-list-item/
│       │   │       └── uni-list-item.vue
│       │   ├── package.json
│       │   └── readme.md
│       └── uview-ui/
│           ├── LICENSE
│           ├── README.md
│           ├── changelog.md
│           ├── components/
│           │   ├── u--form/
│           │   │   └── u--form.vue
│           │   ├── u--image/
│           │   │   └── u--image.vue
│           │   ├── u--input/
│           │   │   └── u--input.vue
│           │   ├── u--text/
│           │   │   └── u--text.vue
│           │   ├── u--textarea/
│           │   │   └── u--textarea.vue
│           │   ├── u-action-sheet/
│           │   │   ├── props.js
│           │   │   └── u-action-sheet.vue
│           │   ├── u-album/
│           │   │   ├── props.js
│           │   │   └── u-album.vue
│           │   ├── u-alert/
│           │   │   ├── props.js
│           │   │   └── u-alert.vue
│           │   ├── u-avatar/
│           │   │   ├── props.js
│           │   │   └── u-avatar.vue
│           │   ├── u-avatar-group/
│           │   │   ├── props.js
│           │   │   └── u-avatar-group.vue
│           │   ├── u-back-top/
│           │   │   ├── props.js
│           │   │   └── u-back-top.vue
│           │   ├── u-badge/
│           │   │   ├── props.js
│           │   │   └── u-badge.vue
│           │   ├── u-button/
│           │   │   ├── nvue.scss
│           │   │   ├── props.js
│           │   │   ├── u-button.vue
│           │   │   └── vue.scss
│           │   ├── u-calendar/
│           │   │   ├── header.vue
│           │   │   ├── month.vue
│           │   │   ├── props.js
│           │   │   ├── u-calendar.vue
│           │   │   └── util.js
│           │   ├── u-car-keyboard/
│           │   │   ├── props.js
│           │   │   └── u-car-keyboard.vue
│           │   ├── u-cell/
│           │   │   ├── props.js
│           │   │   └── u-cell.vue
│           │   ├── u-cell-group/
│           │   │   ├── props.js
│           │   │   └── u-cell-group.vue
│           │   ├── u-checkbox/
│           │   │   ├── props.js
│           │   │   └── u-checkbox.vue
│           │   ├── u-checkbox-group/
│           │   │   ├── props.js
│           │   │   └── u-checkbox-group.vue
│           │   ├── u-circle-progress/
│           │   │   ├── props.js
│           │   │   └── u-circle-progress.vue
│           │   ├── u-code/
│           │   │   ├── props.js
│           │   │   └── u-code.vue
│           │   ├── u-code-input/
│           │   │   ├── props.js
│           │   │   └── u-code-input.vue
│           │   ├── u-col/
│           │   │   ├── props.js
│           │   │   └── u-col.vue
│           │   ├── u-collapse/
│           │   │   ├── props.js
│           │   │   └── u-collapse.vue
│           │   ├── u-collapse-item/
│           │   │   ├── props.js
│           │   │   └── u-collapse-item.vue
│           │   ├── u-column-notice/
│           │   │   ├── props.js
│           │   │   └── u-column-notice.vue
│           │   ├── u-count-down/
│           │   │   ├── props.js
│           │   │   ├── u-count-down.vue
│           │   │   └── utils.js
│           │   ├── u-count-to/
│           │   │   ├── props.js
│           │   │   └── u-count-to.vue
│           │   ├── u-datetime-picker/
│           │   │   ├── props.js
│           │   │   └── u-datetime-picker.vue
│           │   ├── u-divider/
│           │   │   ├── props.js
│           │   │   └── u-divider.vue
│           │   ├── u-dropdown/
│           │   │   ├── props.js
│           │   │   └── u-dropdown.vue
│           │   ├── u-dropdown-item/
│           │   │   ├── props.js
│           │   │   └── u-dropdown-item.vue
│           │   ├── u-empty/
│           │   │   ├── props.js
│           │   │   └── u-empty.vue
│           │   ├── u-form/
│           │   │   ├── props.js
│           │   │   └── u-form.vue
│           │   ├── u-form-item/
│           │   │   ├── props.js
│           │   │   └── u-form-item.vue
│           │   ├── u-gap/
│           │   │   ├── props.js
│           │   │   └── u-gap.vue
│           │   ├── u-grid/
│           │   │   ├── props.js
│           │   │   └── u-grid.vue
│           │   ├── u-grid-item/
│           │   │   ├── props.js
│           │   │   └── u-grid-item.vue
│           │   ├── u-icon/
│           │   │   ├── icons.js
│           │   │   ├── props.js
│           │   │   └── u-icon.vue
│           │   ├── u-image/
│           │   │   ├── props.js
│           │   │   └── u-image.vue
│           │   ├── u-index-anchor/
│           │   │   ├── props.js
│           │   │   └── u-index-anchor.vue
│           │   ├── u-index-item/
│           │   │   ├── props.js
│           │   │   └── u-index-item.vue
│           │   ├── u-index-list/
│           │   │   ├── props.js
│           │   │   └── u-index-list.vue
│           │   ├── u-input/
│           │   │   ├── props.js
│           │   │   └── u-input.vue
│           │   ├── u-keyboard/
│           │   │   ├── props.js
│           │   │   └── u-keyboard.vue
│           │   ├── u-line/
│           │   │   ├── props.js
│           │   │   └── u-line.vue
│           │   ├── u-line-progress/
│           │   │   ├── props.js
│           │   │   └── u-line-progress.vue
│           │   ├── u-link/
│           │   │   ├── props.js
│           │   │   └── u-link.vue
│           │   ├── u-list/
│           │   │   ├── props.js
│           │   │   └── u-list.vue
│           │   ├── u-list-item/
│           │   │   ├── props.js
│           │   │   └── u-list-item.vue
│           │   ├── u-loading-icon/
│           │   │   ├── props.js
│           │   │   └── u-loading-icon.vue
│           │   ├── u-loading-page/
│           │   │   ├── props.js
│           │   │   └── u-loading-page.vue
│           │   ├── u-loadmore/
│           │   │   ├── props.js
│           │   │   └── u-loadmore.vue
│           │   ├── u-modal/
│           │   │   ├── props.js
│           │   │   └── u-modal.vue
│           │   ├── u-navbar/
│           │   │   ├── props.js
│           │   │   └── u-navbar.vue
│           │   ├── u-no-network/
│           │   │   ├── props.js
│           │   │   └── u-no-network.vue
│           │   ├── u-notice-bar/
│           │   │   ├── props.js
│           │   │   └── u-notice-bar.vue
│           │   ├── u-notify/
│           │   │   ├── props.js
│           │   │   └── u-notify.vue
│           │   ├── u-number-box/
│           │   │   ├── props.js
│           │   │   └── u-number-box.vue
│           │   ├── u-number-keyboard/
│           │   │   ├── props.js
│           │   │   └── u-number-keyboard.vue
│           │   ├── u-overlay/
│           │   │   ├── props.js
│           │   │   └── u-overlay.vue
│           │   ├── u-parse/
│           │   │   ├── node/
│           │   │   │   └── node.vue
│           │   │   ├── parser.js
│           │   │   ├── props.js
│           │   │   └── u-parse.vue
│           │   ├── u-picker/
│           │   │   ├── props.js
│           │   │   └── u-picker.vue
│           │   ├── u-picker-column/
│           │   │   ├── props.js
│           │   │   └── u-picker-column.vue
│           │   ├── u-popup/
│           │   │   ├── props.js
│           │   │   └── u-popup.vue
│           │   ├── u-radio/
│           │   │   ├── props.js
│           │   │   └── u-radio.vue
│           │   ├── u-radio-group/
│           │   │   ├── props.js
│           │   │   └── u-radio-group.vue
│           │   ├── u-rate/
│           │   │   ├── props.js
│           │   │   └── u-rate.vue
│           │   ├── u-read-more/
│           │   │   ├── props.js
│           │   │   └── u-read-more.vue
│           │   ├── u-row/
│           │   │   ├── props.js
│           │   │   └── u-row.vue
│           │   ├── u-row-notice/
│           │   │   ├── props.js
│           │   │   └── u-row-notice.vue
│           │   ├── u-safe-bottom/
│           │   │   ├── props.js
│           │   │   └── u-safe-bottom.vue
│           │   ├── u-scroll-list/
│           │   │   ├── nvue.js
│           │   │   ├── other.js
│           │   │   ├── props.js
│           │   │   ├── scrollWxs.wxs
│           │   │   └── u-scroll-list.vue
│           │   ├── u-search/
│           │   │   ├── props.js
│           │   │   └── u-search.vue
│           │   ├── u-skeleton/
│           │   │   ├── props.js
│           │   │   └── u-skeleton.vue
│           │   ├── u-slider/
│           │   │   ├── mpother.js
│           │   │   ├── mpwxs.js
│           │   │   ├── mpwxs.wxs
│           │   │   ├── nvue - 副本.js
│           │   │   ├── nvue.js
│           │   │   ├── props.js
│           │   │   └── u-slider.vue
│           │   ├── u-status-bar/
│           │   │   ├── props.js
│           │   │   └── u-status-bar.vue
│           │   ├── u-steps/
│           │   │   ├── props.js
│           │   │   └── u-steps.vue
│           │   ├── u-steps-item/
│           │   │   ├── props.js
│           │   │   └── u-steps-item.vue
│           │   ├── u-sticky/
│           │   │   ├── props.js
│           │   │   └── u-sticky.vue
│           │   ├── u-subsection/
│           │   │   ├── props.js
│           │   │   └── u-subsection.vue
│           │   ├── u-swipe-action/
│           │   │   ├── props.js
│           │   │   └── u-swipe-action.vue
│           │   ├── u-swipe-action-item/
│           │   │   ├── index - backup.wxs
│           │   │   ├── index.wxs
│           │   │   ├── nvue - backup.js
│           │   │   ├── nvue.js
│           │   │   ├── props.js
│           │   │   ├── u-swipe-action-item.vue
│           │   │   └── wxs.js
│           │   ├── u-swiper/
│           │   │   ├── props.js
│           │   │   └── u-swiper.vue
│           │   ├── u-swiper-indicator/
│           │   │   ├── props.js
│           │   │   └── u-swiper-indicator.vue
│           │   ├── u-switch/
│           │   │   ├── props.js
│           │   │   └── u-switch.vue
│           │   ├── u-tabbar/
│           │   │   ├── props.js
│           │   │   └── u-tabbar.vue
│           │   ├── u-tabbar-item/
│           │   │   ├── props.js
│           │   │   └── u-tabbar-item.vue
│           │   ├── u-table/
│           │   │   ├── props.js
│           │   │   └── u-table.vue
│           │   ├── u-tabs/
│           │   │   ├── props.js
│           │   │   └── u-tabs.vue
│           │   ├── u-tabs-item/
│           │   │   ├── props.js
│           │   │   └── u-tabs-item.vue
│           │   ├── u-tag/
│           │   │   ├── props.js
│           │   │   └── u-tag.vue
│           │   ├── u-td/
│           │   │   ├── props.js
│           │   │   └── u-td.vue
│           │   ├── u-text/
│           │   │   ├── props.js
│           │   │   ├── u-text.vue
│           │   │   └── value.js
│           │   ├── u-textarea/
│           │   │   ├── props.js
│           │   │   └── u-textarea.vue
│           │   ├── u-toast/
│           │   │   └── u-toast.vue
│           │   ├── u-toolbar/
│           │   │   ├── props.js
│           │   │   └── u-toolbar.vue
│           │   ├── u-tooltip/
│           │   │   ├── props.js
│           │   │   └── u-tooltip.vue
│           │   ├── u-tr/
│           │   │   ├── props.js
│           │   │   └── u-tr.vue
│           │   ├── u-transition/
│           │   │   ├── nvue.ani-map.js
│           │   │   ├── props.js
│           │   │   ├── transition.js
│           │   │   ├── u-transition.vue
│           │   │   └── vue.ani-style.scss
│           │   ├── u-upload/
│           │   │   ├── mixin.js
│           │   │   ├── props.js
│           │   │   ├── u-upload.vue
│           │   │   └── utils.js
│           │   └── uview-ui/
│           │       └── uview-ui.vue
│           ├── index.js
│           ├── index.scss
│           ├── libs/
│           │   ├── config/
│           │   │   ├── color.js
│           │   │   ├── config.js
│           │   │   ├── props/
│           │   │   │   ├── actionSheet.js
│           │   │   │   ├── album.js
│           │   │   │   ├── alert.js
│           │   │   │   ├── avatar.js
│           │   │   │   ├── avatarGroup.js
│           │   │   │   ├── backtop.js
│           │   │   │   ├── badge.js
│           │   │   │   ├── button.js
│           │   │   │   ├── calendar.js
│           │   │   │   ├── carKeyboard.js
│           │   │   │   ├── cell.js
│           │   │   │   ├── cellGroup.js
│           │   │   │   ├── checkbox.js
│           │   │   │   ├── checkboxGroup.js
│           │   │   │   ├── circleProgress.js
│           │   │   │   ├── code.js
│           │   │   │   ├── codeInput.js
│           │   │   │   ├── col.js
│           │   │   │   ├── collapse.js
│           │   │   │   ├── collapseItem.js
│           │   │   │   ├── columnNotice.js
│           │   │   │   ├── countDown.js
│           │   │   │   ├── countTo.js
│           │   │   │   ├── datetimePicker.js
│           │   │   │   ├── divider.js
│           │   │   │   ├── empty.js
│           │   │   │   ├── form.js
│           │   │   │   ├── formItem.js
│           │   │   │   ├── gap.js
│           │   │   │   ├── grid.js
│           │   │   │   ├── gridItem.js
│           │   │   │   ├── icon.js
│           │   │   │   ├── image.js
│           │   │   │   ├── indexAnchor.js
│           │   │   │   ├── indexList.js
│           │   │   │   ├── input.js
│           │   │   │   ├── keyboard.js
│           │   │   │   ├── line.js
│           │   │   │   ├── lineProgress.js
│           │   │   │   ├── link.js
│           │   │   │   ├── list.js
│           │   │   │   ├── listItem.js
│           │   │   │   ├── loadingIcon.js
│           │   │   │   ├── loadingPage.js
│           │   │   │   ├── loadmore.js
│           │   │   │   ├── modal.js
│           │   │   │   ├── navbar.js
│           │   │   │   ├── noNetwork.js
│           │   │   │   ├── noticeBar.js
│           │   │   │   ├── notify.js
│           │   │   │   ├── numberBox.js
│           │   │   │   ├── numberKeyboard.js
│           │   │   │   ├── overlay.js
│           │   │   │   ├── parse.js
│           │   │   │   ├── picker.js
│           │   │   │   ├── popup.js
│           │   │   │   ├── radio.js
│           │   │   │   ├── radioGroup.js
│           │   │   │   ├── rate.js
│           │   │   │   ├── readMore.js
│           │   │   │   ├── row.js
│           │   │   │   ├── rowNotice.js
│           │   │   │   ├── scrollList.js
│           │   │   │   ├── search.js
│           │   │   │   ├── section.js
│           │   │   │   ├── skeleton.js
│           │   │   │   ├── slider.js
│           │   │   │   ├── statusBar.js
│           │   │   │   ├── steps.js
│           │   │   │   ├── stepsItem.js
│           │   │   │   ├── sticky.js
│           │   │   │   ├── subsection.js
│           │   │   │   ├── swipeAction.js
│           │   │   │   ├── swipeActionItem.js
│           │   │   │   ├── swiper.js
│           │   │   │   ├── swipterIndicator.js
│           │   │   │   ├── switch.js
│           │   │   │   ├── tabbar.js
│           │   │   │   ├── tabbarItem.js
│           │   │   │   ├── tabs.js
│           │   │   │   ├── tag.js
│           │   │   │   ├── text.js
│           │   │   │   ├── textarea.js
│           │   │   │   ├── toast.js
│           │   │   │   ├── toolbar.js
│           │   │   │   ├── tooltip.js
│           │   │   │   ├── transition.js
│           │   │   │   └── upload.js
│           │   │   ├── props.js
│           │   │   └── zIndex.js
│           │   ├── css/
│           │   │   ├── color.scss
│           │   │   ├── common.scss
│           │   │   ├── components.scss
│           │   │   ├── flex.scss
│           │   │   ├── h5.scss
│           │   │   ├── mixin.scss
│           │   │   ├── mp.scss
│           │   │   ├── nvue.scss
│           │   │   └── vue.scss
│           │   ├── function/
│           │   │   ├── colorGradient.js
│           │   │   ├── debounce.js
│           │   │   ├── digit.js
│           │   │   ├── index.js
│           │   │   ├── platform.js
│           │   │   ├── test.js
│           │   │   └── throttle.js
│           │   ├── luch-request/
│           │   │   ├── adapters/
│           │   │   │   └── index.js
│           │   │   ├── core/
│           │   │   │   ├── InterceptorManager.js
│           │   │   │   ├── Request.js
│           │   │   │   ├── buildFullPath.js
│           │   │   │   ├── defaults.js
│           │   │   │   ├── dispatchRequest.js
│           │   │   │   ├── mergeConfig.js
│           │   │   │   └── settle.js
│           │   │   ├── helpers/
│           │   │   │   ├── buildURL.js
│           │   │   │   ├── combineURLs.js
│           │   │   │   └── isAbsoluteURL.js
│           │   │   ├── index.d.ts
│           │   │   ├── index.js
│           │   │   ├── utils/
│           │   │   │   └── clone.js
│           │   │   └── utils.js
│           │   ├── mixin/
│           │   │   ├── button.js
│           │   │   ├── mixin.js
│           │   │   ├── mpMixin.js
│           │   │   ├── mpShare.js
│           │   │   ├── openType.js
│           │   │   ├── style.js
│           │   │   └── touch.js
│           │   └── util/
│           │       ├── async-validator.js
│           │       ├── calendar.js
│           │       ├── dayjs.js
│           │       ├── emitter.js
│           │       └── route.js
│           ├── package.json
│           └── theme.scss
├── docker/
│   └── mysql/
│       ├── bookkeeping.sql
│       ├── config/
│       │   └── my.cnf
│       └── currency.sql
├── docker-compose.yaml
├── docker-compose2.yaml
└── notes.txt
Download .txt
Showing preview only (314K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3013 symbols across 841 files)

FILE: bookkeeping-user-api/.mvn/wrapper/MavenWrapperDownloader.java
  class MavenWrapperDownloader (line 21) | public class MavenWrapperDownloader {
    method main (line 48) | public static void main(String args[]) {
    method downloadFileFromURL (line 97) | private static void downloadFileFromURL(String urlString, File destina...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/Application.java
  class Application (line 6) | @SpringBootApplication
    method main (line 9) | public static void main(String[] args) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/RegexTest.java
  class RegexTest (line 3) | public class RegexTest implements Runnable {
    method change (line 8) | public synchronized static void change() {
    method run (line 14) | @Override
    method main (line 23) | public static void main(String[] args) throws Exception {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/Account.java
  class Account (line 13) | @Entity
    method Account (line 66) | public Account() { }
    method Account (line 68) | public Account(Integer id) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountAddRequest.java
  class AccountAddRequest (line 14) | @Getter
    method copyPrimitive (line 41) | public void copyPrimitive(Account po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountAdjustBalanceNotValidException.java
  class AccountAdjustBalanceNotValidException (line 3) | public class AccountAdjustBalanceNotValidException extends RuntimeExcept...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountController.java
  class AccountController (line 12) | @RestController
    method handleEnable (line 20) | @RequestMapping(method = RequestMethod.GET, value = "/enable")
    method handleExpenseble (line 25) | @RequestMapping(method = RequestMethod.GET, value = "/expenseable")
    method handleIncomeble (line 30) | @RequestMapping(method = RequestMethod.GET, value = "/incomeable")
    method handleTransferFromAble (line 35) | @RequestMapping(method = RequestMethod.GET, value = "/transfer-from-ab...
    method handleTransferToAble (line 40) | @RequestMapping(method = RequestMethod.GET, value = "/transfer-to-able")
    method handleGet (line 45) | @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    method handleAdjustBalance (line 50) | @RequestMapping(method = RequestMethod.POST, value = "/{id}/adjust-bal...
    method handleDelete (line 58) | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    method handleToggle (line 63) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggle")
    method handleToggleInclude (line 68) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggleInclu...
    method handleToggleExpenseable (line 73) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggleExpen...
    method handleToggleIncomeable (line 78) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggleIncom...
    method handleToggleTransferFromAble (line 83) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggleTrans...
    method handleToggleTransferToAble (line 88) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggleTrans...
    method handleUpdate (line 93) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountExceptionHandler.java
  class AccountExceptionHandler (line 15) | @RestControllerAdvice
    method handleException (line 24) | @ExceptionHandler(value = AccountNameExistsException.class)
    method handleException (line 31) | @ExceptionHandler(value = AccountMaxCountException.class)
    method handleException (line 37) | @ExceptionHandler(value = AccountHasTransactionException.class)
    method handleException (line 43) | @ExceptionHandler(value = AccountAdjustBalanceNotValidException.class)
    method handleException (line 49) | @ExceptionHandler(value = DefaultExpenseAccountException.class)
    method handleException (line 55) | @ExceptionHandler(value = DefaultIncomeAccountException.class)
    method handleException (line 61) | @ExceptionHandler(value = DefaultTransferFromAccountException.class)
    method handleException (line 67) | @ExceptionHandler(value = DefaultTransferToAccountException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountHasTransactionException.java
  class AccountHasTransactionException (line 3) | public class AccountHasTransactionException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountMaxCountException.java
  class AccountMaxCountException (line 3) | public class AccountMaxCountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountNameExistsException.java
  class AccountNameExistsException (line 3) | public class AccountNameExistsException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountQueryRequest.java
  class AccountQueryRequest (line 6) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountRepository.java
  type AccountRepository (line 10) | @Repository
    method findOneByGroupAndName (line 13) | Optional<Account> findOneByGroupAndName(Group group, String name);
    method findOneByGroupAndId (line 15) | Optional<Account> findOneByGroupAndId(Group group, Integer id);
    method countByGroup (line 17) | long countByGroup(Group group);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountService.java
  class AccountService (line 33) | @Service
    method getEnable (line 63) | public List<AccountVOForExtend> getEnable(Integer userSignInId) {
    method getAllExpenseable (line 69) | public List<AccountVOForExtend> getAllExpenseable(Integer userSignInId) {
    method getAllIncomeable (line 75) | public List<AccountVOForExtend> getAllIncomeable(Integer userSignInId) {
    method getAllTransferFromAble (line 81) | public List<AccountVOForExtend> getAllTransferFromAble(Integer userSig...
    method getAllTransferToAble (line 87) | public List<AccountVOForExtend> getAllTransferToAble(Integer userSignI...
    method get (line 93) | public AccountVOForList get(Integer id, Integer userSignInId) {
    method adjustBalance (line 116) | @Transactional
    method remove (line 149) | @Transactional
    method toggle (line 162) | public AccountVOForExtend toggle(Integer id, Integer userSignInId) {
    method toggleInclude (line 174) | public boolean toggleInclude(Integer id, Integer userSignInId) {
    method toggleExpenseable (line 183) | public boolean toggleExpenseable(Integer id, Integer userSignInId) {
    method toggleIncomeable (line 194) | public boolean toggleIncomeable(Integer id, Integer userSignInId) {
    method toggleTransferFromAble (line 205) | public boolean toggleTransferFromAble(Integer id, Integer userSignInId) {
    method toggleTransferToAble (line 216) | public boolean toggleTransferToAble(Integer id, Integer userSignInId) {
    method add (line 227) | public boolean add(Integer type, AccountAddRequest request, Integer us...
    method update (line 261) | public AccountVOForExtend update(Integer id, AccountUpdateRequest requ...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountSpec.java
  class AccountSpec (line 7) | public final class AccountSpec {
    method includeTrue (line 9) | public static<T extends Account> Specification<T> includeTrue() {
    method expenseable (line 13) | public static<T extends Account> Specification<T> expenseable() {
    method incomeable (line 17) | public static<T extends Account> Specification<T> incomeable() {
    method transferFromAble (line 21) | public static<T extends Account> Specification<T> transferFromAble() {
    method transferToAble (line 25) | public static<T extends Account> Specification<T> transferToAble() {
    method inGroup (line 29) | public static<T extends Account> Specification<T> inGroup(Group group) {
    method inGroupAndEnable (line 33) | public static<T extends Account> Specification<T> inGroupAndEnable(Gro...
    method inGroupAndInclude (line 38) | public static<T extends Account> Specification<T> inGroupAndInclude(Gr...
    method inGroupAndExpenseable (line 43) | public static<T extends Account> Specification<T> inGroupAndExpenseabl...
    method inGroupAndIncomeable (line 48) | public static<T extends Account> Specification<T> inGroupAndIncomeable...
    method inGroupAndTransferFromAble (line 53) | public static<T extends Account> Specification<T> inGroupAndTransferFr...
    method inGroupAndTransferToAble (line 58) | public static<T extends Account> Specification<T> inGroupAndTransferTo...
    method buildSpecification (line 63) | public static<T extends Account> Specification<T> buildSpecification(A...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountSumVO.java
  class AccountSumVO (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountUpdateRequest.java
  class AccountUpdateRequest (line 11) | @Getter
    method updatePrimitive (line 36) | public void updatePrimitive(Account po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountVOForExtend.java
  class AccountVOForExtend (line 9) | @Getter
    method setValue (line 29) | public void setValue(Account po) {
    method fromEntity (line 46) | public static AccountVOForExtend fromEntity(Account po) {
    method getTypeName (line 53) | public String getTypeName() {
    method getBalanceFormatted (line 57) | public String getBalanceFormatted() {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountVOForList.java
  class AccountVOForList (line 8) | @Getter
    method getRemainLimit (line 18) | public BigDecimal getRemainLimit() {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultExpenseAccountException.java
  class DefaultExpenseAccountException (line 3) | public class DefaultExpenseAccountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultIncomeAccountException.java
  class DefaultIncomeAccountException (line 3) | public class DefaultIncomeAccountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultTransferFromAccountException.java
  class DefaultTransferFromAccountException (line 3) | public class DefaultTransferFromAccountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultTransferToAccountException.java
  class DefaultTransferToAccountException (line 3) | public class DefaultTransferToAccountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalance.java
  class AdjustBalance (line 7) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceAddRequest.java
  class AdjustBalanceAddRequest (line 10) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceController.java
  class AdjustBalanceController (line 13) | @RestController
    method handleUpdate (line 20) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceRepository.java
  type AdjustBalanceRepository (line 6) | @Repository
    method deleteByAccount_Id (line 9) | void deleteByAccount_Id(Integer id);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceService.java
  class AdjustBalanceService (line 16) | @Service
    method remove (line 28) | @Transactional
    method update (line 40) | public boolean update(Integer id, BalanceFlowUpdateRequest request, In...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceVOForList.java
  class AdjustBalanceVOForList (line 6) | public class AdjustBalanceVOForList extends BalanceFlowVOForExtend {
    method fromEntity (line 8) | public static AdjustBalanceVOForList fromEntity(AdjustBalance po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/aop/TestAspect.java
  class TestAspect (line 12) | @Aspect
    method before (line 18) | @Before("execution(* com.jiukuaitech.bookkeeping.user.service.*.*(..))")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccount.java
  class AssetAccount (line 10) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountController.java
  class AssetAccountController (line 18) | @RestController
    method handleQuery (line 28) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleAdd (line 36) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleSum (line 43) | @RequestMapping(method = RequestMethod.GET, value = "/sum")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountRepository.java
  type AssetAccountRepository (line 6) | @Repository

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountService.java
  class AssetAccountService (line 18) | @Service
    method query (line 30) | public Page<AssetAccountVOForList> query(AccountQueryRequest request, ...
    method sum (line 42) | public AccountSumVO sum(Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountVOForList.java
  class AssetAccountVOForList (line 8) | @Getter
    method fromEntity (line 14) | public static AssetAccountVOForList fromEntity(AssetAccount po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/AccountInvalidateException.java
  class AccountInvalidateException (line 3) | public class AccountInvalidateException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/AmountInvalidateException.java
  class AmountInvalidateException (line 3) | public class AmountInvalidateException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlow.java
  class BalanceFlow (line 17) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowAddRequest.java
  class BalanceFlowAddRequest (line 11) | @Getter
    method copyPrimitive (line 24) | public void copyPrimitive(BalanceFlow po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowController.java
  class BalanceFlowController (line 13) | @RestController
    method handleQuery (line 20) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleAudit (line 28) | @RequestMapping(method = RequestMethod.GET, value = "audit")
    method handleGet (line 36) | @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    method handleDelete (line 41) | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    method handleConfirm (line 48) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/confirm")
    method handleImages (line 55) | @RequestMapping(method = RequestMethod.GET, value = "/{id}/images")
    method handleUpdateImages (line 60) | @RequestMapping(method = RequestMethod.POST, value = "/{id}/images")
    method handleAddImage (line 68) | @RequestMapping(method = RequestMethod.POST, value = "/{id}/image")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowExceptionHandler.java
  class BalanceFlowExceptionHandler (line 15) | @RestControllerAdvice
    method handleException (line 24) | @ExceptionHandler(value = AccountInvalidateException.class)
    method handleException (line 30) | @ExceptionHandler(value = StatusNotValidateException.class)
    method handleException (line 36) | @ExceptionHandler(value = AmountInvalidateException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowQueryRequest.java
  class BalanceFlowQueryRequest (line 7) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowQueryResultVO.java
  class BalanceFlowQueryResultVO (line 8) | @Getter
    method getSurplus (line 16) | public BigDecimal getSurplus() {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowRepository.java
  type BalanceFlowRepository (line 6) | @Repository

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowService.java
  class BalanceFlowService (line 30) | @Service
    method queryWithDefaultBook (line 51) | public BalanceFlowQueryResultVO queryWithDefaultBook(BalanceFlowQueryR...
    method query (line 57) | public BalanceFlowQueryResultVO query(BalanceFlowQueryRequest request,...
    method get (line 103) | public BalanceFlowVOForList get(Integer id, Integer userSignInId) {
    method remove (line 130) | public boolean remove(Integer id, Integer userSignInId) {
    method confirm (line 148) | public boolean confirm(Integer id, Integer userSignInId) {
    method updateImages (line 163) | public boolean updateImages(Integer id, Set<Integer> images, Integer u...
    method getImages (line 180) | public List<FlowImageVOForList> getImages(Integer id, Integer userSign...
    method addImage (line 187) | public boolean addImage(Integer id, Integer imageId, Integer userSignI...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowSpec.java
  class BalanceFlowSpec (line 27) | public final class BalanceFlowSpec {
    method amountGreaterThanOrEqualTo (line 29) | public static<T extends BalanceFlow> Specification<T> amountGreaterTha...
    method amountLessThanOrEqualTo (line 33) | public static<T extends BalanceFlow> Specification<T> amountLessThanOr...
    method createTimeGreaterThanOrEqualTo (line 37) | public static<T extends BalanceFlow> Specification<T> createTimeGreate...
    method createTimeLessThanOrEqualTo (line 41) | public static<T extends BalanceFlow> Specification<T> createTimeLessTh...
    method creatorEqual (line 45) | public static<T extends BalanceFlow> Specification<T> creatorEqual(Use...
    method accountIn (line 49) | public static<T extends BalanceFlow> Specification<T> accountIn(Set<In...
    method idIn (line 57) | public static<T extends BalanceFlow> Specification<T> idIn(Set<Integer...
    method typeEqual (line 65) | public static<T extends BalanceFlow> Specification<T> typeEqual(Intege...
    method isGroup (line 69) | public static<T extends BalanceFlow> Specification<T> isGroup(Group gr...
    method statusEqual (line 73) | public static<T extends BalanceFlow> Specification<T> statusEqual(Inte...
    method statusConfirmed (line 78) | public static<T extends BalanceFlow> Specification<T> statusConfirmed() {
    method descriptionEqual (line 82) | public static<T extends BalanceFlow> Specification<T> descriptionEqual...
    method distinct (line 86) | public static<T extends BalanceFlow> Specification<T> distinct() {
    method buildBaseSpecification (line 94) | private static<T extends BalanceFlow> Specification<T> buildBaseSpecif...
    method buildSpecification (line 128) | public static<T extends BalanceFlow> Specification<T> buildSpecificati...
    method buildFlowSpecification (line 136) | public static Specification<BalanceFlow> buildFlowSpecification(Balanc...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowUpdateRequest.java
  class BalanceFlowUpdateRequest (line 9) | @Getter
    method updatePrimitive (line 22) | public void updatePrimitive(BalanceFlow po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowVOForExtend.java
  class BalanceFlowVOForExtend (line 10) | @Getter
    method setValue (line 28) | public void setValue(BalanceFlow po) {
    method fromEntity (line 41) | public static BalanceFlowVOForExtend fromEntity(BalanceFlow balanceFlo...
    method getStatusName (line 47) | public String getStatusName() {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowVOForList.java
  class BalanceFlowVOForList (line 23) | @Getter
    method fromEntity (line 55) | public static BalanceFlowVOForList fromEntity(BalanceFlow po) {
    method getCreateTimeFormatted (line 98) | public String getCreateTimeFormatted() {
    method getCreateDateFormatted (line 103) | private String getCreateDateFormatted() {
    method getAmountFormatted (line 108) | public String getAmountFormatted() {
    method getTitle (line 112) | public String getTitle() {
    method getSubTitle (line 133) | public String getSubTitle() {
    method getTagsName (line 137) | public String getTagsName() {
    method getTypeName (line 150) | public String getTypeName() {
    method getStatusName (line 154) | public String getStatusName() {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/StatusNotValidateException.java
  class StatusNotValidateException (line 3) | public class StatusNotValidateException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLog.java
  class BalanceLog (line 14) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogAddRequest.java
  class BalanceLogAddRequest (line 11) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogController.java
  class BalanceLogController (line 13) | @RestController
    method handleQuery (line 20) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleAdd (line 27) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleDelete (line 34) | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogRepository.java
  type BalanceLogRepository (line 10) | @Repository
    method findOneByGroupAndId (line 13) | Optional<BalanceLog> findOneByGroupAndId(Group group, Integer integer);
    method findByGroupAndCreateTimeBetweenOrderByCreateTime (line 15) | List<BalanceLog> findByGroupAndCreateTimeBetweenOrderByCreateTime(Grou...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogService.java
  class BalanceLogService (line 17) | @Service
    method query (line 26) | public Page<BalanceLogVOForList> query(Pageable page, Integer userSign...
    method add (line 37) | public BalanceLogVOForList add(BalanceLogAddRequest request, Integer u...
    method remove (line 49) | public BalanceLogVOForList remove(Integer id, Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogVOForList.java
  class BalanceLogVOForList (line 7) | @Getter
    method fromEntity (line 16) | public static BalanceLogVOForList fromEntity(BalanceLog po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseController.java
  class BaseController (line 9) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseEntity.java
  class BaseEntity (line 11) | @MappedSuperclass

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseRepository.java
  type BaseRepository (line 17) | @NoRepositoryBean
    method calcAggregate (line 21) | <E> BigDecimal calcAggregate(Specification<E> spec, SingularAttribute<...
    method calcAggregate (line 23) | <E> List<BigDecimal> calcAggregate(Specification<E> spec, List<Singula...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseRepositoryFactoryBean.java
  class BaseRepositoryFactoryBean (line 12) | public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T,
    method BaseRepositoryFactoryBean (line 15) | public BaseRepositoryFactoryBean(Class<? extends R> repositoryInterfac...
    method createRepositoryFactory (line 19) | @SuppressWarnings("rawtypes")
    class CustomRepositoryFactory (line 24) | private static class CustomRepositoryFactory<T, I extends Serializable>
      method CustomRepositoryFactory (line 29) | public CustomRepositoryFactory(EntityManager em) {
      method getTargetRepository (line 34) | @SuppressWarnings("unchecked")
      method getRepositoryBaseClass (line 40) | protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadat...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseRepositoryImpl.java
  class BaseRepositoryImpl (line 24) | public class BaseRepositoryImpl<T, ID extends Serializable> extends Simp...
    method BaseRepositoryImpl (line 28) | public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityMa...
    method BaseRepositoryImpl (line 33) | public BaseRepositoryImpl(JpaEntityInformation<T, ?> entityInformation...
    method calcAggregate (line 38) | @Override
    method calcAggregate (line 53) | @Override

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BookNameNotesEnableEntity.java
  class BookNameNotesEnableEntity (line 10) | @MappedSuperclass

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BookNameNotesEnableSpec.java
  class BookNameNotesEnableSpec (line 9) | public final class BookNameNotesEnableSpec {
    method isBook (line 11) | public static<T> Specification<T> isBook(Book book) {
    method inBooks (line 15) | public static<T> Specification<T> inBooks(Set<Integer> books) {
    method enable (line 23) | public static<T> Specification<T> enable() {
    method isEnable (line 27) | public static<T> Specification<T> isEnable(Boolean enable) {
    method nameLike (line 31) | public static<T> Specification<T> nameLike(String name) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/HasBookEntity.java
  class HasBookEntity (line 13) | @MappedSuperclass

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/HasBookRepository.java
  type HasBookRepository (line 8) | @NoRepositoryBean
    method findOneByBookAndId (line 11) | Optional<T> findOneByBookAndId(Book book, Integer id);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/JpaDataConfig.java
  class JpaDataConfig (line 7) | @Configuration

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/NameNotesEnableEntity.java
  class NameNotesEnableEntity (line 11) | @MappedSuperclass

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/TestController.java
  class TestController (line 11) | @RestController
    method handleTest1 (line 14) | @RequestMapping(method = RequestMethod.GET, value = "/test1")
    method getBaseUrl (line 19) | @GetMapping("/test2")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/Book.java
  class Book (line 13) | @Entity
    method Book (line 62) | public Book() { }
    method Book (line 64) | public Book(Integer id) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookAddRequest.java
  class BookAddRequest (line 10) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookController.java
  class BookController (line 13) | @RestController
    method handleQuery (line 27) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleGet (line 34) | @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    method handleAdd (line 39) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleUpdate (line 44) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")
    method handleConfig (line 52) | @RequestMapping(method = RequestMethod.PUT, value = "/config")
    method handleDelete (line 59) | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    method handleToggle (line 64) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggle")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookExceptionHandler.java
  class BookExceptionHandler (line 15) | @RestControllerAdvice
    method handleException (line 24) | @ExceptionHandler(value = BookMaxCountException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookMaxCountException.java
  class BookMaxCountException (line 3) | public class BookMaxCountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookRepository.java
  type BookRepository (line 8) | @Repository
    method countByGroup_id (line 11) | Integer countByGroup_id(Integer groupId);
    method findOneByGroupAndId (line 13) | Optional<Book> findOneByGroupAndId(Group group, Integer id);
    method findOneByGroupAndName (line 15) | Optional<Book> findOneByGroupAndName(Group group, String name);
    method deleteByGroup_id (line 17) | long deleteByGroup_id(Integer groupId);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookService.java
  class BookService (line 24) | @Service
    method query (line 48) | public Page<BookVOForList> query(Pageable page, Integer userSignInId) {
    method get (line 59) | public BookVOForList get(Integer id, Integer userSignInId) {
    method add (line 65) | public boolean add(BookAddRequest request, Integer userSignInId) {
    method update (line 86) | public BookVOForList update(Integer id, BookUpdateRequest request, Int...
    method config (line 102) | public BookVOForList config(BookUpdateRequest request, Integer userSig...
    method remove (line 150) | public boolean remove(Integer id, Integer userSignInId) {
    method toggle (line 170) | public boolean toggle(Integer id, Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookUpdateRequest.java
  class BookUpdateRequest (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookVOForList.java
  class BookVOForList (line 8) | @Getter
    method fromEntity (line 28) | public static BookVOForList fromEntity(Book po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/Category.java
  class Category (line 13) | @Entity
    method Category (line 36) | public Category(Integer id) {
    method getChildren (line 40) | public List<Category> getChildren(List<Category> categories) {
    method getOffspring (line 50) | public List<Category> getOffspring(List<Category> categories) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryAddRequest.java
  class CategoryAddRequest (line 10) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryController.java
  class CategoryController (line 10) | @RestController
    method handleDelete (line 17) | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    method handleToggle (line 22) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggle")
    method handleGet (line 27) | @RequestMapping(method = RequestMethod.GET, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryExceptionHandler.java
  class CategoryExceptionHandler (line 16) | @RestControllerAdvice
    method handleException (line 25) | @ExceptionHandler(value = ParentCategoryNotEnableException.class)
    method handleException (line 31) | @ExceptionHandler(value = CategoryNameExistsException.class)
    method handleException (line 37) | @ExceptionHandler(value = CategoryHasDealException.class)
    method handleException (line 43) | @ExceptionHandler(value = CategoryLevelException.class)
    method handleException (line 49) | @ExceptionHandler(value = CategoryIsDefaultExpenseException.class)
    method handleException (line 55) | @ExceptionHandler(value = CategoryIsDefaultIncomeException.class)
    method handleException (line 61) | @ExceptionHandler(value = CategoryMaxCountException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryHasDealException.java
  class CategoryHasDealException (line 6) | public class CategoryHasDealException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryIsDefaultExpenseException.java
  class CategoryIsDefaultExpenseException (line 6) | public class CategoryIsDefaultExpenseException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryIsDefaultIncomeException.java
  class CategoryIsDefaultIncomeException (line 6) | public class CategoryIsDefaultIncomeException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryLevelException.java
  class CategoryLevelException (line 6) | public class CategoryLevelException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryMaxCountException.java
  class CategoryMaxCountException (line 3) | public class CategoryMaxCountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryNameExistsException.java
  class CategoryNameExistsException (line 6) | public class CategoryNameExistsException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryQueryRequest.java
  class CategoryQueryRequest (line 6) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryRepository.java
  type CategoryRepository (line 10) | @Repository
    method findOneByBookAndNameAndParentAndType (line 13) | Optional<Category> findOneByBookAndNameAndParentAndType(Book book, Str...
    method findAllByBookAndType (line 15) | List<Category> findAllByBookAndType(Book book, Integer type);
    method findAllByBook (line 17) | List<Category> findAllByBook(Book book);
    method findAllByBookAndTypeAndEnable (line 19) | List<Category> findAllByBookAndTypeAndEnable(Book book, Integer type, ...
    method countByBookAndType (line 21) | long countByBookAndType(Book book, Integer type);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryService.java
  class CategoryService (line 23) | @Service
    method remove (line 44) | public boolean remove(Integer id, Integer userSignInId) {
    method toggle (line 57) | @Transactional
    method add (line 73) | public boolean add(Integer type, CategoryAddRequest request, Integer u...
    method update (line 108) | public boolean update(Integer type, Integer id, CategoryUpdateRequest ...
    method getAllEnable (line 137) | public List<CategorySimpleVO> getAllEnable(Integer type, Integer userS...
    method getAllTree (line 143) | public List<CategoryTreeVO> getAllTree(CategoryQueryRequest request, I...
    method query (line 150) | public Page<CategorySimpleVO> query(Integer type, Pageable page, Integ...
    method get (line 157) | public CategoryTreeVO get(Integer id, Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategorySimpleVO.java
  class CategorySimpleVO (line 6) | @Getter
    method fromEntity (line 16) | public static CategorySimpleVO fromEntity(Category po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategorySpec.java
  class CategorySpec (line 8) | public final class CategorySpec {
    method typeEqual (line 10) | public static Specification<Category> typeEqual(Integer type) {
    method buildSpecification (line 14) | public static Specification<Category> buildSpecification(CategoryQuery...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryTreeVO.java
  class CategoryTreeVO (line 10) | @Getter
    method valueOfList (line 22) | public static List<CategoryTreeVO> valueOfList(List<Category> categori...
    method valueOf (line 32) | public static CategoryTreeVO valueOf(Category category, List<Category>...
    method valueOf (line 51) | public static CategoryTreeVO valueOf(Category category) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryUpdateRequest.java
  class CategoryUpdateRequest (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/DefaultExpenseCategoryException.java
  class DefaultExpenseCategoryException (line 3) | public class DefaultExpenseCategoryException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/DefaultIncomeCategoryException.java
  class DefaultIncomeCategoryException (line 3) | public class DefaultIncomeCategoryException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/ParentCategoryNotEnableException.java
  class ParentCategoryNotEnableException (line 6) | public class ParentCategoryNotEnableException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category_relation/CategoryRelation.java
  class CategoryRelation (line 14) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category_relation/CategoryRelationAddRequest.java
  class CategoryRelationAddRequest (line 17) | @Getter
    method checkCategory (line 31) | public static void checkCategory(List<CategoryRelationAddRequest> cate...
    method getRelation (line 48) | public CategoryRelation getRelation(Deal deal, Book book) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category_relation/CategoryRelationRepository.java
  type CategoryRelationRepository (line 11) | @Repository
    method findByBookAndCreateTimeBetween (line 14) | @Query("SELECT p1 FROM CategoryRelation p1 INNER JOIN p1.deal p2 WHERE...
    method countByCategory_id (line 17) | Integer countByCategory_id(Integer id);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category_relation/CategoryRelationVOForList.java
  class CategoryRelationVOForList (line 8) | @Getter
    method fromEntity (line 18) | public static CategoryRelationVOForList fromEntity(CategoryRelation po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/checking_account/CheckingAccount.java
  class CheckingAccount (line 11) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/checking_account/CheckingAccountController.java
  class CheckingAccountController (line 17) | @RestController
    method handleQuery (line 27) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleAdd (line 35) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleSum (line 42) | @RequestMapping(method = RequestMethod.GET, value = "/sum")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/checking_account/CheckingAccountRepository.java
  type CheckingAccountRepository (line 6) | @Repository

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/checking_account/CheckingAccountService.java
  class CheckingAccountService (line 15) | @Service
    method query (line 27) | public Page<AccountVOForExtend> query(AccountQueryRequest request, Pag...
    method sum (line 39) | public AccountSumVO sum(Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccount.java
  class CreditAccount (line 19) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountAddRequest.java
  class CreditAccountAddRequest (line 12) | @Getter
    method copyPrimitive (line 23) | public void copyPrimitive(CreditAccount po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountController.java
  class CreditAccountController (line 17) | @RestController
    method handleQuery (line 27) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleAdd (line 35) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleSum (line 42) | @RequestMapping(method = RequestMethod.GET, value = "/sum")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountRepository.java
  type CreditAccountRepository (line 6) | @Repository

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountService.java
  class CreditAccountService (line 16) | @Service
    method query (line 28) | public Page<CreditAccountVOForList> query(AccountQueryRequest request,...
    method sum (line 40) | public CreditAccountSumVO sum(Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountSumVO.java
  class CreditAccountSumVO (line 9) | @Getter
    method getRemainLimit (line 15) | public BigDecimal getRemainLimit() {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountVOForList.java
  class CreditAccountVOForList (line 9) | @Getter
    method fromEntity (line 16) | public static CreditAccountVOForList fromEntity(CreditAccount po) {
    method getRemainLimit (line 24) | public BigDecimal getRemainLimit() {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/currency/Currency.java
  class Currency (line 13) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/currency/CurrencyController.java
  class CurrencyController (line 9) | @RestController
    method handleAll (line 16) | @RequestMapping(method = RequestMethod.GET, value = "/all")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/currency/CurrencyRepository.java
  type CurrencyRepository (line 8) | @Repository
    method findOneByCode (line 11) | Optional<Currency> findOneByCode(String code);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/currency/CurrencyService.java
  class CurrencyService (line 12) | @Service
    method getAll (line 18) | public List<Currency> getAll() {
    method checkCode (line 22) | public void checkCode(String code) {
    method convert (line 32) | public BigDecimal convert(String fromCode, String toCode) {
    method convert (line 40) | public BigDecimal convert(BigDecimal amount, String fromCode, String t...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/dashboard/AssetOverviewVO.java
  class AssetOverviewVO (line 8) | @Getter
    method getNetWorth (line 15) | public BigDecimal getNetWorth() {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/dashboard/DashboardController.java
  class DashboardController (line 10) | @RestController
    method handleAssetOverview (line 17) | @RequestMapping(method = RequestMethod.GET, value = "asset-overview")
    method handleTable (line 22) | @RequestMapping(method = RequestMethod.GET, value = "expense-income-ta...
    method handleExpenseTrend (line 27) | @RequestMapping(method = RequestMethod.GET, value = "expense-trend")
    method handleIncomeTrend (line 32) | @RequestMapping(method = RequestMethod.GET, value = "income-trend")
    method handleExpenseCategory (line 37) | @RequestMapping(method = RequestMethod.GET, value = "expense-category")
    method handleIncomeCategory (line 42) | @RequestMapping(method = RequestMethod.GET, value = "income-category")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/dashboard/DashboardService.java
  class DashboardService (line 34) | @Service
    method assetOverview (line 70) | public AssetOverviewVO assetOverview(Integer userSignInId) {
    method expenseIncomeTable (line 100) | public List<List<BigDecimal>> expenseIncomeTable(Integer userSignInId) {
    method expenseTrend (line 163) | public List<ChartVO> expenseTrend(Integer userSignInId) {
    method incomeTrend (line 176) | public List<ChartVO> incomeTrend(Integer userSignInId) {
    method expenseCategory (line 189) | public List<ChartVO> expenseCategory(Long start, Long end, Integer use...
    method incomeCategory (line 208) | public List<ChartVO> incomeCategory(Long start, Long end, Integer user...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/CategoryConflictException.java
  class CategoryConflictException (line 6) | public class CategoryConflictException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/Deal.java
  class Deal (line 12) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealAddRequest.java
  class DealAddRequest (line 17) | @Getter
    method copyCategories (line 30) | public void copyCategories(Deal po, List<Category> categories, Book bo...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealController.java
  class DealController (line 10) | @RestController
    method handleRefunds (line 17) | @RequestMapping(method = RequestMethod.GET, value = "/{id}/refunds")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealExceptionHandler.java
  class DealExceptionHandler (line 14) | @RestControllerAdvice
    method handleException (line 23) | @ExceptionHandler(value = CategoryConflictException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealQueryResultVO.java
  class DealQueryResultVO (line 9) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealRepository.java
  type DealRepository (line 6) | @Repository
    method countByPayee_id (line 9) | Integer countByPayee_id(Integer payeeId);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealService.java
  class DealService (line 32) | @Service
    method add (line 65) | @Transactional
    method update (line 118) | @Transactional
    method refund (line 178) | @Transactional
    method remove (line 196) | @Transactional
    method confirm (line 220) | @Transactional
    method confirmBalance (line 234) | private void confirmBalance(Deal deal, Integer type) {
    method refundBalance (line 246) | private void refundBalance(Deal deal, Integer type) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealSpec.java
  class DealSpec (line 16) | public final class DealSpec {
    method payeeIn (line 18) | public static<T extends Deal> Specification<T> payeeIn(Set<Integer> pa...
    method categoriesIn (line 26) | public static<T extends Deal> Specification<T> categoriesIn(Set<Intege...
    method buildSpecification (line 33) | public static<T extends Deal> Specification<T> buildSpecification(Bala...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealUpdateRequest.java
  class DealUpdateRequest (line 18) | @Getter
    method updateCategories (line 30) | public void updateCategories(Deal po, List<Category> categories, Book ...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealVOForList.java
  class DealVOForList (line 13) | @Getter
    method setValue (line 21) | public void setValue(Deal po) {
    method fromEntity (line 28) | public static DealVOForList fromEntity(Deal po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccount.java
  class DebtAccount (line 17) | @Entity
    method DebtAccount (line 30) | public DebtAccount() { }

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountAddRequest.java
  class DebtAccountAddRequest (line 11) | @Getter
    method copyPrimitive (line 21) | public void copyPrimitive(DebtAccount po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountController.java
  class DebtAccountController (line 17) | @RestController
    method handleQuery (line 27) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleAdd (line 35) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleSum (line 42) | @RequestMapping(method = RequestMethod.GET, value = "/sum")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountRepository.java
  type DebtAccountRepository (line 7) | @Repository

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountService.java
  class DebtAccountService (line 16) | @Service
    method query (line 28) | public Page<DebtAccountVOForList> query(AccountQueryRequest request, P...
    method sum (line 40) | public DebtAccountSumVO sum(Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountSumVO.java
  class DebtAccountSumVO (line 10) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountVOForList.java
  class DebtAccountVOForList (line 9) | @Getter
    method fromEntity (line 16) | public static DebtAccountVOForList fromEntity(DebtAccount po) {
    method getRemainLimit (line 24) | public BigDecimal getRemainLimit() {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/GlobalExceptionHandler.java
  class GlobalExceptionHandler (line 24) | @RestControllerAdvice
    method defaultExceptionHandler (line 33) | @ExceptionHandler(value = Exception.class)
    method exceptionHandler1 (line 43) | @ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
    method exceptionHandler2 (line 50) | @ExceptionHandler(value = NoHandlerFoundException.class)
    method exceptionHandler3 (line 57) | @ExceptionHandler(value = {DataIntegrityViolationException.class, Cons...
    method exceptionHandler6 (line 65) | @ExceptionHandler({
    method exceptionHandler7 (line 78) | @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    method exceptionHandler8 (line 84) | @ExceptionHandler(value = TokenEmptyException.class)
    method exceptionHandler10 (line 90) | @ExceptionHandler(value = TokenNotValidException.class)
    method exceptionHandler9 (line 96) | @ExceptionHandler(value = PermissionException.class)
    method handleException (line 102) | @ExceptionHandler(value = ItemNotFoundException.class)
    method handleException (line 108) | @ExceptionHandler(value = NameExistsException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/InputNotValidException.java
  class InputNotValidException (line 3) | public class InputNotValidException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/ItemNotFoundException.java
  class ItemNotFoundException (line 3) | public class ItemNotFoundException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/NameExistsException.java
  class NameExistsException (line 3) | public class NameExistsException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/PermissionException.java
  class PermissionException (line 4) | public class PermissionException extends RuntimeException {
    method PermissionException (line 8) | public PermissionException() {}
    method PermissionException (line 10) | public PermissionException(String msg) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/TokenEmptyException.java
  class TokenEmptyException (line 3) | public class TokenEmptyException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/TokenNotValidException.java
  class TokenNotValidException (line 3) | public class TokenNotValidException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense/Expense.java
  class Expense (line 9) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense/ExpenseController.java
  class ExpenseController (line 18) | @RestController
    method handleAdd (line 28) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleQuery (line 36) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleUpdate (line 44) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")
    method handleRefund (line 52) | @RequestMapping(method = RequestMethod.POST, value = "{id}/refund")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense/ExpenseRepository.java
  type ExpenseRepository (line 10) | @Repository
    method findSumAmount (line 13) | @Query("SELECT COALESCE(SUM(p.convertedAmount), 0) FROM Expense p WHER...
    method findCount (line 16) | @Query("SELECT COUNT(p) FROM Expense p WHERE p.book = :book AND p.stat...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense/ExpenseService.java
  class ExpenseService (line 19) | @Service
    method queryWithDefaultBook (line 28) | public DealQueryResultVO queryWithDefaultBook(BalanceFlowQueryRequest ...
    method query (line 34) | public DealQueryResultVO query(BalanceFlowQueryRequest request, Pageab...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense_category/ExpenseCategory.java
  class ExpenseCategory (line 11) | @Entity
    method ExpenseCategory (line 16) | public ExpenseCategory(Integer id) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense_category/ExpenseCategoryController.java
  class ExpenseCategoryController (line 17) | @RestController
    method handleAdd (line 24) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleGetAllEnable (line 31) | @RequestMapping(method = RequestMethod.GET, value = "/enable")
    method handleQuerySimple (line 37) | @RequestMapping(method = RequestMethod.GET, value = "/simple")
    method handleQuery (line 44) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleUpdate (line 49) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImage.java
  class FlowImage (line 12) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImageController.java
  class FlowImageController (line 9) | @RestController
    method handleUploadToken (line 16) | @RequestMapping(method = RequestMethod.GET, value = "/upload-token")
    method handleUploadCallBack (line 21) | @RequestMapping(method = RequestMethod.POST, value = "/upload-callback")
    method handleDelete (line 26) | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImageExceptionHandler.java
  class FlowImageExceptionHandler (line 14) | @RestControllerAdvice
    method handleException (line 23) | @ExceptionHandler(value = ImageExistsException.class)
    method handleException (line 29) | @ExceptionHandler(value = UploadKeyEmptyException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImageRepository.java
  type FlowImageRepository (line 11) | @Repository
    method findByUserAndUri (line 14) | Optional<FlowImage> findByUserAndUri(User user, String uri);
    method findByFlow (line 16) | List<FlowImage> findByFlow(BalanceFlow flow);
    method findByUserAndId (line 18) | Optional<FlowImage> findByUserAndId(User user, Integer id);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImageService.java
  class FlowImageService (line 16) | @Service
    method uploadToken (line 40) | public String uploadToken(Integer userSignInId) {
    method uploadCallBack (line 67) | public FlowImageVOForList uploadCallBack(UploadCallbackRequest request) {
    method remove (line 85) | public boolean remove(Integer id, Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImageVOForList.java
  class FlowImageVOForList (line 6) | @Getter
    method fromEntity (line 15) | public static FlowImageVOForList fromEntity(FlowImage po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/ImageExistsException.java
  class ImageExistsException (line 3) | public class ImageExistsException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/UploadCallbackRequest.java
  class UploadCallbackRequest (line 6) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/UploadKeyEmptyException.java
  class UploadKeyEmptyException (line 3) | public class UploadKeyEmptyException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/Group.java
  class Group (line 15) | @Entity
    method Group (line 42) | public Group() { }
    method Group (line 44) | public Group(Integer id) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupAddRequest.java
  class GroupAddRequest (line 10) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupController.java
  class GroupController (line 13) | @RestController
    method handleQuery (line 20) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleEnable (line 27) | @RequestMapping(method = RequestMethod.GET, value = "/enable")
    method handleAdd (line 32) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleUpdate (line 37) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")
    method handleDelete (line 45) | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupExceptionHandler.java
  class GroupExceptionHandler (line 15) | @RestControllerAdvice
    method handleException (line 24) | @ExceptionHandler(value = GroupHasBookException.class)
    method handleException (line 30) | @ExceptionHandler(value = GroupMaxCountException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupHasBookException.java
  class GroupHasBookException (line 3) | public class GroupHasBookException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupMaxCountException.java
  class GroupMaxCountException (line 3) | public class GroupMaxCountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupRepository.java
  type GroupRepository (line 9) | @Repository
    method countByCreator (line 12) | long countByCreator(User creator);
    method findOneByCreatorAndId (line 14) | Optional<Group> findOneByCreatorAndId(User user, Integer id);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupService.java
  class GroupService (line 23) | @Service
    method query (line 44) | public Page<GroupVOForList> query(Pageable page, Integer userSignInId) {
    method getEnable (line 56) | public List<GroupVOForList> getEnable(Integer userSignInId) {
    method add (line 67) | @Transactional
    method update (line 92) | public boolean update(Integer id, GroupUpdateRequest request, Integer ...
    method remove (line 102) | @Transactional

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupUpdateRequest.java
  class GroupUpdateRequest (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupVOForList.java
  class GroupVOForList (line 6) | @Getter
    method fromEntity (line 16) | public static GroupVOForList fromEntity(Group po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income/Income.java
  class Income (line 9) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income/IncomeController.java
  class IncomeController (line 18) | @RestController
    method handleAdd (line 28) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleQuery (line 36) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleUpdate (line 44) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")
    method handleRefund (line 52) | @RequestMapping(method = RequestMethod.POST, value = "{id}/refund")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income/IncomeRepository.java
  type IncomeRepository (line 11) | @Repository
    method findSumAmount (line 14) | @Query("SELECT COALESCE(SUM(p.convertedAmount), 0) FROM Income p WHERE...
    method findCount (line 17) | @Query("SELECT COUNT(p) FROM Income p WHERE p.book = :book AND p.statu...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income/IncomeService.java
  class IncomeService (line 19) | @Service
    method queryWithDefaultBook (line 28) | public DealQueryResultVO queryWithDefaultBook(BalanceFlowQueryRequest ...
    method query (line 34) | public DealQueryResultVO query(BalanceFlowQueryRequest request, Pageab...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income_category/IncomeCategory.java
  class IncomeCategory (line 11) | @Entity
    method IncomeCategory (line 16) | public IncomeCategory(Integer id) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income_category/IncomeCategoryController.java
  class IncomeCategoryController (line 17) | @RestController
    method handleAdd (line 24) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleGetAllEnable (line 31) | @RequestMapping(method = RequestMethod.GET, value = "/enable")
    method handleQuery (line 36) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleQuerySimple (line 42) | @RequestMapping(method = RequestMethod.GET, value = "/simple")
    method handleUpdate (line 49) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/interceptor/AuthInterceptor.java
  class AuthInterceptor (line 15) | @Component
    method preHandle (line 21) | @Override

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/interceptor/MvcInterceptorConfig.java
  class MvcInterceptorConfig (line 11) | @Configuration
    method addInterceptors (line 17) | @Override
    method addArgumentResolvers (line 24) | @Override

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/interceptor/StringTrimModule.java
  class StringTrimModule (line 11) | @Component
    method StringTrimModule (line 17) | public StringTrimModule() {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/Item.java
  class Item (line 14) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemAddRequest.java
  class ItemAddRequest (line 10) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemController.java
  class ItemController (line 12) | @RestController
    method handleAdd (line 19) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleRun (line 26) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/run")
    method handleRecall (line 31) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/recall")
    method handleQuery (line 36) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleDelete (line 44) | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
    method handleUpdate (line 49) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemCountException.java
  class ItemCountException (line 3) | public class ItemCountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemExceptionHandler.java
  class ItemExceptionHandler (line 14) | @RestControllerAdvice
    method handleException (line 23) | @ExceptionHandler(value = ItemCountException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemQueryRequest.java
  class ItemQueryRequest (line 3) | public class ItemQueryRequest {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemRepository.java
  type ItemRepository (line 8) | @Repository
    method findOneByUserAndTitle (line 11) | Optional<Item> findOneByUserAndTitle(User user, String title);
    method findOneByUserAndId (line 13) | Optional<Item> findOneByUserAndId(User user, Integer id);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemService.java
  class ItemService (line 20) | @Service
    method add (line 29) | public boolean add(ItemAddRequest request, Integer userSignInId) {
    method run (line 83) | public boolean run(Integer id, Integer userSignInId) {
    method recall (line 108) | public boolean recall(Integer id, Integer userSignInId) {
    method remove (line 133) | public boolean remove(Integer id, Integer userSignInId) {
    method update (line 140) | public boolean update(Integer id, ItemUpdateRequest request, Integer u...
    method query (line 182) | public Page<ItemVOForList> query(ItemQueryRequest request, Pageable pa...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemSpec.java
  class ItemSpec (line 6) | public final class ItemSpec {
    method isUser (line 8) | public static Specification<Item> isUser(User user) {
    method buildSpecification (line 13) | public static Specification<Item> buildSpecification(ItemQueryRequest ...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemUpdateRequest.java
  class ItemUpdateRequest (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemVOForList.java
  class ItemVOForList (line 11) | @Getter
    method fromEntity (line 33) | public static ItemVOForList fromEntity(Item po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/Payee.java
  class Payee (line 10) | @Entity
    method Payee (line 27) | public Payee() { }
    method Payee (line 29) | public Payee(Integer id) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeAddRequest.java
  class PayeeAddRequest (line 10) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeController.java
  class PayeeController (line 14) | @RestController
    method handleQuery (line 21) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleGet (line 29) | @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    method handleEnable (line 34) | @RequestMapping(method = RequestMethod.GET, value = "/enable")
    method handleExpenseable (line 39) | @RequestMapping(method = RequestMethod.GET, value = "/expenseable")
    method handleIncomeable (line 44) | @RequestMapping(method = RequestMethod.GET, value = "/incomeable")
    method handleAdd (line 49) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleToggle (line 56) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggle")
    method handleUpdate (line 61) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")
    method handleDelete (line 69) | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeExceptionHandler.java
  class PayeeExceptionHandler (line 15) | @RestControllerAdvice
    method handleException (line 24) | @ExceptionHandler(value = PayeeHasDealException.class)
    method handleException (line 30) | @ExceptionHandler(value = PayeeMaxCountException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeHasDealException.java
  class PayeeHasDealException (line 6) | public class PayeeHasDealException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeMaxCountException.java
  class PayeeMaxCountException (line 3) | public class PayeeMaxCountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeQueryRequest.java
  class PayeeQueryRequest (line 6) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeRepository.java
  type PayeeRepository (line 9) | @Repository
    method findByBookAndName (line 13) | Optional<Payee> findByBookAndName(Book book, String name);
    method findByBookAndEnable (line 15) | List<Payee> findByBookAndEnable(Book book, Boolean enable);
    method findByBookAndEnableAndExpenseable (line 17) | List<Payee> findByBookAndEnableAndExpenseable(Book book, Boolean enabl...
    method findByBookAndEnableAndIncomeable (line 19) | List<Payee> findByBookAndEnableAndIncomeable(Book book, Boolean enable...
    method countByBook (line 21) | long countByBook(Book book);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeService.java
  class PayeeService (line 18) | @Service
    method query (line 33) | public Page<PayeeVOForList> query(PayeeQueryRequest request, Pageable ...
    method get (line 40) | public PayeeVOForList get(Integer id, Integer userSignInId) {
    method getEnable (line 46) | public List<PayeeVOForList> getEnable(Integer userSignInId) {
    method getExpenseable (line 52) | public List<PayeeVOForList> getExpenseable(Integer userSignInId) {
    method getIncomeable (line 58) | public List<PayeeVOForList> getIncomeable(Integer userSignInId) {
    method add (line 64) | public PayeeVOForList add(PayeeAddRequest request, Integer userSignInI...
    method remove (line 83) | public PayeeVOForList remove(Integer id, Integer userSignInId) {
    method update (line 91) | public PayeeVOForList update(Integer id, PayeeUpdateRequest request, I...
    method toggle (line 106) | public PayeeVOForList toggle(Integer id, Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeSpec.java
  class PayeeSpec (line 8) | public final class PayeeSpec {
    method isExpenseable (line 10) | public static Specification<Payee> isExpenseable(Boolean expenseable) {
    method isIncomeable (line 14) | public static Specification<Payee> isIncomeable(Boolean incomeable) {
    method buildSpecification (line 18) | public static Specification<Payee> buildSpecification(PayeeQueryReques...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeUpdateRequest.java
  class PayeeUpdateRequest (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/PayeeVOForList.java
  class PayeeVOForList (line 6) | @Getter
    method fromEntity (line 17) | public static PayeeVOForList fromEntity(Payee po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/permission/PermissionCheckAspect.java
  class PermissionCheckAspect (line 18) | @Aspect
    method permissionCheckCut (line 31) | @Pointcut("@annotation(com.jiukuaitech.bookkeeping.user.permission.Per...
    method before (line 34) | @Before("permissionCheckCut()")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/refund/Refund.java
  class Refund (line 11) | @Entity
    method Refund (line 26) | public Refund(Deal deal, Deal refund) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/refund/RefundRepository.java
  type RefundRepository (line 10) | @Repository
    method findByRefund (line 13) | Optional<Refund> findByRefund(Deal refund);
    method findByDeal (line 15) | List<Refund> findByDeal(Deal deal);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/refund/RefundService.java
  class RefundService (line 14) | @Service
    method getRefunds (line 26) | public List<Integer> getRefunds(Integer dealId, Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/reports/BreakOutOfMaxException.java
  class BreakOutOfMaxException (line 3) | public class BreakOutOfMaxException extends RuntimeException { }

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/reports/ChartVO.java
  class ChartVO (line 7) | @Getter
    method ChartVO (line 15) | public ChartVO() { }
    method ChartVO (line 17) | public ChartVO(String x, BigDecimal y) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/reports/ChartVO2.java
  class ChartVO2 (line 7) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/reports/ExpenseIncomeTrendQueryRequest.java
  class ExpenseIncomeTrendQueryRequest (line 11) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/reports/ReportController.java
  class ReportController (line 15) | @RestController
    method handleExpenseCategory (line 22) | @RequestMapping(method = RequestMethod.GET, value = "expense-category")
    method handleExpenseTag (line 27) | @RequestMapping(method = RequestMethod.GET, value = "expense-tag")
    method handleIncomeCategory (line 32) | @RequestMapping(method = RequestMethod.GET, value = "income-category")
    method handleIncomeTag (line 37) | @RequestMapping(method = RequestMethod.GET, value = "income-tag")
    method handleTrend (line 42) | @RequestMapping(method = RequestMethod.GET, value = "expense-income-tr...
    method handleAsset (line 47) | @RequestMapping(method = RequestMethod.GET, value = "asset")
    method handleDebt (line 52) | @RequestMapping(method = RequestMethod.GET, value = "debt")
    method handleAssetTrend (line 57) | @RequestMapping(method = RequestMethod.GET, value = "asset-debt-trend")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/reports/ReportService.java
  class ReportService (line 44) | @Service
    method reportExpenseCategory (line 86) | public List<ChartVO> reportExpenseCategory(BalanceFlowQueryRequest req...
    method reportExpenseTag (line 135) | public List<ChartVO> reportExpenseTag(BalanceFlowQueryRequest request,...
    method reportIncomeCategory (line 194) | public List<ChartVO> reportIncomeCategory(BalanceFlowQueryRequest requ...
    method reportIncomeTag (line 243) | public List<ChartVO> reportIncomeTag(BalanceFlowQueryRequest request, ...
    method breakTypeToKey (line 299) | private String breakTypeToKey(String type, Calendar calendar) {
    method reportExpenseIncomeTrend (line 318) | public List<ChartVO2> reportExpenseIncomeTrend(ExpenseIncomeTrendQuery...
    method reportAsset (line 384) | public List<ChartVO> reportAsset(Integer userSignInId) {
    method reportDebt (line 404) | public List<ChartVO> reportDebt(Integer userSignInId) {
    method reportAssetDebtTrend (line 424) | public List<ChartVO2> reportAssetDebtTrend(TrendTimeQueryRequest reque...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/reports/ReportsExceptionHandler.java
  class ReportsExceptionHandler (line 15) | @RestControllerAdvice
    method handleException (line 24) | @ExceptionHandler(value = BreakOutOfMaxException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/reports/TrendTimeQueryRequest.java
  class TrendTimeQueryRequest (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/response/BaseResponse.java
  class BaseResponse (line 6) | @Getter
    method BaseResponse (line 12) | public BaseResponse(boolean success) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/response/DataResponse.java
  class DataResponse (line 6) | @Getter
    method DataResponse (line 12) | public DataResponse() {
    method DataResponse (line 16) | public DataResponse(T data) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/response/ErrorResponse.java
  class ErrorResponse (line 6) | @Getter
    method ErrorResponse (line 14) | public ErrorResponse() {
    method ErrorResponse (line 18) | public ErrorResponse(Integer errorCode) {
    method ErrorResponse (line 23) | public ErrorResponse(Integer errorCode, String errorMsg) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/response/HasNameVO.java
  class HasNameVO (line 7) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/scheduled/Scheduled.java
  class Scheduled (line 15) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/scheduled/ScheduledAddRequest.java
  class ScheduledAddRequest (line 6) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/scheduled/ScheduledController.java
  class ScheduledController (line 9) | @RestController
    method handleAdd (line 16) | @RequestMapping(method = RequestMethod.POST, value = "")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/scheduled/ScheduledExpenseAddRequest.java
  class ScheduledExpenseAddRequest (line 6) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/scheduled/ScheduledRepository.java
  type ScheduledRepository (line 7) | @Repository

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/scheduled/ScheduledService.java
  class ScheduledService (line 8) | @Service
    method addExpense (line 14) | public boolean addExpense(ScheduledExpenseAddRequest request, Integer ...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/setting/Setting.java
  class Setting (line 12) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/Tag.java
  class Tag (line 13) | @Entity
    method Tag (line 45) | public Tag() { }
    method Tag (line 47) | public Tag(Integer id) {
    method getChildren (line 51) | public List<Tag> getChildren(List<Tag> tags) {
    method getOffspring (line 61) | public List<Tag> getOffspring(List<Tag> tags) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagAddRequest.java
  class TagAddRequest (line 10) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagController.java
  class TagController (line 11) | @RestController
    method handleQuery (line 18) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleGet (line 25) | @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    method handleEnable (line 30) | @RequestMapping(method = RequestMethod.GET, value = "/enable")
    method handleExpenseable (line 35) | @RequestMapping(method = RequestMethod.GET, value = "/expenseable")
    method handleIncomeable (line 40) | @RequestMapping(method = RequestMethod.GET, value = "/incomeable")
    method handleTransferable (line 45) | @RequestMapping(method = RequestMethod.GET, value = "/transferable")
    method handleAdd (line 50) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleToggle (line 57) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}/toggle")
    method handleUpdate (line 62) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")
    method handleDelete (line 70) | @RequestMapping(method = RequestMethod.DELETE, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagExceptionHandler.java
  class TagExceptionHandler (line 15) | @RestControllerAdvice
    method handleException (line 24) | @ExceptionHandler(value = TagHasTransactionException.class)
    method handleException (line 30) | @ExceptionHandler(value = TagMaxCountException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagHasTransactionException.java
  class TagHasTransactionException (line 6) | public class TagHasTransactionException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagMaxCountException.java
  class TagMaxCountException (line 3) | public class TagMaxCountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagQueryRequest.java
  class TagQueryRequest (line 6) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagRepository.java
  type TagRepository (line 10) | @Repository
    method findByBookAndName (line 14) | Optional<Tag> findByBookAndName(Book book, String name);
    method findByBookAndEnable (line 16) | List<Tag> findByBookAndEnable(Book book, Boolean enable);
    method findByBookAndEnableAndExpenseable (line 18) | List<Tag> findByBookAndEnableAndExpenseable(Book book, Boolean enable,...
    method findByBookAndEnableAndIncomeable (line 20) | List<Tag> findByBookAndEnableAndIncomeable(Book book, Boolean enable, ...
    method findByBookAndEnableAndTransferable (line 22) | List<Tag> findByBookAndEnableAndTransferable(Book book, Boolean enable...
    method countByBook (line 24) | long countByBook(Book book);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagService.java
  class TagService (line 19) | @Service
    method getAllTree (line 37) | public List<TagTreeVO> getAllTree(TagQueryRequest request, Integer use...
    method get (line 44) | public TagTreeVO get(Integer id, Integer userSignInId) {
    method getAllEnable (line 50) | public List<TagVOForList> getAllEnable(Integer userSignInId) {
    method getExpenseable (line 56) | public List<TagVOForList> getExpenseable(Integer userSignInId) {
    method getIncomeable (line 62) | public List<TagVOForList> getIncomeable(Integer userSignInId) {
    method getTransferable (line 68) | public List<TagVOForList> getTransferable(Integer userSignInId) {
    method add (line 74) | public TagVOForList add(TagAddRequest request, Integer userSignInId) {
    method remove (line 113) | public TagVOForList remove(Integer id, Integer userSignInId) {
    method update (line 122) | public TagVOForList update(Integer id, TagUpdateRequest request, Integ...
    method toggle (line 163) | public boolean toggle(Integer id, Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagSpec.java
  class TagSpec (line 8) | public final class TagSpec {
    method isExpenseable (line 10) | public static Specification<Tag> isExpenseable(Boolean expenseable) {
    method isIncomeable (line 14) | public static Specification<Tag> isIncomeable(Boolean incomeable) {
    method isTransferable (line 18) | public static Specification<Tag> isTransferable(Boolean transferable) {
    method buildSpecification (line 22) | public static Specification<Tag> buildSpecification(TagQueryRequest re...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagTreeVO.java
  class TagTreeVO (line 9) | @Getter
    method valueOfList (line 24) | public static List<TagTreeVO> valueOfList(List<Tag> tags) {
    method valueOf (line 34) | public static TagTreeVO valueOf(Tag tag, List<Tag> tags) {
    method valueOf (line 56) | public static TagTreeVO valueOf(Tag tag) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagUpdateRequest.java
  class TagUpdateRequest (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag/TagVOForList.java
  class TagVOForList (line 6) | @Getter
    method fromEntity (line 19) | public static TagVOForList fromEntity(Tag po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag_relation/TagRelation.java
  class TagRelation (line 14) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag_relation/TagRelationController.java
  class TagRelationController (line 10) | @RestController
    method handleUpdate (line 17) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag_relation/TagRelationRepository.java
  type TagRelationRepository (line 7) | @Repository
    method countByTag_id (line 10) | Integer countByTag_id(Integer tagId);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag_relation/TagRelationService.java
  class TagRelationService (line 11) | @Service
    method update (line 20) | public TagRelationVOForList update(Integer id, TagRelationUpdateReques...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag_relation/TagRelationUpdateRequest.java
  class TagRelationUpdateRequest (line 9) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/tag_relation/TagRelationVOForList.java
  class TagRelationVOForList (line 7) | @Getter
    method fromEntity (line 17) | public static TagRelationVOForList fromEntity(TagRelation po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transaction/Transaction.java
  class Transaction (line 11) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transaction/TransactionAddRequest.java
  class TransactionAddRequest (line 16) | @Getter
    method copyPrimitive (line 23) | public void copyPrimitive(Transaction po) {
    method copyTags (line 28) | public void copyTags(Transaction po, List<Tag> tags) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transaction/TransactionRepository.java
  type TransactionRepository (line 6) | @Repository
    method countByAccount_id (line 9) | Long countByAccount_id(Integer accountId);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transaction/TransactionSpec.java
  class TransactionSpec (line 14) | public final class TransactionSpec {
    method tagsIn (line 16) | public static<T extends Transaction> Specification<T> tagsIn(Set<Integ...
    method buildSpecification (line 23) | public static<T extends Transaction> Specification<T> buildSpecificati...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transaction/TransactionUpdateRequest.java
  class TransactionUpdateRequest (line 15) | @Getter
    method updateTags (line 21) | public void updateTags(Transaction po, List<Tag> tags) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transaction/TransactionVOForList.java
  class TransactionVOForList (line 11) | @Getter
    method setValue (line 17) | public void setValue(Transaction po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/Transfer.java
  class Transfer (line 10) | @Entity

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/TransferAddRequest.java
  class TransferAddRequest (line 14) | @Getter
    method copyPrimitive (line 31) | @Override

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/TransferController.java
  class TransferController (line 15) | @RestController
    method handleAdd (line 22) | @RequestMapping(method = RequestMethod.POST, value = "")
    method handleQuery (line 29) | @RequestMapping(method = RequestMethod.GET, value = "")
    method handleUpdate (line 37) | @RequestMapping(method = RequestMethod.PUT, value = "/{id}")

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/TransferExceptionHandler.java
  class TransferExceptionHandler (line 15) | @RestControllerAdvice
    method handleException (line 24) | @ExceptionHandler(value = TransferFromEqualsToException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/TransferFromEqualsToException.java
  class TransferFromEqualsToException (line 6) | public class TransferFromEqualsToException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/TransferQueryResultVO.java
  class TransferQueryResultVO (line 9) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/TransferRepository.java
  type TransferRepository (line 6) | @Repository
    method countByTo_id (line 9) | Long countByTo_id(Integer accountId);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/TransferService.java
  class TransferService (line 28) | @Service
    method add (line 49) | @Transactional
    method refundBalance (line 88) | private void refundBalance(Transfer transfer) {
    method confirmBalance (line 99) | private void confirmBalance(Transfer po) {
    method queryWithDefaultBook (line 110) | public TransferQueryResultVO queryWithDefaultBook(BalanceFlowQueryRequ...
    method query (line 116) | public TransferQueryResultVO query(BalanceFlowQueryRequest request, Pa...
    method remove (line 137) | @Transactional
    method confirm (line 149) | @Transactional
    method update (line 162) | @Transactional

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/TransferSpec.java
  class TransferSpec (line 13) | public final class TransferSpec {
    method fromIn (line 15) | public static Specification<Transfer> fromIn(Set<Integer> accounts) {
    method toIn (line 23) | public static Specification<Transfer> toIn(Set<Integer> accounts) {
    method buildSpecification (line 31) | public static Specification<Transfer> buildSpecification(BalanceFlowQu...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/TransferUpdateRequest.java
  class TransferUpdateRequest (line 13) | @Getter
    method updatePrimitive (line 30) | @Override

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/transfer/TransferVOForList.java
  class TransferVOForList (line 8) | @Getter
    method fromEntity (line 18) | public static TransferVOForList fromEntity(Transfer po) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/InviteCodeErrorException.java
  class InviteCodeErrorException (line 3) | public class InviteCodeErrorException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/IpNotAllowedException.java
  class IpNotAllowedException (line 3) | public class IpNotAllowedException extends Exception {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/OldPasswordErrorException.java
  class OldPasswordErrorException (line 3) | public class OldPasswordErrorException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/RegisterNameExistsException.java
  class RegisterNameExistsException (line 3) | public class RegisterNameExistsException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/SessionUserNotFoundException.java
  class SessionUserNotFoundException (line 3) | public class SessionUserNotFoundException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/SessionVO.java
  class SessionVO (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/SigninFailedException.java
  class SigninFailedException (line 3) | public class SigninFailedException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UploadNotImageException.java
  class UploadNotImageException (line 3) | public class UploadNotImageException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/User.java
  class User (line 14) | @Entity
    method User (line 71) | public User() { }
    method User (line 73) | public User(Integer id) {
    method User (line 77) | public User(String userName, String password) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserController.java
  class UserController (line 11) | @RestController
    method handleSignin (line 18) | @RequestMapping(method = RequestMethod.POST, value = "/signin")
    method handleSignout (line 23) | @RequestMapping(method = RequestMethod.POST, value = "/signout")
    method handleRegister (line 29) | @RequestMapping(method = RequestMethod.POST, value = "/register")
    method handleUpdatePassword (line 35) | @RequestMapping(method = RequestMethod.PUT, value = "/updatePassword")
    method handleSession (line 42) | @RequestMapping(method = RequestMethod.GET, value = "/session")
    method handleSetDefaultBook (line 47) | @RequestMapping(method = RequestMethod.PUT, value = "/setDefaultBook/{...
    method handleSetDefaultGroup (line 54) | @RequestMapping(method = RequestMethod.PUT, value = "/setDefaultGroup/...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserDisabledException.java
  class UserDisabledException (line 3) | public class UserDisabledException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserExceptionHandler.java
  class UserExceptionHandler (line 15) | @RestControllerAdvice
    method handleException (line 24) | @ExceptionHandler(value = RegisterNameExistsException.class)
    method handleException (line 30) | @ExceptionHandler(value = InviteCodeErrorException.class)
    method handleException (line 36) | @ExceptionHandler(value = SigninFailedException.class)
    method handleException (line 42) | @ExceptionHandler(value = UploadNotImageException.class)
    method handleException (line 48) | @ExceptionHandler(value = SessionUserNotFoundException.class)
    method handleException (line 54) | @ExceptionHandler(value = OldPasswordErrorException.class)
    method handleException (line 60) | @ExceptionHandler(value = UserDisabledException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserGroupRelation.java
  class UserGroupRelation (line 11) | @Entity
    method UserGroupRelation (line 31) | public UserGroupRelation() { }
    method UserGroupRelation (line 33) | public UserGroupRelation(User user, Group group, Integer role) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserGroupRelationRepository.java
  type UserGroupRelationRepository (line 9) | @Repository
    method findOneByUserAndGroup (line 12) | UserGroupRelation findOneByUserAndGroup(User user, Group group);
    method findByUser (line 14) | List<UserGroupRelation> findByUser(User user);
    method deleteByGroup (line 16) | Integer deleteByGroup(Group group);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserRegisterRequest.java
  class UserRegisterRequest (line 10) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserRepository.java
  type UserRepository (line 6) | @Repository
    method findOneByUserName (line 9) | User findOneByUserName(String userName);

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserService.java
  class UserService (line 26) | @Service
    method getUser (line 47) | public User getUser(Integer userSignInId) {
    method register (line 51) | @Transactional
    method updatePassword (line 94) | public boolean updatePassword(Integer userSignInId, UserUpdatePassword...
    method signin (line 104) | public UserSignInResponse signin(UserSignInRequest request, HttpServle...
    method signout (line 131) | public boolean signout(HttpServletRequest httpServletRequest, HttpServ...
    method getSession (line 142) | public SessionVO getSession(Integer userSignInId) {
    method setDefaultBook (line 151) | public BookVOForList setDefaultBook(Integer id, Integer userSignInId) {
    method setDefaultGroup (line 162) | public Integer setDefaultGroup(Integer id, Integer userSignInId) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserSessionVO.java
  class UserSessionVO (line 7) | @Getter
    method fromEntity (line 20) | public static UserSessionVO fromEntity(User user) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserSignInRequest.java
  class UserSignInRequest (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserSignInResponse.java
  class UserSignInResponse (line 6) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user/UserUpdatePasswordRequest.java
  class UserUpdatePasswordRequest (line 8) | @Getter

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user_log/FlowMaxCountException.java
  class FlowMaxCountException (line 3) | public class FlowMaxCountException extends RuntimeException {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user_log/UserActionExceptionHandler.java
  class UserActionExceptionHandler (line 15) | @RestControllerAdvice
    method handleException (line 24) | @ExceptionHandler(value = FlowMaxCountException.class)

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user_log/UserActionLog.java
  class UserActionLog (line 10) | @Entity
    method UserActionLog (line 24) | public UserActionLog() { }
    method UserActionLog (line 26) | public UserActionLog(User user, Integer type, Long actionTime) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user_log/UserActionLogRepository.java
  type UserActionLogRepository (line 7) | @Repository
    method countByUserAndTypeAndActionTimeBetween (line 10) | long countByUserAndTypeAndActionTimeBetween(User user, int type, long ...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/user_log/UserActionLogService.java
  class UserActionLogService (line 10) | @Service
    method check (line 19) | public boolean check(User user) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/utils/CalendarUtils.java
  class CalendarUtils (line 7) | public class CalendarUtils {
    method setToStartOfDay (line 9) | public static void setToStartOfDay(Calendar c) {
    method setToEndOfDay (line 16) | public static void setToEndOfDay(Calendar c) {
    method setToStartOfWeek (line 23) | public static void setToStartOfWeek(Calendar c) {
    method setToEndOfWeek (line 31) | public static void setToEndOfWeek(Calendar c) {
    method setToStartOfMonth (line 38) | public static void setToStartOfMonth(Calendar c) {
    method setToEndOfMonth (line 42) | public static void setToEndOfMonth(Calendar c) {
    method setToStartOfQuarter (line 47) | public static void setToStartOfQuarter(Calendar c) {
    method setToEndOfQuarter (line 52) | public static void setToEndOfQuarter(Calendar c) {
    method setToStartOfYear (line 59) | public static void setToStartOfYear(Calendar c) {
    method setToEndOfYear (line 64) | public static void setToEndOfYear(Calendar c) {
    method getStartOfDay (line 69) | public static Long getStartOfDay(Long time) {
    method getEndOfDay (line 76) | public static Long getEndOfDay(Long time) {
    method getThisWeek (line 83) | public static Long[] getThisWeek() {
    method getThisMonth (line 93) | public static Long[] getThisMonth() {
    method getThisYear (line 103) | public static Long[] getThisYear() {
    method getLastYear (line 113) | public static Long[] getLastYear() {
    method getIn7Days (line 125) | public static Long[] getIn7Days() {
    method getIn1Day (line 134) | public static Long[] getIn1Day() {
    method getIn30Days (line 141) | public static Long[] getIn30Days() {
    method getIn1Year (line 150) | public static Long[] getIn1Year() {
    method getMonths (line 159) | public static List<Calendar[]> getMonths(Integer year) {
    method getBreaks (line 184) | public static List<Calendar[]> getBreaks(Long start, Long end, String ...

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/utils/CommonUtils.java
  class CommonUtils (line 15) | public class CommonUtils {
    method coalesce (line 17) | public static List<BigDecimal> coalesce(BigDecimal... items) {
    method cleanTagRelation (line 21) | public static void cleanTagRelation(Set<TagRelation> tagRelations, Set...
    method getTagRelation (line 39) | public static TagRelation getTagRelation(Integer tagId, Transaction tr...
    method getRealIP (line 54) | public static String getRealIP(HttpServletRequest request) {
    method encodePassword (line 89) | public static String encodePassword(String str) {
    method formatDate (line 94) | public static String formatDate(Long date) {

FILE: bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/utils/EnumUtils.java
  class EnumUtils (line 3) | public class EnumUtils {
    method translateFlowType (line 5) | public static String translateFlowType(int value) {
    method translateFlowStatus (line 19) | public static String translateFlowStatus(int value) {
    method translateAccountType (line 31) | public static String translateAccountType(int value) {
    method translateItemRepeatType (line 45) | public static String translateItemRepeatType(int type) {

FILE: bookkeeping-user-fe/src/app.js
  method onError (line 3) | onError(err) {

FILE: bookkeeping-user-fe/src/components/AccountRecordTable/index.jsx
  function fetchData (line 15) | async function fetchData(id, query) {
  function handleTableChange (line 22) | function handleTableChange(pagination, _, sorter) {

FILE: bookkeeping-user-fe/src/components/AdjustBalanceModal/index.jsx
  function successHandler (line 30) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/components/AvatarDropdown/UpdatePasswordModal.jsx
  function successHandler (line 12) | function successHandler() {

FILE: bookkeeping-user-fe/src/components/ExpenseModal/index.jsx
  function successHandler (line 109) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/components/FlowImageUploadModal/index.jsx
  function cancelHandler (line 28) | function cancelHandler() {
  method onChange (line 74) | onChange(info) {
  method beforeUpload (line 95) | beforeUpload(file) {
  function okHandler (line 109) | async function okHandler() {

FILE: bookkeeping-user-fe/src/components/FlowRecordTable/index.jsx
  function deleteHandler (line 30) | function deleteHandler(record) {
  function confirmHandler (line 44) | function confirmHandler(record) {
  function refundHandler (line 57) | function refundHandler(record) {
  function copyHandler (line 65) | function copyHandler(record) {
  function updateHandler (line 75) | function updateHandler(record) {
  function rowExpandableRecord (line 152) | function rowExpandableRecord(record) {
  function descriptionsItemRecord (line 159) | function descriptionsItemRecord(record) {

FILE: bookkeeping-user-fe/src/components/FlowStatusDisplay/index.jsx
  function clickHandler (line 14) | async function clickHandler() {

FILE: bookkeeping-user-fe/src/components/FlowTagDisplay/TagModal.jsx
  function successHandler (line 29) | function successHandler() {

FILE: bookkeeping-user-fe/src/components/FormItemDateRange/index.jsx
  function createTimeRadioChangeHandler (line 10) | function createTimeRadioChangeHandler(e) {

FILE: bookkeeping-user-fe/src/components/FormItemDateRangeWithBreak/index.jsx
  function createTimeRadioChangeHandler (line 10) | function createTimeRadioChangeHandler(e) {

FILE: bookkeeping-user-fe/src/components/FormItemPayee/index.jsx
  function addPayeeInputChange (line 15) | function addPayeeInputChange(event) {
  function addPayeeHandler (line 19) | async function addPayeeHandler() {

FILE: bookkeeping-user-fe/src/components/FormItemTag/AddTagModal.jsx
  function okHandler (line 42) | async function okHandler() {
  function successHandler (line 56) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/components/FormItemTag/index.jsx
  function addHandler (line 20) | function addHandler() {
  function hide (line 24) | function hide() {

FILE: bookkeeping-user-fe/src/components/FormModal/index.jsx
  function okHandler (line 26) | async function okHandler() {
  function resetHandler (line 55) | function resetHandler() {
  function cancelHandler (line 65) | function cancelHandler() {

FILE: bookkeeping-user-fe/src/components/IncomeModal/index.jsx
  function successHandler (line 96) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/components/TransferModal/index.jsx
  function successHandler (line 94) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/models/account.js
  method fetchEnable (line 15) | *fetchEnable(_, { call, put }) {
  method fetchExpenseable (line 22) | *fetchExpenseable(_, { call, put }) {
  method fetchIncomeable (line 29) | *fetchIncomeable(_, { call, put }) {
  method fetchTransferFromAble (line 36) | *fetchTransferFromAble(_, { call, put }) {
  method fetchTransferToAble (line 43) | *fetchTransferToAble(_, { call, put }) {
  method refresh (line 50) | *refresh(_, { __, put }) {

FILE: bookkeeping-user-fe/src/models/currency.js
  method fetchAll (line 11) | *fetchAll(_, { call, put }) {

FILE: bookkeeping-user-fe/src/models/expenseCategory.js
  method fetchSimple (line 11) | *fetchSimple({ payload }, { call, put }) {
  method refresh (line 18) | *refresh(_, { __, put }) {

FILE: bookkeeping-user-fe/src/models/flow.js
  method fetchUploadToken (line 13) | *fetchUploadToken(_, { call, put }) {
  method fetchImages (line 24) | *fetchImages({ payload }, { call, put }) {

FILE: bookkeeping-user-fe/src/models/incomeCategory.js
  method fetchSimple (line 11) | *fetchSimple({ payload }, { call, put }) {
  method refresh (line 18) | *refresh(_, { __, put }) {

FILE: bookkeeping-user-fe/src/models/modal.js
  method show (line 10) | show(state, { payload }) {
  method hide (line 13) | hide(state) {

FILE: bookkeeping-user-fe/src/models/payee.js
  method fetchEnable (line 13) | *fetchEnable(_, { call, put }) {
  method fetchExpenseable (line 20) | *fetchExpenseable(_, { call, put }) {
  method fetchIncomeable (line 27) | *fetchIncomeable(_, { call, put }) {
  method refresh (line 34) | *refresh({ payload }, { _, put }) {

FILE: bookkeeping-user-fe/src/models/session.js
  method fetchSession (line 13) | *fetchSession(_, { call, put }) {

FILE: bookkeeping-user-fe/src/models/tag.js
  method fetchEnable (line 14) | *fetchEnable(_, { call, put }) {
  method fetchExpenseable (line 21) | *fetchExpenseable(_, { call, put }) {
  method fetchIncomeable (line 28) | *fetchIncomeable(_, { call, put }) {
  method fetchTransferable (line 35) | *fetchTransferable(_, { call, put }) {
  method refresh (line 42) | *refresh({ payload }, { _, put }) {

FILE: bookkeeping-user-fe/src/pages/accounts/AssetAccountModal.jsx
  function successHandler (line 55) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/pages/accounts/AssetAccountTable.jsx
  function tableChangeHandler (line 48) | function tableChangeHandler(pagination, _, sorter) {
  function refresh (line 53) | function refresh() {

FILE: bookkeeping-user-fe/src/pages/accounts/CheckingAccountModal.jsx
  function successHandler (line 57) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/pages/accounts/CheckingAccountTable.jsx
  function tableChangeHandler (line 39) | function tableChangeHandler(pagination, _, sorter) {
  function refresh (line 44) | function refresh() {

FILE: bookkeeping-user-fe/src/pages/accounts/CreditAccountModal.jsx
  function successHandler (line 57) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/pages/accounts/CreditAccountTable.jsx
  function tableChangeHandler (line 47) | function tableChangeHandler(pagination, _, sorter) {
  function refresh (line 52) | function refresh() {

FILE: bookkeeping-user-fe/src/pages/accounts/DebtAccountModal.jsx
  function successHandler (line 58) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/pages/accounts/DebtAccountTable.jsx
  function tableChangeHandler (line 48) | function tableChangeHandler(pagination, _, sorter) {
  function refresh (line 53) | function refresh() {

FILE: bookkeeping-user-fe/src/pages/accounts/model.js
  method queryCheckingAccount (line 32) | *queryCheckingAccount({ payload }, { call, put }) {
  method queryCreditAccount (line 39) | *queryCreditAccount({ payload }, { call, put }) {
  method queryDebtAccount (line 46) | *queryDebtAccount({ payload }, { call, put }) {
  method queryAssetAccount (line 53) | *queryAssetAccount({ payload }, { call, put }) {
  method refresh (line 60) | *refresh(_, { __, put, select }) {

FILE: bookkeeping-user-fe/src/pages/asset-accounts/GeneralBar.jsx
  function refreshHandler (line 21) | function refreshHandler() {

FILE: bookkeeping-user-fe/src/pages/asset-accounts/ItemCard.jsx
  function expenseHandler (line 21) | function expenseHandler() {
  function incomeHandler (line 25) | function incomeHandler() {
  function transferToHandler (line 29) | function transferToHandler() {
  function transferFromHandler (line 33) | function transferFromHandler() {
  function adjustBalanceHandler (line 37) | function adjustBalanceHandler() {

FILE: bookkeeping-user-fe/src/pages/asset-accounts/model.js
  method sum (line 15) | *sum(_, { call, put }) {
  method query (line 22) | *query({ payload }, { call, put }) {
  method refresh (line 29) | *refresh(_, { call, put, select }) {
  method setup (line 37) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/audit/OperationBar.jsx
  function resetHandler (line 31) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/audit/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/balance-logs/OperationModal.jsx
  function successHandler (line 28) | function successHandler() {

FILE: bookkeeping-user-fe/src/pages/balance-logs/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/books/ConfigModal.jsx
  function successHandler (line 59) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/pages/books/OperationModal.jsx
  function successHandler (line 49) | function successHandler() {

FILE: bookkeeping-user-fe/src/pages/books/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/categories/ExpenseCategoryFilterBar.jsx
  function resetHandler (line 11) | async function resetHandler() {
  function searchHandler (line 17) | async function searchHandler(form) {

FILE: bookkeeping-user-fe/src/pages/categories/ExpenseCategoryModal.jsx
  function successHandler (line 43) | function successHandler() {

FILE: bookkeeping-user-fe/src/pages/categories/ExpenseCategoryTable.jsx
  function refresh (line 28) | function refresh() {

FILE: bookkeeping-user-fe/src/pages/categories/IncomeCategoryFilterBar.jsx
  function resetHandler (line 11) | async function resetHandler() {
  function searchHandler (line 17) | async function searchHandler(form) {

FILE: bookkeeping-user-fe/src/pages/categories/IncomeCategoryModal.jsx
  function successHandler (line 43) | function successHandler() {

FILE: bookkeeping-user-fe/src/pages/categories/PayeeFilterBar.jsx
  function resetHandler (line 11) | async function resetHandler() {
  function searchHandler (line 17) | async function searchHandler(form) {

FILE: bookkeeping-user-fe/src/pages/categories/PayeeModal.jsx
  function successHandler (line 33) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/pages/categories/PayeeTable.jsx
  function tableChangeHandler (line 25) | function tableChangeHandler(pagination, _, sorter) {
  function refresh (line 30) | function refresh(response) {

FILE: bookkeeping-user-fe/src/pages/categories/TagFilterBar.jsx
  function resetHandler (line 11) | async function resetHandler() {
  function searchHandler (line 17) | async function searchHandler(form) {

FILE: bookkeeping-user-fe/src/pages/categories/TagModal.jsx
  function successHandler (line 45) | function successHandler(response) {

FILE: bookkeeping-user-fe/src/pages/categories/TagTable.jsx
  function refresh (line 24) | function refresh() {

FILE: bookkeeping-user-fe/src/pages/categories/model.js
  method queryExpenseCategory (line 28) | *queryExpenseCategory({ payload }, { call, put }) {
  method queryIncomeCategory (line 35) | *queryIncomeCategory({ payload }, { call, put }) {
  method queryTag (line 42) | *queryTag({ payload }, { call, put }) {
  method queryPayee (line 49) | *queryPayee({ payload }, { call, put }) {

FILE: bookkeeping-user-fe/src/pages/checking-accounts/GeneralBar.jsx
  function refreshHandler (line 21) | function refreshHandler() {

FILE: bookkeeping-user-fe/src/pages/checking-accounts/ItemCard.jsx
  function expenseHandler (line 15) | function expenseHandler() {
  function incomeHandler (line 19) | function incomeHandler() {
  function transferToHandler (line 23) | function transferToHandler() {
  function transferFromHandler (line 27) | function transferFromHandler() {
  function adjustBalanceHandler (line 31) | function adjustBalanceHandler() {

FILE: bookkeeping-user-fe/src/pages/checking-accounts/model.js
  method sum (line 14) | *sum(_, { call, put }) {
  method query (line 21) | *query({ payload }, { call, put }) {
  method refresh (line 28) | *refresh(_, { call, put, select }) {
  method setup (line 36) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/credit-accounts/GeneralBar.jsx
  function refreshHandler (line 21) | function refreshHandler() {

FILE: bookkeeping-user-fe/src/pages/credit-accounts/ItemCard.jsx
  function expenseHandler (line 15) | function expenseHandler() {
  function incomeHandler (line 19) | function incomeHandler() {
  function transferToHandler (line 23) | function transferToHandler() {
  function transferFromHandler (line 27) | function transferFromHandler() {
  function adjustBalanceHandler (line 31) | function adjustBalanceHandler() {

FILE: bookkeeping-user-fe/src/pages/credit-accounts/model.js
  method sum (line 14) | *sum(_, { call, put }) {
  method query (line 21) | *query({ payload }, { call, put }) {
  method refresh (line 28) | *refresh(_, { call, put, select }) {
  method setup (line 36) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/dashboard/CardExtra.jsx
  function radioChangeHandler (line 17) | function radioChangeHandler(e) {

FILE: bookkeeping-user-fe/src/pages/dashboard/ExpenseCategory.jsx
  function timeRangeChangeHanlder (line 15) | function timeRangeChangeHanlder(value) {

FILE: bookkeeping-user-fe/src/pages/dashboard/IncomeCategory.jsx
  function timeRangeChangeHanlder (line 15) | function timeRangeChangeHanlder(value) {

FILE: bookkeeping-user-fe/src/pages/dashboard/model.js
  method fetchAssetOverview (line 16) | *fetchAssetOverview(_, { call, put }) {
  method fetchExpenseIncomeTable (line 23) | *fetchExpenseIncomeTable(_, { call, put }) {
  method fetchExpenseTrend (line 30) | *fetchExpenseTrend(_, { call, put }) {
  method fetchIncomeTrend (line 37) | *fetchIncomeTrend(_, { call, put }) {
  method fetchExpenseCategory (line 44) | *fetchExpenseCategory({ payload }, { call, put }) {
  method fetchIncomeCategory (line 51) | *fetchIncomeCategory({ payload }, { call, put }) {

FILE: bookkeeping-user-fe/src/pages/debt-accounts/GeneralBar.jsx
  function refreshHandler (line 21) | function refreshHandler() {

FILE: bookkeeping-user-fe/src/pages/debt-accounts/ItemCard.jsx
  function expenseHandler (line 14) | function expenseHandler() {
  function incomeHandler (line 18) | function incomeHandler() {
  function transferToHandler (line 22) | function transferToHandler() {
  function transferFromHandler (line 26) | function transferFromHandler() {
  function adjustBalanceHandler (line 30) | function adjustBalanceHandler() {

FILE: bookkeeping-user-fe/src/pages/debt-accounts/model.js
  method sum (line 14) | *sum(_, { call, put }) {
  method query (line 21) | *query({ payload }, { call, put }) {
  method refresh (line 28) | *refresh(_, { call, put, select }) {
  method setup (line 36) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/expenses/OperationBar.jsx
  function addHandler (line 47) | function addHandler() {
  function resetHandler (line 52) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/expenses/RecordTable.jsx
  function copyHandler (line 89) | function copyHandler(record) {
  function deleteHandler (line 100) | function deleteHandler(record) {
  function refundHandler (line 113) | function refundHandler(record) {
  function confirmHandler (line 118) | function confirmHandler(record) {

FILE: bookkeeping-user-fe/src/pages/expenses/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/flows/OperationBar.jsx
  function resetHandler (line 39) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/flows/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/groups/OperationModal.jsx
  function successHandler (line 40) | function successHandler() {

FILE: bookkeeping-user-fe/src/pages/groups/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/incomes/OperationBar.jsx
  function addHandler (line 44) | function addHandler() {
  function resetHandler (line 49) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/incomes/RecordTable.jsx
  function copyHandler (line 88) | function copyHandler(record) {
  function deleteHandler (line 99) | function deleteHandler(record) {
  function refundHandler (line 112) | function refundHandler(record) {
  function confirmHandler (line 117) | function confirmHandler(record) {

FILE: bookkeeping-user-fe/src/pages/incomes/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/items/OperationModal.jsx
  function successHandler (line 47) | function successHandler() {
  function parseValues (line 51) | function parseValues(values) {

FILE: bookkeeping-user-fe/src/pages/items/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/register/model.js
  method submit (line 9) | *submit({ payload }, { call, put }) {
  method registerHandler (line 18) | registerHandler(state, { payload }) {
  method clearRegisterResponse (line 21) | clearRegisterResponse(state) {

FILE: bookkeeping-user-fe/src/pages/reports/asset-debt-trend/OperationBar.jsx
  function resetHandler (line 15) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/reports/asset-debt-trend/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/reports/balance-sheet/model.js
  method getAsset (line 13) | *getAsset(_, { call, put }) {
  method getDebt (line 20) | *getDebt(_, { call, put }) {

FILE: bookkeeping-user-fe/src/pages/reports/expense-category/OperationBar.jsx
  function resetHandler (line 42) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/reports/expense-category/model.js
  method getCategory (line 13) | *getCategory({ payload }, { call, put }) {
  method query (line 20) | *query({ payload }, { call, put }) {
  method setup (line 29) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/reports/expense-income-trend/OperationBar.jsx
  function resetHandler (line 58) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/reports/expense-income-trend/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/reports/expense-tag/OperationBar.jsx
  function resetHandler (line 43) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/reports/expense-tag/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/reports/income-category/OperationBar.jsx
  function resetHandler (line 43) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/reports/income-category/model.js
  method getCategory (line 13) | *getCategory({ payload }, { call, put }) {
  method query (line 20) | *query({ payload }, { call, put }) {
  method setup (line 29) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/reports/income-tag/OperationBar.jsx
  function resetHandler (line 42) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/reports/income-tag/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/signin/model.js
  method submit (line 9) | *submit({ payload }, { put, call }) {
  method signInHandler (line 18) | signInHandler(state, { payload }) {
  method clearSignInResponse (line 21) | clearSignInResponse(state) {
  method setup (line 26) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/pages/test/index.jsx
  method render (line 4) | render() {

FILE: bookkeeping-user-fe/src/pages/transfers/OperationBar.jsx
  function addHandler (line 38) | function addHandler() {
  function resetHandler (line 43) | function resetHandler() {

FILE: bookkeeping-user-fe/src/pages/transfers/RecordTable.jsx
  function copyHandler (line 72) | function copyHandler(record) {
  function deleteHandler (line 83) | function deleteHandler(record) {
  function confirmHandler (line 97) | function confirmHandler(record) {

FILE: bookkeeping-user-fe/src/pages/transfers/model.js
  method query (line 11) | *query({ payload }, { call, put }) {
  method setup (line 20) | setup({ dispatch, history }) {

FILE: bookkeeping-user-fe/src/services/account.js
  function getEnable (line 6) | async function getEnable() {
  function getExpenseable (line 12) | async function getExpenseable() {
  function getIncomeable (line 18) | async function getIncomeable() {
  function getTransferFromAble (line 24) | async function getTransferFromAble() {
  function getTransferToAble (line 30) | async function getTransferToAble() {
  function adjustBalance (line 36) | async function adjustBalance(id, json) {
  function remove (line 43) | async function remove(id) {
  function toggle (line 49) | async function toggle(id) {
  function toggleInclude (line 55) | async function toggleInclude(id) {
  function toggleExpenseable (line 61) | async function toggleExpenseable(id) {
  function toggleIncomeable (line 67) | async function toggleIncomeable(id) {
  function toggleTransferFromAble (line 73) | async function toggleTransferFromAble(id) {
  function toggleTransferToAble (line 79) | async function toggleTransferToAble(id) {
  function update (line 85) | async function update(id, json) {

FILE: bookkeeping-user-fe/src/services/adjust-balance.js
  function query (line 5) | async function query(params) {
  function remove (line 12) | async function remove(id) {

FILE: bookkeeping-user-fe/src/services/asset-account.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function sum (line 19) | async function sum() {

FILE: bookkeeping-user-fe/src/services/book.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function update (line 19) | async function update(id, json) {
  function config (line 26) | async function config(_, json) {
  function remove (line 33) | async function remove(id) {
  function toggle (line 39) | async function toggle(id) {

FILE: bookkeeping-user-fe/src/services/category.js
  function remove (line 5) | async function remove(id) {
  function toggle (line 11) | async function toggle(id) {

FILE: bookkeeping-user-fe/src/services/checking-account.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function sum (line 19) | async function sum() {

FILE: bookkeeping-user-fe/src/services/credit-account.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function sum (line 19) | async function sum() {

FILE: bookkeeping-user-fe/src/services/currency.js
  function getAll (line 5) | async function getAll() {

FILE: bookkeeping-user-fe/src/services/dashboard.js
  function getAssetOverview (line 5) | async function getAssetOverview() {
  function getExpenseIncomeTable (line 11) | async function getExpenseIncomeTable() {
  function getExpenseTrend (line 17) | async function getExpenseTrend() {
  function getIncomeTrend (line 23) | async function getIncomeTrend() {
  function getExpenseCategory (line 29) | async function getExpenseCategory(params) {
  function getIncomeCategory (line 36) | async function getIncomeCategory(params) {

FILE: bookkeeping-user-fe/src/services/deal.js
  function getRefunds (line 5) | async function getRefunds(id) {

FILE: bookkeeping-user-fe/src/services/debt-account.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function sum (line 19) | async function sum() {

FILE: bookkeeping-user-fe/src/services/expense-category.js
  function query (line 6) | async function query(params) {
  function querySimple (line 14) | async function querySimple(params) {
  function create (line 21) | async function create(json) {
  function update (line 28) | async function update(id, json) {

FILE: bookkeeping-user-fe/src/services/expense.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function update (line 19) | async function update(id, json) {
  function refund (line 26) | async function refund(id, json) {

FILE: bookkeeping-user-fe/src/services/flow-image.js
  function getUploadToken (line 5) | async function getUploadToken() {

FILE: bookkeeping-user-fe/src/services/flow.js
  function query (line 5) | async function query(params) {
  function remove (line 12) | async function remove(record) {
  function confirm (line 18) | async function confirm(record) {
  function audit (line 24) | async function audit(params) {
  function getImages (line 31) | async function getImages(id) {
  function updateImages (line 37) | async function updateImages(id, images) {

FILE: bookkeeping-user-fe/src/services/group.js
  function query (line 5) | async function query(params) {
  function getEnable (line 12) | async function getEnable() {
  function create (line 18) | async function create(json) {
  function update (line 25) | async function update(id, json) {
  function remove (line 32) | async function remove(id) {

FILE: bookkeeping-user-fe/src/services/income-category.js
  function query (line 5) | async function query(params) {
  function querySimple (line 12) | async function querySimple(params) {
  function create (line 19) | async function create(json) {
  function update (line 26) | async function update(id, json) {

FILE: bookkeeping-user-fe/src/services/income.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function update (line 19) | async function update(id, json) {
  function refund (line 26) | async function refund(id, json) {

FILE: bookkeeping-user-fe/src/services/item.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function update (line 19) | async function update(id, json) {
  function run (line 26) | async function run(id, json) {
  function recall (line 33) | async function recall(id, json) {
  function remove (line 40) | async function remove(id) {

FILE: bookkeeping-user-fe/src/services/log.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function remove (line 19) | async function remove(id) {

FILE: bookkeeping-user-fe/src/services/payee.js
  function query (line 5) | async function query(params) {
  function getEnable (line 12) | async function getEnable() {
  function getExpenseable (line 18) | async function getExpenseable() {
  function getIncomeable (line 24) | async function getIncomeable() {
  function create (line 30) | async function create(json) {
  function update (line 37) | async function update(id, json) {
  function remove (line 44) | async function remove(id) {
  function toggle (line 50) | async function toggle(id) {

FILE: bookkeeping-user-fe/src/services/report.js
  function getExpenseCategory (line 5) | async function getExpenseCategory(params) {
  function getExpenseTag (line 12) | async function getExpenseTag(params) {
  function getIncomeCategory (line 19) | async function getIncomeCategory(params) {
  function getIncomeTag (line 26) | async function getIncomeTag(params) {
  function getExpenseIncomeTrend (line 33) | async function getExpenseIncomeTrend(params) {
  function getAssetDebtTrend (line 40) | async function getAssetDebtTrend(params) {
  function getAsset (line 47) | async function getAsset() {
  function getDebt (line 53) | async function getDebt() {

FILE: bookkeeping-user-fe/src/services/schedule.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function update (line 19) | async function update(id, json) {
  function remove (line 26) | async function remove(id) {

FILE: bookkeeping-user-fe/src/services/tag-relation.js
  function update (line 5) | async function update(id, json) {

FILE: bookkeeping-user-fe/src/services/tag.js
  function query (line 5) | async function query(params) {
  function getEnable (line 12) | async function getEnable() {
  function getExpenseable (line 18) | async function getExpenseable() {
  function getIncomeable (line 24) | async function getIncomeable() {
  function getTransferable (line 30) | async function getTransferable() {
  function create (line 36) | async function create(json) {
  function update (line 43) | async function update(id, json) {
  function remove (line 50) | async function remove(id) {
  function toggle (line 56) | async function toggle(id) {

FILE: bookkeeping-user-fe/src/services/transfer.js
  function query (line 5) | async function query(params) {
  function create (line 12) | async function create(json) {
  function update (line 19) | async function update(id, json) {

FILE: bookkeeping-user-fe/src/services/user.js
  function register (line 3) | async function register(params) {
  function signin (line 10) | async function signin(params) {
  function signout (line 17) | async function signout() {
  function updatePassword (line 23) | async function updatePassword(params) {
  function getSessionUser (line 30) | async function getSessionUser() {
  function setDefaultBook (line 36) | async function setDefaultBook(id) {
  function setDefaultGroup (line 42) | async function setDefaultGroup(id) {

FILE: bookkeeping-user-fe/src/utils/flow.js
  function showFlowModal (line 9) | function showFlowModal(flowType, modalType, currentItem) {
  function imageHandler (line 27) | function imageHandler(record) {

FILE: bookkeeping-user-fe/src/utils/hooks.js
  function useFocus (line 5) | function useFocus() {
  function usePaginationAndData (line 11) | function usePaginationAndData(queryResponse) {
  function useResultPaginationAndData (line 40) | function useResultPaginationAndData(queryResponse) {
  function useResponseData (line 69) | function useResponseData(queryResponse) {
  function useResponseSelectData (line 79) | function useResponseSelectData(queryResponse) {
  function useCurrencyResponseSelectData (line 95) | function useCurrencyResponseSelectData(queryResponse) {
  function useCategoryTreeSelectData (line 111) | function useCategoryTreeSelectData(categoriesResponse) {
  function useImageEnable (line 128) | function useImageEnable() {
  function useDescriptionEnable (line 141) | function useDescriptionEnable() {
  function useTimeFormat (line 154) | function useTimeFormat() {

FILE: bookkeeping-user-fe/src/utils/model.js
  method updateState (line 3) | updateState(state, { payload }) {

FILE: bookkeeping-user-fe/src/utils/util.js
  function tableSortFormat (line 4) | function tableSortFormat(sorter) {
  function handleTableChange (line 17) | function handleTableChange(pagination, _, sorter) {
  function paginationChange (line 30) | function paginationChange(page, pageSize) {
  function tableChangeQueryFormat (line 42) | function tableChangeQueryFormat(pagination, sorter) {
  function offSpring (line 50) | function offSpring(categories, category) {
  function parseCreateTimeRange (line 59) | function parseCreateTimeRange(values) {
  function searchHandler (line 69) | async function searchHandler(form) {
  function searchHandlerWithCategory (line 78) | async function searchHandlerWithCategory(form) {
  function flowStatusToColor (line 93) | function flowStatusToColor(code) {
  function getNull (line 106) | function getNull(obj) {
  function validateForm (line 112) | async function validateForm(form) {
  function radioValueToTimeRange (line 121) | function radioValueToTimeRange(value) {
  function initPagination (line 142) | function initPagination() {
  function getPagination (line 152) | function getPagination(data, pagination) {
  function getTimeFormat (line 161) | function getTimeFormat() {
  function getTimeEnable (line 169) | function getTimeEnable() {
  function getDescriptionEnable (line 175) | function getDescriptionEnable() {
  function getImageEnable (line 181) | function getImageEnable() {
  function categoryTypeToCreateParam (line 187) | function categoryTypeToCreateParam(type) {
  function refreshFlow (line 198) | function refreshFlow(data) {
  function searchTreeArray (line 232) | function searchTreeArray(treeArray, value, key = 'id', reverse = true) {

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_adjust_balance/account_adjust_balance_bloc.dart
  class AccountAdjustBalanceBloc (line 13) | class AccountAdjustBalanceBloc extends Bloc<AccountAdjustBalanceEvent, A...
    method _onDescriptionChanged (line 29) | void _onDescriptionChanged(AccountAdjustBalanceDescriptionChanged even...
    method _onNotesChanged (line 35) | void _onNotesChanged(AccountAdjustBalanceNotesChanged event, Emitter<A...
    method _onCreateDateChanged (line 41) | void _onCreateDateChanged(AccountAdjustBalanceCreateDateChanged event,...
    method _onCreateTimeChanged (line 49) | void _onCreateTimeChanged(AccountAdjustBalanceCreateTimeChanged event,...
    method _onDefaultLoaded (line 57) | void _onDefaultLoaded(AccountAdjustBalanceDefaultLoaded event, Emitter...
    method _onBalanceChanged (line 68) | void _onBalanceChanged(AccountAdjustBalanceBalanceChanged event, Emitt...
    method _onSubmitted (line 74) | void _onSubmitted(AccountAdjustBalanceSubmitted event, Emitter<Account...

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_adjust_balance/account_adjust_balance_event.dart
  class AccountAdjustBalanceEvent (line 3) | @immutable
  class AccountAdjustBalanceCreateTimeChanged (line 10) | class AccountAdjustBalanceCreateTimeChanged extends AccountAdjustBalance...
  class AccountAdjustBalanceCreateDateChanged (line 17) | class AccountAdjustBalanceCreateDateChanged extends AccountAdjustBalance...
  class AccountAdjustBalanceBalanceChanged (line 24) | class AccountAdjustBalanceBalanceChanged extends AccountAdjustBalanceEve...
  class AccountAdjustBalanceDescriptionChanged (line 32) | class AccountAdjustBalanceDescriptionChanged extends AccountAdjustBalanc...
  class AccountAdjustBalanceNotesChanged (line 39) | class AccountAdjustBalanceNotesChanged extends AccountAdjustBalanceEvent {
  class AccountAdjustBalanceDefaultLoaded (line 46) | class AccountAdjustBalanceDefaultLoaded extends AccountAdjustBalanceEvent {
  class AccountAdjustBalanceSubmitted (line 54) | class AccountAdjustBalanceSubmitted extends AccountAdjustBalanceEvent {

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_adjust_balance/account_adjust_balance_state.dart
  class AccountAdjustBalanceState (line 3) | @immutable
    method copyWith (line 14) | AccountAdjustBalanceState copyWith({

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_enable/account_enable_bloc.dart
  class AccountEnableBloc (line 9) | class AccountEnableBloc extends Bloc<AccountEnableEvent, AccountEnableSt...
    method _onAccountEnableLoaded (line 19) | void _onAccountEnableLoaded(_, Emitter<AccountEnableState> emit)

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_enable/account_enable_event.dart
  class AccountEnableEvent (line 3) | abstract class AccountEnableEvent extends Equatable {
  class AccountEnableLoaded (line 9) | class AccountEnableLoaded extends AccountEnableEvent { }

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_enable/account_enable_state.dart
  class AccountEnableState (line 3) | abstract class AccountEnableState extends Equatable {
  class AccountEnableStateLoadInProgress (line 9) | class AccountEnableStateLoadInProgress extends AccountEnableState { }
  class AccountEnableStateLoadSuccess (line 11) | class AccountEnableStateLoadSuccess extends AccountEnableState {
  class AccountEnableStateLoadFailure (line 18) | class AccountEnableStateLoadFailure extends AccountEnableState { }

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_expenseable/account_expenseable_bloc.dart
  class AccountExpenseableBloc (line 9) | class AccountExpenseableBloc extends Bloc<AccountExpenseableEvent, Accou...
    method _onAccountExpenseableLoaded (line 19) | void _onAccountExpenseableLoaded(_, Emitter<AccountExpenseableState> e...

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_expenseable/account_expenseable_event.dart
  class AccountExpenseableEvent (line 3) | abstract class AccountExpenseableEvent extends Equatable {
  class AccountExpenseableLoaded (line 9) | class AccountExpenseableLoaded extends AccountExpenseableEvent { }

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_expenseable/account_expenseable_state.dart
  class AccountExpenseableState (line 3) | abstract class AccountExpenseableState extends Equatable {
  class AccountExpenseableStateLoadInProgress (line 9) | class AccountExpenseableStateLoadInProgress extends AccountExpenseableSt...
  class AccountExpenseableStateLoadSuccess (line 11) | class AccountExpenseableStateLoadSuccess extends AccountExpenseableState {
  class AccountExpenseableStateLoadFailure (line 18) | class AccountExpenseableStateLoadFailure extends AccountExpenseableState...

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_fetch/account_fetch_bloc.dart
  class AccountFetchBloc (line 11) | class AccountFetchBloc extends Bloc<AccountFetchEvent, AccountFetchState> {
    method _onDefault (line 22) | void _onDefault(AccountLoadDefault event, Emitter<AccountFetchState> e...
    method _onFetched (line 29) | void _onFetched(_, Emitter<AccountFetchState> emit)

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_fetch/account_fetch_event.dart
  class AccountFetchEvent (line 3) | @immutable
  class AccountFetched (line 10) | class AccountFetched extends AccountFetchEvent {}
  class AccountLoadDefault (line 12) | class AccountLoadDefault extends AccountFetchEvent {

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_fetch/account_fetch_state.dart
  class AccountFetchState (line 3) | @immutable
    method copyWith (line 14) | AccountFetchState copyWith({

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_form/account_form_bloc.dart
  class AccountFormBloc (line 12) | class AccountFormBloc extends Bloc<AccountFormEvent, AccountFormState> {
    method _onCurrencyCodeChanged (line 38) | void _onCurrencyCodeChanged(AccountFormCurrencyCodeChanged event, Emit...
    method _onNameChanged (line 44) | void _onNameChanged(AccountFormNameChanged event, Emitter<AccountFormS...
    method _onBalanceChanged (line 50) | void _onBalanceChanged(AccountFormBalanceChanged event, Emitter<Accoun...
    method _onNoChanged (line 56) | void _onNoChanged(AccountFormNoChanged event, Emitter<AccountFormState...
    method _onExpenseableChanged (line 62) | void _onExpenseableChanged(AccountFormExpenseableChanged event, Emitte...
    method _onIncomeableChanged (line 68) | void _onIncomeableChanged(AccountFormIncomeableChanged event, Emitter<...
    method _onTransferFromAbleChanged (line 74) | void _onTransferFromAbleChanged(AccountFormTransferFromAbleChanged eve...
    method _onTransferToAbleChanged (line 80) | void _onTransferToAbleChanged(AccountFormTransferToAbleChanged event, ...
    method _onIncludeChanged (line 86) | void _onIncludeChanged(AccountFormIncludeChanged event, Emitter<Accoun...
    method _onNotesChanged (line 92) | void _onNotesChanged(AccountFormNotesChanged event, Emitter<AccountFor...
    method _onLimitChanged (line 98) | void _onLimitChanged(AccountFormLimitChanged event, Emitter<AccountFor...
    method _onBillDayChanged (line 104) | void _onBillDayChanged(AccountFormBillDayChanged event, Emitter<Accoun...
    method _onAprChanged (line 110) | void _onAprChanged(AccountFormAprChanged event, Emitter<AccountFormSta...
    method _onDefaultLoaded (line 116) | void _onDefaultLoaded(AccountFormDefaultLoaded event, Emitter<AccountF...
    method _onSubmitted (line 137) | void _onSubmitted(AccountFormSubmitted event, Emitter<AccountFormState...

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_form/account_form_event.dart
  class AccountFormEvent (line 3) | @immutable
  class AccountFormCurrencyCodeChanged (line 10) | class AccountFormCurrencyCodeChanged extends AccountFormEvent {
  class AccountFormNameChanged (line 17) | class AccountFormNameChanged extends AccountFormEvent {
  class AccountFormBalanceChanged (line 24) | class AccountFormBalanceChanged extends AccountFormEvent {
  class AccountFormNoChanged (line 31) | class AccountFormNoChanged extends AccountFormEvent {
  class AccountFormExpenseableChanged (line 38) | class AccountFormExpenseableChanged extends AccountFormEvent {
  class AccountFormIncomeableChanged (line 45) | class AccountFormIncomeableChanged extends AccountFormEvent {
  class AccountFormTransferFromAbleChanged (line 52) | class AccountFormTransferFromAbleChanged extends AccountFormEvent {
  class AccountFormTransferToAbleChanged (line 59) | class AccountFormTransferToAbleChanged extends AccountFormEvent {
  class AccountFormIncludeChanged (line 66) | class AccountFormIncludeChanged extends AccountFormEvent {
  class AccountFormNotesChanged (line 73) | class AccountFormNotesChanged extends AccountFormEvent {
  class AccountFormLimitChanged (line 80) | class AccountFormLimitChanged extends AccountFormEvent {
  class AccountFormBillDayChanged (line 87) | class AccountFormBillDayChanged extends AccountFormEvent {
  class AccountFormAprChanged (line 94) | class AccountFormAprChanged extends AccountFormEvent {
  class AccountFormDefaultLoaded (line 101) | class AccountFormDefaultLoaded extends AccountFormEvent {
  class AccountFormSubmitted (line 110) | class AccountFormSubmitted extends AccountFormEvent {

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_form/account_form_state.dart
  class AccountFormState (line 3) | @immutable
    method copyWith (line 14) | AccountFormState copyWith({

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_incomeable/account_incomeable_bloc.dart
  class AccountIncomeableBloc (line 9) | class AccountIncomeableBloc extends Bloc<AccountIncomeableEvent, Account...
    method _onAccountIncomeableLoaded (line 19) | void _onAccountIncomeableLoaded(_, Emitter<AccountIncomeableState> emit)

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_incomeable/account_incomeable_event.dart
  class AccountIncomeableEvent (line 3) | abstract class AccountIncomeableEvent extends Equatable {
  class AccountIncomeableLoaded (line 9) | class AccountIncomeableLoaded extends AccountIncomeableEvent { }

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_incomeable/account_incomeable_state.dart
  class AccountIncomeableState (line 3) | abstract class AccountIncomeableState extends Equatable {
  class AccountIncomeableStateLoadInProgress (line 9) | class AccountIncomeableStateLoadInProgress extends AccountIncomeableStat...
  class AccountIncomeableStateLoadSuccess (line 11) | class AccountIncomeableStateLoadSuccess extends AccountIncomeableState {
  class AccountIncomeableStateLoadFailure (line 18) | class AccountIncomeableStateLoadFailure extends AccountIncomeableState { }

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_transfer_from_able/account_transfer_from_able_bloc.dart
  class AccountTransferFromAbleBloc (line 9) | class AccountTransferFromAbleBloc extends Bloc<AccountTransferFromAbleEv...
    method _onAccountTransferFromAbleLoaded (line 19) | void _onAccountTransferFromAbleLoaded(_, Emitter<AccountTransferFromAb...

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_transfer_from_able/account_transfer_from_able_event.dart
  class AccountTransferFromAbleEvent (line 3) | abstract class AccountTransferFromAbleEvent extends Equatable {
  class AccountTransferFromAbleLoaded (line 9) | class AccountTransferFromAbleLoaded extends AccountTransferFromAbleEvent...

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_transfer_from_able/account_transfer_from_able_state.dart
  class AccountTransferFromAbleState (line 3) | abstract class AccountTransferFromAbleState extends Equatable {
  class AccountTransferFromAbleStateLoadInProgress (line 9) | class AccountTransferFromAbleStateLoadInProgress extends AccountTransfer...
  class AccountTransferFromAbleStateLoadSuccess (line 11) | class AccountTransferFromAbleStateLoadSuccess extends AccountTransferFro...
  class AccountTransferFromAbleStateLoadFailure (line 18) | class AccountTransferFromAbleStateLoadFailure extends AccountTransferFro...

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_transfer_to_able/account_transfer_to_able_bloc.dart
  class AccountTransferToAbleBloc (line 9) | class AccountTransferToAbleBloc extends Bloc<AccountTransferToAbleEvent,...
    method _onAccountTransferToAbleLoaded (line 19) | void _onAccountTransferToAbleLoaded(_, Emitter<AccountTransferToAbleSt...

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_transfer_to_able/account_transfer_to_able_event.dart
  class AccountTransferToAbleEvent (line 3) | abstract class AccountTransferToAbleEvent extends Equatable {
  class AccountTransferToAbleLoaded (line 9) | class AccountTransferToAbleLoaded extends AccountTransferToAbleEvent { }

FILE: bookkeeping_user_flutter/lib/accounts/bloc/account_transfer_to_able/account_transfer_to_able_state.dart
  class AccountTransferToAbleState (line 3) | abstract class AccountTransferToAbleState extends Equatable {
  class AccountTransferToAbleStateLoadInProgress (line 9) | class AccountTransferToAbleStateLoadInProgress extends AccountTransferTo...
  class AccountTransferToAbleStateLoadSuccess (line 11) | class AccountTransferToAbleStateLoadSuccess extends AccountTransferToAbl...
  class AccountTransferToAbleStateLoadFailure (line 18) | class AccountTransferToAbleStateLoadFailure extends AccountTransferToAbl...

FILE: bookkeeping_user_flutter/lib/accounts/bloc/accounts/accounts_bloc.dart
  class AccountsBloc (line 11) | class AccountsBloc extends Bloc<AccountsEvent, AccountsState> {
    method _onRefreshed (line 26) | void _onRefreshed(_, Emitter<AccountsState> emit)
    method _onLoadMore (line 43) | void _onLoadMore(_, Emitter<AccountsState> emit)
    method _onTabChanged (line 61) | void _onTabChanged(AccountsTabChanged event, Emitter<AccountsState> emit)
    method _onSortChanged (line 67) | void _onSortChanged(AccountsSortChanged event, Emitter<AccountsState> ...
    method _onDeleted (line 73) | void _onDeleted(AccountDeleted event, Emitter<AccountsState> emit)
    method _onToggled (line 87) | void _onToggled(AccountToggled event, Emitter<AccountsState> emit)

FILE: bookkeeping_user_flutter/lib/accounts/bloc/accounts/accounts_event.dart
  class AccountsEvent (line 3) | @immutable
  class AccountsRefreshed (line 10) | class AccountsRefreshed extends AccountsEvent {}
  class AccountsLoadMore (line 12) | class AccountsLoadMore extends AccountsEvent {}
  class AccountDeleted (line 14) | class AccountDeleted extends AccountsEvent {
  class AccountToggled (line 21) | class AccountToggled extends AccountsEvent {
  class AccountsTabChanged (line 28) | class AccountsTabChanged extends AccountsEvent {
  class AccountsSortChanged (line 35) | class AccountsSortChanged extends AccountsEvent {

FILE: bookkeeping_user_flutter/lib/accounts/bloc/accounts/accounts_state.dart
  class AccountsState (line 3) | @immutable
    method copyWith (line 22) | AccountsState copyWith({

FILE: bookkeeping_user_flutter/lib/accounts/data/account_repository.dart
  class AccountRepository (line 5) | class AccountRepository {
    method _responseToList (line 7) | List<Account> _responseToList(String response)
    method _responseAccount (line 11) | Account _responseAccount(String response)
    method _responseToList2 (line 15) | List<Account> _responseToList2(String response)
    method getExpenseable (line 19) | Future<List<Account>> getExpenseable()
    method getIncomeable (line 24) | Future<List<Account>> getIncomeable()
    method getTransferFromAble (line 29) | Future<List<Account>> getTransferFromAble()
    method getTransferToAble (line 34) | Future<List<Account>> getTransferToAble()
    method getEnable (line 39) | Future<List<Account>> getEnable()
    method query (line 44) | Future<List<Account>> query(AccountQueryRequest request)
    method get (line 59) | Future<Account> get(int id)
    method delete (line 63) | Future<bool> delete(String id)
    method toggle (line 68) | Future<bool> toggle(String id)
    method add (line 73) | Future<bool> add(int type, AccountFormRequest request)
    method update (line 93) | Future<bool> update(int id, AccountFormRequest request)
    method adjustBalance (line 98) | Future<bool> adjustBalance(int id, AdjustBalanceRequest request)
    method updateAdjustBalance (line 103) | Future<bool> updateAdjustBalance(int id, AdjustBalanceRequest request)

FILE: bookkeeping_user_flutter/lib/accounts/data/models/account.dart
  class Account (line 6) | @JsonSerializable()
    method toJson (line 59) | Map<String, dynamic> toJson()

FILE: bookkeeping_user_flutter/lib/accounts/data/models/account.g.dart
  function _$AccountFromJson (line 9) | Account _$AccountFromJson(Map<String, dynamic> json)
  function _$AccountToJson (line 33) | Map<String, dynamic> _$AccountToJson(Account instance)

FILE: bookkeeping_user_flutter/lib/accounts/data/models/account_form_request.dart
  class AccountFormRequest (line 6) | @JsonSerializable()
    method toJson (line 39) | Map<String, dynamic> toJson()
    method copyWith (line 41) | AccountFormRequest copyWith({

FILE: bookkeeping_user_flutter/lib/accounts/data/models/account_form_request.g.dart
  function _$AccountFormRequestFromJson (line 9) | AccountFormRequest _$AccountFormRequestFromJson(Map<String, dynamic> json)
  function _$AccountFormRequestToJson (line 26) | Map<String, dynamic> _$AccountFormRequestToJson(AccountFormRequest insta...

FILE: bookkeeping_user_flutter/lib/accounts/data/models/account_query_request.dart
  class AccountQueryRequest (line 6) | @JsonSerializable()
    method toJson (line 23) | Map<String, dynamic> toJson()
    method copyWith (line 28) | AccountQueryRequest copyWith({

FILE: bookkeeping_user_flutter/lib/accounts/data/models/account_query_request.g.dart
  function _$AccountQueryRequestFromJson (line 9) | AccountQueryRequest _$AccountQueryRequestFromJson(Map<String, dynamic> j...
  function _$AccountQueryRequestToJson (line 17) | Map<String, dynamic> _$AccountQueryRequestToJson(

FILE: bookkeeping_user_flutter/lib/accounts/data/models/adjust_balance_request.dart
  class AdjustBalanceRequest (line 6) | @JsonSerializable()
    method copyWith (line 23) | AdjustBalanceRequest copyWith({
    method toJson (line 41) | Map<String, dynamic> toJson()

FILE: bookkeeping_user_flutter/lib/accounts/data/models/adjust_balance_request.g.dart
  function _$AdjustBalanceRequestFromJson (line 9) | AdjustBalanceRequest _$AdjustBalanceRequestFromJson(
  function _$AdjustBalanceRequestToJson (line 19) | Map<String, dynamic> _$AdjustBalanceRequestToJson(

FILE: bookkeeping_user_flutter/lib/accounts/ui/account_adjust_balance.dart
  class AccountAdjustBalance (line 6) | class AccountAdjustBalance extends StatelessWidget {
    method build (line 15) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/account_detail_page.dart
  class AccountDetailPage (line 9) | class AccountDetailPage extends StatefulWidget {
    method createState (line 17) | State<AccountDetailPage> createState()
  class _AccountDetailPageState (line 20) | class _AccountDetailPageState extends State<AccountDetailPage> {
    method initState (line 23) | void initState()
    method build (line 29) | Widget build(BuildContext context)
    method _buildActions (line 83) | List<Widget> _buildActions(BuildContext context, Account account)
    method _buildBody (line 107) | Widget _buildBody(BuildContext context, Account account)

FILE: bookkeeping_user_flutter/lib/accounts/ui/account_form_page.dart
  class AccountFormPage (line 9) | class AccountFormPage extends StatelessWidget {
    method build (line 22) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/accounts_page.dart
  class AccountsPage (line 9) | class AccountsPage extends StatefulWidget {
    method createState (line 11) | State<AccountsPage> createState()
  class _AccountsPageState (line 15) | class _AccountsPageState extends State<AccountsPage> with TickerProvider...
    method initState (line 21) | void initState()
    method dispose (line 34) | void dispose()
    method build (line 40) | Widget build(BuildContext context)
    method _buildList (line 137) | Widget _buildList(BuildContext context, List<Account> accounts)

FILE: bookkeeping_user_flutter/lib/accounts/ui/asset_account_form_page.dart
  class AssetAccountFormPage (line 6) | class AssetAccountFormPage extends StatelessWidget {
    method build (line 19) | Widget build(BuildContext context)
    method _buildTitle (line 63) | String _buildTitle(int type)

FILE: bookkeeping_user_flutter/lib/accounts/ui/checking_account_form_page.dart
  class CheckingAccountFormPage (line 6) | class CheckingAccountFormPage extends StatelessWidget {
    method build (line 19) | Widget build(BuildContext context)
    method _buildTitle (line 65) | String _buildTitle(int type)

FILE: bookkeeping_user_flutter/lib/accounts/ui/credit_account_form_page.dart
  class CreditAccountFormPage (line 6) | class CreditAccountFormPage extends StatelessWidget {
    method build (line 19) | Widget build(BuildContext context)
    method _buildTitle (line 69) | String _buildTitle(int type)

FILE: bookkeeping_user_flutter/lib/accounts/ui/debt_account_form_page.dart
  class DebtAccountFormPage (line 6) | class DebtAccountFormPage extends StatelessWidget {
    method build (line 19) | Widget build(BuildContext context)
    method _buildTitle (line 69) | String _buildTitle(int type)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/account_apr_input.dart
  class AccountAprInput (line 6) | class AccountAprInput extends StatelessWidget {
    method build (line 8) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/account_balance_input.dart
  class AccountBalanceInput (line 6) | class AccountBalanceInput extends StatelessWidget {
    method build (line 8) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/account_billday_input.dart
  class AccountBillDayInput (line 6) | class AccountBillDayInput extends StatelessWidget {
    method build (line 8) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/account_limit_input.dart
  class AccountLimitInput (line 6) | class AccountLimitInput extends StatelessWidget {
    method build (line 8) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/currency_input.dart
  class CurrencyInput (line 9) | class CurrencyInput extends StatelessWidget {
    method build (line 11) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/expenseable_input.dart
  class ExpenseableSwitch (line 7) | class ExpenseableSwitch extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/inclue_input.dart
  class IncludeSwitch (line 7) | class IncludeSwitch extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/incomeable_input.dart
  class IncomeableSwitch (line 7) | class IncomeableSwitch extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/name_input.dart
  class NameInput (line 6) | class NameInput extends StatelessWidget {
    method build (line 8) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/no_input.dart
  class NoInput (line 6) | class NoInput extends StatelessWidget {
    method build (line 8) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/notes_input.dart
  class NotesInput (line 6) | class NotesInput extends StatelessWidget {
    method build (line 8) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/transfer_from_able_input.dart
  class TransferFromAbleSwitch (line 7) | class TransferFromAbleSwitch extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/account_form/transfer_to_able_input.dart
  class TransferToAbleSwitch (line 7) | class TransferToAbleSwitch extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/adjust_balance/adjust_balance_form.dart
  class AdjustBalanceForm (line 9) | class AdjustBalanceForm extends StatefulWidget {
    method createState (line 22) | State<AdjustBalanceForm> createState()
  class _AdjustBalanceFormState (line 25) | class _AdjustBalanceFormState extends State<AdjustBalanceForm> {
    method initState (line 28) | void initState()
    method build (line 34) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/adjust_balance/balance_input.dart
  class BalanceInput (line 7) | class BalanceInput extends StatelessWidget {
    method build (line 16) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/adjust_balance/date_time_input.dart
  class AdjustBlanceDateTimeInput (line 7) | class AdjustBlanceDateTimeInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/adjust_balance/description_input.dart
  class DescriptionInput (line 7) | class DescriptionInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/adjust_balance/notes_input.dart
  class NoteInput (line 7) | class NoteInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/accounts/ui/widgets/order_button.dart
  class OrderButton (line 7) | class OrderButton extends StatelessWidget {
    method build (line 10) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/add_expense/add_expense_bloc.dart
  class AddExpenseBloc (line 13) | class AddExpenseBloc extends Bloc<AddExpenseEvent, AddExpenseState> {
    method _onAccountChanged (line 39) | void _onAccountChanged(AddExpenseAccountChanged event, Emitter<AddExpe...
    method _onTagChanged (line 52) | void _onTagChanged(AddExpenseTagChanged event, Emitter<AddExpenseState...
    method _onDescriptionChanged (line 58) | void _onDescriptionChanged(AddExpenseDescriptionChanged event, Emitter...
    method _onNotesChanged (line 64) | void _onNotesChanged(AddExpenseNotesChanged event, Emitter<AddExpenseS...
    method _onConfirmedChanged (line 70) | void _onConfirmedChanged(AddExpenseConfirmedChanged event, Emitter<Add...
    method _onPayeeChanged (line 76) | void _onPayeeChanged(AddExpensePayeeChanged event, Emitter<AddExpenseS...
    method _onCreateTimeChanged (line 82) | void _onCreateTimeChanged(AddExpenseCreateTimeChanged event, Emitter<A...
    method _onCreateDateChanged (line 90) | void _onCreateDateChanged(AddExpenseCreateDateChanged event, Emitter<A...
    method _onCategoryChanged (line 98) | void _onCategoryChanged(AddExpenseCategoryChanged event, Emitter<AddEx...
    method _onAmountChanged (line 109) | void _onAmountChanged(AddExpenseAmountChanged event, Emitter<AddExpens...
    method _onConvertedAmountChanged (line 113) | void _onConvertedAmountChanged(AddExpenseConvertedAmountChanged event,...
    method _onDefaultLoaded (line 117) | void _onDefaultLoaded(AddExpenseDefaultLoaded event, Emitter<AddExpens...
    method _onSubmitted (line 160) | void _onSubmitted(AddExpenseSubmitted event, Emitter<AddExpenseState> ...

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/add_expense/add_expense_event.dart
  class AddExpenseEvent (line 3) | abstract class AddExpenseEvent extends Equatable {
  class AddExpenseCreateTimeChanged (line 9) | class AddExpenseCreateTimeChanged extends AddExpenseEvent {
  class AddExpenseCreateDateChanged (line 16) | class AddExpenseCreateDateChanged extends AddExpenseEvent {
  class AddExpenseAccountChanged (line 23) | class AddExpenseAccountChanged extends AddExpenseEvent {
  class AddExpensePayeeChanged (line 30) | class AddExpensePayeeChanged extends AddExpenseEvent {
  class AddExpenseCategoryChanged (line 37) | class AddExpenseCategoryChanged extends AddExpenseEvent {
  class AddExpenseTagChanged (line 45) | class AddExpenseTagChanged extends AddExpenseEvent {
  class AddExpenseAmountChanged (line 52) | class AddExpenseAmountChanged extends AddExpenseEvent {
  class AddExpenseConvertedAmountChanged (line 60) | class AddExpenseConvertedAmountChanged extends AddExpenseEvent {
  class AddExpenseDescriptionChanged (line 68) | class AddExpenseDescriptionChanged extends AddExpenseEvent {
  class AddExpenseNotesChanged (line 75) | class AddExpenseNotesChanged extends AddExpenseEvent {
  class AddExpenseConfirmedChanged (line 82) | class AddExpenseConfirmedChanged extends AddExpenseEvent {
  class AddExpenseDefaultLoaded (line 89) | class AddExpenseDefaultLoaded extends AddExpenseEvent {
  class AddExpenseSubmitted (line 97) | class AddExpenseSubmitted extends AddExpenseEvent {

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/add_expense/add_expense_state.dart
  class AddExpenseState (line 3) | class AddExpenseState extends Equatable {
    method copyWith (line 15) | AddExpenseState copyWith({

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/add_income/add_income_bloc.dart
  class AddIncomeBloc (line 13) | class AddIncomeBloc extends Bloc<AddIncomeEvent, AddIncomeState> {
    method _onAccountChanged (line 39) | void _onAccountChanged(AddIncomeAccountChanged event, Emitter<AddIncom...
    method _onTagChanged (line 52) | void _onTagChanged(AddIncomeTagChanged event, Emitter<AddIncomeState> ...
    method _onDescriptionChanged (line 58) | void _onDescriptionChanged(AddIncomeDescriptionChanged event, Emitter<...
    method _onNotesChanged (line 64) | void _onNotesChanged(AddIncomeNotesChanged event, Emitter<AddIncomeSta...
    method _onConfirmedChanged (line 70) | void _onConfirmedChanged(AddIncomeConfirmedChanged event, Emitter<AddI...
    method _onPayeeChanged (line 76) | void _onPayeeChanged(AddIncomePayeeChanged event, Emitter<AddIncomeSta...
    method _onCreateTimeChanged (line 82) | void _onCreateTimeChanged(AddIncomeCreateTimeChanged event, Emitter<Ad...
    method _onCreateDateChanged (line 90) | void _onCreateDateChanged(AddIncomeCreateDateChanged event, Emitter<Ad...
    method _onCategoryChanged (line 98) | void _onCategoryChanged(AddIncomeCategoryChanged event, Emitter<AddInc...
    method _onAmountChanged (line 109) | void _onAmountChanged(AddIncomeAmountChanged event, Emitter<AddIncomeS...
    method _onConvertedAmountChanged (line 113) | void _onConvertedAmountChanged(AddIncomeConvertedAmountChanged event, ...
    method _onDefaultLoaded (line 117) | void _onDefaultLoaded(AddIncomeDefaultLoaded event, Emitter<AddIncomeS...
    method _onSubmitted (line 160) | void _onSubmitted(AddIncomeSubmitted event, Emitter<AddIncomeState> emit)

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/add_income/add_income_event.dart
  class AddIncomeEvent (line 3) | abstract class AddIncomeEvent extends Equatable {
  class AddIncomeCreateTimeChanged (line 9) | class AddIncomeCreateTimeChanged extends AddIncomeEvent {
  class AddIncomeCreateDateChanged (line 16) | class AddIncomeCreateDateChanged extends AddIncomeEvent {
  class AddIncomeAccountChanged (line 23) | class AddIncomeAccountChanged extends AddIncomeEvent {
  class AddIncomePayeeChanged (line 30) | class AddIncomePayeeChanged extends AddIncomeEvent {
  class AddIncomeCategoryChanged (line 37) | class AddIncomeCategoryChanged extends AddIncomeEvent {
  class AddIncomeTagChanged (line 45) | class AddIncomeTagChanged extends AddIncomeEvent {
  class AddIncomeAmountChanged (line 52) | class AddIncomeAmountChanged extends AddIncomeEvent {
  class AddIncomeConvertedAmountChanged (line 60) | class AddIncomeConvertedAmountChanged extends AddIncomeEvent {
  class AddIncomeDescriptionChanged (line 68) | class AddIncomeDescriptionChanged extends AddIncomeEvent {
  class AddIncomeNotesChanged (line 75) | class AddIncomeNotesChanged extends AddIncomeEvent {
  class AddIncomeConfirmedChanged (line 82) | class AddIncomeConfirmedChanged extends AddIncomeEvent {
  class AddIncomeDefaultLoaded (line 89) | class AddIncomeDefaultLoaded extends AddIncomeEvent {
  class AddIncomeSubmitted (line 97) | class AddIncomeSubmitted extends AddIncomeEvent {

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/add_income/add_income_state.dart
  class AddIncomeState (line 3) | class AddIncomeState extends Equatable {
    method copyWith (line 15) | AddIncomeState copyWith({

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/add_transfer/add_transfer_bloc.dart
  class AddTransferBloc (line 13) | class AddTransferBloc extends Bloc<AddTransferEvent, AddTransferState> {
    method _onFromChanged (line 40) | void _onFromChanged(AddTransferFromChanged event, Emitter<AddTransferS...
    method _onToChanged (line 53) | void _onToChanged(AddTransferToChanged event, Emitter<AddTransferState...
    method _onTagChanged (line 66) | void _onTagChanged(AddTransferTagChanged event, Emitter<AddTransferSta...
    method _onDescriptionChanged (line 72) | void _onDescriptionChanged(AddTransferDescriptionChanged event, Emitte...
    method _onNotesChanged (line 78) | void _onNotesChanged(AddTransferNotesChanged event, Emitter<AddTransfe...
    method _onConfirmedChanged (line 84) | void _onConfirmedChanged(AddTransferConfirmedChanged event, Emitter<Ad...
    method _onCreateTimeChanged (line 90) | void _onCreateTimeChanged(AddTransferCreateTimeChanged event, Emitter<...
    method _onCreateDateChanged (line 98) | void _onCreateDateChanged(AddTransferCreateDateChanged event, Emitter<...
    method _onAmountChanged (line 106) | void _onAmountChanged(AddTransferAmountChanged event, Emitter<AddTrans...
    method _onConvertedAmountChanged (line 112) | void _onConvertedAmountChanged(AddTransferConvertedAmountChanged event...
    method _onDefaultLoaded (line 118) | void _onDefaultLoaded(AddTransferDefaultLoaded event, Emitter<AddTrans...
    method _onSubmitted (line 150) | void _onSubmitted(AddTransferSubmitted event, Emitter<AddTransferState...

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/add_transfer/add_transfer_event.dart
  class AddTransferEvent (line 3) | abstract class AddTransferEvent extends Equatable {
  class AddTransferCreateTimeChanged (line 9) | class AddTransferCreateTimeChanged extends AddTransferEvent {
  class AddTransferCreateDateChanged (line 16) | class AddTransferCreateDateChanged extends AddTransferEvent {
  class AddTransferFromChanged (line 23) | class AddTransferFromChanged extends AddTransferEvent {
  class AddTransferToChanged (line 30) | class AddTransferToChanged extends AddTransferEvent {
  class AddTransferTagChanged (line 37) | class AddTransferTagChanged extends AddTransferEvent {
  class AddTransferAmountChanged (line 44) | class AddTransferAmountChanged extends AddTransferEvent {
  class AddTransferConvertedAmountChanged (line 51) | class AddTransferConvertedAmountChanged extends AddTransferEvent {
  class AddTransferDescriptionChanged (line 58) | class AddTransferDescriptionChanged extends AddTransferEvent {
  class AddTransferNotesChanged (line 65) | class AddTransferNotesChanged extends AddTransferEvent {
  class AddTransferConfirmedChanged (line 72) | class AddTransferConfirmedChanged extends AddTransferEvent {
  class AddTransferDefaultLoaded (line 79) | class AddTransferDefaultLoaded extends AddTransferEvent {
  class AddTransferSubmitted (line 87) | class AddTransferSubmitted extends AddTransferEvent {

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/add_transfer/add_transfer_state.dart
  class AddTransferState (line 3) | class AddTransferState extends Equatable {
    method copyWith (line 17) | AddTransferState copyWith({

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/models/deal_add_request.dart
  class DealAddRequest (line 5) | @JsonSerializable()
    method copyWith (line 28) | DealAddRequest copyWith({
    method toJson (line 52) | Map<String, dynamic> toJson()
  class CategoryIdAmountRequest (line 64) | @JsonSerializable()
    method toJson (line 81) | Map<String, dynamic> toJson()

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/models/deal_add_request.g.dart
  function _$DealAddRequestFromJson (line 9) | DealAddRequest _$DealAddRequestFromJson(Map<String, dynamic> json)
  function _$DealAddRequestToJson (line 24) | Map<String, dynamic> _$DealAddRequestToJson(DealAddRequest instance)
  function _$CategoryIdAmountRequestFromJson (line 36) | CategoryIdAmountRequest _$CategoryIdAmountRequestFromJson(
  function _$CategoryIdAmountRequestToJson (line 45) | Map<String, dynamic> _$CategoryIdAmountRequestToJson(

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/models/transfer_add_request.dart
  class TransferAddRequest (line 5) | @JsonSerializable()
    method copyWith (line 30) | TransferAddRequest copyWith({
    method toJson (line 54) | Map<String, dynamic> toJson()

FILE: bookkeeping_user_flutter/lib/add_flow/bloc/models/transfer_add_request.g.dart
  function _$TransferAddRequestFromJson (line 9) | TransferAddRequest _$TransferAddRequestFromJson(Map<String, dynamic> json)
  function _$TransferAddRequestToJson (line 22) | Map<String, dynamic> _$TransferAddRequestToJson(TransferAddRequest insta...

FILE: bookkeeping_user_flutter/lib/add_flow/ui/add_flow_page.dart
  class AddFlowPage (line 8) | class AddFlowPage extends StatelessWidget {
    method build (line 19) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/no_tab_page.dart
  class NoTabPage (line 9) | class NoTabPage extends StatelessWidget {
    method build (line 20) | Widget build(BuildContext context)
    method _buildBody (line 53) | Widget _buildBody(FlowModel flow)
    method _buildTitle (line 68) | String _buildTitle(int type, FlowModel flow)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/tab_page.dart
  class TabPage (line 5) | class TabPage extends StatelessWidget {
    method build (line 7) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/expense/account_input.dart
  class AccountInput (line 9) | class AccountInput extends StatelessWidget {
    method build (line 11) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/expense/add_expense_form.dart
  class AddExpenseForm (line 10) | class AddExpenseForm extends StatelessWidget {
    method build (line 18) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/expense/category_input.dart
  class CategoryInput (line 10) | class CategoryInput extends StatelessWidget {
    method build (line 12) | Widget build(BuildContext context)
    method buildAddCategoryItem (line 49) | Widget buildAddCategoryItem(CategoryIdAmountRequest item, String defau...

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/expense/date_time_input.dart
  class AddExpenseDateTimeInput (line 7) | class AddExpenseDateTimeInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/expense/description_input.dart
  class DescriptionInput (line 7) | class DescriptionInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/expense/is_confirm_input.dart
  class IsConfirmSwitch (line 7) | class IsConfirmSwitch extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/expense/notes_input.dart
  class NotesInput (line 7) | class NotesInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/expense/payee_input.dart
  class PayeeInput (line 9) | class PayeeInput extends StatelessWidget {
    method build (line 11) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/expense/tag_input.dart
  class TagInput (line 9) | class TagInput extends StatelessWidget {
    method build (line 11) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/income/account_input.dart
  class AccountInput (line 9) | class AccountInput extends StatelessWidget {
    method build (line 11) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/income/add_income_form.dart
  class AddIncomeForm (line 11) | class AddIncomeForm extends StatelessWidget {
    method build (line 19) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/income/category_input.dart
  class CategoryInput (line 10) | class CategoryInput extends StatelessWidget {
    method build (line 13) | Widget build(BuildContext context)
    method buildAddCategoryItem (line 50) | Widget buildAddCategoryItem(CategoryIdAmountRequest item, String defau...

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/income/date_time_input.dart
  class AddIncomeDateTimeInput (line 7) | class AddIncomeDateTimeInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/income/description_input.dart
  class DescriptionInput (line 7) | class DescriptionInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/income/is_confirm_input.dart
  class IsConfirmSwitch (line 7) | class IsConfirmSwitch extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/income/notes_input.dart
  class NotesInput (line 7) | class NotesInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/income/payee_input.dart
  class PayeeInput (line 9) | class PayeeInput extends StatelessWidget {
    method build (line 11) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/income/tag_input.dart
  class TagInput (line 9) | class TagInput extends StatelessWidget {
    method build (line 11) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/transfer/add_transfer_form.dart
  class AddTransferForm (line 11) | class AddTransferForm extends StatelessWidget {
    method build (line 19) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/transfer/amount_input.dart
  class AmountInput (line 7) | class AmountInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/transfer/converted_amount_input.dart
  class ConvertedAmountInput (line 7) | class ConvertedAmountInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/transfer/date_time_input.dart
  class AddTransferDateTimeInput (line 7) | class AddTransferDateTimeInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/transfer/description_input.dart
  class DescriptionInput (line 7) | class DescriptionInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/transfer/from_input.dart
  class FromInput (line 9) | class FromInput extends StatelessWidget {
    method build (line 11) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/transfer/is_confirm_input.dart
  class IsConfirmSwitch (line 7) | class IsConfirmSwitch extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/transfer/notes_input.dart
  class NotesInput (line 7) | class NotesInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/transfer/tag_input.dart
  class TagInput (line 9) | class TagInput extends StatelessWidget {
    method build (line 11) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/add_flow/ui/widgets/transfer/to_input.dart
  class ToInput (line 9) | class ToInput extends StatelessWidget {
    method build (line 11) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/app.dart
  class App (line 17) | class App extends StatelessWidget {
    method build (line 45) | Widget build(BuildContext context)
  class AppView (line 202) | class AppView extends StatelessWidget {
    method build (line 204) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/books/bloc/book_fetch/book_fetch_bloc.dart
  class BookFetchBloc (line 11) | class BookFetchBloc extends Bloc<BookFetchEvent, BookFetchState> {
    method _onDefault (line 22) | void _onDefault(BookLoadDefault event, Emitter<BookFetchState> emit)
    method _onFetched (line 29) | void _onFetched(_, Emitter<BookFetchState> emit)

FILE: bookkeeping_user_flutter/lib/books/bloc/book_fetch/book_fetch_event.dart
  class BookFetchEvent (line 3) | @immutable
  class BookFetched (line 10) | class BookFetched extends BookFetchEvent {}
  class BookLoadDefault (line 12) | class BookLoadDefault extends BookFetchEvent {

FILE: bookkeeping_user_flutter/lib/books/bloc/book_fetch/book_fetch_state.dart
  class BookFetchState (line 3) | @immutable
    method copyWith (line 14) | BookFetchState copyWith({

FILE: bookkeeping_user_flutter/lib/books/bloc/books/books_bloc.dart
  class BooksBloc (line 15) | class BooksBloc extends Bloc<BooksEvent, BooksState> {
    method _onRefreshed (line 49) | void _onRefreshed(_, Emitter<BooksState> emit)
    method _onLoadMore (line 66) | void _onLoadMore(_, Emitter<BooksState> emit)
    method _onDefault (line 84) | void _onDefault(BookSetDefault event, Emitter<BooksState> emit)

FILE: bookkeeping_user_flutter/lib/books/bloc/books/books_event.dart
  class BooksEvent (line 3) | @immutable
  class BooksRefreshed (line 10) | class BooksRefreshed extends BooksEvent { }
  class BooksLoadMore (line 12) | class BooksLoadMore extends BooksEvent { }
  class BookSetDefault (line 14) | class BookSetDefault extends BooksEvent {

FILE: bookkeeping_user_flutter/lib/books/bloc/books/books_state.dart
  class BooksState (line 3) | @immutable
    method copyWith (line 22) | BooksState copyWith({

FILE: bookkeeping_user_flutter/lib/books/data/book_repository.dart
  class BookRepository (line 5) | class BookRepository {
    method _responseToList (line 7) | List<Book> _responseToList(String response)
    method _responseBook (line 11) | Book _responseBook(String response)
    method query (line 15) | Future<List<Book>> query(BookQueryRequest request)
    method get (line 19) | Future<Book> get(int id)
    method setDefault (line 23) | Future<bool> setDefault(String id)

FILE: bookkeeping_user_flutter/lib/books/data/models/book.dart
  class Book (line 8) | @JsonSerializable()
    method toJson (line 43) | Map<String, dynamic> toJson()

FILE: bookkeeping_user_flutter/lib/books/data/models/book.g.dart
  function _$BookFromJson (line 9) | Book _$BookFromJson(Map<String, dynamic> json)
  function _$BookToJson (line 43) | Map<String, dynamic> _$BookToJson(Book instance)

FILE: bookkeeping_user_flutter/lib/books/data/models/book_query_request.dart
  class BookQueryRequest (line 6) | @JsonSerializable()
    method copyWith (line 17) | BookQueryRequest copyWith({
    method toJson (line 29) | Map<String, dynamic> toJson()

FILE: bookkeeping_user_flutter/lib/books/data/models/book_query_request.g.dart
  function _$BookQueryRequestFromJson (line 9) | BookQueryRequest _$BookQueryRequestFromJson(Map<String, dynamic> json)
  function _$BookQueryRequestToJson (line 15) | Map<String, dynamic> _$BookQueryRequestToJson(BookQueryRequest instance)

FILE: bookkeeping_user_flutter/lib/books/ui/book_detail_page.dart
  class BookDetailPage (line 10) | class BookDetailPage extends StatefulWidget {
    method createState (line 18) | State<BookDetailPage> createState()
  class _BookDetailPageState (line 21) | class _BookDetailPageState extends State<BookDetailPage> {
    method initState (line 24) | void initState()
    method build (line 30) | Widget build(BuildContext context)
    method _buildActions (line 83) | List<Widget> _buildActions(BuildContext context, Book book)
    method _buildBody (line 107) | Widget _buildBody(BuildContext context, Book book)

FILE: bookkeeping_user_flutter/lib/books/ui/books_page.dart
  class BooksPage (line 10) | class BooksPage extends StatefulWidget {
    method createState (line 12) | State<BooksPage> createState()
  class _BooksPageState (line 15) | class _BooksPageState extends State<BooksPage> {
    method initState (line 20) | void initState()
    method build (line 26) | Widget build(BuildContext context)
    method _buildList (line 88) | Widget _buildList(BuildContext context, List<Book> books)

FILE: bookkeeping_user_flutter/lib/categories/bloc/category_fetch/category_fetch_bloc.dart
  class CategoryFetchBloc (line 11) | class CategoryFetchBloc extends Bloc<CategoryFetchEvent, CategoryFetchSt...
    method _onDefault (line 22) | void _onDefault(CategoryLoadDefault event, Emitter<CategoryFetchState>...
    method _onFetched (line 29) | void _onFetched(_, Emitter<CategoryFetchState> emit)

FILE: bookkeeping_user_flutter/lib/categories/bloc/category_fetch/category_fetch_event.dart
  class CategoryFetchEvent (line 3) | @immutable
  class CategoryFetched (line 10) | class CategoryFetched extends CategoryFetchEvent {}
  class CategoryLoadDefault (line 12) | class CategoryLoadDefault extends CategoryFetchEvent {

FILE: bookkeeping_user_flutter/lib/categories/bloc/category_fetch/category_fetch_state.dart
  class CategoryFetchState (line 3) | @immutable
    method copyWith (line 14) | CategoryFetchState copyWith({

FILE: bookkeeping_user_flutter/lib/categories/bloc/category_form/category_form_bloc.dart
  class CategoryFormBloc (line 10) | class CategoryFormBloc extends Bloc<CategoryFormEvent, CategoryFormState> {
    method _onNameChanged (line 28) | void _onNameChanged(CategoryFormNameChanged event, Emitter<CategoryFor...
    method _onNotesChanged (line 34) | void _onNotesChanged(CategoryFormNotesChanged event, Emitter<CategoryF...
    method _onParentChanged (line 40) | void _onParentChanged(CategoryFormParentChanged event, Emitter<Categor...
    method _onDefaultLoaded (line 46) | void _onDefaultLoaded(CategoryFormDefaultLoaded event, Emitter<Categor...
    method _onSubmitted (line 57) | void _onSubmitted(CategoryFormSubmitted event, Emitter<CategoryFormSta...

FILE: bookkeeping_user_flutter/lib/categories/bloc/category_form/category_form_event.dart
  class CategoryFormEvent (line 3) | @immutable
  class CategoryFormNameChanged (line 10) | class CategoryFormNameChanged extends CategoryFormEvent {
  class CategoryFormNotesChanged (line 17) | class CategoryFormNotesChanged extends CategoryFormEvent {
  class CategoryFormParentChanged (line 24) | class CategoryFormParentChanged extends CategoryFormEvent {
  class CategoryFormDefaultLoaded (line 31) | class CategoryFormDefaultLoaded extends CategoryFormEvent {
  class CategoryFormSubmitted (line 40) | class CategoryFormSubmitted extends CategoryFormEvent {

FILE: bookkeeping_user_flutter/lib/categories/bloc/category_form/category_form_state.dart
  class CategoryFormState (line 3) | @immutable
    method copyWith (line 14) | CategoryFormState copyWith({

FILE: bookkeeping_user_flutter/lib/categories/bloc/category_tree/category_tree_bloc.dart
  class CategoryTreeBloc (line 10) | class CategoryTreeBloc extends Bloc<CategoryTreeEvent, CategoryTreeState> {
    method _onExpenseCategoryRefreshed (line 29) | void _onExpenseCategoryRefreshed(_, Emitter<CategoryTreeState> emit)
    method _onIncomeCategoryRefreshed (line 46) | void _onIncomeCategoryRefreshed(_, Emitter<CategoryTreeState> emit)
    method _onItemClicked (line 63) | void _onItemClicked(CategoryItemClicked event, Emitter<CategoryTreeSta...
    method _onBackClicked (line 73) | void _onBackClicked(CategoryBackClicked event, Emitter<CategoryTreeSta...
    method _onToggled (line 80) | void _onToggled(CategoryToggled event, Emitter<CategoryTreeState> emit)
    method _onDeleted (line 96) | void _onDeleted(CategoryDeleted event, Emitter<CategoryTreeState> emit)

FILE: bookkeeping_user_flutter/lib/categories/bloc/category_tree/category_tree_event.dart
  class CategoryTreeEvent (line 3) | @immutable
  class ExpenseCategoryTreeRefreshed (line 10) | class ExpenseCategoryTreeRefreshed extends CategoryTreeEvent { }
  class IncomeCategoryTreeRefreshed (line 12) | class IncomeCategoryTreeRefreshed extends CategoryTreeEvent { }
  class CategoryItemClicked (line 14) | class CategoryItemClicked extends CategoryTreeEvent {
  class CategoryBackClicked (line 21) | class CategoryBackClicked extends CategoryTreeEvent { }
  class CategoryDeleted (line 23) | class CategoryDeleted extends CategoryTreeEvent {
  class CategoryToggled (line 30) | class CategoryToggled extends CategoryTreeEvent {

FILE: bookkeeping_user_flutter/lib/categories/bloc/category_tree/category_tree_state.dart
  class CategoryTreeState (line 3) | @immutable
    method copyWith (line 27) | CategoryTreeState copyWith({

FILE: bookkeeping_user_flutter/lib/categories/bloc/expense_category_select/expense_category_select_bloc.dart
  class ExpenseCategorySelectBloc (line 9) | class ExpenseCategorySelectBloc extends Bloc<ExpenseCategorySelectEvent,...
    method _onExpenseCategorySelectLoaded (line 19) | void _onExpenseCategorySelectLoaded(_, Emitter<ExpenseCategorySelectSt...

FILE: bookkeeping_user_flutter/lib/categories/bloc/expense_category_select/expense_category_select_event.dart
  class ExpenseCategorySelectEvent (line 3) | abstract class ExpenseCategorySelectEvent extends Equatable {
  class ExpenseCategorySelectLoaded (line 12) | class ExpenseCategorySelectLoaded extends ExpenseCategorySelectEvent { }

FILE: bookkeeping_user_flutter/lib/categories/bloc/expense_category_select/expense_category_select_state.dart
  class ExpenseCategorySelectState (line 4) | abstract class ExpenseCategorySelectState extends Equatable {
  class ExpenseCategorySelectStateLoadInProgress (line 13) | class ExpenseCategorySelectStateLoadInProgress extends ExpenseCategorySe...
  class ExpenseCategorySelectStateLoadSuccess (line 15) | class ExpenseCategorySelectStateLoadSuccess extends ExpenseCategorySelec...
  class ExpenseCategorySelectStateLoadFailure (line 26) | class ExpenseCategorySelectStateLoadFailure extends ExpenseCategorySelec...

FILE: bookkeeping_user_flutter/lib/categories/bloc/income_category_select/income_category_select_bloc.dart
  class IncomeCategorySelectBloc (line 9) | class IncomeCategorySelectBloc extends Bloc<IncomeCategorySelectEvent, I...
    method _onIncomeCategorySelectLoaded (line 19) | void _onIncomeCategorySelectLoaded(_, Emitter<IncomeCategorySelectStat...

FILE: bookkeeping_user_flutter/lib/categories/bloc/income_category_select/income_category_select_event.dart
  class IncomeCategorySelectEvent (line 3) | abstract class IncomeCategorySelectEvent extends Equatable {
  class IncomeCategorySelectLoaded (line 12) | class IncomeCategorySelectLoaded extends IncomeCategorySelectEvent { }

FILE: bookkeeping_user_flutter/lib/categories/bloc/income_category_select/income_category_select_state.dart
  class IncomeCategorySelectState (line 4) | abstract class IncomeCategorySelectState extends Equatable {
  class IncomeCategorySelectStateLoadInProgress (line 13) | class IncomeCategorySelectStateLoadInProgress extends IncomeCategorySele...
  class IncomeCategorySelectStateLoadSuccess (line 15) | class IncomeCategorySelectStateLoadSuccess extends IncomeCategorySelectS...
  class IncomeCategorySelectStateLoadFailure (line 26) | class IncomeCategorySelectStateLoadFailure extends IncomeCategorySelectS...

FILE: bookkeeping_user_flutter/lib/categories/data/category_repository.dart
  class CategoryRepository (line 7) | class CategoryRepository {
    method _responseToList (line 9) | List<Category> _responseToList(String response)
    method getExpenseable (line 13) | Future<List<Category>> getExpenseable()
    method getIncomeable (line 18) | Future<List<Category>> getIncomeable()
    method queryExpense (line 23) | Future<List<CategoryTree>> queryExpense()
    method queryIncome (line 28) | Future<List<CategoryTree>> queryIncome()
    method get (line 33) | Future<Category> get(int id)
    method toggle (line 38) | Future<bool> toggle(String id)
    method delete (line 43) | Future<bool> delete(String id)
    method add (line 48) | Future<bool> add(int type, CategoryFormRequest request)
    method update (line 62) | Future<bool> update(int type, int id, CategoryFormRequest request)

FILE: bookkeeping_user_flutter/lib/categories/data/models/category.dart
  class Category (line 7) | @JsonSerializable()
    method toJson (line 28) | Map<String, dynamic> toJson()

FILE: bookkeeping_user_flutter/lib/categories/data/models/category.g.dart
  function _$CategoryFromJson (line 9) | Category _$CategoryFromJson(Map<String, dynamic> json)
  function _$CategoryToJson (line 18) | Map<String, dynamic> _$CategoryToJson(Category instance)

FILE: bookkeeping_user_flutter/lib/categories/data/models/category_form_request.dart
  class CategoryFormRequest (line 6) | @JsonSerializable()
    method toJson (line 19) | Map<String, dynamic> toJson()
    method copyWith (line 21) | CategoryFormRequest copyWith({

FILE: bookkeeping_user_flutter/lib/categories/data/models/category_form_request.g.dart
  function _$CategoryFormRequestFromJson (line 9) | CategoryFormRequest _$CategoryFormRequestFromJson(Map<String, dynamic> j...
  function _$CategoryFormRequestToJson (line 16) | Map<String, dynamic> _$CategoryFormRequestToJson(

FILE: bookkeeping_user_flutter/lib/categories/data/models/category_tree.dart
  class CategoryTree (line 6) | @JsonSerializable()
    method toJson (line 29) | Map<String, dynamic> toJson()

FILE: bookkeeping_user_flutter/lib/categories/data/models/category_tree.g.dart
  function _$CategoryTreeFromJson (line 9) | CategoryTree _$CategoryTreeFromJson(Map<String, dynamic> json)
  function _$CategoryTreeToJson (line 21) | Map<String, dynamic> _$CategoryTreeToJson(CategoryTree instance)

FILE: bookkeeping_user_flutter/lib/categories/ui/category_detail_page.dart
  class CategoryDetailPage (line 9) | class CategoryDetailPage extends StatefulWidget {
    method createState (line 20) | State<CategoryDetailPage> createState()
  class _CategoryDetailPageState (line 24) | class _CategoryDetailPageState extends State<CategoryDetailPage> {
    method initState (line 26) | void initState()
    method build (line 31) | Widget build(BuildContext context)
    method _buildActions (line 84) | List<Widget> _buildActions(BuildContext context, Category category)
    method _buildBody (line 114) | Widget _buildBody(BuildContext context, Category category)

FILE: bookkeeping_user_flutter/lib/categories/ui/category_form_page.dart
  class CategoryFormPage (line 8) | class CategoryFormPage extends StatelessWidget {
    method build (line 21) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/categories/ui/expense_categories_page.dart
  class ExpenseCategoryPage (line 9) | class ExpenseCategoryPage extends StatefulWidget {
    method createState (line 11) | State<ExpenseCategoryPage> createState()
  class _ExpenseCategoryPageState (line 14) | class _ExpenseCategoryPageState extends State<ExpenseCategoryPage> {
    method initState (line 17) | void initState()
    method build (line 23) | Widget build(BuildContext context)
    method _buildList (line 82) | Widget _buildList(BuildContext context, List<CategoryTree> categories)
    method _onWillPop (line 111) | Future<bool> _onWillPop(state)

FILE: bookkeeping_user_flutter/lib/categories/ui/expense_category_form_page.dart
  class ExpenseCategoryFormPage (line 5) | class ExpenseCategoryFormPage extends StatelessWidget {
    method build (line 16) | Widget build(BuildContext context)
    method _buildTitle (line 47) | String _buildTitle(int type)

FILE: bookkeeping_user_flutter/lib/categories/ui/income_categories_page.dart
  class IncomeCategoryPage (line 9) | class IncomeCategoryPage extends StatefulWidget {
    method createState (line 11) | State<IncomeCategoryPage> createState()
  class _IncomeCategoryPageState (line 14) | class _IncomeCategoryPageState extends State<IncomeCategoryPage> {
    method initState (line 17) | void initState()
    method build (line 23) | Widget build(BuildContext context)
    method _buildList (line 82) | Widget _buildList(BuildContext context, List<CategoryTree> categories)
    method _onWillPop (line 111) | Future<bool> _onWillPop(state)

FILE: bookkeeping_user_flutter/lib/categories/ui/income_category_form_page.dart
  class IncomeCategoryFormPage (line 5) | class IncomeCategoryFormPage extends StatelessWidget {
    method build (line 16) | Widget build(BuildContext context)
    method _buildTitle (line 47) | String _buildTitle(int type)

FILE: bookkeeping_user_flutter/lib/categories/ui/widgets/category_form/expense_category_input.dart
  class ExpenseCategoryInput (line 8) | class ExpenseCategoryInput extends StatelessWidget {
    method build (line 10) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/categories/ui/widgets/category_form/income_category_input.dart
  class IncomeCategoryInput (line 7) | class IncomeCategoryInput extends StatelessWidget {
    method build (line 9) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/categories/ui/widgets/category_form/name_input.dart
  class NameInput (line 6) | class NameInput extends StatelessWidget {
    method build (line 8) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/categories/ui/widgets/category_form/notes_input.dart
  class NotesInput (line 6) | class NotesInput extends StatelessWidget {
    method build (line 8) | Widget build(BuildContext context)

FILE: bookkeeping_user_flutter/lib/charts/bloc/report_asset/report_asset_bloc.dart
  class ReportAssetBloc (line 8) | class ReportAssetBloc extends Bloc<ReportAssetEvent, ReportAssetState> {
    method _onReportAssetLoaded (line 18) | void _onReportAssetLoaded(_, Emitter<ReportAssetState> emit)

FILE: bookkeeping_user_flutter/lib/charts/bloc/report_asset/report_asset_event.dart
  class ReportAssetEvent (line 3) | abstract class ReportAssetEvent extends Equatable {
  class ReportAssetLoaded (line 9) | class ReportAssetLoaded extends ReportAssetEvent { }

FILE: bookkeeping_user_flutter/lib/charts/bloc/report_asset/report_asset_state.dart
  class ReportAssetState (line 3) | abstract class ReportAssetState extends Equatable {
  class ReportAssetStateLoadInProgress (line 9) | class ReportAssetStateLoadInProgress extends ReportAssetState { }
  class ReportAssetStateLoadSuccess (line 11) | class ReportAssetStateLoadSuccess extends ReportAssetState {
  class ReportAssetStateLoadFailure (line 22) | class ReportAssetStateLoadFailure extends ReportAssetState { }

FILE: bookkeeping_user_flutter/lib/charts/bloc/report_d
Condensed preview — 1544 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,897K chars).
[
  {
    "path": ".gitattributes",
    "chars": 1025,
    "preview": "# https://github.com/alexkaratarakis/gitattributes\n# Handle line endings automatically for files detected as text\n# and "
  },
  {
    "path": ".gitignore",
    "chars": 502,
    "preview": "target/\n!.mvn/wrapper/maven-wrapper.jar\n!**/src/main/**\n!**/src/test/**\n\n### STS ###\n.apt_generated\n.classpath\n.factoryp"
  },
  {
    "path": "LICENSE",
    "chars": 11341,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 170,
    "preview": "# DEPRECATED \n\nThis is no longer supported, please consider using [https://github.com/getmoneynote/moneynote-api](https:"
  },
  {
    "path": "bookkeeping-user-api/.mvn/wrapper/MavenWrapperDownloader.java",
    "chars": 4942,
    "preview": "/*\n * Copyright 2007-present the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \""
  },
  {
    "path": "bookkeeping-user-api/.mvn/wrapper/maven-wrapper.properties",
    "chars": 218,
    "preview": "distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip\nwrap"
  },
  {
    "path": "bookkeeping-user-api/Dockerfile",
    "chars": 364,
    "preview": "#FROM openjdk:11-slim\n#COPY target/*.jar app.jar\n#ENTRYPOINT [\"java\",\"-jar\",\"/app.jar\"]\n\nFROM openjdk:11-slim as build\nW"
  },
  {
    "path": "bookkeeping-user-api/mvnw",
    "chars": 10070,
    "preview": "#!/bin/sh\n# ----------------------------------------------------------------------------\n# Licensed to the Apache Softwa"
  },
  {
    "path": "bookkeeping-user-api/mvnw.cmd",
    "chars": 6608,
    "preview": "@REM ----------------------------------------------------------------------------\n@REM Licensed to the Apache Software F"
  },
  {
    "path": "bookkeeping-user-api/pom.xml",
    "chars": 3153,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www"
  },
  {
    "path": "bookkeeping-user-api/restart.sh",
    "chars": 47,
    "preview": "#!/bin/bash\n. stop.sh\nrm -rf 1.log\n. startup.sh"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/Application.java",
    "chars": 313,
    "preview": "package com.jiukuaitech.bookkeeping.user;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/RegexTest.java",
    "chars": 639,
    "preview": "package com.jiukuaitech.bookkeeping.user;\n\npublic class RegexTest implements Runnable {\n\n\n    private static int i;\n\n   "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/Account.java",
    "chars": 1960,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport com.jiukuaitech.bookkeeping.user.base.NameNotesEnableEntity;\ni"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountAddRequest.java",
    "chars": 1482,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport java.math.BigDecimal;\nimport javax.validation.constraints.NotB"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountAdjustBalanceNotValidException.java",
    "chars": 131,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\npublic class AccountAdjustBalanceNotValidException extends RuntimeExc"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountController.java",
    "chars": 5135,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport com.jiukuaitech.bookkeeping.user.adjust_balance.AdjustBalanceA"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountExceptionHandler.java",
    "chars": 3043,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountHasTransactionException.java",
    "chars": 124,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\npublic class AccountHasTransactionException extends RuntimeException "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountMaxCountException.java",
    "chars": 118,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\npublic class AccountMaxCountException extends RuntimeException {\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountNameExistsException.java",
    "chars": 125,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\npublic class AccountNameExistsException extends RuntimeException {\n  "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountQueryRequest.java",
    "chars": 179,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n@Getter\n@Setter\npublic c"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountRepository.java",
    "chars": 566,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseRepository;\nimport c"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountService.java",
    "chars": 12661,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport com.jiukuaitech.bookkeeping.user.adjust_balance.AdjustBalance;"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountSpec.java",
    "chars": 3062,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport com.jiukuaitech.bookkeeping.user.group.Group;\nimport com.jiuku"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountSumVO.java",
    "chars": 206,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport java.math.BigDeci"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountUpdateRequest.java",
    "chars": 1749,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport java.math.BigDecimal;\n\nimport com.jiukuaitech.bookkeeping.user"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountVOForExtend.java",
    "chars": 1714,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport com.jiukuaitech.bookkeeping.user.utils.EnumUtils;\nimport lombo"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/AccountVOForList.java",
    "chars": 448,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport java.math.BigDeci"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultExpenseAccountException.java",
    "chars": 124,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\npublic class DefaultExpenseAccountException extends RuntimeException "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultIncomeAccountException.java",
    "chars": 123,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\npublic class DefaultIncomeAccountException extends RuntimeException {"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultTransferFromAccountException.java",
    "chars": 130,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\npublic class DefaultTransferFromAccountException extends RuntimeExcep"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/account/DefaultTransferToAccountException.java",
    "chars": 128,
    "preview": "package com.jiukuaitech.bookkeeping.user.account;\n\npublic class DefaultTransferToAccountException extends RuntimeExcepti"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalance.java",
    "chars": 251,
    "preview": "package com.jiukuaitech.bookkeeping.user.adjust_balance;\n\nimport com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFl"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceAddRequest.java",
    "chars": 388,
    "preview": "package com.jiukuaitech.bookkeeping.user.adjust_balance;\n\nimport com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFl"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceController.java",
    "chars": 1010,
    "preview": "package com.jiukuaitech.bookkeeping.user.adjust_balance;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseController;\ni"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceRepository.java",
    "chars": 314,
    "preview": "package com.jiukuaitech.bookkeeping.user.adjust_balance;\n\nimport com.jiukuaitech.bookkeeping.user.base.HasBookRepository"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceService.java",
    "chars": 1920,
    "preview": "package com.jiukuaitech.bookkeeping.user.adjust_balance;\n\nimport com.jiukuaitech.bookkeeping.user.account.Account;\nimpor"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/adjust_balance/AdjustBalanceVOForList.java",
    "chars": 398,
    "preview": "package com.jiukuaitech.bookkeeping.user.adjust_balance;\n\nimport com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFl"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/aop/TestAspect.java",
    "chars": 774,
    "preview": "package com.jiukuaitech.bookkeeping.user.aop;\n\nimport org.aspectj.lang.JoinPoint;\nimport org.aspectj.lang.annotation.Asp"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccount.java",
    "chars": 422,
    "preview": "package com.jiukuaitech.bookkeeping.user.asset_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.Account;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountController.java",
    "chars": 1908,
    "preview": "package com.jiukuaitech.bookkeeping.user.asset_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountQueryReq"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountRepository.java",
    "chars": 814,
    "preview": "package com.jiukuaitech.bookkeeping.user.asset_account;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseRepository;\nim"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountService.java",
    "chars": 2327,
    "preview": "package com.jiukuaitech.bookkeeping.user.asset_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.Account;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/asset_account/AssetAccountVOForList.java",
    "chars": 509,
    "preview": "package com.jiukuaitech.bookkeeping.user.asset_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountVOForExt"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/AccountInvalidateException.java",
    "chars": 125,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\npublic class AccountInvalidateException extends RuntimeException"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/AmountInvalidateException.java",
    "chars": 124,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\npublic class AmountInvalidateException extends RuntimeException "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlow.java",
    "chars": 1964,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport com.jiukuaitech.bookkeeping.user.account.Account;\nimport "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowAddRequest.java",
    "chars": 831,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport com.jiukuaitech.bookkeeping.user.validation.DescriptionVa"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowController.java",
    "chars": 3419,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\ni"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowExceptionHandler.java",
    "chars": 1595,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\ni"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowQueryRequest.java",
    "chars": 790,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport java.util.Set;\nimport lombok.Getter;\nimport lombok.Setter"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowQueryResultVO.java",
    "chars": 430,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport org.springfra"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowRepository.java",
    "chars": 266,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport com.jiukuaitech.bookkeeping.user.base.HasBookRepository;\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowService.java",
    "chars": 8772,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport com.ji"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowSpec.java",
    "chars": 9866,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport com.jiukuaitech.bookkeeping.user.account.Account;\nimport "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowUpdateRequest.java",
    "chars": 752,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport com.jiukuaitech.bookkeeping.user.validation.DescriptionVa"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowVOForExtend.java",
    "chars": 1677,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountVOForExte"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/BalanceFlowVOForList.java",
    "chars": 6367,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\nimport com.jiukuaitech.bookkeeping.user.adjust_balance.AdjustBal"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_flow/StatusNotValidateException.java",
    "chars": 125,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_flow;\n\npublic class StatusNotValidateException extends RuntimeException"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLog.java",
    "chars": 1137,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_log;\n\nimport com.jiukuaitech.bookkeeping.user.group.Group;\nimport com.j"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogAddRequest.java",
    "chars": 620,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_log;\n\nimport com.jiukuaitech.bookkeeping.user.validation.BalanceValidat"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogController.java",
    "chars": 1538,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_log;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nim"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogRepository.java",
    "chars": 552,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_log;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseRepository;\nimpo"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogService.java",
    "chars": 2315,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_log;\n\nimport com.jiukuaitech.bookkeeping.user.exception.ItemNotFoundExc"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/balance_log/BalanceLogVOForList.java",
    "chars": 594,
    "preview": "package com.jiukuaitech.bookkeeping.user.balance_log;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport java.math.BigD"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseController.java",
    "chars": 381,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport javax.annotation.Reso"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseEntity.java",
    "chars": 454,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport javax.persistence.Ge"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseRepository.java",
    "chars": 1114,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport org.springframework.data.jpa.domain.Specification;\nimport org.spr"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseRepositoryFactoryBean.java",
    "chars": 1595,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport org.springframework.data.jpa.repository.JpaRepository;\nimport org"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BaseRepositoryImpl.java",
    "chars": 3031,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport com.jiukuaitech.bookkeeping.user.utils.CommonUtils;\nimport org.sp"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BookNameNotesEnableEntity.java",
    "chars": 661,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport com.jiukuaitech.bookkeeping.user.validation.NameValidator;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/BookNameNotesEnableSpec.java",
    "chars": 1352,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport org.springfram"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/HasBookEntity.java",
    "chars": 564,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport lombok.Getter;"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/HasBookRepository.java",
    "chars": 368,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport org.springfra"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/JpaDataConfig.java",
    "chars": 476,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport org.springframework.context.annotation.Configuration;\nimport org."
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/NameNotesEnableEntity.java",
    "chars": 703,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport com.jiukuaitech.bookkeeping.user.validation.NameValidator;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/base/TestController.java",
    "chars": 878,
    "preview": "package com.jiukuaitech.bookkeeping.user.base;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimport co"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/Book.java",
    "chars": 1682,
    "preview": "package com.jiukuaitech.bookkeeping.user.book;\n\nimport com.jiukuaitech.bookkeeping.user.expense_category.ExpenseCategory"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookAddRequest.java",
    "chars": 611,
    "preview": "package com.jiukuaitech.bookkeeping.user.book;\n\nimport com.jiukuaitech.bookkeeping.user.validation.NameValidator;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookController.java",
    "chars": 3010,
    "preview": "package com.jiukuaitech.bookkeeping.user.book;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseController;\nimport com."
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookExceptionHandler.java",
    "chars": 1036,
    "preview": "package com.jiukuaitech.bookkeeping.user.book;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimport co"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookMaxCountException.java",
    "chars": 112,
    "preview": "package com.jiukuaitech.bookkeeping.user.book;\n\npublic class BookMaxCountException extends RuntimeException {\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookRepository.java",
    "chars": 558,
    "preview": "package com.jiukuaitech.bookkeeping.user.book;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseRepository;\nimport com."
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookService.java",
    "chars": 7616,
    "preview": "package com.jiukuaitech.bookkeeping.user.book;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport com.jiukuaite"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookUpdateRequest.java",
    "chars": 753,
    "preview": "package com.jiukuaitech.bookkeeping.user.book;\n\nimport com.jiukuaitech.bookkeeping.user.validation.NameValidator;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/book/BookVOForList.java",
    "chars": 2515,
    "preview": "package com.jiukuaitech.bookkeeping.user.book;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountVOForExtend;\nimpo"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/Category.java",
    "chars": 2031,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport com.jiukuaitech.bookkeeping.user.base.BookNameNotesEnableEnti"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryAddRequest.java",
    "chars": 467,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport com.jiukuaitech.bookkeeping.user.validation.NameValidator;\nim"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryController.java",
    "chars": 1320,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseController;\nimport "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryExceptionHandler.java",
    "chars": 2817,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimpor"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryHasDealException.java",
    "chars": 136,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\n/*\n删除有账单的分类\n */\npublic class CategoryHasDealException extends Runtim"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryIsDefaultExpenseException.java",
    "chars": 170,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\n/*\nCategoryIsDefaultExpenseException\n */\npublic class CategoryIsDefa"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryIsDefaultIncomeException.java",
    "chars": 149,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\n/*\n账本的默认收入类别不能删除\n */\npublic class CategoryIsDefaultIncomeException e"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryLevelException.java",
    "chars": 135,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\n/*\n添加支出时,层级超过\n */\npublic class CategoryLevelException extends Runtim"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryMaxCountException.java",
    "chars": 121,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\npublic class CategoryMaxCountException extends RuntimeException {\n\n}"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryNameExistsException.java",
    "chars": 141,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\n/*\n添加分类时,名称重复\n */\npublic class CategoryNameExistsException extends R"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryQueryRequest.java",
    "chars": 206,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n@Getter\n@Setter\npublic "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryRepository.java",
    "chars": 787,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport com.jiukua"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryService.java",
    "chars": 7334,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport com.jiukua"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategorySimpleVO.java",
    "chars": 676,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n@Getter\n@Setter\npublic "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategorySpec.java",
    "chars": 1178,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport com.jiukua"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryTreeVO.java",
    "chars": 2415,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport org.springframewo"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/CategoryUpdateRequest.java",
    "chars": 409,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\nimport com.jiukuaitech.bookkeeping.user.validation.NameValidator;\nim"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/DefaultExpenseCategoryException.java",
    "chars": 126,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\npublic class DefaultExpenseCategoryException extends RuntimeExceptio"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/DefaultIncomeCategoryException.java",
    "chars": 125,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\npublic class DefaultIncomeCategoryException extends RuntimeException"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category/ParentCategoryNotEnableException.java",
    "chars": 153,
    "preview": "package com.jiukuaitech.bookkeeping.user.category;\n\n/*\n添加子分类时,父分类不可用\n */\npublic class ParentCategoryNotEnableException e"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category_relation/CategoryRelation.java",
    "chars": 1162,
    "preview": "package com.jiukuaitech.bookkeeping.user.category_relation;\n\nimport com.jiukuaitech.bookkeeping.user.category.Category;\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category_relation/CategoryRelationAddRequest.java",
    "chars": 2054,
    "preview": "package com.jiukuaitech.bookkeeping.user.category_relation;\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport c"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category_relation/CategoryRelationRepository.java",
    "chars": 706,
    "preview": "package com.jiukuaitech.bookkeeping.user.category_relation;\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport c"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/category_relation/CategoryRelationVOForList.java",
    "chars": 802,
    "preview": "package com.jiukuaitech.bookkeeping.user.category_relation;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport java.mat"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/checking_account/CheckingAccount.java",
    "chars": 361,
    "preview": "package com.jiukuaitech.bookkeeping.user.checking_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.Account;\n\nim"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/checking_account/CheckingAccountController.java",
    "chars": 1928,
    "preview": "package com.jiukuaitech.bookkeeping.user.checking_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountQuery"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/checking_account/CheckingAccountRepository.java",
    "chars": 830,
    "preview": "package com.jiukuaitech.bookkeeping.user.checking_account;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseRepository;"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/checking_account/CheckingAccountService.java",
    "chars": 2147,
    "preview": "package com.jiukuaitech.bookkeeping.user.checking_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.*;\nimport co"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccount.java",
    "chars": 836,
    "preview": "package com.jiukuaitech.bookkeeping.user.credit_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.Account;\nimpor"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountAddRequest.java",
    "chars": 764,
    "preview": "package com.jiukuaitech.bookkeeping.user.credit_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountAddRequ"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountController.java",
    "chars": 1853,
    "preview": "package com.jiukuaitech.bookkeeping.user.credit_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountService"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountRepository.java",
    "chars": 863,
    "preview": "package com.jiukuaitech.bookkeeping.user.credit_account;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseRepository;\ni"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountService.java",
    "chars": 2451,
    "preview": "package com.jiukuaitech.bookkeeping.user.credit_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountQueryRe"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountSumVO.java",
    "chars": 387,
    "preview": "package com.jiukuaitech.bookkeeping.user.credit_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountSumVO;\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/credit_account/CreditAccountVOForList.java",
    "chars": 697,
    "preview": "package com.jiukuaitech.bookkeeping.user.credit_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountVOForEx"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/currency/Currency.java",
    "chars": 691,
    "preview": "package com.jiukuaitech.bookkeeping.user.currency;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseEntity;\nimport lomb"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/currency/CurrencyController.java",
    "chars": 658,
    "preview": "package com.jiukuaitech.bookkeeping.user.currency;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseController;\nimport "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/currency/CurrencyRepository.java",
    "chars": 339,
    "preview": "package com.jiukuaitech.bookkeeping.user.currency;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseRepository;\nimport "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/currency/CurrencyService.java",
    "chars": 1577,
    "preview": "package com.jiukuaitech.bookkeeping.user.currency;\n\nimport com.jiukuaitech.bookkeeping.user.exception.InputNotValidExcep"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/dashboard/AssetOverviewVO.java",
    "chars": 328,
    "preview": "package com.jiukuaitech.bookkeeping.user.dashboard;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport java.math.BigDe"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/dashboard/DashboardController.java",
    "chars": 2207,
    "preview": "package com.jiukuaitech.bookkeeping.user.dashboard;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseController;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/dashboard/DashboardService.java",
    "chars": 11850,
    "preview": "package com.jiukuaitech.bookkeeping.user.dashboard;\n\nimport com.jiukuaitech.bookkeeping.user.account.Account;\nimport com"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/CategoryConflictException.java",
    "chars": 142,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\n\n/*\n添加支出或收入时,选择的分类有重复\n */\npublic class CategoryConflictException extends "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/Deal.java",
    "chars": 683,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\n\nimport com.jiukuaitech.bookkeeping.user.payee.Payee;\nimport com.jiukuait"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealAddRequest.java",
    "chars": 1374,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseEntity;\nimport com.jiuk"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealController.java",
    "chars": 823,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseController;\nimport com."
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealExceptionHandler.java",
    "chars": 1044,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimport com"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealQueryResultVO.java",
    "chars": 291,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport org.springframework.d"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealRepository.java",
    "chars": 291,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\n\nimport com.jiukuaitech.bookkeeping.user.base.HasBookRepository;\nimport o"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealService.java",
    "chars": 11339,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\n\nimport com.jiukuaitech.bookkeeping.user.account.Account;\nimport com.jiuk"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealSpec.java",
    "chars": 1889,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\n\nimport com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlowQueryReq"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealUpdateRequest.java",
    "chars": 1365,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseEntity;\nimport com.jiuk"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/deal/DealVOForList.java",
    "chars": 1252,
    "preview": "package com.jiukuaitech.bookkeeping.user.deal;\n\nimport com.jiukuaitech.bookkeeping.user.category_relation.CategoryRelati"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccount.java",
    "chars": 776,
    "preview": "package com.jiukuaitech.bookkeeping.user.debt_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.Account;\nimport "
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountAddRequest.java",
    "chars": 670,
    "preview": "package com.jiukuaitech.bookkeeping.user.debt_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountAddReques"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountController.java",
    "chars": 1837,
    "preview": "package com.jiukuaitech.bookkeeping.user.debt_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountQueryRequ"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountRepository.java",
    "chars": 854,
    "preview": "package com.jiukuaitech.bookkeeping.user.debt_account;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseRepository;\nimp"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountService.java",
    "chars": 2830,
    "preview": "package com.jiukuaitech.bookkeeping.user.debt_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountQueryRequ"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountSumVO.java",
    "chars": 334,
    "preview": "package com.jiukuaitech.bookkeeping.user.debt_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountSumVO;\nim"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/debt_account/DebtAccountVOForList.java",
    "chars": 781,
    "preview": "package com.jiukuaitech.bookkeeping.user.debt_account;\n\nimport com.jiukuaitech.bookkeeping.user.account.AccountVOForExte"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/GlobalExceptionHandler.java",
    "chars": 4729,
    "preview": "package com.jiukuaitech.bookkeeping.user.exception;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimpo"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/InputNotValidException.java",
    "chars": 119,
    "preview": "package com.jiukuaitech.bookkeeping.user.exception;\n\npublic class InputNotValidException extends RuntimeException {\n\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/ItemNotFoundException.java",
    "chars": 117,
    "preview": "package com.jiukuaitech.bookkeeping.user.exception;\n\npublic class ItemNotFoundException extends RuntimeException {\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/NameExistsException.java",
    "chars": 115,
    "preview": "package com.jiukuaitech.bookkeeping.user.exception;\n\npublic class NameExistsException extends RuntimeException {\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/PermissionException.java",
    "chars": 299,
    "preview": "package com.jiukuaitech.bookkeeping.user.exception;\n\n\npublic class PermissionException extends RuntimeException {\n\n    p"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/TokenEmptyException.java",
    "chars": 115,
    "preview": "package com.jiukuaitech.bookkeeping.user.exception;\n\npublic class TokenEmptyException extends RuntimeException {\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/exception/TokenNotValidException.java",
    "chars": 118,
    "preview": "package com.jiukuaitech.bookkeeping.user.exception;\n\npublic class TokenNotValidException extends RuntimeException {\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense/Expense.java",
    "chars": 513,
    "preview": "package com.jiukuaitech.bookkeeping.user.expense;\n\nimport com.jiukuaitech.bookkeeping.user.deal.Deal;\nimport lombok.Gett"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense/ExpenseController.java",
    "chars": 2472,
    "preview": "package com.jiukuaitech.bookkeeping.user.expense;\n\nimport com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlowQuery"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense/ExpenseRepository.java",
    "chars": 1122,
    "preview": "package com.jiukuaitech.bookkeeping.user.expense;\n\nimport com.jiukuaitech.bookkeeping.user.base.HasBookRepository;\nimpor"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense/ExpenseService.java",
    "chars": 4084,
    "preview": "package com.jiukuaitech.bookkeeping.user.expense;\n\nimport com.jiukuaitech.bookkeeping.user.deal.DealQueryResultVO;\nimpor"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense_category/ExpenseCategory.java",
    "chars": 376,
    "preview": "package com.jiukuaitech.bookkeeping.user.expense_category;\n\nimport javax.persistence.*;\n\nimport com.jiukuaitech.bookkeep"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/expense_category/ExpenseCategoryController.java",
    "chars": 2572,
    "preview": "package com.jiukuaitech.bookkeeping.user.expense_category;\n\nimport com.jiukuaitech.bookkeeping.user.category.CategoryAdd"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImage.java",
    "chars": 939,
    "preview": "package com.jiukuaitech.bookkeeping.user.flow_images;\n\nimport com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlow;"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImageController.java",
    "chars": 1206,
    "preview": "package com.jiukuaitech.bookkeeping.user.flow_images;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nim"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImageExceptionHandler.java",
    "chars": 1307,
    "preview": "package com.jiukuaitech.bookkeeping.user.flow_images;\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimp"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImageRepository.java",
    "chars": 614,
    "preview": "package com.jiukuaitech.bookkeeping.user.flow_images;\n\nimport com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlow;"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImageService.java",
    "chars": 3472,
    "preview": "package com.jiukuaitech.bookkeeping.user.flow_images;\n\nimport com.jiukuaitech.bookkeeping.user.user.User;\nimport com.jiu"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/FlowImageVOForList.java",
    "chars": 634,
    "preview": "package com.jiukuaitech.bookkeeping.user.flow_images;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n@Getter\n@Setter\npubl"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/ImageExistsException.java",
    "chars": 119,
    "preview": "package com.jiukuaitech.bookkeeping.user.flow_images;\n\npublic class ImageExistsException extends RuntimeException {\n\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/UploadCallbackRequest.java",
    "chars": 209,
    "preview": "package com.jiukuaitech.bookkeeping.user.flow_images;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n@Getter\n@Setter\npubl"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/flow_images/UploadKeyEmptyException.java",
    "chars": 122,
    "preview": "package com.jiukuaitech.bookkeeping.user.flow_images;\n\npublic class UploadKeyEmptyException extends RuntimeException {\n\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/Group.java",
    "chars": 1278,
    "preview": "package com.jiukuaitech.bookkeeping.user.group;\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport com.jiukuaite"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupAddRequest.java",
    "chars": 519,
    "preview": "package com.jiukuaitech.bookkeeping.user.group;\n\nimport com.jiukuaitech.bookkeeping.user.validation.NameValidator;\nimpor"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupController.java",
    "chars": 2084,
    "preview": "package com.jiukuaitech.bookkeeping.user.group;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimport c"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupExceptionHandler.java",
    "chars": 1298,
    "preview": "package com.jiukuaitech.bookkeeping.user.group;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimport c"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupHasBookException.java",
    "chars": 113,
    "preview": "package com.jiukuaitech.bookkeeping.user.group;\n\npublic class GroupHasBookException extends RuntimeException {\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupMaxCountException.java",
    "chars": 114,
    "preview": "package com.jiukuaitech.bookkeeping.user.group;\n\npublic class GroupMaxCountException extends RuntimeException {\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupRepository.java",
    "chars": 436,
    "preview": "package com.jiukuaitech.bookkeeping.user.group;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseRepository;\nimport com"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupService.java",
    "chars": 5114,
    "preview": "package com.jiukuaitech.bookkeeping.user.group;\n\nimport com.jiukuaitech.bookkeeping.user.book.Book;\nimport com.jiukuaite"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupUpdateRequest.java",
    "chars": 372,
    "preview": "package com.jiukuaitech.bookkeeping.user.group;\n\nimport com.jiukuaitech.bookkeeping.user.validation.NameValidator;\nimpor"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/group/GroupVOForList.java",
    "chars": 581,
    "preview": "package com.jiukuaitech.bookkeeping.user.group;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n@Getter\n@Setter\npublic cla"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income/Income.java",
    "chars": 274,
    "preview": "package com.jiukuaitech.bookkeeping.user.income;\n\nimport com.jiukuaitech.bookkeeping.user.deal.Deal;\nimport lombok.Gette"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income/IncomeController.java",
    "chars": 2466,
    "preview": "package com.jiukuaitech.bookkeeping.user.income;\n\nimport com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlowQueryR"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income/IncomeRepository.java",
    "chars": 782,
    "preview": "package com.jiukuaitech.bookkeeping.user.income;\n\nimport com.jiukuaitech.bookkeeping.user.base.HasBookRepository;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income/IncomeService.java",
    "chars": 2606,
    "preview": "package com.jiukuaitech.bookkeeping.user.income;\n\nimport com.jiukuaitech.bookkeeping.user.balance_flow.BalanceFlowQueryR"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income_category/IncomeCategory.java",
    "chars": 373,
    "preview": "package com.jiukuaitech.bookkeeping.user.income_category;\n\nimport javax.persistence.*;\n\nimport com.jiukuaitech.bookkeepi"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/income_category/IncomeCategoryController.java",
    "chars": 2569,
    "preview": "package com.jiukuaitech.bookkeeping.user.income_category;\n\nimport com.jiukuaitech.bookkeeping.user.category.CategoryAddR"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/interceptor/AuthInterceptor.java",
    "chars": 1628,
    "preview": "package com.jiukuaitech.bookkeeping.user.interceptor;\n\nimport com.jiukuaitech.bookkeeping.user.exception.TokenEmptyExcep"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/interceptor/MvcInterceptorConfig.java",
    "chars": 1275,
    "preview": "package com.jiukuaitech.bookkeeping.user.interceptor;\n\nimport org.springframework.context.annotation.Configuration;\nimpo"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/interceptor/StringTrimModule.java",
    "chars": 1034,
    "preview": "package com.jiukuaitech.bookkeeping.user.interceptor;\n\nimport com.fasterxml.jackson.core.JsonParser;\nimport com.fasterxm"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/Item.java",
    "chars": 1376,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseEntity;\nimport com.jiuk"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemAddRequest.java",
    "chars": 684,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\nimport com.jiukuaitech.bookkeeping.user.validation.NameValidator;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemController.java",
    "chars": 2441,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimport co"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemCountException.java",
    "chars": 109,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\npublic class ItemCountException extends RuntimeException {\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemExceptionHandler.java",
    "chars": 1029,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\nimport com.jiukuaitech.bookkeeping.user.response.BaseResponse;\nimport co"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemQueryRequest.java",
    "chars": 82,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\npublic class ItemQueryRequest {\n}\n"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemRepository.java",
    "chars": 456,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\nimport com.jiukuaitech.bookkeeping.user.base.BaseRepository;\nimport com."
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemService.java",
    "chars": 8270,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\nimport com.jiukuaitech.bookkeeping.user.exception.ItemNotFoundException;"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemSpec.java",
    "chars": 484,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\nimport com.jiukuaitech.bookkeeping.user.user.User;\nimport org.springfram"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemUpdateRequest.java",
    "chars": 396,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\nimport com.jiukuaitech.bookkeeping.user.validation.NameValidator;\nimport"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/item/ItemVOForList.java",
    "chars": 2040,
    "preview": "package com.jiukuaitech.bookkeeping.user.item;\n\nimport com.jiukuaitech.bookkeeping.user.utils.EnumUtils;\nimport lombok.G"
  },
  {
    "path": "bookkeeping-user-api/src/main/java/com/jiukuaitech/bookkeeping/user/payee/Payee.java",
    "chars": 709,
    "preview": "package com.jiukuaitech.bookkeeping.user.payee;\n\nimport com.jiukuaitech.bookkeeping.user.base.BookNameNotesEnableEntity;"
  }
]

// ... and 1344 more files (download for full content)

About this extraction

This page contains the full source code of the markliu2013/bookkeeping GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1544 files (3.2 MB), approximately 928.8k tokens, and a symbol index with 3013 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!